npx skills add ...
npx skills add datadog-labs/agent-skills --skill enable-ssi
npx skills add datadog-labs/agent-skills --skill enable-ssi
Configure Unified Service Tags and verify Single Step Instrumentation (SSI) injection on Linux hosts — SSI automatically instruments applications for APM without code changes. Only use if the Datadog Agent is already installed.
Before doing anything else: Fully resolve all variables in
## Context to resolve before acting. Do not begin Step 0 until every variable has a concrete value.
Invoke this skill when:
DD_APM_INSTRUMENTATION_ENABLED=host was used) and you need to configure Unified Service Tags on the application serviceDD_SERVICE, DD_ENV, DD_VERSION on a running service/proc/<pid>/maps doesn't show the language tracer (launcher-only injection)Do NOT invoke this skill if:
agent-install first/opt/datadog-packages/ — re-run agent-installdd-apm-k8s-enable-ssi insteadWhen the install script runs with DD_APM_INSTRUMENTATION_ENABLED=host, it:
datadog-apm-inject and language library packages under /opt/datadog-packages//etc/ld.so.preloadWhat SSI does NOT configure automatically:
DD_SERVICE, DD_ENV, DD_VERSION — these must be set on the application process for traces to be tagged correctlyDD_SERVICE, the tracer auto-detects a service name (often the process name or framework name), which may not match what the user expectsVerify SSI is armed:
If /etc/ld.so.preload contains a path to the launcher, and /opt/datadog-packages/datadog-apm-inject exists — SSI is armed.
ERROR: Either missing — run agent-install first.
Check for existing manual instrumentation:
ERROR: Manual instrumentation found — SSI silently disables itself when it detects an existing tracer. Remove the manual import/package before proceeding.
Check base libc:
ERROR: musl — SSI requires glibc. No workaround; must use a glibc-based OS.
| Variable | How to resolve |
|---|---|
SERVICE_NAME | Ask the user — how the service should appear in Datadog APM (e.g. payment-api) |
ENV | Ask the user — environment name (e.g. production, staging, dev) |
VERSION | Ask the user or read from the app's version file / git tag |
SYSTEMD_SERVICE_NAME | From systemctl list-units --type=service --state=running on the host — the unit running the app |
SSH_KEY | Path to SSH private key |
SSH_USER | SSH username |
SSH_HOST | Hostname or IP of the target host |
pip uninstall ddtrace, remove import ddtrace / ddtrace-run from CMDnpm uninstall dd-trace, remove require('dd-trace')-javaagent:/path/to/dd-java-agent.jar JVM flaggem uninstall ddtrace, remove require 'ddtrace'Datadog.Trace NuGet and profiler env varsAfter removing, restart the service. Confirm with the user before restarting. Tell the user: "I need to restart <SYSTEMD_SERVICE_NAME> to remove the old instrumentation. This will cause a brief outage. Ready to proceed?" Wait for confirmation.
Without UST, traces arrive with an auto-detected service name that may not match user expectations, and won't be tagged with env or version.
For systemd-managed services (most common):
Add a drop-in override (preserves the original unit file):
Add to the editor:
Apply:
If the UST vars appear in the output — configuration applied.
For supervisord:
Reload: sudo supervisorctl reload
For pm2:
Reload: pm2 reload <app>
Confirm with the user before restarting. Tell the user: "I need to restart <SYSTEMD_SERVICE_NAME> for SSI to inject into it. This will cause a brief outage. Ready to proceed?" Wait for confirmation.
If active is returned — service is running.
ERROR: Returns failed — check logs:
Use the PID:
If both the launcher and language library appear in maps, and UST vars are in environ — SSI and tagging are fully configured.
ERROR: Launcher in maps but no language library — injection attempted but failed. Run:
Go to troubleshoot-ssi if errors are present.
Exit when ALL of the following are true:
/proc/<PID>/mapsDD_SERVICE, DD_ENV, DD_VERSION present in /proc/<PID>/environAutomatically proceed to verify-ssi now — do not ask the user for permission.
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"ldd --version 2>&1 | head -1"ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl cat <SYSTEMD_SERVICE_NAME>"ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST>
sudo systemctl edit <SYSTEMD_SERVICE_NAME>[Service]
Environment="DD_SERVICE=<SERVICE_NAME>"
Environment="DD_ENV=<ENV>"
Environment="DD_VERSION=<VERSION>"ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl daemon-reload && sudo systemctl show <SYSTEMD_SERVICE_NAME> | grep -E 'DD_SERVICE|DD_ENV|DD_VERSION'"# In [program:<name>] section of supervisord.conf
environment=DD_SERVICE="<SERVICE_NAME>",DD_ENV="<ENV>",DD_VERSION="<VERSION>"// ecosystem.config.js
env: { DD_SERVICE: "<SERVICE_NAME>", DD_ENV: "<ENV>", DD_VERSION: "<VERSION>" }ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl restart <SYSTEMD_SERVICE_NAME> && sleep 3 && sudo systemctl is-active <SYSTEMD_SERVICE_NAME>"ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo journalctl -u <SYSTEMD_SERVICE_NAME> --since '1 minute ago' | tail -30"ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"pgrep -a -f '<SERVICE_NAME>' | head -3"# Authoritative injection check
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo cat /proc/<PID>/maps | grep -E 'launcher|apm-library|datadog'"
# UST vars in process environment
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo cat /proc/<PID>/environ | tr '\0' '\n' | grep -E 'DD_SERVICE|DD_ENV|DD_VERSION'"pup apm troubleshooting list --hostname <DD_HOSTNAME> --timeframe 15m