Full-stack injection for automatic instrumentation means Dynatrace automatically weaves its monitoring code into your applications without you touching a single line of application code.

Let’s see it in action. Imagine you’ve got a Java application running in a Kubernetes cluster. You want Dynatrace to automatically monitor it.

First, you’ll need to deploy the Dynatrace OneAgent operator to your Kubernetes cluster. This operator is responsible for managing the OneAgent deployments.

apiVersion: dynatrace.com/v1beta1
kind: OneAgent
metadata:
  name: oneagent
  namespace: dynatrace
spec:
  tokens:
    # Replace with your actual Dynatrace API token
    - name: paas-token
      secret: dynatrace-api-token
  # Replace with your actual Dynatrace Environment ID
  environmentID: "YOUR_ENVIRONMENT_ID"
  # Replace with your actual Dynatrace Tenant URL
  apiUrl: "https://YOUR_TENANT_URL/api"
  # Enable automatic injection for Kubernetes pods
  applicationInjection:
    # For Java applications, set this to true
    java: true
    # If you have other languages, enable them here too
    # python: true
    # nodejs: true

Once the OneAgent custom resource is applied, the operator will automatically inject the OneAgent into your application pods. For Java, this typically involves modifying the pod’s JAVA_TOOL_OPTIONS environment variable to include the OneAgent Java agent path.

# Example of what the injected JAVA_TOOL_OPTIONS might look like
export JAVA_TOOL_OPTIONS="-javaagent:/opt/dynatrace/oneagent/agent/lib/codenotify.jar"

This injection happens before your application’s JVM starts. The codenotify.jar is the Dynatrace OneAgent. When your Java application launches, the JVM loads this agent. The agent then hooks into the JVM’s internal mechanisms, allowing it to observe and record everything from incoming requests and outgoing calls to method executions and exceptions, all without any code changes on your part.

The problem this solves is the immense overhead of manual instrumentation. Before automatic injection, you’d have to manually add agent JARs to your build process, configure JVM arguments for every single instance, and maintain these configurations as your application evolved. This was error-prone and time-consuming, especially in dynamic environments like Kubernetes. Dynatrace’s full-stack injection automates this entire process, making it trivial to get deep, end-to-end visibility.

Internally, the OneAgent leverages Java’s java.lang.instrument package. This package allows agents to dynamically modify class bytecode after the class has been loaded by the JVM but before it’s executed. The OneAgent’s codenotify.jar acts as this instrumenting agent. It intercepts class loading and method invocation events. For example, when a request comes in, the agent can modify the entry point method to record the start time and relevant context. Similarly, when an outgoing HTTP call is made, the agent can intercept the relevant network calls to trace the request and its latency. It doesn’t just observe; it actively modifies the execution flow (byte code level) to add tracing and metrics collection points on the fly.

The applicationInjection section in the OneAgent custom resource is your primary lever. You enable specific languages by setting their respective boolean flags to true. The operator then uses this information to determine which environment variables or startup parameters to inject for each detected workload. For instance, if python: true is set, it might inject environment variables like LD_PRELOAD for native extensions or modify PYTHONPATH for Python-specific agents.

The most surprising part is how effectively Dynatrace can trace requests across different technologies and even process boundaries without explicit developer configuration. It achieves this by leveraging a combination of bytecode instrumentation for in-process calls and network-level sniffing for inter-process communication. For example, if a Java application calls a Python microservice over HTTP, the OneAgent in the Java app traces the outgoing request, and if a OneAgent is also active in the Python environment, it can pick up the incoming request and link the two traces, creating a seamless end-to-end view of the transaction, even though the two services are running in entirely different runtimes and potentially different containers.

The next hurdle is understanding how to leverage the detailed topology and dependency maps generated by this injection to proactively identify performance bottlenecks.

Want structured learning?

Take the full Dynatrace course →