Cross-Cutting Concerns — Series 3

Preview — 3 of 10 questions

Why name spans after the route template?

javascript
span.updateName(`${req.method} ${req.route?.path ?? 'unmatched'}`);
// "GET /cats/:id"   rather than   "GET /cats/42"
ABecause span names must not contain digits
BBecause tracing backends group and aggregate by operation name: a template yields one operation with a latency distribution across all ids, while the raw URL produces a distinct operation per entity — which destroys the aggregate view and inflates the backend's index
CBecause the raw URL would leak the entity id, which is always sensitive
DBecause the route template is the only value available inside an interceptor

What would change that?

javascript
1% of traces are kept. Almost no captured trace contains an error.
ARaising the rate to 100%, which is the only reliable option
BSampling per service rather than per trace
CSampling only requests that exceed a latency threshold, decided at the edge
DTail-based sampling: buffer each trace until it completes, then decide — keeping everything that errored or ran slowly plus a small random share of the rest — whereas head-based sampling decides at the first span, before anything is known about the outcome

What does this measure, and why is it a better saturation signal than CPU usage?

javascript
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
setInterval(() => metrics.gauge('event_loop_delay_p99', h.percentile(99)), 5000);
AIt measures how long callbacks wait to run, which is what users experience as latency: a single-threaded process can be at moderate CPU and still be saturated by one blocking operation, so the delay captures the queueing that CPU percentage hides
BIt measures garbage-collection pauses exclusively
CIt measures the number of pending promises, which grows before CPU does
DIt measures I/O wait, and is high whenever the process is idle

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.