Build the safeguards
Eight explained steps, a source example and a checkpoint at each decision.
Read the tutorialOpenTelemetry / Observability / SLOs
Follow Request Tracing Lab from its visible failure to a testable implementation. Each step names one decision and a checkpoint.
Step 1 of 8
The root span describes GET /report, not an internal implementation detail. Its duration represents the operation the visitor experiences in this fixture. A health endpoint checks a different question and cannot replace a user-facing indicator.
const root = tracer.startSpan("GET /report", {}, ROOT_CONTEXT);Checkpoint: Explain why a successful health check does not prove the report is responsive.
Step 2 of 8
The service and database-fixture spans surround work that can explain the request. Their names remain bounded and understandable. Attributes describe the operation without embedding arbitrary customer data. Too many tiny spans can create overhead without helping a diagnosis.
tracer.startSpan("db.query orders", {}, parentContext);Checkpoint: Identify what the database span actually measures in this exercise.
Step 3 of 8
The broken database span uses ROOT_CONTEXT and becomes an independent trace. The safeguarded path places the service span in the supplied context before creating the child. A real network boundary additionally needs compatible injection and extraction of trace headers.
const childContext = trace.setSpan(parentContext, serviceSpan);Checkpoint: Verify that all three safeguarded spans share one trace ID.
Step 4 of 8
Eight responses succeed, but one intentionally waits much longer. An availability-only indicator remains 100%. The latency indicator counts requests under 100 ms, including queueing and work inside the measured boundary. Define eligibility before choosing a target.
goodLatencyEvents / eligibleRequestsCheckpoint: Read the under-100-ms fraction independently from response success.
Step 5 of 8
The example uses nearest-rank p95 on eight recorded durations. One long sample can dominate the tail while barely moving an average. A tiny fixture makes this arithmetic visible; production percentile estimates depend on aggregation methods, histogram buckets and traffic volume.
sorted[Math.ceil(0.95 * sorted.length) - 1]Checkpoint: Explain why averaging p95 values across servers is generally not a valid fleet p95.
Step 6 of 8
A target states the permitted fraction of bad eligible events over a specified window. The lab’s illustrative target is 90% under 100 ms. Real alerts need a window, minimum useful volume and burn-rate reasoning rather than an alarm on every slow request.
budgetFraction = 1 - target;
consumedFraction = badEvents / eligibleEvents;Checkpoint: Name the missing production choices before calling the fixture an SLO policy.
Step 7 of 8
The cardinality preset counts label combinations. A customer ID creates a new series for each customer; a route template keeps the dimension bounded. Trace and log storage have their own privacy and cost rules, but they need not force every identifier into metric labels.
lab_requests_total{route="/report"}Checkpoint: Find the eight label sets in the broken example and the one bounded set in the safe example.
Step 8 of 8
The local Node service exports real request spans and a Prometheus text endpoint. An optional Compose setup connects it to Prometheus and a provisioned Grafana dashboard. The browser itself runs neither a collector nor Grafana. Inspect the service and scrape configuration before extending them.
GET /report
GET /traces
GET /metricsCheckpoint: Make local requests, then verify that the request and good-latency counters change.
Use the experiment as an example. State the failure, explain the chosen boundary, show the test and name the tradeoff. Keep measured results separate from production assumptions.
Prefect’s platform opening explicitly includes service indicators, error budgets and OpenTelemetry-style monitoring.
Eight explained steps, a source example and a checkpoint at each decision.
Read the tutorialUnderstand where each pattern helps and which tradeoffs remain.
Compare approachesDownload the independent environment, run the native checks and try a specific extension.
Open the how-to guideLab discussion / Trace the Wait Lab
Ask about the code, compare an approach, or describe an edge case. Reader comments are reviewed before publication.