Unified Service Tagging in Practice
The idea in one sentence
Section titled “The idea in one sentence”Set env, service, and version once on a deployable unit, and that same triple is what lets a metrics dashboard, an APM service page, and the Logs Explorer all agree on exactly which service you are looking at.
One deployable unit, tagged once
Section titled “One deployable unit, tagged once”Take a single deployable unit, checkout-service, and tag it with DD_ENV=production, DD_SERVICE=checkout-service, and DD_VERSION=2.4.1. Rather than hardcoding those three values in several places, the same Kubernetes labels/downward-API pattern from Foundations sets them once on the pod and reflects them into environment variables.
apiVersion: apps/v1kind: Deploymentmetadata: name: checkout-servicespec: template: metadata: labels: tags.datadoghq.com/env: "production" tags.datadoghq.com/service: "checkout-service" tags.datadoghq.com/version: "2.4.1" spec: containers: - name: checkout-service image: registry.example.com/checkout-service:2.4.1 env: - name: DD_ENV valueFrom: fieldRef: fieldPath: metadata.labels['tags.datadoghq.com/env'] - name: DD_SERVICE valueFrom: fieldRef: fieldPath: metadata.labels['tags.datadoghq.com/service'] - name: DD_VERSION valueFrom: fieldRef: fieldPath: metadata.labels['tags.datadoghq.com/version']The labels are the single source of truth. The downward API reflects them into DD_ENV/DD_SERVICE/DD_VERSION, so those environment variables always match what Kubernetes — and the Agent’s autodiscovery — already see on the pod. Change the label once, and every consumer downstream picks up the new value on the next rollout.
Three consumers, one identity
Section titled “Three consumers, one identity”- The Agent’s infrastructure/container metrics — autodiscovery tags container and infra metrics straight from the pod’s labels, so CPU, memory, and request-rate metrics for
checkout-servicepods carryenv,service, andversionwithout any separate configuration. - The tracer initialization for APM —
dd-tracereadsDD_ENV,DD_SERVICE, andDD_VERSIONfrom the environment automatically, so every span it creates is tagged with the same triple.
// dd-trace picks up DD_ENV, DD_SERVICE, and DD_VERSION from the environment automaticallyrequire('dd-trace').init({ log_injection: true});- The log integration from the previous lesson — because log injection reads the same active service configuration the tracer uses, the
dd.env,dd.service, anddd.versionfields stamped onto every log line are that identical triple too.
The pivot: one triple, three products, zero cross-referencing
Section titled “The pivot: one triple, three products, zero cross-referencing”With the triple flowing into all three products, a single incident walk looks like this: start on a metrics dashboard scoped to service:checkout-service env:production, and see CPU, latency, and request rate climbing. Jump to the APM service page for the same service, env, and version, and see trace latency, error rate, and the service’s neighbors on the service map. Jump again to the Logs Explorer, pre-filtered to that same triple, and see the exact log lines — including any dd.trace_id-tagged errors from the previous lesson — for that version, in that environment.
Compare that with the before state: metrics tagged service:checkout, a Java tracer tagged service:checkout-svc, and logs tagged application:checkout. Nothing lines up, and whoever is debugging has to remember three different names while moving between products. After tagging consistently, the string is identical everywhere, so any of the three products’ UI can pre-filter to the same identity, and a saved view in one product describes the exact same slice of the world in another.
flowchart LR T["env=production\nservice=checkout-service\nversion=2.4.1"] --> Agent[Agent autodiscovery] T --> Tracer[Tracer init] T --> LogInj[Log injection] Agent --> M[Metrics dashboard] Tracer --> A[APM service page] LogInj --> L[Logs Explorer] M -.pivot.-> A A -.pivot.-> L L -.pivot.-> M