Implementing Distributed Tracing in Sentry to Map Microservice Latency
Learn how to use Sentry's Distributed Tracing to link requests across microservices using header propagation and sampling strategies to identify latency bottlenecks.
05 Aug 2025, 15:46 UTC

Solving the "Black Box" Request Problem
In a microservices architecture, a single user request often triggers a chain of calls across multiple services. When a request is slow or fails, logs from a single service only show a fragment of the story. The core problem is context loss: Service A knows it called Service B, but Service B doesn't know which specific request from Service A it is processing.
The solution is Distributed Tracing. By injecting a unique trace identifier into every cross-service request, Sentry can stitch together individual "spans" (units of work) into a single timeline. This allows you to identify exactly which hop in the network is causing a bottleneck or where a failure originated.
How Trace Propagation Works
Sentry achieves distributed tracing through header injection. When an instrumented SDK makes an outgoing HTTP request, it attaches two specific headers to the request: sentry-trace and baggage.
- sentry-trace: Contains the trace ID (the unique ID for the entire request chain) and the span ID (the ID for that specific operation).
- baggage: Carries metadata (like user IDs or custom tags) that should persist across all services in the trace.
When the downstream service receives the request, its Sentry SDK extracts these headers and starts a new span as a child of the incoming trace ID, maintaining the lineage.
Configuration Example: Node.js to Python
To enable this, both the upstream and downstream services must have the Sentry SDK initialized with a tracesSampleRate greater than 0. This value determines the percentage of requests that are recorded to avoid overloading your quota.
Upstream Service (Node.js)
const Sentry = require("@sentry/node");
Sentry.init({
dsn: "YOUR_DSN",
// Sample 10% of transactions
tracesSampleRate: 0.1,
});
// Sentry automatically wraps the 'http' and 'https' modules
// to inject headers into outgoing requests.
async function callDownstream() {
await fetch("https://api.service-b.com/data");
}
Downstream Service (Python/Flask)
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from flask import Flask
sentry_sdk.init(
dsn="YOUR_DSN",
integrations=[FlaskIntegration()],
# Sample 10% of transactions
traces_sample_rate=0.1,
)
app = Flask(__name__)
@app.route("/data")
def data():
return {"status": "ok"}
Operational Limits and Risks
While distributed tracing provides deep visibility, it introduces specific overheads and configuration risks:
The Sampling Trap
Setting tracesSampleRate: 1.0 in a high-traffic production environment can lead to two issues: quota exhaustion (hitting your Sentry plan limits rapidly) and performance degradation due to the overhead of capturing and sending every single transaction.
Non-HTTP Protocols
Sentry's automatic instrumentation primarily targets HTTP/HTTPS. If your services communicate via gRPC, RabbitMQ, or Kafka, the SDK cannot automatically inject headers. In these cases, you must manually extract the trace context from the producer and inject it into the consumer's span.
Clock Drift
Because spans are recorded on different physical servers, slight differences in system clocks can occasionally cause spans to appear out of order or overlap incorrectly in the Performance UI.
Verifying the Implementation
To ensure tracing is working correctly before relying on it for production debugging, perform these three checks:
- Network Inspection: Use a tool like Wireshark or a proxy to verify that the
sentry-traceheader is present in the request sent from Service A to Service B. - SDK Logs: Check your application logs for Sentry initialization errors, specifically ensuring the DSN is valid and the SDK has successfully wrapped the HTTP client.
- Performance Dashboard: Trigger a request and navigate to the Performance tab in Sentry. Search for the transaction; you should see a waterfall chart showing the request entering Service A and then a child span representing the call to Service B.
Rollback Procedure
If you observe increased latency or memory usage after enabling tracing, you can disable it without redeploying code if you use environment variables for configuration:
- Set
SENTRY_TRACES_SAMPLE_RATE=0in your environment configuration. - Restart the service pods/instances.
- Verify that the
sentry-traceheaders are no longer being sent in outgoing requests.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.