Routing: Query Path Tracer

Query Path Tracer

The Query Path Tracer runs a dry-run simulation of the DNS resolution algorithm for any service and client IP you choose. It replays the exact filter chain that a real query would execute — using live health state and geo-IP data — and returns a step-by-step trace of which members were in contention at each stage and which member was ultimately selected.

No live DNS state is mutated. The round-robin counter is not advanced.


What the tracer shows

For a service with filter chain ["geo-ip", "weighted-round-robin"] and three members:

Step Filter Action Candidates before Candidates after
1 geo-ip narrowed 3 1
2 weighted-rr selected 1 1

Selected: 10.0.0.1

Each step records:

  • filter — the filter name
  • action — narrowed, reordered, selected, or skipped
  • candidatesBefore / candidatesAfter — member IPs, weights, regions, scores at that point
  • note — optional explanation (e.g. "no region match — kept all candidates")

WebUI — Trace panel

Click Trace in the top-right toolbar on the Topology page to open the trace panel.

  1. Select a service from the dropdown.
  2. Optionally enter a client IP (leave blank to use an unknown/default region).
  3. Click Trace — the panel shows the step list and the selected member.
  4. Click a step to highlight the corresponding members on the canvas:
    • Blue glow — still in the candidate set after this step
    • Dimmed — eliminated at or before this step
    • Green outline — the final selected member
  5. Use ▶ Play to animate through steps automatically, or click ← / → to step manually.

API

POST /api/v1/simulate

Requires: pools:read permission.

Request body:

<span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;serviceId&quot;</span><span class="fu">:</span> <span class="st">&quot;svc-abc123&quot;</span><span class="fu">,</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;clientIp&quot;</span><span class="fu">:</span> <span class="st">&quot;94.100.14.1&quot;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span>

clientIp is optional. Omit or pass "" to simulate from an unknown region.

Response:

<span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;serviceId&quot;</span><span class="fu">:</span> <span class="st">&quot;svc-abc123&quot;</span><span class="fu">,</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;domain&quot;</span><span class="fu">:</span> <span class="st">&quot;api.example.com.&quot;</span><span class="fu">,</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;clientIp&quot;</span><span class="fu">:</span> <span class="st">&quot;94.100.14.1&quot;</span><span class="fu">,</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;clientRegion&quot;</span><span class="fu">:</span> <span class="st">&quot;GB&quot;</span><span class="fu">,</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;algorithm&quot;</span><span class="fu">:</span> <span class="st">&quot;geo-ip → weighted-round-robin&quot;</span><span class="fu">,</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;steps&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;filter&quot;</span><span class="fu">:</span> <span class="st">&quot;geo-ip&quot;</span><span class="fu">,</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;action&quot;</span><span class="fu">:</span> <span class="st">&quot;narrowed&quot;</span><span class="fu">,</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;candidatesBefore&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span> <span class="dt">&quot;ip&quot;</span><span class="fu">:</span> <span class="st">&quot;10.0.0.1&quot;</span><span class="fu">,</span> <span class="dt">&quot;weight&quot;</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">&quot;region&quot;</span><span class="fu">:</span> <span class="st">&quot;GB&quot;</span><span class="fu">,</span> <span class="dt">&quot;score&quot;</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">&quot;priority&quot;</span><span class="fu">:</span> <span class="dv">0</span> <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span> <span class="dt">&quot;ip&quot;</span><span class="fu">:</span> <span class="st">&quot;10.0.0.2&quot;</span><span class="fu">,</span> <span class="dt">&quot;weight&quot;</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">&quot;region&quot;</span><span class="fu">:</span> <span class="st">&quot;US&quot;</span><span class="fu">,</span> <span class="dt">&quot;score&quot;</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">&quot;priority&quot;</span><span class="fu">:</span> <span class="dv">0</span> <span class="fu">}</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;candidatesAfter&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span> <span class="dt">&quot;ip&quot;</span><span class="fu">:</span> <span class="st">&quot;10.0.0.1&quot;</span><span class="fu">,</span> <span class="dt">&quot;weight&quot;</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">&quot;region&quot;</span><span class="fu">:</span> <span class="st">&quot;GB&quot;</span><span class="fu">,</span> <span class="dt">&quot;score&quot;</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">&quot;priority&quot;</span><span class="fu">:</span> <span class="dv">0</span> <span class="fu">}</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> <span class="ot">]</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;filter&quot;</span><span class="fu">:</span> <span class="st">&quot;weighted-round-robin&quot;</span><span class="fu">,</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;action&quot;</span><span class="fu">:</span> <span class="st">&quot;selected&quot;</span><span class="fu">,</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;candidatesBefore&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span> <span class="dt">&quot;ip&quot;</span><span class="fu">:</span> <span class="st">&quot;10.0.0.1&quot;</span><span class="fu">,</span> <span class="dt">&quot;weight&quot;</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">&quot;region&quot;</span><span class="fu">:</span> <span class="st">&quot;GB&quot;</span><span class="fu">,</span> <span class="dt">&quot;score&quot;</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">&quot;priority&quot;</span><span class="fu">:</span> <span class="dv">0</span> <span class="fu">}</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a> <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;candidatesAfter&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span> <span class="dt">&quot;ip&quot;</span><span class="fu">:</span> <span class="st">&quot;10.0.0.1&quot;</span><span class="fu">,</span> <span class="dt">&quot;weight&quot;</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">&quot;region&quot;</span><span class="fu">:</span> <span class="st">&quot;GB&quot;</span><span class="fu">,</span> <span class="dt">&quot;score&quot;</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">&quot;priority&quot;</span><span class="fu">:</span> <span class="dv">0</span> <span class="fu">}</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;note&quot;</span><span class="fu">:</span> <span class="st">&quot;simulated — actual rotation uses live counter&quot;</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a> <span class="fu">}</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a> <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;selectedIp&quot;</span><span class="fu">:</span> <span class="st">&quot;10.0.0.1&quot;</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span>

When no healthy candidates exist, the response has "noCandidate": true and "selectedIp": "".


gslbctl

<span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Trace with a specific client IP</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">gslbctl</span> trace <span class="op"><</span>service-id<span class="op">></span> --client-ip 94.100.14.1 <span class="at">--server</span> https://nexus-api.example.com</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co"># Trace with unknown/default region</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="ex">gslbctl</span> trace <span class="op"><</span>service-id<span class="op">></span> --server https://nexus-api.example.com</span>

Example output:

Service: api.example.com. (svc-abc1)
Client: 94.100.14.1 [region: GB]
Chain: geo-ip → weighted-round-robin
 
STEP FILTER ACTION N→N NOTE
────────────────────────────────────────────────────────────────────────────
1 geo-ip narrowed 2→1
· 10.0.0.1 w=10 (GB)
2 weighted-rr selected 1→1 simulated — actual rotation uses live counter
✓ 10.0.0.1 w=10 (GB)
 
Selected: 10.0.0.1

Behaviour notes

Scenario What happens
Filter would eliminate all candidates Step is marked skipped and all candidates pass through
latency filter with no RTT data Step is marked skipped
round-robin Always picks index 0 in simulate mode — live counter not advanced
weighted-round-robin Random pick (reproducible within the simulation, but random across calls)
No pool assigned to service noCandidate: true
All members unhealthy or disabled noCandidate: true

Permissions

Requires pools:read. Available to tenant_admin, operator, and viewer roles.


Was this article helpful?