Service Mesh Observability: The Unified Sidecar Playbook for Traces, Metrics, and Logs
Teams running Istio, Linkerd, or any Envoy-based mesh can replace scattered SDK instrumentation with one unified observability layer, but only if they propagate Trace Context correctly across proxies and survive the sampling and cardinality pitfalls that silently break traces and blow up Prometheus memory.
Traditional microservice observability forces each service to embed SDKs, log manually, and report metrics, which turns into a mess of inconsistent instrumentation, broken traces across old or third-party services, and painful upgrade cycles. Service Mesh flips that by running an Envoy sidecar in front of every service, so all traffic passes through a proxy that naturally sits at the perfect observation point.
The article builds a complete observability stack on that foundation. Distributed tracing works through W3C Trace Context headers: Envoy reads `traceparent` on inbound requests, creates its own span, and injects context on outbound calls, so inter-service call trees appear even when business code has no instrumentation. Metrics follow the RED methodology, with Envoy exposing Prometheus-format stats on `:15090/stats/prometheus`, and the article provides PromQL for rate, error rate, and P99 latency. Access logs get the same Trace ID injected, letting teams drill from a Grafana alert into Tempo to find a slow trace, then into Loki to see the exact request logs.
The practical details matter: header allow-lists in Istio, consistent sampling at the ingress, avoiding high-cardinality labels like `path`, and separating trace and log storage. The article also acknowledges the mesh layer's blind spot; it cannot see inside a service, so the best setup combines sidecar observability with application-level instrumentation, unified through the same Trace Context.
The article positions mesh observability as a complement, not a replacement, for application-layer instrumentation; the sidecar sees inter-service traffic but is blind to database calls and internal logic, so a truly complete picture requires both layers sharing the same Trace Context.
The biggest operational risks in this design are not the Envoy config but the subtle propagation details: header allow-lists, sampling consistency, and matching propagation formats between the SDK and proxy, where small mistakes silently create disconnected traces.
The recommendation to control metric cardinality and separate trace/log storage reflects real cost constraints; at scale, observability data volume becomes a financial problem, and the article's sampling and storage guidance is a practical answer to that.
Grafana's Exemplar feature is presented as the cleanest bridge between metrics and traces, but it only works if trace IDs are embedded in metric labels, which itself requires careful design of the Prometheus scrape configuration.