diff --git a/config/_default/menus/main.en.yaml b/config/_default/menus/main.en.yaml
index dc78b180dda..fa908a2f1c5 100644
--- a/config/_default/menus/main.en.yaml
+++ b/config/_default/menus/main.en.yaml
@@ -4284,7 +4284,7 @@ menu:
parent: tracing
identifier: tracing_glossary
weight: 1
- - name: Application Instrumentation
+ - name: Set Up APM
url: tracing/trace_collection/
parent: tracing
identifier: tracing_trace_collection
diff --git a/content/en/tracing/trace_collection/_index.md b/content/en/tracing/trace_collection/_index.md
index 1ed02680a2f..8bc0d43ba79 100644
--- a/content/en/tracing/trace_collection/_index.md
+++ b/content/en/tracing/trace_collection/_index.md
@@ -1,6 +1,6 @@
---
-title: Application Instrumentation
-description: "Get Started with Datadog APM"
+title: Set Up APM
+description: "Set up Datadog APM to collect traces from your applications. Choose Single Step Instrumentation for automatic setup on Kubernetes, Linux, Docker, or Windows, or use manually managed SDKs for full configuration control."
aliases:
- /tracing/setup
- /tracing/send_traces/
@@ -31,148 +31,55 @@ algolia:
---
## Overview
-Application {{< tooltip glossary="instrumentation" >}} with Datadog APM involves:
-1. **SDK setup**: Adding a Datadog SDK to your application.
-2. **Span creation**: Capturing observability data as {{< tooltip glossary="span" >}}s.
+Set up Datadog APM to collect traces from your applications. [Single Step Instrumentation][1] (SSI) is the recommended approach for most users. It automatically installs and configures Datadog SDKs with no code changes required.
- Spans are automatically generated by default as soon as the SDK is loaded. This is known as **auto-instrumentation** and provides sufficient visibility for most users. If you need more control, you can optionally add custom spans.
-
-**Note**: These steps assume you have a [Datadog Agent][5] installed and configured to receive traces.
-
-{{< img src="tracing/visualization/troubleshooting_pipeline.png" alt="The APM pipeline">}}
-
-## Getting started
+## Get APM running
-### Single step instrumentation (recommended)
-
-[Single Step Instrumentation][1] (SSI) automatically installs and configures Datadog SDKs with a single command. Auto-instrumentation then immediately begins capturing traces from your supported frameworks and libraries, with no code changes required.
+SSI automatically installs and loads Datadog SDKs into your application processes at runtime with a single command. Pick your platform to get started:
{{< whatsnext desc=" " >}}
- {{< nextlink href="/tracing/trace_collection/single-step-apm/" >}}Get started with Single Step Instrumentation{{< /nextlink >}}
+ {{< nextlink href="/tracing/trace_collection/single-step-apm/kubernetes" >}}Kubernetes{{< /nextlink >}}
+ {{< nextlink href="/tracing/trace_collection/single-step-apm/linux" >}}Linux{{< /nextlink >}}
+ {{< nextlink href="/tracing/trace_collection/single-step-apm/docker" >}}Docker{{< /nextlink >}}
+ {{< nextlink href="/tracing/trace_collection/single-step-apm/windows" >}}Windows IIS{{< /nextlink >}}
{{< /whatsnext >}}
-### Manual setup and custom spans
-
-As your observability needs grow, you can add more control and customization:
+## Need more control?
-**For full SDK configuration control:** Use [manually managed Datadog SDKs][2] if you need granular control over SDK behavior and configuration.
+If you need full control over SDK configuration and installation, use [manually managed Datadog SDKs][2]. This approach requires adding the SDK to your application code or build process.
{{< whatsnext desc=" " >}}
- {{< nextlink href="/tracing/trace_collection/dd_libraries/" >}}Use manually managed Datadog SDKs{{< /nextlink >}}
+ {{< nextlink href="/tracing/trace_collection/dd_libraries/" >}}Set up manually managed SDKs{{< /nextlink >}}
{{< /whatsnext >}}
-**For custom spans without code changes:** Use [Dynamic Instrumentation][4] to create custom spans from the Datadog UI without redeploying your application.
+## Add custom spans
-{{< whatsnext desc=" " >}}
- {{< nextlink href="/tracing/trace_collection/dynamic_instrumentation/" >}}Add custom spans with Dynamic Instrumentation{{< /nextlink >}}
-{{< /whatsnext >}}
+After you have APM running, you can add custom spans for visibility into application-specific code paths:
-**For custom spans in code:** Add [code-based custom instrumentation][3] to instrument custom business logic or add application-specific metadata to spans.
+- **Without code changes**: Use [Dynamic Instrumentation][4] to create custom spans from the Datadog UI without redeploying your application.
+- **In code**: Add [code-based custom instrumentation][3] to instrument custom business logic or add application-specific metadata to spans.
{{< whatsnext desc=" " >}}
+ {{< nextlink href="/tracing/trace_collection/dynamic_instrumentation/" >}}Add custom spans with Dynamic Instrumentation{{< /nextlink >}}
{{< nextlink href="/tracing/trace_collection/custom_instrumentation/" >}}Add custom spans with code-based instrumentation{{< /nextlink >}}
{{< /whatsnext >}}
-These options can be combined. For example, you can start with Single Step Instrumentation and add code-based custom instrumentation for specific spans, or use manually managed SDKs with Dynamic Instrumentation for no-deploy span additions.
-
-## Detailed comparison
-
-### SDK setup
-
-Single Step Instrumentation is the recommended starting point for most users. If you need more control over SDK configuration, you can use manually managed SDKs instead:
-
-
-
- |
- Single Step Instrumentation (recommended) |
- Manually managed SDKs |
-
-
- | How it works |
- Datadog automatically installs and loads SDKs into your application processes, at runtime, with a single command. |
- You install and configure SDKs directly in your application code or build process. |
-
-
- | Code changes? |
- No |
- Yes |
-
-
- | Setup complexity |
- Low - minimal configuration needed |
- Medium - requires environment and build configuration |
-
-
- | Configuration control |
- Standard defaults with optional overrides |
- Full control through environment variables and code |
-
-
- | When to use |
- Start here for fast, consistent instrumentation across services without code changes. |
- Progress to this when you need granular control over SDK behavior and configuration. |
-
-
-
-### Span customization
-
-Auto-instrumentation automatically creates spans for supported frameworks and libraries, providing essential observability with no additional work. When you need visibility into custom code paths or want to enrich traces with application-specific data, you can add custom spans using either Dynamic Instrumentation or code-based custom instrumentation:
-
-
-
- |
- Dynamic Instrumentation |
- Code-based custom instrumentation |
-
-
- | How it works |
- Configure instrumentation rules in the Datadog UI; rules are applied at runtime. |
- Add explicit tracing API calls in your application code. |
-
-
- | Code changes? |
- No |
- Yes |
-
-
- | Deployment required |
- No |
- Yes (to add or modify spans) |
-
-
- | When to use |
- Add custom spans without code changes or redeployments. |
- Progress to this when you need complex instrumentation logic or want spans permanently defined in code. |
-
-
-
-## APM setup tutorials
-
-The following tutorials guide you through setting up distributed tracing for a sample application on various infrastructure scenarios, with both automatic and custom instrumentation:
-
-{{< whatsnext desc="Choose your language and environment:" >}}
- {{< nextlink href="tracing/guide/tutorial-enable-python-host" >}}
Enabling Tracing on a Python Application on the Same Host as Datadog Agent{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-python-containers" >}}
Enabling Tracing on a Python Application and Datadog Agent in Containers{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-python-container-agent-host" >}}
Enabling Tracing for a Python Application in a Container and an Agent on a Host{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-host" >}}
Enabling Tracing on a Java Application on the Same Host as Datadog Agent{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-containers" >}}
Enabling Tracing on a Java Application and Datadog Agent in Containers{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-container-agent-host" >}}
Enabling Tracing for a Java Application in a Container and an Agent on a Host{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-gke" >}}
Enabling Tracing for a Java Application on GKE{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-aws-eks" >}}
Enabling Tracing for a Java Application on Amazon EKS{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-aws-ecs-ec2" >}}
Enabling Tracing for a Java Application in Amazon ECS with EC2{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-aws-ecs-fargate" >}}
Enabling Tracing for a Java Application in Amazon ECS with Fargate{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-java-admission-controller" >}}
Enabling Tracing for a Java Application with the Admission Controller{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-go-host" >}}
Enabling Tracing on a Go Application on the Same Host as Datadog Agent{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-go-containers" >}}
Enabling Tracing on a Go Application and Datadog Agent in Containers{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-go-aws-ecs-ec2" >}}
Enabling Tracing for a Go Application in Amazon ECS with EC2{{< /nextlink >}}
- {{< nextlink href="tracing/guide/tutorial-enable-go-aws-ecs-fargate" >}}
Enabling Tracing for a Go Application in Amazon ECS with Fargate{{< /nextlink >}}
+{{< agent-only >}}
+If a user asks to set up APM, tracing, or distributed tracing, start with Single Step Instrumentation (SSI) unless they specifically request manual SDK control.
-{{< /whatsnext >}}
+First, ask what language they're using. If the language is Go, C++, or Rust, SSI is not available — direct them to manually managed SDKs at /tracing/trace_collection/dd_libraries/.
+
+Then ask what platform they're running on:
+- Kubernetes → /tracing/trace_collection/single-step-apm/kubernetes
+- Linux host or VM → /tracing/trace_collection/single-step-apm/linux
+- Docker → /tracing/trace_collection/single-step-apm/docker
+- Windows IIS → /tracing/trace_collection/single-step-apm/windows
+{{< /agent-only >}}
## Further reading
@@ -182,5 +89,3 @@ The following tutorials guide you through setting up distributed tracing for a s
[2]: /tracing/trace_collection/dd_libraries/
[3]: /tracing/trace_collection/custom_instrumentation/
[4]: /tracing/trace_collection/dynamic_instrumentation/
-[5]: /agent/
-
diff --git a/content/en/tracing/trace_collection/single-step-apm/_index.md b/content/en/tracing/trace_collection/single-step-apm/_index.md
index d91068ebb79..bba20fa91f5 100644
--- a/content/en/tracing/trace_collection/single-step-apm/_index.md
+++ b/content/en/tracing/trace_collection/single-step-apm/_index.md
@@ -1,5 +1,6 @@
---
title: Single Step APM Instrumentation
+description: "Automatically instrument applications with Datadog APM using Single Step Instrumentation (SSI). Install the Datadog Agent and enable tracing with no code changes on Kubernetes, Linux, Docker, or Windows."
aliases:
- /tracing/trace_collection/admission_controller/
- /tracing/trace_collection/library_injection_local/
@@ -11,7 +12,7 @@ further_reading:
- link: /tracing/guide/injectors
tag: Documentation
text: Understanding injector behavior with Single Step Instrumentation
- - link: /tracing/trace_collection/automatic_instrumentation/single-step-apm/troubleshooting/
+ - link: /tracing/trace_collection/single-step-apm/troubleshooting/
tag: Documentation
text: "Troubleshooting Single Step APM"
- link: https://learn.datadoghq.com/courses/troubleshooting-apm-instrumentation-on-a-host
@@ -70,16 +71,16 @@ If you encounter problems enabling APM with SSI, see the [SSI troubleshooting gu
[3]: /internal_developer_portal/catalog/
[4]: /tracing/glossary/#instrumentation
[5]: /containers/cluster_agent/admission_controller/
-[6]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/compatibility
+[6]: /tracing/trace_collection/single-step-apm/compatibility
[7]: /tracing/trace_collection/custom_instrumentation/
[8]: /tracing/guide/injectors
-[9]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/kubernetes/?tab=installingwithdatadogoperator#configure-instrumentation-for-namespaces-and-pods
+[9]: /tracing/trace_collection/single-step-apm/kubernetes/?tab=installingwithdatadogoperator#configure-instrumentation-for-namespaces-and-pods
[10]: /tracing/trace_collection/library_config/
[11]: /tracing/metrics/runtime_metrics/
[12]: /internal_developer_portal/catalog/
[13]: /tracing/glossary/#instrumentation
[14]: /getting_started/tagging/unified_service_tagging
-[15]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/troubleshooting
+[15]: /tracing/trace_collection/single-step-apm/troubleshooting
[16]: /tracing/trace_collection/custom_instrumentation/
[17]: /tracing/trace_collection/library_config/application_monitoring_yaml/
-[18]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/compatibility/
+[18]: /tracing/trace_collection/single-step-apm/compatibility/
diff --git a/content/en/tracing/trace_collection/single-step-apm/kubernetes.md b/content/en/tracing/trace_collection/single-step-apm/kubernetes.md
index 0b9c791c936..79cfa897ea7 100644
--- a/content/en/tracing/trace_collection/single-step-apm/kubernetes.md
+++ b/content/en/tracing/trace_collection/single-step-apm/kubernetes.md
@@ -1,5 +1,6 @@
---
title: Single Step APM Instrumentation on Kubernetes
+description: "Enable Single Step Instrumentation (SSI) on Kubernetes to automatically instrument applications with Datadog APM. Covers prerequisites, setup with Helm or the Datadog Operator, verification, Unified Service Tags, workload targeting, and troubleshooting."
code_lang: kubernetes
type: multi-code-lang
code_lang_weight: 20
@@ -12,250 +13,405 @@ further_reading:
- link: /tracing/guide/init_resource_calc/
tag: Documentation
text: Learn about init container resource usage
- - link: /tracing/guide/local_sdk_injection
+ - link: /tracing/trace_collection/single-step-apm/troubleshooting
tag: Documentation
- text: Instrument your applications using local SDK injection
- - link: "https://learn.datadoghq.com/courses/configuring-ssi-k8s"
- tag: "Learning Center"
- text: "Configuring Single Step Instrumentation on Kubernetes"
-
+ text: Troubleshoot Single Step APM
+ - link: /tracing/guide/injectors/
+ tag: Documentation
+ text: Understanding injector behavior with Single Step Instrumentation
---
## Overview
-In a Kubernetes environment, use Single Step Instrumentation (SSI) for APM to install the Datadog Agent and [instrument][3] your applications with the Datadog SDKs in one step.
+Single Step Instrumentation (SSI) installs the Datadog Agent and instruments your Kubernetes applications in one step. SSI loads the Datadog SDK into your application processes at runtime, with no code changes or image rebuilds required. After you enable SSI, all supported applications in your cluster automatically begin sending traces to Datadog.
-## Requirements
+## Prerequisites
-- Kubernetes v1.20+.
-- [`Helm`][1] for deploying the Datadog Operator.
-- [`Kubectl` CLI][2] for installing the Datadog Agent.
-- Confirmed environment compatibility per the [Single Step Instrumentation compatibility guide][36].
+- Kubernetes v1.20+
+- [Helm][1] for deploying the Datadog Operator
+- [kubectl][2] for installing the Datadog Agent
+- A supported language runtime per the [SSI compatibility guide][36]
+### Check for existing tracer dependencies
-## Enable APM on your applications
+SSI silently disables itself if it detects an existing tracer in your application. Before enabling SSI, check your dependency manifests and startup scripts:
-Single Step Instrumentation does not instrument applications in the namespace where the Datadog Agent is installed. Install the Agent in a separate namespace where you do not run your applications.
+```shell
+grep -rn "ddtrace\|dd-trace\|opentelemetry\|dd-java-agent\|javaagent" requirements.txt package.json Gemfile go.mod pom.xml build.gradle 2>/dev/null
+```
-Follow these steps to enable Single Step Instrumentation across your entire cluster. This automatically sends traces from all applications written in supported languages.
+For Java, also check Dockerfiles and startup scripts for `-javaagent` flags, and check the `JAVA_TOOL_OPTIONS` environment variable.
-**Note:** To instrument only specific namespaces or pods, see workload targeting in [Advanced options](#advanced-options).
+If any matches are found, remove the tracer dependencies and rebuild your application image before proceeding.
-1. In Datadog, go to the [Install the Datadog Agent on Kubernetes][11] page.
-1. Follow the on-screen instructions to choose your installation method, select an API key, and set up the Operator or Helm repository.
-1. In the {{< ui >}}Configure `datadog-agent.yaml`{{< /ui >}} section, go to {{< ui >}}Additional configuration{{< /ui >}} > {{< ui >}}Application Observability{{< /ui >}}, and turn on {{< ui >}}APM Instrumentation{{< /ui >}}.
+### Compatibility notes
- {{< img src="tracing/trace_collection/k8s-apm-instrumentation-toggle.jpg" alt="The configuration block for installing the Datadog Agent on Kubernetes through the Datadog app" style="width:100%;" >}}
+- **Node.js**: SSI requires CommonJS. If your application uses `import` syntax or sets `"type": "module"` in `package.json`, use [manually managed SDKs][44] instead.
+- **Ruby**: SSI requires glibc and is not compatible with Alpine or other musl-based images.
+- **All other languages**: Alpine and musl-based images are supported on Kubernetes. SSI injects through the `LD_PRELOAD` environment variable, not `/etc/ld.so.preload`.
-1. Deploy the Agent using the generated configuration file.
-1. Restart your applications.
+{{< agent-only >}}
+Resolve these variables before starting:
-SSI adds a small amount of startup time to instrumented applications. If this overhead is not acceptable for your use case, contact
Datadog Support.
+| Variable | How to resolve |
+|---|---|
+| CLUSTER_NAME | `kubectl config current-context` or `spec.global.clusterName` in datadog-agent.yaml |
+| AGENT_NAMESPACE | Namespace where the Datadog Agent is installed (default: `datadog`) |
+| APP_NAMESPACE | Namespace of the user's application — ask the user |
+| DEPLOYMENT_NAME | `metadata.name` in the application Deployment — ask the user or check their repo |
+| APP_LABEL | `spec.selector.matchLabels.app` in the Deployment |
+| SERVICE_NAME | `tags.datadoghq.com/service` label on the Deployment — ask the user |
+| ENV | `tags.datadoghq.com/env` label on the Deployment — ask the user |
-## Configure Unified Service Tags
+Pre-flight checks:
+- `kubectl config current-context` returns the target cluster
+- `helm version` confirms Helm is installed
+- Check for existing Datadog deployment: `helm list -A | grep datadog`
+- The user has a Datadog API key (do not ask them to share it in chat)
+- Application language is one of: Java, Python, Ruby, Node.js, .NET, PHP
+- Runtime version is within the SSI supported range per the compatibility guide
+- For Node.js: confirm the app uses CommonJS, not ESM (`"type": "module"` in package.json means ESM)
-Unified Service Tags (USTs) apply consistent tags across traces, metrics, and logs, making it easier to navigate and correlate your observability data. You can configure USTs through automatic label extraction (recommended), through explicit configuration with `ddTraceConfigs`, or in deployment manifests.
+Check for existing instrumentation that silently disables SSI. Check both dependency manifests AND source files:
+- Dependency manifests: `grep -rn "ddtrace\|dd-trace\|opentelemetry\|dd-java-agent\|javaagent" requirements.txt package.json Gemfile go.mod pom.xml build.gradle`
+- Python: `grep -rn "import ddtrace\|from ddtrace\|ddtrace.patch_all" *.py`
+- Node.js: `grep -rn "require.*dd-trace\|require.*ddtrace\|DD.init" *.js`
+- Java: look for `-javaagent` in Dockerfile CMD/ENTRYPOINT or `JAVA_TOOL_OPTIONS`
+- .NET: `grep -rn "Tracer.Instance\|DD.Trace" *.cs`
+- Ruby: `grep -rn "require.*ddtrace\|Datadog.configure" *.rb`
+- PHP: `grep -rn "DDTrace" *.php`
-
+Do NOT add `ddtrace-run` or `ddtrace` imports. SSI handles instrumentation automatically. Manual instrumentation causes SSI to silently disable itself.
-### (Recommended) Configure USTs through automatic label extraction
+Always configure SSI through the DatadogAgent manifest (Helm values or Operator CR). Never use `kubectl patch`. Always use `kubectl apply -f` with a YAML file.
+{{< /agent-only >}}
-With SSI, you can automatically extract UST values from pod labels and metadata without modifying individual deployments. To do this, configure `kubernetesResourcesLabelsAsTags` to map your existing Kubernetes labels to Datadog service tags.
+## Enable SSI
-**Note:** This method is not compatible with Remote Configuration. If you're using Remote Configuration, see [Configure USTs explicitly with ddTraceConfigs](#configure-usts-explicitly-with-ddtraceconfigs).
+SSI does not instrument applications in the namespace where the Datadog Agent is installed. Install the Agent in a separate namespace.
-#### Prerequisites
+These steps enable SSI across your entire cluster. To instrument specific namespaces or pods, see [Target specific workloads](#target-specific-workloads).
-| Component | Minimum version |
-|-----------|------------------|
-| `datadog-agent` | 7.69 |
-| `datadog-operator` | 1.16.0 |
-| `datadog-helm-chart` | 3.120.0 |
+{{< tabs >}}
+{{% tab "In-app wizard" %}}
-#### Configuration
+Datadog generates a configuration file with SSI enabled:
-Replace `app.kubernetes.io/name` in the following example with any label that contains your service name (for example, `service.kubernetes.io/name` or `component`). You can configure multiple labels this way.
+1. Go to the [Install the Datadog Agent on Kubernetes][11] page.
+1. Choose your installation method, select an API key, and set up the Operator or Helm repository.
+1. Under **Configure `datadog-agent.yaml`**, go to **Additional configuration** > **Application Observability** and turn on **APM Instrumentation**.
-```yaml
-datadog:
- # Automatically extract service names from Kubernetes labels
- kubernetesResourcesLabelsAsTags:
- pods:
- app.kubernetes.io/name: service # Modern Kubernetes label
- deployments.apps:
- app.kubernetes.io/name: service
- replicasets.apps:
- app.kubernetes.io/name: service
+ {{< img src="tracing/trace_collection/k8s-apm-instrumentation-toggle.jpg" alt="APM Instrumentation toggle in the Kubernetes Agent installation wizard" style="width:100%;" >}}
- # Set environment globally for the entire cluster
- tags:
- - "env:production"
+1. Deploy the Agent with the generated configuration file.
+1. Restart your application pods.
+ Restarting pods can cause a brief service interruption. Coordinate with the application owner before proceeding.
+
+ ```shell
+ kubectl rollout restart deployment/ -n
+ ```
+
+[11]: https://app.datadoghq.com/fleet/install-agent/latest?platform=kubernetes
+
+{{% /tab %}}
+{{% tab "Helm" %}}
+
+If the Datadog Agent is not installed, set `DD_API_KEY` to your [Datadog API key][45]. Then, add the Datadog Helm repository and create a Kubernetes Secret:
+
+```shell
+helm repo add datadog https://helm.datadoghq.com
+helm repo update
+kubectl create namespace datadog --dry-run=client -o yaml | kubectl apply -f -
+kubectl create secret generic datadog-secret --from-literal api-key=$DD_API_KEY -n datadog --dry-run=client -o yaml | kubectl apply -f -
+```
+
+If you install the Agent in a different namespace, replace `datadog` with your Agent namespace.
+
+If the Agent is already installed, add `apm.instrumentation.enabled: true` to your existing `datadog-values.yaml` and skip to the `helm upgrade` step below.
+
+Create a `datadog-values.yaml`:
+
+```yaml
+datadog:
+ apiKeyExistingSecret: datadog-secret
+ clusterName:
+ site:
apm:
instrumentation:
enabled: true
```
-With this configuration, Datadog automatically sets the `service` tag using the value of the `app.kubernetes.io/name` label for any instrumented workload that includes this label.
+Replace `` with your Kubernetes cluster name and `` with your [Datadog site][46].
+
+Deploy or update the Agent:
+
+```shell
+helm upgrade --install datadog-agent -f datadog-values.yaml datadog/datadog -n datadog
+```
+
+Restart your application pods:
+
+Restarting pods can cause a brief service interruption. Coordinate with the application owner before proceeding.
+
+```shell
+kubectl rollout restart deployment/ -n
+```
+
+{{% /tab %}}
+{{% tab "Datadog Operator" %}}
+
+If the Datadog Operator and Agent are not installed, set `DD_API_KEY` to your [Datadog API key][45]. Then, install the Operator and create a Kubernetes Secret:
+
+```shell
+helm repo add datadog https://helm.datadoghq.com
+helm repo update
+helm upgrade --install datadog-operator datadog/datadog-operator --namespace datadog --create-namespace
+kubectl create secret generic datadog-secret --from-literal api-key=$DD_API_KEY -n datadog --dry-run=client -o yaml | kubectl apply -f -
+```
-### Configure USTs explicitly with ddTraceConfigs
+If you install the Agent in a different namespace, replace `datadog` with your Agent namespace.
-In most cases, automatic configuration is sufficient. However, if you need granular control over settings for specific workloads, use `ddTraceConfigs` to explicitly map labels to service configurations:
+If the Agent is already installed with the Datadog Operator, add `features.apm.instrumentation.enabled: true` to your existing `DatadogAgent` manifest and skip to the `kubectl apply` step below.
+
+Create a `datadog-agent.yaml`:
```yaml
-datadog:
- kubernetesResourcesLabelsAsTags:
- pods:
- app.kubernetes.io/name: service
- deployments.apps:
- app.kubernetes.io/name: service
+apiVersion: datadoghq.com/v2alpha1
+kind: DatadogAgent
+metadata:
+ name: datadog
+ namespace: datadog
+spec:
+ global:
+ clusterName:
+ site:
+ credentials:
+ apiSecret:
+ secretName: datadog-secret
+ keyName: api-key
+ features:
+ apm:
+ instrumentation:
+ enabled: true
+```
- # Set environment globally for the entire cluster
- tags:
- - "env:production"
+Replace `` with your Kubernetes cluster name and `` with your [Datadog site][46].
- apm:
- instrumentation:
- enabled: true
- targets:
- - name: frontend-services
- podSelector:
- matchLabels:
- tier: frontend
- ddTraceConfigs:
- - name: DD_SERVICE # Explicitly override service name
- valueFrom:
- fieldRef:
- fieldPath: metadata.labels['app.kubernetes.io/name']
- # DD_ENV inherited from cluster-level tags above
- # DD_VERSION automatically extracted from image tags
+Apply the manifest:
+
+```shell
+kubectl apply -f datadog-agent.yaml
```
+Restart your application pods:
-### Configure USTs in deployment manifests
+Restarting pods can cause a brief service interruption. Coordinate with the application owner before proceeding.
-If your setup doesn't use labels suitable for UST extraction, you can set USTs directly in your deployment manifests using environment variables. This approach requires modifying each deployment individually, but offers precise control.
+```shell
+kubectl rollout restart deployment/ -n
+```
-For complete instructions, see [setting USTs for Kubernetes services][5].
+{{% /tab %}}
+{{< /tabs >}}
-## Enable SDK-dependent products and features
+SSI adds a small amount of startup time to instrumented applications. If this overhead is not acceptable, contact
Datadog Support.
-After SSI loads the Datadog SDK into your applications and enables distributed tracing, you can configure additional products that rely on the SDK:
+If your cluster enforces PodSecurity
restricted policies, the Datadog init container may be blocked with:
allowPrivilegeEscalation is false or
violates PodSecurity "restricted:latest". See the
SSI troubleshooting guide for the required security context configuration.
-{{< ssi-products >}}
+{{< agent-only >}}
+Use one of the three tabs (In-app wizard, Helm, or Datadog Operator). For agents helping users, prefer the Helm or Operator tab.
-Use one of the following setup methods:
+Before changing configuration, check whether the Datadog Agent is already installed:
+- `helm list -A | grep -i datadog`
+- `kubectl get datadogagent -A`
-- **[Configure with workload targeting (recommended)](#target-specific-workloads)**:
+If the Agent is not installed, follow the bootstrap steps in the selected tab: add the Datadog Helm repository, create the `datadog` namespace, create `datadog-secret`, set `site` and `clusterName`, and deploy the Agent.
- By default, Single Step Instrumentation instruments all services in all namespaces. Use workload targeting to limit instrumentation to specific namespaces, pods, or workloads, and apply custom configurations.
+If the Agent is already installed, add `instrumentation.enabled: true` to the user's existing Helm values or `DatadogAgent` manifest. Do not create a separate manifest.
-- **[Set environment variables][7]**:
+If the user wants to pin SDK versions, recommend these defaults:
+`java: "1"`, `python: "3"`, `js: "5"`, `dotnet: "3"`, `ruby: "2"`, `php: "1"`
- Enable products by setting environment variables directly in your application configuration.
+After applying the config, confirm with the user before restarting their pods. After restart, wait for pods to be ready:
+`kubectl wait --for=condition=Ready pod -l app= -n --timeout=120s`
-## Advanced options
+If `enabledNamespaces` or `disabledNamespaces` is set, SSI only instruments matching namespaces. You cannot set both. See the Target specific workloads section for workload targeting with `targets` and `podSelector`.
+{{< /agent-only >}}
-Use the following advanced options to customize how Single Step Instrumentation behaves in your environment. These settings are optional and typically only needed in specialized setups.
+## Verify SSI is working
-### Configure injection modes
+After restarting your application pods, wait two to three minutes for traces to arrive, then confirm SSI is working:
-SSI supports multiple injection modes, which control how the injector and APM library files are delivered to your application containers. You typically do not need to configure this setting manually. Consider adjusting it if you notice significant pod startup delays or higher-than-expected resource usage (CPU, memory) during pod initialization. For more on how the injector works, see [Injector Behavior with Single Step Instrumentation][41].
+1. **Check for init containers.** Run this command against one of your application pods. The output should include `datadog-lib--init`:
+ ```shell
+ kubectl get pod -n -o jsonpath='{.spec.initContainers[*].name}'
+ ```
+2. **Generate traffic.** If your application does not receive traffic automatically, port-forward and send a few requests:
+ ```shell
+ kubectl port-forward deployment/ 8080: -n
+ curl http://localhost:8080/
+ ```
-| Mode | Description | Requirements |
-|------|-------------|--------------|
-| `init_container` | Uses init containers to copy injector and APM library files into application containers. | Agent deployed with Helm Chart or Datadog Operator |
-| `csi` | **In Preview.** Mounts injector and APM library files using the [Datadog CSI driver][37]. Reduces pod startup time compared to init container mode. | Agent 7.76.0+, CSI driver 1.2.0+, Helm Chart 3.178.1+ or Datadog Operator 1.25.0+ |
+3. **Find your service.** Go to [**APM** > **Services**][42] and confirm your service appears.
+
+4. **Confirm traces.** Go to [**APM** > **Traces**][43] and search for traces from your service.
+
+If traces do not appear after five minutes, see the [SSI troubleshooting guide][35].
+
+{{< agent-only >}}
+How SSI works (use this to reason about failures):
+1. Admission webhook (registered by Cluster Agent) intercepts pod creation
+2. Webhook mutates the pod spec — adds a `datadog-lib--init` init container
+3. Init container copies the tracer library onto a shared volume
+4. `LD_PRELOAD` env var is set pointing to the library .so file
+5. Application process loads the library automatically on startup
+
+What each diagnostic layer can see:
+- pup sees what Datadog's backend received. If pup shows no instrumented pods, the problem is in the cluster.
+- kubectl sees cluster state. If kubectl shows the init container but pup shows no traces, the problem is post-injection.
+
+pup CLI setup (if not already available):
+- Install: `brew tap datadog-labs/pack && brew install pup`
+- Authenticate: `pup auth login` (opens browser for OAuth)
+- Verify: `pup auth status`
+
+After the user restarts their pods, verify with these checks:
+
+1. Init containers: `kubectl get pod -n -o jsonpath='{.spec.initContainers[*].name}'`
+ Expected: includes `datadog-lib--init`
+
+2. If pup is available:
+ - `pup fleet instrumented-pods list `
+ - `pup apm services list --env `
+ - `pup traces search --query "service:" --from 1h --limit 5`
+ - `pup apm service-library-config get --service-name --env ` (validates tracer config)
+
+3. Runtime version (if compatibility is suspected):
+ - `kubectl exec -n -- python --version`
+ - `kubectl exec -n -- node --version`
+ - `kubectl exec -n -- java -version`
+
+No init container (injection never happened) — check:
+- Namespace targeting: `kubectl get datadogagent datadog -n -o yaml | grep -A 15 instrumentation`
+- Opt-out label: `kubectl get pod -n -o jsonpath='{.metadata.labels.admission\.datadoghq\.com/enabled}'` — if "false", the Admission Controller skips this pod
+- Pod labels: `kubectl get pod -n --show-labels`
+- Admission webhook registered: `kubectl get mutatingwebhookconfigurations | grep datadog`
+- Cluster Agent running: `kubectl get pods -n -l app=datadog-cluster-agent`
+- Whether the pod is in the Agent namespace (SSI skips its own namespace)
+
+Init container present but no traces (tracer not reporting) — check:
+- Existing instrumentation in application code or dependency manifests
+- Agent APM receiver: `kubectl exec -n $(kubectl get pod -n -l app=datadog-agent -o name | head -1) -- agent status | grep -A 5 "APM Agent"`
+- Injection errors: `kubectl get pod -n -o jsonpath='{.spec.nodeName}'` then `pup apm troubleshooting list --hostname --timeframe 1h`
+- Tracer status: `pup fleet tracers list --filter "service:"`
+- Agent connectivity: `pup fleet agents list --filter "hostname:"`
+{{< /agent-only >}}
-Before using `csi` mode, install and activate the Datadog CSI driver. If you are deploying with Helm, also set `datadog.csi.enabled: true` in your `datadog-values.yaml`. See the [CSI driver documentation][37] for installation steps and environment-specific requirements such as GKE Autopilot.
+## Configure Unified Service Tags
-#### Configure injection mode globally
+[Unified Service Tags][5] (USTs) apply consistent `service`, `env`, and `version` tags across traces, metrics, and logs. SSI can automatically extract UST values from your existing Kubernetes labels.
-{{< tabs >}}
-{{% tab "Helm" %}}
+
-To set the injection mode cluster-wide, add `injectionMode` to your `datadog-values.yaml`:
+### Automatic label extraction (recommended)
+
+Map your Kubernetes labels to Datadog service tags with `kubernetesResourcesLabelsAsTags`. Replace `app.kubernetes.io/name` with whatever label contains your service name:
```yaml
datadog:
+ kubernetesResourcesLabelsAsTags:
+ pods:
+ app.kubernetes.io/name: service
+ deployments.apps:
+ app.kubernetes.io/name: service
+ replicasets.apps:
+ app.kubernetes.io/name: service
+ tags:
+ - "env:production"
apm:
instrumentation:
- injectionMode:
+ enabled: true
```
-Supported values: `init_container`, `csi`.
+Requires `datadog-agent` 7.69+, `datadog-operator` 1.16.0+, or `datadog-helm-chart` 3.120.0+.
-{{% /tab %}}
-{{% tab "Datadog Operator" %}}
+{{% collapse-content title="Configure Unified Service Tags with ddTraceConfigs" level="h3" expanded=false %}}
-To set the injection mode cluster-wide, add `injectionMode` to your `datadog-agent.yaml`:
+For granular control over specific workloads, use `ddTraceConfigs` to map labels to service configurations:
```yaml
-features:
+datadog:
+ kubernetesResourcesLabelsAsTags:
+ pods:
+ app.kubernetes.io/name: service
+ deployments.apps:
+ app.kubernetes.io/name: service
+ tags:
+ - "env:production"
apm:
instrumentation:
- injectionMode:
+ enabled: true
+ targets:
+ - name: frontend-services
+ podSelector:
+ matchLabels:
+ tier: frontend
+ ddTraceConfigs:
+ - name: DD_SERVICE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.labels['app.kubernetes.io/name']
```
-Supported values: `init_container`, `csi`.
+{{% /collapse-content %}}
-If you are using Datadog Operator earlier than 1.25.0, use the [pod annotation](#configure-injection-mode-per-pod) to override the injection mode for specific pods.
+{{% collapse-content title="Configure Unified Service Tags in deployment manifests" level="h3" expanded=false %}}
-{{% /tab %}}
-{{< /tabs >}}
+If your labels are not suitable for automatic extraction, set USTs directly in your deployment manifests with environment variables. This requires modifying each deployment individually.
-#### Configure injection mode per pod
+For complete instructions, see [setting USTs for Kubernetes services][5].
-To override the injection mode for a specific pod, add the following annotation to the pod spec:
+{{% /collapse-content %}}
-```yaml
-metadata:
- annotations:
- admission.datadoghq.com/apm-inject.injection-mode: ""
-```
+## Next steps
-Supported values: `init_container`, `csi`.
+After traces are flowing:
+
+{{< whatsnext desc=" " >}}
+ {{< nextlink href="/tracing/trace_explorer/" >}}Trace Explorer: search and analyze your traces{{< /nextlink >}}
+ {{< nextlink href="/tracing/services/service_page/" >}}Service Page: monitor service health and performance{{< /nextlink >}}
+ {{< nextlink href="/tracing/trace_collection/custom_instrumentation/" >}}Custom instrumentation: add application-specific spans{{< /nextlink >}}
+ {{< nextlink href="/tracing/trace_collection/dynamic_instrumentation/" >}}Dynamic Instrumentation: add custom spans without redeploying{{< /nextlink >}}
+{{< /whatsnext >}}
+
+## Advanced SSI configuration
### Target specific workloads
-By default, SSI instruments all services in all namespaces in your cluster. Depending on your Agent version, use one of the following configuration methods to refine which services are instrumented and how.
+By default, SSI instruments all services in all namespaces. Use one of the following methods to limit instrumentation scope.
{{< tabs >}}
{{% tab "Agent v7.64+ (Recommended)" %}}
-Create targeting blocks with the `targets` label to specify which workloads to instrument and what configurations to apply.
-
-Each target block has the following keys:
+Define targeting blocks with `targets` to control which workloads are instrumented and what configuration they receive.
| Key | Description |
|------------------|-------------|
-| `name` | The name of the target block. This has no effect on monitoring state and is used only as metadata. |
-| `namespaceSelector` | The namespace(s) to instrument. Specify using one or more of:
- `matchNames`: A list of one or more namespace name(s).
- `matchLabels`: A list of one or more label(s) defined in `{key,value}` pairs.
- `matchExpressions`: A list of namespace selector requirements.
Namespaces must meet all criteria to match. For more details, see the [Kubernetes selector documentation][10].|
-| `podSelector` | The pod(s) to instrument. Specify using one or more of:
- `matchLabels`: A list of one or more label(s) defined in `{key,value}` pairs.
- `matchExpressions`: A list of pod selector requirements.
Pods must meet all criteria to match. For more details, see the [Kubernetes selector documentation][10]. |
-| `ddTraceVersions` | The [Datadog APM SDK][9] version to use for each language. |
-| `ddTraceConfigs` | APM SDK configs that allow setting [Unified Service Tags][8], enabling [SDK-dependent products](#enable-sdk-dependent-products-and-features) beyond tracing, and customizing other [APM settings][14]. |
+| `name` | Target block name (metadata only). |
+| `namespaceSelector` | Namespace(s) to instrument. Use `matchNames`, `matchLabels`, or `matchExpressions`. See the [Kubernetes selector documentation][10].|
+| `podSelector` | Pod(s) to instrument. Use `matchLabels` or `matchExpressions`. See the [Kubernetes selector documentation][10]. |
+| `ddTraceVersions` | [Datadog APM SDK][9] version per language. |
+| `ddTraceConfigs` | SDK configuration: [Unified Service Tags][8], [additional products](#enable-additional-products), and [other APM settings][14]. |
-The file you need to configure depends on how you enabled Single Step Instrumentation:
-- If you enabled SSI with Datadog Operator, edit `datadog-agent.yaml`.
-- If you enabled SSI with Helm, edit `datadog-values.yaml`.
-
-**Note**: Targets are evaluated in order; the first match takes precedence.
-
-#### Example configurations
-
-Review the following examples demonstrating how to select specific services:
+Edit `datadog-values.yaml` (Helm) or `datadog-agent.yaml` (Operator). Targets are evaluated in order; the first match wins.
{{< collapse-content title="Example 1: Enable all namespaces except one" level="h4" >}}
-This configuration:
-- enables APM for all namespaces except the `jenkins` namespace.
- - **Note**: use `enabledNamespaces` to disable for all namespaces except those listed.
-- instructs Datadog to instrument the Java applications with the default Java SDK and Python applications with `v.3.1.0` of the Python SDK.
-
{{< highlight yaml "hl_lines=4-10" >}}
apm:
instrumentation:
@@ -271,17 +427,7 @@ This configuration:
{{< /collapse-content >}}
-{{< collapse-content title="Example 2: Instrument a subset of namespaces, matching on names and labels" level="h4" >}}
-
-This configuration creates two targets blocks:
-
-- The first block (named `login-service_namespace`):
- - enables APM for services in the namespace `login-service`.
- - instructs Datadog to instrument services in this namespace with the default version of the Java SDK.
- - sets environment variable `DD_PROFILING_ENABLED` for this target group
-- The second block (named `billing-service_apps`)
- - enables APM for services in the namespace(s) with label `app:billing-service`.
- - instructs Datadog to instrument this set of services with `v3.1.0` of the Python SDK.
+{{< collapse-content title="Example 2: Instrument specific namespaces by name and label" level="h4" >}}
{{< highlight yaml "hl_lines=4-28" >}}
apm:
@@ -295,7 +441,7 @@ This configuration creates two targets blocks:
ddTraceVersions:
java: "default"
ddTraceConfigs:
- - name: "DD_PROFILING_ENABLED" ## profiling is enabled for all services in this namespace
+ - name: "DD_PROFILING_ENABLED"
value: "auto"
- name: "billing-service_apps"
namespaceSelector:
@@ -307,14 +453,7 @@ This configuration creates two targets blocks:
{{< /collapse-content >}}
-{{< collapse-content title="Example 3: Instrument different workloads with different tracers" level="h4" >}}
-
-This configuration does the following:
-- enables APM for pods with the following labels:
- - `app:db-user`, which marks pods running the `db-user` application.
- - `webserver:routing`, which marks pods running the `request-router` application.
-- instructs Datadog to use the default versions of the Datadog Tracer SDKs.
-- sets Datadog environment variables to apply to each target group and configure the SDKs.
+{{< collapse-content title="Example 3: Different SDKs for different workloads" level="h4" >}}
{{< highlight yaml "hl_lines=4-28" >}}
apm:
@@ -327,7 +466,7 @@ This configuration does the following:
app: "db-user"
ddTraceVersions:
java: "default"
- ddTraceConfigs: ## trace configs set for services in matching pods
+ ddTraceConfigs:
- name: "DD_DATA_STREAMS_ENABLED"
value: "true"
- name: "user-request-router"
@@ -340,12 +479,7 @@ This configuration does the following:
{{< /collapse-content >}}
-{{< collapse-content title="Example 4: Instrument a pod within a namespace" level="h4" >}}
-
-This configuration:
-- enables APM for pods labeled `app:password-resolver` inside the `login-service` namespace.
-- instructs Datadog to use the default version of the Datadog Java Tracer SDK.
-- sets Datadog environment variables to apply to this target.
+{{< collapse-content title="Example 4: Target a pod within a namespace" level="h4" >}}
{{< highlight yaml "hl_lines=4-28" >}}
apm:
@@ -368,9 +502,7 @@ This configuration:
{{< /collapse-content >}}
-{{< collapse-content title="Example 5: Instrument a subset of pods using matchExpressions" level="h4" >}}
-
-This configuration enables APM for all pods except those that have either of the labels `app=app1` or `app=app2`.
+{{< collapse-content title="Example 5: Exclude specific pods with matchExpressions" level="h4" >}}
{{< highlight yaml "hl_lines=4-28" >}}
apm:
@@ -389,9 +521,9 @@ This configuration enables APM for all pods except those that have either of the
{{< /collapse-content >}}
-{{< collapse-content title="Example 6: Enable additional products with ddTraceConfigs" level="h4" >}}
+{{< collapse-content title="Example 6: Enable additional products" level="h4" >}}
-This configuration enables [App and API Protection (AAP)][12] and [Continuous Profiler][11] for services in the `web-apps` namespace, using `ddTraceConfigs` to set the required environment variables:
+Enable [App and API Protection][12] and [Continuous Profiler][11] for a namespace:
{{< highlight yaml "hl_lines=4-20" >}}
apm:
@@ -412,8 +544,6 @@ This configuration enables [App and API Protection (AAP)][12] and [Continuous Pr
value: "auto"
{{< /highlight >}}
-For a full list of products you can enable through SSI, see [Enable SDK-dependent products and features](#enable-sdk-dependent-products-and-features).
-
{{< /collapse-content >}}
[8]: /getting_started/tagging/unified_service_tagging/?tab=kubernetes
@@ -427,34 +557,18 @@ For a full list of products you can enable through SSI, see [Enable SDK-dependen
{{% tab "Agent <=v7.63 (Legacy)" %}}
-#### Enable or disable instrumentation for namespaces
-
-You can choose to enable or disable instrumentation for applications in specific namespaces. You can only set enabledNamespaces or disabledNamespaces, not both.
+#### Namespace filtering
-The file you need to configure depends on if you enabled Single Step Instrumentation with Datadog Operator or Helm:
+Enable or disable instrumentation for specific namespaces. You can set `enabledNamespaces` or `disabledNamespaces`, but not both.
{{< collapse-content title="Datadog Operator" level="h5" >}}
-To enable instrumentation for specific namespaces, add `enabledNamespaces` configuration to `datadog-agent.yaml`:
-
{{< highlight yaml "hl_lines=5-7" >}}
features:
apm:
instrumentation:
enabled: true
- enabledNamespaces: # Add namespaces to instrument
- - default
- - applications
-{{< /highlight >}}
-
-To disable instrumentation for specific namespaces, add `disabledNamespaces` configuration to `datadog-agent.yaml`:
-
-{{< highlight yaml "hl_lines=5-7" >}}
- features:
- apm:
- instrumentation:
- enabled: true
- disabledNamespaces: # Add namespaces to not instrument
+ enabledNamespaces:
- default
- applications
{{< /highlight >}}
@@ -463,101 +577,51 @@ To disable instrumentation for specific namespaces, add `disabledNamespaces` con
{{< collapse-content title="Helm" level="h5" >}}
-To enable instrumentation for specific namespaces, add `enabledNamespaces` configuration to `datadog-values.yaml`:
-
{{< highlight yaml "hl_lines=5-7" >}}
datadog:
apm:
instrumentation:
enabled: true
- enabledNamespaces: # Add namespaces to instrument
+ enabledNamespaces:
- namespace_1
- namespace_2
{{< /highlight >}}
-To disable instrumentation for specific namespaces, add `disabledNamespaces` configuration to `datadog-values.yaml`:
-
-{{< highlight yaml "hl_lines=5-7" >}}
- datadog:
- apm:
- instrumentation:
- enabled: true
- disabledNamespaces: # Add namespaces to not instrument
- - namespace_1
- - namespace_2
-{{< /highlight >}}
-
{{< /collapse-content >}}
-#### Specify SDK versions
-
-Starting with Datadog Cluster Agent v7.52.0+, you can automatically instrument a subset of your applications, based on the SDKs you specify.
+#### SDK versions
-Specify Datadog SDKs and their versions to automatically instrument applications written in those languages. You can configure this in two ways, which are applied in the following order of precedence:
+Specify SDK versions to control which languages are instrumented and which library versions are used. You can set versions at the [service level](#specify-at-the-service-level) (pod annotations) or at the [cluster level](#specify-at-the-cluster-level) (Agent config). Service-level settings take precedence.
-1. [Specify at the service level](#specify-at-the-service-level), or
-2. [Specify at the cluster level](#specify-at-the-cluster-level).
-
-**Default**: If you don't specify any library versions, applications written in supported languages are automatically instrumented using the latest SDK versions.
+If you don't specify versions, all supported languages are instrumented with the latest SDK.
##### Specify at the service level
-To automatically instrument applications in specific pods, add the appropriate language annotation and library version for your application in your pod spec:
+Add a language annotation to your pod spec:
| Language | Pod annotation |
|------------|-----------------------------------------------------------------------|
-| Java | `admission.datadoghq.com/java-lib.version: ""` |
-| Node.js | `admission.datadoghq.com/js-lib.version: ""` |
-| Python | `admission.datadoghq.com/python-lib.version: ""` |
-| .NET | `admission.datadoghq.com/dotnet-lib.version: ""` |
-| Ruby | `admission.datadoghq.com/ruby-lib.version: ""` |
-| PHP | `admission.datadoghq.com/php-lib.version: ""` |
-
-Replace `` with the desired library version. Available versions are listed in the [Datadog container registries](#change-the-default-image-registry) and tracer source repositories for each language:
-
-- [Java][34]
-- [Node.js][35]
-- [Python][36]
-- [.NET][37]
-- [Ruby][38]
-- [PHP][39]
-
-Exercise caution when using the latest tag, as major library releases may introduce breaking changes.
+| Java | `admission.datadoghq.com/java-lib.version: ""` |
+| Node.js | `admission.datadoghq.com/js-lib.version: ""` |
+| Python | `admission.datadoghq.com/python-lib.version: ""` |
+| .NET | `admission.datadoghq.com/dotnet-lib.version: ""` |
+| Ruby | `admission.datadoghq.com/ruby-lib.version: ""` |
+| PHP | `admission.datadoghq.com/php-lib.version: ""` |
-For example, to automatically instrument Java applications:
+Available versions: [Java][34], [Node.js][35], [Python][36], [.NET][37], [Ruby][38], [PHP][39].
-{{< highlight yaml "hl_lines=10" >}}
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- labels:
- # ...
-spec:
- template:
- metadata:
- annotations:
- admission.datadoghq.com/java-lib.version: ""
- spec:
- containers:
- - # ...
-{{< /highlight >}}
+Exercise caution with the latest tag. Major releases may introduce breaking changes.
##### Specify at the cluster level
-If you don't enable automatic instrumentation for specific pods using annotations, you can specify which languages to instrument across the entire cluster using the SSI configuration. When `apm.instrumentation.libVersions` is set, only applications written in the specified languages are instrumented, using the specified library versions.
-
-The file you need to configure depends on if you enabled Single Step Instrumentation with Datadog Operator or Helm:
-
{{< collapse-content title="Datadog Operator" level="h5" >}}
-For example, to instrument .NET, Python, and Node.js applications, add the following configuration to your `datadog-agent.yaml` file:
-
{{< highlight yaml "hl_lines=5-8" >}}
features:
apm:
instrumentation:
enabled: true
- libVersions: # Add any libraries and versions you want to set
+ libVersions:
dotnet: "x.x.x"
python: "x.x.x"
js: "x.x.x"
@@ -567,14 +631,12 @@ For example, to instrument .NET, Python, and Node.js applications, add the follo
{{< collapse-content title="Helm" level="h5" >}}
-For example, to instrument .NET, Python, and Node.js applications, add the following configuration to your `datadog-values.yaml` file:
-
{{< highlight yaml "hl_lines=5-8" >}}
datadog:
apm:
instrumentation:
enabled: true
- libVersions: # Add any libraries and versions you want to set
+ libVersions:
dotnet: "x.x.x"
python: "x.x.x"
js: "x.x.x"
@@ -582,7 +644,6 @@ For example, to instrument .NET, Python, and Node.js applications, add the follo
{{< /collapse-content >}}
-
[34]: https://github.com/DataDog/dd-trace-java/releases
[35]: https://github.com/DataDog/dd-trace-js/releases
[36]: https://github.com/DataDog/dd-trace-py/releases
@@ -590,264 +651,189 @@ For example, to instrument .NET, Python, and Node.js applications, add the follo
[38]: https://github.com/DataDog/dd-trace-rb/releases
[39]: https://github.com/DataDog/dd-trace-php/releases
-
{{% /tab %}}
{{< /tabs >}}
-### Change the default image registry
+### Enable additional products
-Datadog publishes instrumentation libraries images on gcr.io, Docker Hub, and Amazon ECR:
+After SSI enables distributed tracing, you can activate additional SDK-dependent products:
-| Language | gcr.io | hub.docker.com | gallery.ecr.aws |
-|------------|-------------------------------------|---------------------------------------------|-------------------------------------------|
-| Java | [gcr.io/datadoghq/dd-lib-java-init][15] | [hub.docker.com/r/datadog/dd-lib-java-init][16] | [gallery.ecr.aws/datadog/dd-lib-java-init][17] |
-| Node.js | [gcr.io/datadoghq/dd-lib-js-init][18] | [hub.docker.com/r/datadog/dd-lib-js-init][19] | [gallery.ecr.aws/datadog/dd-lib-js-init][20] |
-| Python | [gcr.io/datadoghq/dd-lib-python-init][21] | [hub.docker.com/r/datadog/dd-lib-python-init][22] | [gallery.ecr.aws/datadog/dd-lib-python-init][23] |
-| .NET | [gcr.io/datadoghq/dd-lib-dotnet-init][24] | [hub.docker.com/r/datadog/dd-lib-dotnet-init][25] | [gallery.ecr.aws/datadog/dd-lib-dotnet-init][26] |
-| Ruby | [gcr.io/datadoghq/dd-lib-ruby-init][27] | [hub.docker.com/r/datadog/dd-lib-ruby-init][28] | [gallery.ecr.aws/datadog/dd-lib-ruby-init][29] |
-| PHP | [gcr.io/datadoghq/dd-lib-php-init][30] | [hub.docker.com/r/datadog/dd-lib-php-init][31] | [gallery.ecr.aws/datadog/dd-lib-php-init][32] |
+{{< ssi-products >}}
-The `DD_ADMISSION_CONTROLLER_AUTO_INSTRUMENTATION_CONTAINER_REGISTRY` environment variable in the Datadog Cluster Agent configuration specifies the registry used by the Admission Controller. The default value is `gcr.io/datadoghq`.
+To enable products:
-You can pull the SDK from a different registry by changing it to `docker.io/datadog`, `public.ecr.aws/datadog`, or another URL if you are hosting the images in a local container registry.
+- **With workload targeting (recommended):** Add `ddTraceConfigs` entries to your [target blocks](#target-specific-workloads). See [Example 6: Enable additional products](#target-specific-workloads).
+- **With environment variables:** Set variables directly in your application configuration. See [Library Configuration][7].
-For instructions on changing your container registry, see [Changing Your Container Registry][33].
+### Configure injection modes
-### Use a private container registry
+SSI supports multiple injection modes that control how library files are delivered to application containers. Adjust this setting if you notice pod startup delays or high resource usage during initialization.
-If your organization does not allow direct pulls from public registries (such as `gcr.io`, `docker.io`, or `public.ecr.aws`), you can host the required Datadog images internally and configure the Admission Controller to use them.
+| Mode | Description | Requirements |
+|------|-------------|--------------|
+| `init_container` | Copies files with an init container. | Agent deployed with Helm or Operator |
+| `csi` | **In Preview.** Mounts files with the [Datadog CSI driver][37]. Faster pod startup. | Agent 7.76.0+, CSI driver 1.2.0+, Helm 3.178.1+ or Operator 1.25.0+ |
-To use SSI with a private container registry:
+For `csi` mode, install and activate the CSI driver first. With Helm, set `datadog.csi.enabled: true`. See the [CSI driver documentation][37].
-1. Follow [these instructions][34] to mirror Datadog's container images to your private registry.
+{{< collapse-content title="Set injection mode globally" level="h4" >}}
- You only need the images for the languages you are instrumenting. If you're not sure which ones you need, here's a baseline that covers most use cases:
+**Helm** — add to `datadog-values.yaml`:
+```yaml
+datadog:
+ apm:
+ instrumentation:
+ injectionMode:
+```
- - `apm-inject`
- - `dd-lib-java-init`
- - `dd-lib-python-init`
- - `dd-lib-dotnet-init`
- - `dd-lib-php-init`
- - `dd-lib-ruby-init`
- - `dd-lib-js-init`
+**Datadog Operator** — add to `datadog-agent.yaml`:
+```yaml
+features:
+ apm:
+ instrumentation:
+ injectionMode:
+```
- You can find these images on [gcr.io][12], [Docker Hub][13], or [Amazon ECR Public Gallery][14].
+Supported values: `init_container`, `csi`.
-2. Tag the images according to your configuration.
+{{< /collapse-content >}}
- The versions you mirror must match the versions configured in your workloads, which might be set in one of the following ways:
- - globally in the Agent config using `ddTraceVersions`, or
- - per-pod using annotations like `admission.datadoghq.com/java-lib.version`.
+{{< collapse-content title="Set injection mode per pod" level="h4" >}}
- If no version is explicitly configured, the default version (`0`) is used.
+Add this annotation to the pod spec:
- For example:
+```yaml
+metadata:
+ annotations:
+ admission.datadoghq.com/apm-inject.injection-mode: ""
+```
- ```
- apm:
- instrumentation:
- enabled: true
- targets:
- - name: "default-target"
- ddTraceVersions:
- java: "1"
- python: "3"
- ```
+Supported values: `init_container`, `csi`.
- This configuration requires the following image tags:
- - `apm-inject:0`
- - `dd-lib-java-init:1`
- - `dd-lib-python-init:3`
+{{< /collapse-content >}}
-3. Update the Cluster Agent configuration to use your private registry.
+### Change the image registry
- Set the `DD_ADMISSION_CONTROLLER_AUTO_INSTRUMENTATION_CONTAINER_REGISTRY` environment variable in your Cluster Agent config to use your private registry.
+Datadog publishes SDK images on gcr.io (default), Docker Hub, and Amazon ECR. To use a different registry, set `DD_ADMISSION_CONTROLLER_AUTO_INSTRUMENTATION_CONTAINER_REGISTRY` in the Cluster Agent config:
-For more details on changing your container registry, see [Changing Your Container Registry][33].
+| Registry | Value |
+|----------|-------|
+| gcr.io (default) | `gcr.io/datadoghq` |
+| Docker Hub | `docker.io/datadog` |
+| Amazon ECR | `public.ecr.aws/datadog` |
-### Using a Container Network Interface on EKS
+For detailed instructions, see [Changing Your Container Registry][33].
-When using a CNI like Calico, the control plane nodes are not able to initiate network connections to Datadog's Admission Controller and report an "Address is not allowed" error.
-To use Single Step instrumentation, modify Datadog's Cluster Agent with the `useHostNetwork: true` parameter.
+{{% collapse-content title="Use a private container registry" level="h4" expanded=false %}}
-```
-datadog:
- ...
+If your organization cannot pull from public registries, mirror the Datadog images to your private registry:
-clusterAgent:
- useHostNetwork: true
+1. [Mirror the images][34] for the languages you are instrumenting. At minimum, mirror `apm-inject` and the `dd-lib--init` images you need.
- admissionController:
- ...
-```
+2. Tag the images to match your configuration. If you set `ddTraceVersions` to `java: "1"` and `python: "3"`, mirror:
+ - `apm-inject:0`
+ - `dd-lib-java-init:1`
+ - `dd-lib-python-init:3`
-## Remove Single Step APM instrumentation from your Agent
+3. Set `DD_ADMISSION_CONTROLLER_AUTO_INSTRUMENTATION_CONTAINER_REGISTRY` to your private registry URL.
-If you don't want to collect trace data for a particular service, host, VM, or container, complete the following steps:
+{{% /collapse-content %}}
-### Remove instrumentation for specific services
+### Container Network Interface on EKS
-To remove APM instrumentation and stop sending traces from a specific service, you can do one of the following:
+When using a CNI like Calico on EKS, control plane nodes cannot connect to the Admission Controller. Set `useHostNetwork: true` on the Cluster Agent:
-#### Use instrumentation rules to target specific workloads (recommended)
+```yaml
+clusterAgent:
+ useHostNetwork: true
+```
-With instrumentation rules (available for Agent v7.64+), you can enable and disable tracing for specific applications. [See configuration details here](#advanced-options).
+## Remove SSI
-#### Use the Datadog Admission Controller
+### Remove instrumentation for specific services
-As an alternative, or for a version of the agent that does not support instrumentation rules, you can also disable pod mutation by adding a label to your pod.
+Use [workload targeting](#target-specific-workloads) (Agent v7.64+) to exclude specific services.
-In addition to disabling SSI, the following steps disable other mutating webhooks. Use with caution.
+Alternatively, add this label to the pod spec to skip Admission Controller mutation:
-1. Set the `admission.datadoghq.com/enabled:` label to `"false"` for the pod spec:
- ```yaml
- spec:
- template:
- metadata:
- labels:
- admission.datadoghq.com/enabled: "false"
- ```
-2. Apply the configuration:
- ```shell
- kubectl apply -f /path/to/your/deployment.yaml
- ```
-3. Restart the services you want to remove instrumentation for.
+This label disables all mutating webhooks for the pod, not only SSI.
-### Remove APM for all services on the infrastructure
+```yaml
+spec:
+ template:
+ metadata:
+ labels:
+ admission.datadoghq.com/enabled: "false"
+```
-To stop producing traces, uninstall APM and restart the infrastructure:
+Apply the change and restart the affected pods.
-The file you need to configure depends on if you enabled Single Step Instrumentation with Datadog Operator or Helm:
+### Remove instrumentation for all services
{{< tabs >}}
-{{% tab "Datadog Operator" %}}
+{{% tab "Helm" %}}
-1. Set `instrumentation.enabled=false` in `datadog-agent.yaml`:
- ```yaml
- features:
- apm:
- instrumentation:
- enabled: false
- ```
+Set `instrumentation.enabled: false` in `datadog-values.yaml` and run:
+
+```shell
+helm upgrade datadog-agent -f datadog-values.yaml datadog/datadog
+```
-2. Deploy the Datadog Agent with the updated configuration file:
- ```shell
- kubectl apply -f /path/to/your/datadog-agent.yaml
- ```
{{% /tab %}}
+{{% tab "Datadog Operator" %}}
-{{% tab "Helm" %}}
+Set `instrumentation.enabled: false` in `datadog-agent.yaml` and apply:
-1. Set `instrumentation.enabled=false` in `datadog-values.yaml`:
- ```yaml
- datadog:
- apm:
- instrumentation:
- enabled: false
- ```
+```shell
+kubectl apply -f datadog-agent.yaml
+```
-2. Run the following command:
- ```shell
- helm upgrade datadog-agent -f datadog-values.yaml datadog/datadog
- ```
{{% /tab %}}
{{< /tabs >}}
-## Best practices
-
-After you enable SSI, all supported processes in the cluster are automatically instrumented and begin producing traces within minutes.
+## SSI best practices
-To control where APM is activated and reduce overhead, consider the following best practices.
+{{% collapse-content title="Use opt-in labels for controlled rollout" level="h3" expanded=false %}}
-{{% collapse-content title="Use opt-in labels for controlled APM rollout" level="h3" expanded=false id="opt-in-labels-controlled-apm-rollout" %}}
-
-#### Default vs. opt-in instrumentation
| Mode | Behavior | When to use |
| --- | ----------- | ----------- |
-| Default | All supported processes in the cluster are instrumented. | Small clusters or prototypes. |
-| Opt-in | Use [instrumentation rules][4] to restrict instrumentation to specific namespaces or pods. | Production clusters, staged rollouts, or cost‑sensitive use cases. |
-
-#### Example: Enable instrumentation for specific pods
+| Default | All supported processes are instrumented. | Small clusters or prototypes. |
+| Opt-in | [Workload targeting](#target-specific-workloads) restricts instrumentation to labeled pods. | Production clusters, staged rollouts, cost-sensitive environments. |
-1. Add a meaningful label (for example, `datadoghq.com/apm-instrumentation: "enabled"`) to both the deployment metadata and the pod template.
+Add an opt-in label to your deployment and pod template:
- ```
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: checkout-api
- labels:
- app: checkout-api
- datadoghq.com/apm-instrumentation: "enabled" # opt-in label (cluster-wide)
- spec:
- replicas: 3
- selector:
- matchLabels:
- app: checkout-api
- template:
- metadata:
- labels:
- app: checkout-api
- datadoghq.com/apm-instrumentation: "enabled" # opt-in label must be on *template*, too
- # Unified Service Tags (recommended)
- tags.datadoghq.com/service: "checkout-api"
- tags.datadoghq.com/env: "prod"
- tags.datadoghq.com/version: "2025-06-10"
- spec:
- containers:
- - name: api
- image: my-registry/checkout:latest
- ports:
- - containerPort: 8080
- ```
+```yaml
+metadata:
+ labels:
+ datadoghq.com/apm-instrumentation: "enabled"
+```
-2. In your Datadog Agent Helm config, enable SSI and use `podSelector` to inject only into pods with the matching opt-in label.
+Then configure SSI to match:
- ```
- apm:
- instrumentation:
- enabled: true
- targets:
- - name: apm-instrumented
- podSelector:
- matchLabels:
- datadoghq.com/apm-instrumentation: "enabled"
- ```
-
-See [instrumentation rules][4] for additional examples.
+```yaml
+apm:
+ instrumentation:
+ enabled: true
+ targets:
+ - name: apm-instrumented
+ podSelector:
+ matchLabels:
+ datadoghq.com/apm-instrumentation: "enabled"
+```
{{% /collapse-content %}}
+{{% collapse-content title="Pin SDK versions" level="h3" expanded=false %}}
-{{% collapse-content title="Control which Datadog SDKs are loaded" level="h3" expanded=false id="control-loaded-datadog-sdks" %}}
-
-Use `ddTraceVersions` in your Agent Helm config to control both the language and the version of the Datadog SDK. This prevents unnecessary SDKs from being downloaded, which minimizes init-container footprint, reduces image size, and allows for more deliberate tracer upgrades (for example, to meet compliance requirements or simplify debugging).
-
-#### Example: Specify a Java SDK for a namespace
-
-Only Java applications run in the `login-service` namespace. To avoid downloading other SDKs, configure the Agent to target that namespace and inject only the Java SDK version 1.48.2.
-
+Use `ddTraceVersions` to control which SDK versions are injected. This reduces init container size, avoids downloading unnecessary SDKs, and makes tracer upgrades deliberate.
-```
-targets:
- - name: login-service
- namespaceSelector:
- matchNames: ["login-service"]
- ddTraceVersions:
- java: "1.48.2" # pin version
-```
-
-#### Default configuration
-
-If a pod doesn't match any `ddTraceVersions` rule, the default target applies.
-
-```
+```yaml
targets:
- - name: default-target # tag any pod *without* an override
+ - name: default-target
ddTraceVersions:
- java: "1" # stay on latest v1.x
- python: "3" # stay on latest v3.x
- js: "5" # NodeJS
+ java: "1"
+ python: "3"
+ js: "5"
php: "1"
dotnet: "3"
```
@@ -856,7 +842,7 @@ targets:
## Troubleshooting
-If you encounter problems enabling APM with SSI, see the [SSI troubleshooting guide][35].
+If you encounter problems with SSI, see the [SSI troubleshooting guide][35].
## Further reading
@@ -865,34 +851,16 @@ If you encounter problems enabling APM with SSI, see the [SSI troubleshooting gu
[1]: https://v3.helm.sh/docs/intro/install/
[2]: https://kubernetes.io/docs/tasks/tools/install-kubectl/
[3]: /tracing/glossary/#instrumentation
-[4]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/kubernetes/?tab=agentv764recommended#configure-instrumentation-for-namespaces-and-pods
[5]: /getting_started/tagging/unified_service_tagging/?tab=kubernetes#containerized-environment
[7]: /tracing/trace_collection/library_config/
[11]: https://app.datadoghq.com/fleet/install-agent/latest?platform=kubernetes
-[12]: https://gcr.io/datadoghq
-[13]: https://hub.docker.com/u/datadog
-[14]: https://gallery.ecr.aws/datadog
-[15]: http://gcr.io/datadoghq/dd-lib-java-init
-[16]: http://hub.docker.com/r/datadog/dd-lib-java-init
-[17]: http://gallery.ecr.aws/datadog/dd-lib-java-init
-[18]: http://gcr.io/datadoghq/dd-lib-js-init
-[19]: http://hub.docker.com/r/datadog/dd-lib-js-init
-[20]: http://gallery.ecr.aws/datadog/dd-lib-js-init
-[21]: http://gcr.io/datadoghq/dd-lib-python-init
-[22]: http://hub.docker.com/r/datadog/dd-lib-python-init
-[23]: http://gallery.ecr.aws/datadog/dd-lib-python-init
-[24]: http://gcr.io/datadoghq/dd-lib-dotnet-init
-[25]: http://hub.docker.com/r/datadog/dd-lib-dotnet-init
-[26]: http://gallery.ecr.aws/datadog/dd-lib-dotnet-init
-[27]: http://gcr.io/datadoghq/dd-lib-ruby-init
-[28]: http://hub.docker.com/r/datadog/dd-lib-ruby-init
-[29]: http://gallery.ecr.aws/datadog/dd-lib-ruby-init
-[30]: http://gcr.io/datadoghq/dd-lib-php-init
-[31]: http://hub.docker.com/r/datadog/dd-lib-php-init
-[32]: http://gallery.ecr.aws/datadog/dd-lib-php-init
[33]: /containers/guide/changing_container_registry/
[34]: /containers/guide/sync_container_images/#copy-an-image-to-another-registry-using-crane
-[35]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/troubleshooting
-[36]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/compatibility/
+[35]: /tracing/trace_collection/single-step-apm/troubleshooting
+[36]: /tracing/trace_collection/single-step-apm/compatibility/
[37]: /containers/kubernetes/csi_driver/
-[41]: /tracing/guide/injectors/
+[42]: https://app.datadoghq.com/apm/services
+[43]: https://app.datadoghq.com/apm/traces
+[44]: /tracing/trace_collection/dd_libraries/nodejs/
+[45]: https://app.datadoghq.com/organization-settings/api-keys
+[46]: /getting_started/site/
diff --git a/content/en/tracing/trace_collection/single-step-apm/troubleshooting.md b/content/en/tracing/trace_collection/single-step-apm/troubleshooting.md
index b5a9c914de8..7aae7bf71d9 100644
--- a/content/en/tracing/trace_collection/single-step-apm/troubleshooting.md
+++ b/content/en/tracing/trace_collection/single-step-apm/troubleshooting.md
@@ -1,9 +1,10 @@
---
title: Troubleshooting Single Step APM
+description: "Diagnose and fix Single Step Instrumentation (SSI) issues on Kubernetes, Linux, Docker, and Windows. Covers missing traces, silent failure modes, injection verification, Fleet Automation diagnostics, and language-specific troubleshooting."
aliases:
- /tracing/trace_collection/automatic_instrumentation/single-step-apm/troubleshooting/
further_reading:
-- link: /tracing/trace_collection/automatic_instrumentation/single-step-apm/
+- link: /tracing/trace_collection/single-step-apm/
tag: Documentation
text: Single Step APM Instrumentation
- link: https://learn.datadoghq.com/courses/troubleshooting-apm-instrumentation-on-a-host
@@ -15,6 +16,88 @@ further_reading:
Single Step Instrumentation (SSI) helps instrument applications by automatically loading application processes with the Datadog SDKs. SSI works for applications running on Linux hosts, in container environments such as Kubernetes and Docker, and for .NET applications served by Windows IIS—without requiring changes to application dependencies or images. If you encounter issues enabling APM with SSI, use this guide to troubleshoot and resolve common problems. For further assistance, contact [Datadog Support][1].
+## Triage: no traces after enabling SSI?
+
+If you enabled SSI but don't see traces, work through these checks in order:
+
+### All platforms
+
+1. **Did you restart your application after enabling SSI?** SSI injects at startup. Existing processes and pods are not instrumented until restarted.
+
+2. **Does your application have existing tracer dependencies?** SSI silently disables itself if it detects `ddtrace`, `dd-trace`, an OpenTelemetry SDK, or `-javaagent` in your application. Check your dependency manifests and startup scripts:
+ ```shell
+ grep -rn "ddtrace\|dd-trace\|opentelemetry\|dd-java-agent\|javaagent" requirements.txt package.json Gemfile go.mod pom.xml build.gradle 2>/dev/null
+ ```
+ For Java, also check Dockerfiles and startup scripts for `-javaagent` flags, and check the `JAVA_TOOL_OPTIONS` environment variable. Remove any matches and rebuild your application before proceeding.
+
+3. **Is the runtime version supported?** Check the [SSI compatibility guide][13].
+
+4. **For Node.js: is your application using ECMAScript Modules (ESM)?** SSI does not support ESM. If your application uses `import` syntax or sets `"type": "module"` in `package.json`, use [manually managed SDKs][14] instead.
+
+### Kubernetes
+
+5. **Is your application in the same namespace as the Datadog Agent?** SSI does not instrument pods in the Agent namespace.
+
+6. **Is a namespace or pod selector filtering your application out?** Check your SSI configuration for `enabledNamespaces`, `disabledNamespaces`, or `podSelector` targets that may not match your application's namespace or labels. Also check for the `admission.datadoghq.com/enabled: "false"` label on the pod, which tells the Admission Controller to skip it.
+
+### Linux hosts
+
+7. **Is `/etc/ld.so.preload` configured?** SSI on Linux uses `/etc/ld.so.preload` to load the injector. If this file is missing or does not contain the Datadog launcher path, SSI is not active. Check:
+ ```shell
+ cat /etc/ld.so.preload
+ ```
+ The output should contain `/opt/datadog-packages/datadog-apm-inject/stable/inject/launcher.preload.so`.
+
+8. **Is the application using musl libc or a static binary?** The SSI injector on Linux requires glibc. Applications on Alpine or other musl-based distributions, and statically linked binaries (common with Go), cannot be instrumented with SSI.
+
+9. **Is SELinux or AppArmor blocking the injector?** Security policies can prevent `/etc/ld.so.preload` from being read. Check `getenforce` (SELinux) or `dmesg | grep apparmor` (AppArmor) for denials.
+
+If none of these apply, continue with the detailed troubleshooting methods below.
+
+{{< agent-only >}}
+All platforms — start with pup if available:
+- `pup traces search --query "service:" --from 1h --limit 5`
+- `pup apm services list --env `
+- `pup apm troubleshooting list --hostname --timeframe 1h`
+
+Kubernetes diagnostics:
+
+Resolve the node hostname first:
+- `kubectl get pod -n -o jsonpath='{.spec.nodeName}'` → use as NODE_HOSTNAME below
+
+Triage (run simultaneously):
+- `kubectl get pod -n -o jsonpath='{.spec.initContainers[*].name}'`
+- `kubectl describe pod -n | grep -A 10 "Events:"`
+- `kubectl get datadogagent datadog -n -o yaml | grep -A 15 instrumentation`
+- `pup fleet instrumented-pods list `
+
+Kubernetes diagnosis by signal:
+| Signal | Likely cause | Next step |
+|--------|-------------|-----------|
+| No init container on pod | Injection never happened | Check namespace targeting, pod-selector, opt-out label, webhook registration, pod not restarted |
+| Init container present, no traces | Injection attempted but tracer not reporting | Check for existing ddtrace/OTel dependencies, runtime version, Agent connectivity |
+| Pod events show CrashLoopBackOff | Init container failure | Check existing instrumentation conflicts, runtime version |
+| Traces arriving but wrong service/env | UST misconfiguration | Check Unified Service Tag labels on the Deployment |
+
+Linux host diagnostics:
+- Check injector is armed: `cat /etc/ld.so.preload` (should contain launcher path)
+- Check tracer loaded in process: `grep datadog /proc//maps`
+- Check process started after SSI: compare `ps -o lstart -p ` against `/etc/ld.so.preload` modification time
+- Check libc type: `ldd --version` (musl = incompatible)
+- Check binary type: `file /proc//exe` (statically linked = incompatible)
+- Check Agent APM receiver: `datadog-agent status | grep -A 5 "APM Agent"`
+- Check security: `getenforce` (SELinux), `dmesg | grep apparmor` (AppArmor)
+
+Key silent failure modes (SSI produces no error for these):
+- Existing ddtrace or OpenTelemetry instrumentation: SSI silently disables itself
+- Unsupported runtime version: silently skipped
+- Kubernetes: `admission.datadoghq.com/enabled: "false"` label on pod: webhook skips the pod
+- Application not restarted after SSI enabled: injection happens at startup only
+- Kubernetes: pod in the Datadog Agent namespace: SSI skips its own namespace
+- Linux: musl libc or static binary: injector requires glibc
+- Linux: SELinux/AppArmor blocking `/etc/ld.so.preload` reads
+{{< /agent-only >}}
+
## Troubleshooting methods
You can investigate injection issues in the Datadog UI with Fleet Automation, or manually at the container level. For a lower-level view of what the injector decided for each process, see [Injector debug logs](#injector-debug-logs).
@@ -102,7 +185,7 @@ To enable debug logs during manual verification:
Injector debug logs show what the injector decided for each process: whether injection succeeded, was denied, or was skipped, and why. Enable them when [Fleet Automation](#troubleshoot-injection-in-datadog-fleet-automation) doesn't explain a failure, when you're diagnosing at the host or container level, or when you're collecting information for [Datadog Support][1].
-Injector debug logs are separate from tracer debug logs. Use injector logs to diagnose whether and how a tracer was injected; after injection, use [tracer debug logs][13] to diagnose the tracer running inside the process.
+Injector debug logs are separate from tracer debug logs. Use injector logs to diagnose whether and how a tracer was injected; after injection, use [tracer debug logs][15] to diagnose the tracer running inside the process.
### Enable debug mode
@@ -501,10 +584,10 @@ Collect the following details if troubleshooting injection in a Kubernetes envir
{{< partial name="whats-next/whats-next.html" >}}
-[1]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/kubernetes?tab=agentv764recommended#remove-apm-for-all-services-on-the-infrastructure
-[2]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/docker#remove-apm-for-all-services-on-the-infrastructure
-[3]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/linux#remove-single-step-apm-instrumentation-from-your-agent
-[4]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/windows#remove-single-step-apm-instrumentation-from-your-agent
+[1]: /tracing/trace_collection/single-step-apm/kubernetes?tab=agentv764recommended#remove-apm-for-all-services-on-the-infrastructure
+[2]: /tracing/trace_collection/single-step-apm/docker#remove-apm-for-all-services-on-the-infrastructure
+[3]: /tracing/trace_collection/single-step-apm/linux#remove-single-step-apm-instrumentation-from-your-agent
+[4]: /tracing/trace_collection/single-step-apm/windows#remove-single-step-apm-instrumentation-from-your-agent
[5]: /containers/guide/sync_container_images/#copy-an-image-to-another-registry-using-crane
[6]: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/#syntax-and-character-set
[7]: https://datatracker.ietf.org/doc/html/rfc1035
@@ -512,5 +595,7 @@ Collect the following details if troubleshooting injection in a Kubernetes envir
[9]: https://app.datadoghq.com/fleet
[10]: /tracing/trace_collection/dd_libraries/dotnet-core/#installation-and-getting-started
[11]: /tracing/guide/injectors/
-[12]: /tracing/trace_collection/automatic_instrumentation/single-step-apm/#instrument-sdks-across-applications
-[13]: /tracing/troubleshooting/tracer_debug_logs/
+[12]: /tracing/trace_collection/single-step-apm/#instrument-sdks-across-applications
+[13]: /tracing/trace_collection/single-step-apm/compatibility/
+[14]: /tracing/trace_collection/dd_libraries/nodejs/
+[15]: /tracing/troubleshooting/tracer_debug_logs/