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 nameaction—narrowed,reordered,selected, orskippedcandidatesBefore/candidatesAfter— member IPs, weights, regions, scores at that pointnote— 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.
- Select a service from the dropdown.
- Optionally enter a client IP (leave blank to use an unknown/default region).
- Click Trace — the panel shows the step list and the selected member.
- 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
- 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">"serviceId"</span><span class="fu">:</span> <span class="st">"svc-abc123"</span><span class="fu">,</span></span><span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">"clientIp"</span><span class="fu">:</span> <span class="st">"94.100.14.1"</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">"serviceId"</span><span class="fu">:</span> <span class="st">"svc-abc123"</span><span class="fu">,</span></span><span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">"domain"</span><span class="fu">:</span> <span class="st">"api.example.com."</span><span class="fu">,</span></span><span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">"clientIp"</span><span class="fu">:</span> <span class="st">"94.100.14.1"</span><span class="fu">,</span></span><span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">"clientRegion"</span><span class="fu">:</span> <span class="st">"GB"</span><span class="fu">,</span></span><span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">"algorithm"</span><span class="fu">:</span> <span class="st">"geo-ip → weighted-round-robin"</span><span class="fu">,</span></span><span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">"steps"</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">"filter"</span><span class="fu">:</span> <span class="st">"geo-ip"</span><span class="fu">,</span></span><span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="dt">"action"</span><span class="fu">:</span> <span class="st">"narrowed"</span><span class="fu">,</span></span><span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="dt">"candidatesBefore"</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">"ip"</span><span class="fu">:</span> <span class="st">"10.0.0.1"</span><span class="fu">,</span> <span class="dt">"weight"</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">"region"</span><span class="fu">:</span> <span class="st">"GB"</span><span class="fu">,</span> <span class="dt">"score"</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">"priority"</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">"ip"</span><span class="fu">:</span> <span class="st">"10.0.0.2"</span><span class="fu">,</span> <span class="dt">"weight"</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">"region"</span><span class="fu">:</span> <span class="st">"US"</span><span class="fu">,</span> <span class="dt">"score"</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">"priority"</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">"candidatesAfter"</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">"ip"</span><span class="fu">:</span> <span class="st">"10.0.0.1"</span><span class="fu">,</span> <span class="dt">"weight"</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">"region"</span><span class="fu">:</span> <span class="st">"GB"</span><span class="fu">,</span> <span class="dt">"score"</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">"priority"</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">"filter"</span><span class="fu">:</span> <span class="st">"weighted-round-robin"</span><span class="fu">,</span></span><span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a> <span class="dt">"action"</span><span class="fu">:</span> <span class="st">"selected"</span><span class="fu">,</span></span><span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> <span class="dt">"candidatesBefore"</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">"ip"</span><span class="fu">:</span> <span class="st">"10.0.0.1"</span><span class="fu">,</span> <span class="dt">"weight"</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">"region"</span><span class="fu">:</span> <span class="st">"GB"</span><span class="fu">,</span> <span class="dt">"score"</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">"priority"</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">"candidatesAfter"</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">"ip"</span><span class="fu">:</span> <span class="st">"10.0.0.1"</span><span class="fu">,</span> <span class="dt">"weight"</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span> <span class="dt">"region"</span><span class="fu">:</span> <span class="st">"GB"</span><span class="fu">,</span> <span class="dt">"score"</span><span class="fu">:</span> <span class="fl">1.0</span><span class="fu">,</span> <span class="dt">"priority"</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">"note"</span><span class="fu">:</span> <span class="st">"simulated — actual rotation uses live counter"</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">"selectedIp"</span><span class="fu">:</span> <span class="st">"10.0.0.1"</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.