---
title: "Trace requests across services · Agent Wranglers"
url: https://agentwranglers.se/playbook/operations/metrics-and-traces/distributed-tracing
updated: 2026-10-20
licence: "All rights reserved"
---

# Trace requests across services

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Recommended
- Chapter: [Metrics and traces](https://agentwranglers.se/playbook/operations/metrics-and-traces)
- Rule: When a request crosses services, record one trace that follows it, and pass the trace context with the W3C `traceparent` header.
- How: Add OpenTelemetry to each service with its automatic instrumentation, so incoming and outgoing calls create spans. Give each service a fixed `service.name`. Keep every error trace and a share of the rest by sampling in a collector after the trace ends. A service deciding at the start cannot know a request will fail. Use the trace ID as the request ID in logs.
- Check: Make one request that crosses two services on staging. The tracing tool shows one trace with spans from both, and the logs carry the same trace ID. A request that fails is always in the tracing tool.

Example:

```http
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
```

```js
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';

new NodeSDK({
  serviceName: 'checkout',
  traceExporter: new OTLPTraceExporter({ url: 'https://otel.example.com/v1/traces' }),
  instrumentations: [getNodeAutoInstrumentations()],
}).start();
```

```python
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

provider = TracerProvider(resource=Resource.create({"service.name": "checkout"}))
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="https://otel.example.com/v1/traces")))
trace.set_tracer_provider(provider)
RequestsInstrumentor().instrument()
```

```yaml
# OpenTelemetry Collector: keep every failed trace and 10% of the rest
processors:
  tail_sampling:
    decision_wait: 10s
    policies:
      - name: keep-errors
        type: status_code
        status_code: { status_codes: [ERROR] }
      - name: sample-rest
        type: probabilistic
        probabilistic: { sampling_percentage: 10 }
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers operations playbook: https://agentwranglers.se/playbook/operations/metrics-and-traces/distributed-tracing`.

- Previous: [Measure what each machine uses](https://agentwranglers.se/playbook/operations/metrics-and-traces/resource-metrics)
- Next: [Give each service one dashboard](https://agentwranglers.se/playbook/operations/metrics-and-traces/service-dashboards)
- [Metrics and traces](https://agentwranglers.se/playbook/operations/metrics-and-traces)
