AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured workflow to configure Unified Service Tags (DD_SERVICE, DD_ENV, DD_VERSION) for applications running on Linux hosts where Datadog Single Step Instrumentation (SSI) is already installed. It ensures that services are correctly tagged for APM and verifies that the SSI launcher and language libraries are properly injected into the application process. The process includes checking for existing manual instrumentation, applying environment variable overrides via systemd or other service managers, and validating the final configuration in the running process.
What it does
- Verifies that SSI is correctly armed on the target Linux host.
- Identifies and guides the removal of conflicting manual instrumentation.
- Configures Unified Service Tags (UST) via service manager overrides.
- Integrates with event-driven service detection where applicable.
- Validates successful injection and environment variable application in the running process.
- Ensures service health after configuration changes.
When to use it
- When SSI is installed but application services lack proper Unified Service Tags.
- When you need to set or update DD_SERVICE, DD_ENV, or DD_VERSION for an instrumented service.
- When troubleshooting missing APM data for services where SSI is expected to be active.
- When transitioning from manual instrumentation to SSI-based auto-instrumentation.
Advantages
- Standardizes service tagging across infrastructure.
- Prevents configuration conflicts by detecting manual instrumentation.
- Minimizes manual effort by automating the verification of process-level injection.
- Ensures safe deployment by requiring user confirmation before service restarts.
Usage examples
- “Configure Unified Service Tags for my payment-api service on the production host.”
- The agent will verify SSI status, apply the necessary environment variables to the systemd unit, restart the service with user consent, and confirm the injection and tags are active.
- “My service isn't showing up correctly in APM, can you check the SSI configuration?”
- The agent will inspect the host for SSI readiness, check for conflicting manual tracers, and verify if the required environment variables are present in the process environment.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/datadog-labs/enable-ssi/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip enable-ssi.zip -d .agents/skills
Documentation by datadog-labs
Configure SSI and Unified Service Tags on Linux
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.
Triggers
Invoke this skill when:
The Datadog Agent is already installed with SSI (
DD_APM_INSTRUMENTATION_ENABLED=hostwas used) and you need to configure Unified Service Tags on the application serviceThe user wants to set
DD_SERVICE,DD_ENV,DD_VERSIONon a running serviceSSI is installed but
/proc/<pid>/mapsdoesn't show the language tracer (launcher-only injection)
Do NOT invoke this skill if:
The Datadog Agent is not yet installed — run
agent-installfirstSSI packages are missing from
/opt/datadog-packages/— re-runagent-installThe target is a Kubernetes cluster — use
enable-ssiatdd-apm/k8s-ssi/enable-ssiinstead
Background
When the install script runs with DD_APM_INSTRUMENTATION_ENABLED=host, it:
Installs
datadog-apm-injectand language library packages under/opt/datadog-packages/Writes the launcher path into
/etc/ld.so.preloadSSI is now armed — every new process on the host gets the launcher injected at startup
What SSI does NOT configure automatically:
DD_SERVICE,DD_ENV,DD_VERSION— these must be set on the application process for traces to be tagged correctlyWithout
DD_SERVICE, the tracer auto-detects a service name (often the process name or framework name), which may not match what the user expects
Prerequisites
Verify SSI is armed:
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"cat /etc/ld.so.preload && ls /opt/datadog-packages/ | grep apm"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:
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> "
grep -r 'import ddtrace\|from ddtrace\|require .dd-trace.\|opentelemetry' <SOURCE_DIR> 2>/dev/null | head -5 || echo 'No manual instrumentation found'
"ERROR: Manual instrumentation found — SSI silently disables itself when it detects an existing tracer. Remove the manual import/package before proceeding.
Check base libc:
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"ldd --version 2>&1 | head -1"ERROR: musl — SSI requires glibc. No workaround; must use a glibc-based OS.
Context to resolve before acting
| 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 |
Step 0 (Only if existing instrumentation detected): Remove Manual Instrumentation
Python:
pip uninstall ddtrace, removeimport ddtrace/ddtrace-runfrom CMDNode.js:
npm uninstall dd-trace, removerequire('dd-trace')Java: remove
-javaagent:/path/to/dd-java-agent.jarJVM flagRuby:
gem uninstall ddtrace, removerequire 'ddtrace'.NET: remove
Datadog.TraceNuGet and profiler env vars
After 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.
Step 1: Set Unified Service Tags on the Application Process
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):
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl cat <SYSTEMD_SERVICE_NAME>"Add a drop-in override (preserves the original unit file):
What you need to do in a terminal
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST>
sudo systemctl edit <SYSTEMD_SERVICE_NAME>Add to the editor:
[Service]
Environment="DD_SERVICE=<SERVICE_NAME>"
Environment="DD_ENV=<ENV>"
Environment="DD_VERSION=<VERSION>"Apply:
Claude runs
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|DD_DATA_STREAMS_ENABLED'"If the UST vars appear in the output — configuration applied.
For supervisord:
# In [program:<name>] section of supervisord.conf
environment=DD_SERVICE="<SERVICE_NAME>",DD_ENV="<ENV>",DD_VERSION="<VERSION>"Reload: sudo supervisorctl reload
For pm2:
// ecosystem.config.js
env: { DD_SERVICE: "<SERVICE_NAME>", DD_ENV: "<ENV>", DD_VERSION: "<VERSION>" }Reload: pm2 reload <app>
Step 1b: Check for Event-Driven Services
Skip this step entirely in an eval cluster (kind cluster name contains "evalya") or when running non-interactively: run nothing, ask nothing, and continue to the next step.
Otherwise, read the ## Is DSM a fit? section of .claude/skills/dd-apm/enable-dsm/SKILL.md and run its detection command.
Fit found (messaging client, broker, queue-triggered Lambda, or the user describes services handing work to each other asynchronously) → follow
enable-dsm. It asks the user once, states the plan rule, and makes the config change without restarting.No fit → skip. Do not mention DSM.
If the user agrees, enable-dsm adds its variable to the drop-in from Step 1, so the restart in Step 2 picks up both.
Step 2: Restart the Service
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.
Claude runs
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>"If active is returned — service is running.
ERROR: Returns failed — check logs:
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo journalctl -u <SYSTEMD_SERVICE_NAME> --since '1 minute ago' | tail -30"Step 3: Confirm Injection and UST in the Running Process
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"pgrep -a -f '<SERVICE_NAME>' | head -3"Use the PID:
# 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|DD_DATA_STREAMS_ENABLED'"If both the launcher and language library appear in maps, and UST vars are in environ (plus DD_DATA_STREAMS_ENABLED=true if DSM was enabled in Step 1b), SSI and tagging are fully configured.
ERROR: Launcher in maps but no language library — injection attempted but failed. Run:
pup apm troubleshooting list --hostname <DD_HOSTNAME> --timeframe 15mGo to troubleshoot-ssi if errors are present.
Done
Exit when ALL of the following are true:
[ ] Launcher and language library visible in
/proc/<PID>/maps[ ]
DD_SERVICE,DD_ENV,DD_VERSIONpresent in/proc/<PID>/environ[ ] Service is running and healthy
Automatically proceed to verify-ssi now — do not ask the user for permission.
Security constraints
Never write a raw API key into any file or chat message
Always confirm with the user before restarting production services
Do not modify application source code — configure only via environment variables in the service unit
Files
- ATTRIBUTION.mdAdded by AutoGineer963 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md8.7 KiB
SKILL.md
Configure SSI and Unified Service Tags on Linux
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.
Triggers
Invoke this skill when:
The Datadog Agent is already installed with SSI (
DD_APM_INSTRUMENTATION_ENABLED=hostwas used) and you need to configure Unified Service Tags on the application serviceThe user wants to set
DD_SERVICE,DD_ENV,DD_VERSIONon a running serviceSSI is installed but
/proc/<pid>/mapsdoesn't show the language tracer (launcher-only injection)
Do NOT invoke this skill if:
The Datadog Agent is not yet installed — run
agent-installfirstSSI packages are missing from
/opt/datadog-packages/— re-runagent-installThe target is a Kubernetes cluster — use
enable-ssiatdd-apm/k8s-ssi/enable-ssiinstead
Background
When the install script runs with DD_APM_INSTRUMENTATION_ENABLED=host, it:
Installs
datadog-apm-injectand language library packages under/opt/datadog-packages/Writes the launcher path into
/etc/ld.so.preloadSSI is now armed — every new process on the host gets the launcher injected at startup
What SSI does NOT configure automatically:
DD_SERVICE,DD_ENV,DD_VERSION— these must be set on the application process for traces to be tagged correctlyWithout
DD_SERVICE, the tracer auto-detects a service name (often the process name or framework name), which may not match what the user expects
Prerequisites
Verify SSI is armed:
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"cat /etc/ld.so.preload && ls /opt/datadog-packages/ | grep apm"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:
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> "
grep -r 'import ddtrace\|from ddtrace\|require .dd-trace.\|opentelemetry' <SOURCE_DIR> 2>/dev/null | head -5 || echo 'No manual instrumentation found'
"ERROR: Manual instrumentation found — SSI silently disables itself when it detects an existing tracer. Remove the manual import/package before proceeding.
Check base libc:
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"ldd --version 2>&1 | head -1"ERROR: musl — SSI requires glibc. No workaround; must use a glibc-based OS.
Context to resolve before acting
| 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 |
Step 0 (Only if existing instrumentation detected): Remove Manual Instrumentation
Python:
pip uninstall ddtrace, removeimport ddtrace/ddtrace-runfrom CMDNode.js:
npm uninstall dd-trace, removerequire('dd-trace')Java: remove
-javaagent:/path/to/dd-java-agent.jarJVM flagRuby:
gem uninstall ddtrace, removerequire 'ddtrace'.NET: remove
Datadog.TraceNuGet and profiler env vars
After 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.
Step 1: Set Unified Service Tags on the Application Process
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):
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl cat <SYSTEMD_SERVICE_NAME>"Add a drop-in override (preserves the original unit file):
What you need to do in a terminal
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST>
sudo systemctl edit <SYSTEMD_SERVICE_NAME>Add to the editor:
[Service]
Environment="DD_SERVICE=<SERVICE_NAME>"
Environment="DD_ENV=<ENV>"
Environment="DD_VERSION=<VERSION>"Apply:
Claude runs
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|DD_DATA_STREAMS_ENABLED'"If the UST vars appear in the output — configuration applied.
For supervisord:
# In [program:<name>] section of supervisord.conf
environment=DD_SERVICE="<SERVICE_NAME>",DD_ENV="<ENV>",DD_VERSION="<VERSION>"Reload: sudo supervisorctl reload
For pm2:
// ecosystem.config.js
env: { DD_SERVICE: "<SERVICE_NAME>", DD_ENV: "<ENV>", DD_VERSION: "<VERSION>" }Reload: pm2 reload <app>
Step 1b: Check for Event-Driven Services
Skip this step entirely in an eval cluster (kind cluster name contains "evalya") or when running non-interactively: run nothing, ask nothing, and continue to the next step.
Otherwise, read the ## Is DSM a fit? section of .claude/skills/dd-apm/enable-dsm/SKILL.md and run its detection command.
Fit found (messaging client, broker, queue-triggered Lambda, or the user describes services handing work to each other asynchronously) → follow
enable-dsm. It asks the user once, states the plan rule, and makes the config change without restarting.No fit → skip. Do not mention DSM.
If the user agrees, enable-dsm adds its variable to the drop-in from Step 1, so the restart in Step 2 picks up both.
Step 2: Restart the Service
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.
Claude runs
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>"If active is returned — service is running.
ERROR: Returns failed — check logs:
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo journalctl -u <SYSTEMD_SERVICE_NAME> --since '1 minute ago' | tail -30"Step 3: Confirm Injection and UST in the Running Process
Claude runs
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"pgrep -a -f '<SERVICE_NAME>' | head -3"Use the PID:
# 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|DD_DATA_STREAMS_ENABLED'"If both the launcher and language library appear in maps, and UST vars are in environ (plus DD_DATA_STREAMS_ENABLED=true if DSM was enabled in Step 1b), SSI and tagging are fully configured.
ERROR: Launcher in maps but no language library — injection attempted but failed. Run:
pup apm troubleshooting list --hostname <DD_HOSTNAME> --timeframe 15mGo to troubleshoot-ssi if errors are present.
Done
Exit when ALL of the following are true:
[ ] Launcher and language library visible in
/proc/<PID>/maps[ ]
DD_SERVICE,DD_ENV,DD_VERSIONpresent in/proc/<PID>/environ[ ] Service is running and healthy
Automatically proceed to verify-ssi now — do not ask the user for permission.
Security constraints
Never write a raw API key into any file or chat message
Always confirm with the user before restarting production services
Do not modify application source code — configure only via environment variables in the service unit
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs an API key
Security
What our scanner noticed· Low risk
- Phrasing that asks for actions without confirmation
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- datadog-labs
- Publisher
- Datadog (Official)
- Source
- datadog-labs/agent-skills · dd-apm/linux-ssi/enable-ssi · commit 8e1306a
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by datadog-labs or Datadog.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download enable-ssi.zip