Skip to content

DDTrace Java

The DDTrace Java Agent uses the JVM -javaagent mechanism to instrument classes as they load, so common frameworks usually need no business-code changes. This page explains how to send Java Agent traces to DataKit; it is not a complete guide to log collection, profiling, or JMX metrics.

Preconditions

  1. Install DataKit and enable the DDTrace collector. Explicitly configure the Java Agent to send traces to the DataKit HTTP address and port 9529.
  2. Use JDK 8 or later and choose an Agent version compatible with the application runtime, operating system, and CPU architecture. Validate JDK or Agent upgrades before production.
  3. Ensure that the JVM runtime user can read the Agent JAR at its absolute path.
  4. Profiling and JMX metrics use separate data paths: profiling requires the Profiling collector, and JMX metrics require the StatsD collector.
Warning

A JVM can load multiple Java Agents, but their class-transformation order and compatibility affect startup and data quality. Do not add two DDTrace Java Agents to one process. When combining with another APM, security, or bytecode Agent, load-test and validate critical application paths first.

Get the Agent

The extended version adds selected framework integrations and finer-grained collection on top of the upstream Java Agent. Pin an exact version after downloading it, and read the Java extension guide and changelog:

wget -O /opt/dd-java-agent.jar \
  'https://static.guance.com/dd-image/dd-java-agent.jar'
wget -O /opt/dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'

The extended and upstream versions can have different defaults and supported settings. Whichever JAR you use, explicitly set the DataKit host and port in startup configuration to avoid sending to the common upstream default port 8126 by mistake.

Running the Application

Host Application

Place every -D option before -jar. The following command provides a minimal, identifiable service configuration:

java \
  -javaagent:/opt/dd-java-agent.jar \
  -Ddd.service=my-java-service \
  -Ddd.env=production \
  -Ddd.version=1.0.0 \
  -Ddd.agent.host=127.0.0.1 \
  -Ddd.trace.agent.port=9529 \
  -Ddd.logs.injection=true \
  -jar /opt/my-app.jar

The environment-variable equivalent of dd.service is DD_SERVICE; do not write the property as dd.service.name. You can also set DD_AGENT_HOST, DD_TRACE_AGENT_PORT, DD_SERVICE, DD_ENV, and DD_VERSION before process startup. DD_TRACE_AGENT_URL / dd.trace.agent.url, when set, normally takes precedence over host and port, so use only one destination mechanism.

Kubernetes

For Kubernetes, use DataKit Operator DDTrace injection where possible. The Operator injects the JAR, volumes, and language-specific startup configuration into newly created Pods. Changing Operator configuration or a Pod annotation requires Pod recreation (for example, a rollout restart) before the webhook runs again.

An application image can also carry its own Agent. The following fragment works only when the JAR already exists at /opt/dd-java-agent.jar in the image. Environment variables alone do not load an Agent and cannot enable automatic instrumentation.

containers:
  - name: app
    image: registry.example/my-java-app:1.0.0
    env:
      - name: JAVA_TOOL_OPTIONS
        value: "-javaagent:/opt/dd-java-agent.jar"
      - name: DD_SERVICE
        value: "my-java-service"
      - name: DD_ENV
        value: "production"
      - name: DD_VERSION
        value: "1.0.0"
      - name: DD_AGENT_HOST
        value: "datakit-service.datakit.svc.cluster.local"
      - name: DD_TRACE_AGENT_PORT
        value: "9529"

If the image does not contain the JAR, use the Operator or a controlled initContainer plus shared volume. Do not put an unverified JAR download into a business-container startup script.

Enable Profiling

Profiling data goes to the DataKit Profiling receiver, not the DDTrace trace receiver. Enable the Profiling collector first, then enable the Agent feature:

DD_PROFILING_ENABLED=true \
java -javaagent:/opt/dd-java-agent.jar \
  -Ddd.agent.host=127.0.0.1 \
  -Ddd.trace.agent.port=9529 \
  -jar /opt/my-app.jar

Assess performance, storage, and compliance impact before enabling it in production. Do not diagnose missing profiling data as a trace-receiver problem.

Set a Sampling Rate

Application-side sampling reduces traffic at the source:

DD_TRACE_SAMPLE_RATE=0.8 \
java -javaagent:/opt/dd-java-agent.jar \
  -Ddd.agent.host=127.0.0.1 \
  -Ddd.trace.agent.port=9529 \
  -jar /opt/my-app.jar

0.8 means 80% SDK-side sampling. It is independent of receiver-side sampling in the DataKit ddtrace collector. Decide which layer controls traffic so the combined result remains explainable.

Enable JVM Metrics Collection

JMXFetch can collect JVM metrics by default, but it sends them through DogStatsD. Enable the StatsD collector and use a separate StatsD address and port, normally UDP 8125:

DD_JMXFETCH_ENABLED=true \
DD_JMXFETCH_STATSD_HOST=<YOUR-DATAKIT-HOST> \
DD_JMXFETCH_STATSD_PORT=8125 \
java -javaagent:/opt/dd-java-agent.jar \
  -Ddd.agent.host=<YOUR-DATAKIT-HOST> \
  -Ddd.trace.agent.port=9529 \
  -jar /opt/my-app.jar

Do not set DD_JMXFETCH_STATSD_PORT to 9529. See DDTrace JMX for custom MBean metrics.

Parameter Explanation

The table lists settings most relevant to DataKit. For the complete set, version requirements, and defaults, use the Datadog Java configuration guide.

JVM property Environment variable Purpose and DataKit guidance
dd.service DD_SERVICE Service name. Set it explicitly so it does not change with auto-detection.
dd.env DD_ENV Deployment environment, such as production or staging.
dd.version DD_VERSION Application version, useful for release and regression comparison.
dd.trace.agent.url DD_TRACE_AGENT_URL Full trace-receiver URL. It normally overrides host/port.
dd.agent.host DD_AGENT_HOST DataKit host or Kubernetes Service.
dd.trace.agent.port DD_TRACE_AGENT_PORT Trace receiver port. The common upstream default is 8126; DataKit uses 9529.
dd.trace.sample.rate DD_TRACE_SAMPLE_RATE SDK-side root-trace sampling rate from 0.0 to 1.0.
dd.trace.enabled DD_TRACE_ENABLED Controls automatic instrumentation and trace generation; during troubleshooting, make sure it is not false.
dd.logs.injection DD_LOGS_INJECTION Adds trace/span correlation fields to supported log frameworks; log collection remains a separate setup.
dd.profiling.enabled DD_PROFILING_ENABLED Enables Continuous Profiling and requires DataKit profile.
dd.jmxfetch.enabled DD_JMXFETCH_ENABLED Enables JMXFetch; metrics must go to DataKit StatsD on 8125.
dd.trace.startup.logs, dd.trace.debug DD_TRACE_STARTUP_LOGS, DD_TRACE_DEBUG Startup configuration and debug logs. Enable only temporarily for troubleshooting.

Trace Error Behavior

Whether automatic instrumentation marks a span as an error depends on the integration and SDK configuration. Do not assume that every exception or every 4xx/5xx response is an error. In general:

  • An exception that is not handled by the application and reaches a supported framework boundary is normally recorded with error information and a stack trace.
  • HTTP server and client error-status ranges are configurable independently. Common upstream defaults treat server 5xx and client 4xx responses as errors; the extended Agent can add further behavior.
  • When application code catches and handles an exception, automatic instrumentation may not mark the current span as an error. If the failure is still meaningful to the business, use the installed SDK API to record it explicitly.
  • DataKit commonly exposes error.type, error.message, and error.stack. Stack traces and messages can contain sensitive data, so control access and retention according to your data-governance policy.

To investigate, reproduce a minimal request and inspect the application log, Agent startup log, and trace detail together. Do not infer instrumentation success solely from an HTTP status code.

Verification and Troubleshooting

  1. Temporarily set DD_TRACE_STARTUP_LOGS=true and confirm in JVM logs that the Agent loaded and points to DataKit.
  2. Call an endpoint that passes through HTTP, a database, or RPC, then confirm requests to /v0.3/traces, /v0.4/traces, or /v0.5/traces in the DataKit monitor.
  3. In Kubernetes, also check JAVA_TOOL_OPTIONS/the command line, the Agent-file mount, DD_AGENT_HOST, and DD_TRACE_AGENT_PORT in the Pod.
  4. If traces arrive but cross-service topology is broken, check propagation protocols and Multi-Tracing Propagation.

More Reading

Feedback

Is this page helpful? ×