From 275cd8cc45320e662b00672d5eb9c7cb82d2705e Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 14:46:12 +0100 Subject: [PATCH 01/15] feat(doc): Initial architecture documentation --- ARCHITECTURE.md | 279 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000000..8b8b94307da --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,279 @@ +# Architecture of dd-trace-java + +This document describes the high-level architecture of the Datadog Java APM agent. +If you want to familiarize yourself with the codebase, this is a good place to start. + +## Bird's Eye View + +dd-trace-java is a Java agent that auto-instruments JVM applications at runtime via bytecode manipulation. +It attaches to a running JVM using the `-javaagent` flag, intercepts class loading, and rewrites method bytecode +to inject tracing, security, profiling, and observability logic - all without requiring application code changes. + +The agent ships roughly 120 integrations (about 200 instrumentations) covering popular frameworks +(Spring, Servlet, gRPC, JDBC, Kafka, etc.) and supports multiple Datadog products through a single agent jar: +**Tracing**, **Profiling**, **Application Security (AppSec)**, **IAST**, **CI Visibility**, +**Dynamic Instrumentation**, **LLM Observability**, **Crash Tracking**, **Data Streams**, +**Feature Flagging**, and **USM**. + +The agent communicates with a local Datadog Agent process (or directly with the Datadog intake APIs) +to send collected telemetry. + +## Startup Sequence + +Understanding the startup sequence is key to understanding the project: + +1. **`AgentBootstrap.premain()`** — The JVM calls this entry point. It runs on the application classloader + with minimal logic: it locates the agent jar, creates an isolated classloader, and jumps to `Agent.start()`. + This class must remain tiny and side-effect-free. + +2. **`Agent.start()`** — Running on the bootstrap classloader, this method orchestrates everything: + creates the agent classloader, reads configuration, determines which products are enabled + (tracing, AppSec, IAST, profiling, etc.), and starts each subsystem on dedicated threads. + +3. **`AgentInstaller`** — Installs the ByteBuddy `ClassFileTransformer` that intercepts all class loading. + It discovers all `InstrumenterModule` implementations via service loading and registers their + type matchers and advice classes with ByteBuddy. + +4. **Product subsystems start** — Each enabled product (AppSec, IAST, CI Visibility, Profiling, Debugger, etc.) + is started via its own `*System.start()` method, receiving shared communication objects. + +## Codemap + +### `dd-java-agent/` + +The main agent module. Its build produces the final shadow jar (`dd-java-agent.jar`). + +- **`src/`** — Contains `AgentBootstrap` and `AgentJar`, the true entry point loaded by the JVM's + `-javaagent` mechanism. Deliberately minimal. + +- **`agent-bootstrap/`** — Classes loaded on the bootstrap classloader. Contains `Agent` (the real startup + orchestrator), decorator base classes (`HttpServerDecorator`, `DatabaseClientDecorator`, etc.), + and bootstrap-safe utilities. Code here must not use `java.util.logging`, `java.nio`, or `javax.management` + (see Bootstrap Constraints below). + +- **`agent-builder/`** — ByteBuddy integration layer. Contains custom matchers (`DDElementMatchers`, + `HierarchyMatchers`), the class transformer pipeline, and the `ignored_class_name.trie` that skips + unsafe or pointless classes. + +- **`agent-tooling/`** — The instrumentation framework. Key types: + - `InstrumenterModule` — Base class for all instrumentation modules. Each declares a target system + (Tracing, AppSec, IAST, Profiling, CiVisibility, USM, etc.) and one or more instrumentations. + - `Instrumenter` — Interface with variants for type matching: `ForSingleType`, `ForKnownTypes`, + `ForTypeHierarchy`, `ForBootstrap`. + - `muzzle/` — Build-time and runtime safety checks. Verifies that the types and methods an + instrumentation expects actually exist in the library version present at runtime. + If they don't, the instrumentation is silently skipped. + +- **`instrumentation/`** — All auto-instrumentations, organized as `{framework}/{framework}-{minVersion}/`. + About 186 framework directories. Each contains an `InstrumenterModule` subclass, one or more `Instrumenter` + implementations, advice classes, decorators, and helpers. See `docs/how_instrumentations_work.md` for details. + +- **`appsec/`** — Application Security. Entry point: `AppSecSystem.start()`. Integrates the Datadog WAF + (Web Application Firewall) to detect and block attacks in real-time. + Hooks into the gateway event system to intercept HTTP requests. + +- **`agent-iast/`** — Interactive Application Security Testing. Entry point: `IastSystem.start()`. + Performs taint tracking: marks user input as tainted, propagates taint through string operations, + and reports when tainted data reaches dangerous sinks (SQL injection, XSS, command injection, etc.). + +- **`agent-ci-visibility/`** — CI Visibility. Entry point: `CiVisibilitySystem.start()`. + Instruments test frameworks (JUnit, TestNG, Gradle, Maven, Cucumber) to collect test results, + code coverage, and performance metrics. + +- **`agent-profiling/`** — Continuous Profiling. Entry point: `ProfilingAgent`. + Collects CPU, memory, and wall-clock profiles using JFR or the Datadog native profiler (`ddprof`). + Uploads profiles to the Datadog backend. + +- **`agent-debugger/`** — Dynamic Instrumentation. Entry point: `DebuggerAgent`. + Enables live debugging (set breakpoints, capture snapshots), exception replay, code origin mapping, + and distributed debugging — all without restarting the JVM. Driven by remote configuration. + +- **`agent-llmobs/`** — LLM Observability. Entry point: `LLMObsSystem.start()`. + Monitors LLM API calls (OpenAI, LangChain, etc.), tracking token usage, model inference, and evaluations. + +- **`agent-crashtracking/`** — Crash Tracking. Detects JVM crashes and fatal exceptions, + collects system metadata, and uploads crash reports to Datadog's error tracking intake. + +- **`agent-otel/`** — OpenTelemetry compatibility shim. Allows applications using the OTel API + to have their spans captured by the Datadog agent. + +### `dd-trace-core/` + +The core tracing engine. Key types: + +- `CoreTracer` — The tracer implementation. Creates spans, manages sampling, drives the writer pipeline. + Implements `AgentTracer.TracerAPI`. +- `DDSpan` / `DDSpanContext` — Concrete span and context implementations with Datadog-specific metadata. +- `PendingTrace` — Tracks all spans belonging to a single trace. When all spans finish, flushes the trace + to the writer. +- `scopemanager/` — `ContinuableScopeManager`, `ContinuableScope`, `ScopeContinuation`. Manages the + active span on each thread and supports async context propagation via continuations. +- `propagation/` — Trace context propagation codecs: Datadog, W3C TraceContext, B3, Haystack, X-Ray. +- `common/writer/` — The writer pipeline. `DDAgentWriter` buffers traces and dispatches them via + `PayloadDispatcherImpl` to the Datadog Agent's `/v0.4/traces` endpoint. Also: `DDIntakeWriter` for + direct API submission, and `TraceProcessingWorker` for async trace processing. +- `common/sampling/` — Sampling logic: `RuleBasedTraceSampler`, `RateByServiceTraceSampler`, + `SingleSpanSampler`. Supports both head-based and rule-based sampling. +- `datastreams/` — Data Streams Monitoring. Tracks message pipeline latency across Kafka, RabbitMQ, + SQS, etc. +- `tagprocessor/` — Post-processing of span tags: peer service calculation, base service naming, + query obfuscation, endpoint resolution. + +### `dd-trace-api/` + +The public API. Contains types that application developers may interact with directly: +`Tracer`, `GlobalTracer`, `DDTags`, `DDSpanTypes`, `Trace` (annotation), `ConfigDefaults`. +Also houses all configuration key constants organized by domain: `TracerConfig`, `GeneralConfig`, +`AppSecConfig`, `ProfilingConfig`, `CiVisibilityConfig`, `IastConfig`, `DebuggerConfig`, etc. + +### `internal-api/` + +Internal shared API used across all agent modules but not part of the public API. +Key abstractions that instrumentations interact with: + +- `AgentTracer` — Static facade for the tracer. Instrumentations call `AgentTracer.startSpan()`, + `AgentTracer.activateSpan()`, etc. +- `AgentSpan` / `AgentScope` / `AgentSpanContext` — Internal span/scope/context interfaces. +- `AgentPropagation` — Context propagation interfaces (`Getter`, `Setter`) that instrumentations + implement to inject/extract trace context from framework-specific carriers (HTTP headers, message + properties, etc.). +- `InstrumentationContext` — Provides context stores for attaching data to instrumented objects + (e.g., storing a span on a request object). Works by dynamically adding fields via bytecode. +- `gateway/` — The Instrumentation Gateway: an event bus (`InstrumentationGateway`, `SubscriptionService`, + `Events`, `CallbackProvider`, `RequestContext`) that decouples instrumentations from product modules. + Instrumentations fire events (request started, response body received, etc.), + and products (AppSec, IAST) subscribe to react. + +### `communication/` + +HTTP transport to the Datadog Agent and intake APIs. Key type: `SharedCommunicationObjects`, +which holds shared `OkHttpClient` instances (with Unix domain socket and named pipe support), +agent URL, feature discovery, and the configuration poller. All product modules receive this +at startup. + +### `remote-config/` + +Remote configuration client. `DefaultConfigurationPoller` periodically polls the Datadog Agent +for configuration updates (AppSec rules, debugger probes, sampling rates, feature flags). +Uses TUF (The Update Framework) for signature validation. + +### `telemetry/` + +Agent telemetry. `TelemetrySystem` collects and reports which features are enabled, +which integrations loaded, performance metrics, and product-specific counters. +Each product registers periodic actions that collect domain-specific metrics. + +### `components/` + +Low-level shared components: `context` (context propagation primitives), `environment` (JVM/OS detection), +`json` (lightweight JSON handling), `native-loader` (native library loading), `yaml`. + +### `utils/` + +Shared utilities: `config-utils`, `container-utils`, `filesystem-utils`, `flare-utils`, +`queue-utils`, `socket-utils`, `time-utils`, `version-utils`, `test-utils`. + +### `products/` + +Additional product modules: `metrics/` (StatsD client and monitoring abstraction) and +`feature-flagging/` (server-side feature flag evaluation via remote config). + +### `dd-trace-ot/` + +OpenTracing compatibility layer. Wraps the Datadog tracer behind the OpenTracing API. + +### `dd-smoke-tests/` + +End-to-end smoke tests. Each test boots a real application with the agent jar attached and verifies +traces, spans, and product behavior. Covers Spring Boot, Play, Vert.x, Quarkus, WildFly, and more. + +## Instrumentation Pattern + +Every instrumentation follows the same pattern: + +1. An **`InstrumenterModule`** subclass declares which product it serves (Tracing, AppSec, etc.), + its integration name, helper classes, and context stores. + +2. One or more **`Instrumenter`** implementations select target types via matchers + (`ForSingleType`, `ForKnownTypes`, `ForTypeHierarchy`) and register method advice. + +3. **Advice classes** use ByteBuddy's `@Advice.OnMethodEnter` / `@Advice.OnMethodExit` to inject + bytecode before/after matched methods. Advice code runs in the application's classloader context. + +4. **Decorator/helper classes** contain the actual tracing logic (start span, set tags, finish span). + These are injected into the application classloader at runtime. + +5. **Muzzle** validates at build time (and runtime) that the instrumented library's API matches + what the instrumentation expects, preventing `NoSuchMethodError` at runtime. + +Instrumentations are discovered via `@AutoService(InstrumenterModule.class)` (Java SPI). + +## The Instrumentation Gateway + +The gateway (`InstrumentationGateway`) is the central integration point between instrumentations +and product modules. It implements a publish-subscribe pattern: + +- **Instrumentations** (e.g., Servlet, Spring) fire events like "request started", "request header received", + "response body committed" through the gateway. +- **Product modules** (AppSec, IAST) subscribe to these events via `SubscriptionService` and react + (e.g., run WAF checks, track tainted data). +- `RequestContext` carries per-request state across products using `RequestContextSlot` + for type-safe storage. + +This design allows adding new products without modifying existing instrumentations. + +## Writer Pipeline + +When a trace completes, it flows through: + +1. `PendingTrace` collects all spans until the root span finishes. +2. `CoreTracer.write()` sends the trace to the `Writer`. +3. `DDAgentWriter` (the default writer) enqueues the trace in `TraceProcessingWorker`. +4. The worker serializes traces to MessagePack via `PayloadDispatcherImpl`. +5. The dispatcher sends batched payloads to the Datadog Agent's trace intake endpoint. +6. Sampling responses from the Agent are fed back to update sampling rates. + +## Architectural Invariants + +- **Bootstrap classloader isolation**: The agent jar is a shadow jar with all dependencies relocated + (shaded) under `datadog.` prefixes. This prevents classpath conflicts with application dependencies. + The agent classloader is separate from the application classloader. + +- **No premain side effects**: Code running during `premain` must not use `java.util.logging`, + `java.nio`, or `javax.management`. These trigger JVM initialization that can break applications + that configure these subsystems after `main`. See `docs/bootstrap_design_guidelines.md`. + +- **Advice is bytecode, not code**: Advice classes are templates whose bytecode gets copied into + target methods. They cannot reference methods on their own class or the instrumentation class. + They can only use bootstrap classpath types or injected helpers. + +- **Context stores are not maps**: `InstrumentationContext.get()` attaches data to objects by adding + fields via bytecode. The same object instance (identity, not equality) must be used for put and get. + +- **Instrumentations must be safe to skip**: Muzzle ensures any instrumentation can be silently + disabled if the target library version is incompatible. No instrumentation should cause the agent + to crash or the application to break. + +- **Product independence**: Each product (AppSec, IAST, Profiling, etc.) can be enabled/disabled + independently. Products communicate through the gateway, not direct dependencies. + +## Cross-Cutting Concerns + +- **Configuration**: The `Config` singleton reads from system properties, environment variables, + remote configuration, and config files. Keys are defined as constants in `dd-trace-api` + (e.g., `TracerConfig`, `GeneralConfig`). Configuration is immutable after startup, + except for values updated via remote configuration. + +- **Logging**: Uses a shaded SLF4J that redirects to an internal logger. Never use `java.util.logging` + in agent code. In advice classes, move logging to helper classes. + +- **Formatting**: google-java-format enforced via Spotless (`./gradlew spotlessApply`). + +- **Testing**: Unit tests use JUnit 5 or Spock 2. Instrumentation tests extend + `InstrumentationSpecification`. HTTP server integrations share base test classes + that enforce consistency. Smoke tests use the real agent jar against real applications. + Flaky tests are annotated with `@Flaky` and skipped in CI by default. + +- **Build**: Gradle with Kotlin DSL. The agent jar is built via `shadowJar` which relocates all + dependencies. Instrumentations declare framework dependencies as `compileOnly` so they don't leak + into the agent jar. Muzzle runs at build time to validate version compatibility. From 9ed5c4f04c07c17de70420aa180d1f9a0b7ba239 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 15:21:29 +0100 Subject: [PATCH 02/15] feat(doc): Iterating on content --- ARCHITECTURE.md | 59 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 8b8b94307da..f00b9dd9f5e 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -41,19 +41,36 @@ Understanding the startup sequence is key to understanding the project: ### `dd-java-agent/` -The main agent module. Its build produces the final shadow jar (`dd-java-agent.jar`). +The main agent module. Its build produces the final shadow jar (`dd-java-agent.jar`) using a +composite shadow jar strategy. Each product module (instrumentation, profiling, AppSec, IAST, +debugger, CI Visibility, LLM Obs, etc.) builds its own shadow jar, which is then embedded as a +nested directory inside the main jar (`inst/`, `profiling/`, `appsec/`, `iast/`, `debugger/`, +`ci-visibility/`, `llm-obs/`, `shared/`, `trace/`, etc.). A dedicated `sharedShadowJar` bundles +common transitive dependencies (OkHttp, JCTools, LZ4, etc.) so they are not duplicated across +feature jars. All dependencies are relocated under `datadog.` prefixes to prevent classpath conflicts +with application libraries. Class files inside feature jars are renamed to `.classdata` to prevent +unintended loading. See `docs/how_to_work_with_gradle.md` for build details. - **`src/`** — Contains `AgentBootstrap` and `AgentJar`, the true entry point loaded by the JVM's `-javaagent` mechanism. Deliberately minimal. - **`agent-bootstrap/`** — Classes loaded on the bootstrap classloader. Contains `Agent` (the real startup orchestrator), decorator base classes (`HttpServerDecorator`, `DatabaseClientDecorator`, etc.), - and bootstrap-safe utilities. Code here must not use `java.util.logging`, `java.nio`, or `javax.management` - (see Bootstrap Constraints below). - -- **`agent-builder/`** — ByteBuddy integration layer. Contains custom matchers (`DDElementMatchers`, - `HierarchyMatchers`), the class transformer pipeline, and the `ignored_class_name.trie` that skips - unsafe or pointless classes. + and bootstrap-safe utilities. Because these classes are on the bootstrap classloader, they are + visible to all classloaders and can be injected into and used by instrumentation advice and helpers + at runtime. + + See `docs/boostrap_design_guidelines.md` + +- **`agent-builder/`** — ByteBuddy integration layer. Contains the class transformer pipeline: + `DDClassFileTransformer` intercepts every class being loaded, `GlobalIgnoresMatcher` applies + early filtering, `CombiningMatcher` evaluates all instrumentation matchers, and + `SplittingTransformer` applies the matched transformations. The `ignored_class_name.trie` is + a compiled trie built at build time that acts as the first and most efficient filter in this + pipeline — it short-circuits expensive matcher evaluation for known non-transformable classes + (JVM internals, agent infrastructure, monitoring libraries, large framework packages). + When a class is unexpectedly not instrumented, the trie is the first place to check: it may + be matched by a system-level ignore or an optimization ignore pattern. - **`agent-tooling/`** — The instrumentation framework. Key types: - `InstrumenterModule` — Base class for all instrumentation modules. Each declares a target system @@ -64,6 +81,8 @@ The main agent module. Its build produces the final shadow jar (`dd-java-agent.j instrumentation expects actually exist in the library version present at runtime. If they don't, the instrumentation is silently skipped. + See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md` for details. + - **`instrumentation/`** — All auto-instrumentations, organized as `{framework}/{framework}-{minVersion}/`. About 186 framework directories. Each contains an `InstrumenterModule` subclass, one or more `Instrumenter` implementations, advice classes, decorators, and helpers. See `docs/how_instrumentations_work.md` for details. @@ -94,12 +113,19 @@ The main agent module. Its build produces the final shadow jar (`dd-java-agent.j - **`agent-crashtracking/`** — Crash Tracking. Detects JVM crashes and fatal exceptions, collects system metadata, and uploads crash reports to Datadog's error tracking intake. -- **`agent-otel/`** — OpenTelemetry compatibility shim. Allows applications using the OTel API - to have their spans captured by the Datadog agent. +- **`agent-otel/`** — OpenTelemetry compatibility shim. Provides `OtelTracerProvider`, `OtelSpan`, + `OtelContext`, and other wrapper classes that implement the OTel API by delegating to the Datadog + tracer. Works in tandem with the OpenTelemetry instrumentations in `instrumentation/opentelemetry/`, + which use ByteBuddy advice to intercept OTel API calls (e.g., `OpenTelemetry.getTracerProvider()`) + and redirect them to the shim instances. This allows applications and libraries using the OTel API + to have their spans captured by the Datadog agent transparently. ### `dd-trace-core/` -The core tracing engine. Key types: +Originally the core tracing engine, this module grew organically and now also hosts several +product-specific features that depend on tight integration with span creation, interception, +or serialization. New module code should prefer `products/` or `components/` over adding to +this module. Core tracing types: - `CoreTracer` — The tracer implementation. Creates spans, manages sampling, drives the writer pipeline. Implements `AgentTracer.TracerAPI`. @@ -114,11 +140,20 @@ The core tracing engine. Key types: direct API submission, and `TraceProcessingWorker` for async trace processing. - `common/sampling/` — Sampling logic: `RuleBasedTraceSampler`, `RateByServiceTraceSampler`, `SingleSpanSampler`. Supports both head-based and rule-based sampling. -- `datastreams/` — Data Streams Monitoring. Tracks message pipeline latency across Kafka, RabbitMQ, - SQS, etc. - `tagprocessor/` — Post-processing of span tags: peer service calculation, base service naming, query obfuscation, endpoint resolution. +Non-tracing code that also lives here due to organic growth: + +- `datastreams/` — Data Streams Monitoring. Tracks message pipeline latency across Kafka, RabbitMQ, + SQS, etc. Core infrastructure shared across many instrumentations. +- `civisibility/` — CI Visibility trace interceptors and protocol adapters. Hooks into the trace + completion pipeline to filter and reformat test spans for the CI Test Cycle intake. +- `lambda/` — AWS Lambda support. Coordinates span creation with the serverless extension, + handling invocation start/end and trace context propagation. +- `llmobs/` — LLM Observability span mapper. Serializes LLM-specific spans (messages, tool calls) + to the dedicated LLM Obs intake format. + ### `dd-trace-api/` The public API. Contains types that application developers may interact with directly: From db33dfd252c51cc2f0583d8f53fda6929aaceb2e Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 15:27:45 +0100 Subject: [PATCH 03/15] feat(doc): Add 2nd round of comments --- ARCHITECTURE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index f00b9dd9f5e..be9dec1c48e 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -179,6 +179,11 @@ Key abstractions that instrumentations interact with: Instrumentations fire events (request started, response body received, etc.), and products (AppSec, IAST) subscribe to react. +TODO: Explain than similarly to dd-trace-core, it grows organically and nows contains other products and concerns than tracing +TODO: Like for example appsec, civisibility, datastreams, iast, llmobs +FIXME: Gateway is not strictly tracing but an abstraction for ASM/IAST products. +FIXME: InstrumentationContext is not part of internal-api. You should re-analyze internal-api to get a better understanding. + ### `communication/` HTTP transport to the Datadog Agent and intake APIs. Key type: `SharedCommunicationObjects`, From e20c825dcadeadca4e702369e6a742dba9491662 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 16:18:12 +0100 Subject: [PATCH 04/15] feat(doc): Add 3rd round of comments --- ARCHITECTURE.md | 71 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index be9dec1c48e..7ddd6f15c97 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -164,7 +164,9 @@ Also houses all configuration key constants organized by domain: `TracerConfig`, ### `internal-api/` Internal shared API used across all agent modules but not part of the public API. -Key abstractions that instrumentations interact with: +Similarly to `dd-trace-core`, this module grew organically and now hosts internal interfaces +for many products beyond tracing. New product APIs should consider `products/` or `components/` +instead. Core tracing abstractions: - `AgentTracer` — Static facade for the tracer. Instrumentations call `AgentTracer.startSpan()`, `AgentTracer.activateSpan()`, etc. @@ -172,17 +174,48 @@ Key abstractions that instrumentations interact with: - `AgentPropagation` — Context propagation interfaces (`Getter`, `Setter`) that instrumentations implement to inject/extract trace context from framework-specific carriers (HTTP headers, message properties, etc.). -- `InstrumentationContext` — Provides context stores for attaching data to instrumented objects - (e.g., storing a span on a request object). Works by dynamically adding fields via bytecode. -- `gateway/` — The Instrumentation Gateway: an event bus (`InstrumentationGateway`, `SubscriptionService`, - `Events`, `CallbackProvider`, `RequestContext`) that decouples instrumentations from product modules. - Instrumentations fire events (request started, response body received, etc.), - and products (AppSec, IAST) subscribe to react. - -TODO: Explain than similarly to dd-trace-core, it grows organically and nows contains other products and concerns than tracing -TODO: Like for example appsec, civisibility, datastreams, iast, llmobs -FIXME: Gateway is not strictly tracing but an abstraction for ASM/IAST products. -FIXME: InstrumentationContext is not part of internal-api. You should re-analyze internal-api to get a better understanding. +- `naming/` — Service and span operation naming schemas (v0, v1) for databases, messaging, + cloud services, etc. +- `Config` / `InstrumenterConfig` — Master configuration class and instrumenter-specific config, + centralizing settings for all products. + TODO: Add an explaination why we have `InstrumenterConfig` due to native-image build time + +Cross-product abstractions: + +- `gateway/` — The Instrumentation Gateway: an event bus (`InstrumentationGateway`, + `SubscriptionService`, `Events`, `CallbackProvider`, `RequestContext`) that decouples + instrumentations from product modules. Despite living in `internal-api`, this is primarily + an abstraction for AppSec and IAST to hook into the HTTP request lifecycle without modifying + instrumentations directly. +- `cache/` — Shared caching primitives (`DDCache`, `FixedSizeCache`, `RadixTreeCache`) used + throughout the agent. +- `telemetry/` — Multi-product telemetry collection interfaces (`MetricCollector`, + `WafMetricCollector`, `LLMObsMetricCollector`, etc.). + +Product-specific APIs that also live here: + +- `iast/` — IAST vulnerability detection interfaces: taint tracking (`Taintable`, `IastContext`), + sink definitions for each vulnerability type (SQL injection, XSS, command injection, etc.), + and call site instrumentation hooks. About 60 files. +- `civisibility/` — CI Visibility interfaces: test identification, code coverage, build/test + event handlers, and CI-specific telemetry metrics. About 95 files. +- `datastreams/` — Data Streams Monitoring interfaces: pathway context, stats points, + and schema registry integration. +- `appsec/` — AppSec interfaces: HTTP client request/response payloads for WAF analysis, + RASP call sites. +- `profiling/` — Profiler integration: recording data, timing, and enablement interfaces. +- `llmobs/` — LLM Observability context. + +### `components/` + +Low-level shared components: `context` (context propagation primitives), `environment` (JVM/OS detection), +`json` (lightweight JSON handling), `native-loader` (native library loading), `yaml`. + +### `products/` + +Additional product modules: `metrics/` (StatsD client and monitoring abstraction) and +`feature-flagging/` (server-side feature flag evaluation via remote config). + ### `communication/` @@ -203,29 +236,23 @@ Agent telemetry. `TelemetrySystem` collects and reports which features are enabl which integrations loaded, performance metrics, and product-specific counters. Each product registers periodic actions that collect domain-specific metrics. -### `components/` - -Low-level shared components: `context` (context propagation primitives), `environment` (JVM/OS detection), -`json` (lightweight JSON handling), `native-loader` (native library loading), `yaml`. - ### `utils/` +TODO: Describe what each utils module could be useful for Shared utilities: `config-utils`, `container-utils`, `filesystem-utils`, `flare-utils`, `queue-utils`, `socket-utils`, `time-utils`, `version-utils`, `test-utils`. -### `products/` - -Additional product modules: `metrics/` (StatsD client and monitoring abstraction) and -`feature-flagging/` (server-side feature flag evaluation via remote config). - ### `dd-trace-ot/` +TODO: Explain this is a legacy module. It's goal is to provide an OpenTracing implementation artefact. +TODO: The tracer will be the datadog one but there won't be any auto instrumentation. OpenTracing compatibility layer. Wraps the Datadog tracer behind the OpenTracing API. ### `dd-smoke-tests/` End-to-end smoke tests. Each test boots a real application with the agent jar attached and verifies traces, spans, and product behavior. Covers Spring Boot, Play, Vert.x, Quarkus, WildFly, and more. +TODO: Add details about the few core classes to write a smoke tests (test class hierarchy and reuse) ## Instrumentation Pattern From 11ac8a7493c4598ab519eac347228243fef46c61 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 16:28:13 +0100 Subject: [PATCH 05/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 7ddd6f15c97..176f3d8a9ce 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -177,8 +177,12 @@ instead. Core tracing abstractions: - `naming/` — Service and span operation naming schemas (v0, v1) for databases, messaging, cloud services, etc. - `Config` / `InstrumenterConfig` — Master configuration class and instrumenter-specific config, - centralizing settings for all products. - TODO: Add an explaination why we have `InstrumenterConfig` due to native-image build time + centralizing settings for all products. `InstrumenterConfig` is separated from `Config` due to + GraalVM native-image constraints: in native-image builds, all bytecode instrumentation must be + applied at build time (ahead-of-time compilation), so configuration that controls instrumentation + decisions (which classes to instrument, which integrations to enable, resolver behavior, field + injection flags) must be frozen into the native image binary. Runtime-only settings (agent + endpoints, service names, sampling rates) remain in `Config`. Cross-product abstractions: @@ -238,15 +242,31 @@ Each product registers periodic actions that collect domain-specific metrics. ### `utils/` -TODO: Describe what each utils module could be useful for -Shared utilities: `config-utils`, `container-utils`, `filesystem-utils`, `flare-utils`, -`queue-utils`, `socket-utils`, `time-utils`, `version-utils`, `test-utils`. +Shared utilities, each in its own submodule: + +- `config-utils` — `ConfigProvider` for reading and merging configuration from environment variables, + system properties, properties files, and CI environment. +- `container-utils` — Parses container runtime information (Docker, Kubernetes, ECS). +- `filesystem-utils` — Permission-safe file existence checks that handle `SecurityException`. +- `flare-utils` — Tracer flare collection (`TracerFlareService`) that gathers diagnostics + (logs, spans, system info) and sends them to Datadog for troubleshooting. +- `queue-utils` — High-performance lock-free queues (`MpscArrayQueue`, `SpscArrayQueue`) for + inter-thread communication and span buffering. +- `socket-utils` — Socket factories (`UnixDomainSocketFactory`, `NamedPipeSocket`) for connecting + to the local Datadog Agent via Unix sockets or named pipes. +- `time-utils` — Time source abstractions (`TimeSource`, `ControllableTimeSource`) for testable + time handling and delay parsing. +- `version-utils` — Agent version string (`VersionInfo.VERSION`) read from packaged resources. +- `test-utils` — Testing utilities: `@Flaky` annotation, log capture, GC control, + forked test configuration. +- `test-agent-utils` — Message decoders for parsing v04/v05 binary protocol frames in tests. ### `dd-trace-ot/` -TODO: Explain this is a legacy module. It's goal is to provide an OpenTracing implementation artefact. -TODO: The tracer will be the datadog one but there won't be any auto instrumentation. -OpenTracing compatibility layer. Wraps the Datadog tracer behind the OpenTracing API. +Legacy OpenTracing compatibility library. Publishes a standalone JAR artifact (`dd-trace-ot.jar`) +that implements the `io.opentracing.Tracer` interface by wrapping the Datadog `CoreTracer`. +This is a pure library for manual instrumentation only — there is no auto-instrumentation or +bytecode advice. ### `dd-smoke-tests/` From 9442a304346524dde0a306525aa2837d67d0c934 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:18:40 +0100 Subject: [PATCH 06/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 176f3d8a9ce..021050c98f2 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -272,7 +272,17 @@ bytecode advice. End-to-end smoke tests. Each test boots a real application with the agent jar attached and verifies traces, spans, and product behavior. Covers Spring Boot, Play, Vert.x, Quarkus, WildFly, and more. -TODO: Add details about the few core classes to write a smoke tests (test class hierarchy and reuse) +The core test hierarchy (Groovy/Spock) is: +- `ProcessManager` — Base class. Manages forked JVM processes: spawns the application with the agent + jar via `ProcessBuilder`, captures stdout to log files, and tears down processes on cleanup. + Provides `assertNoErrorLogs()` to scan logs for errors. +- `AbstractSmokeTest` extends `ProcessManager` — Adds a mock Datadog Agent (`TestHttpServer`) that + receives traces (v0.4/v0.5), telemetry, remote config, and EVP proxy requests. Provides polling + helpers (`waitForTraceCount`, `waitForSpan`, `waitForTelemetryFlat`) and decoded trace/telemetry + storage. +- `AbstractServerSmokeTest` extends `AbstractSmokeTest` — For HTTP server applications. Adds HTTP + port management, waits for the server port to open, and verifies expected trace output from a + structured log file. ## Instrumentation Pattern @@ -295,20 +305,6 @@ Every instrumentation follows the same pattern: Instrumentations are discovered via `@AutoService(InstrumenterModule.class)` (Java SPI). -## The Instrumentation Gateway - -The gateway (`InstrumentationGateway`) is the central integration point between instrumentations -and product modules. It implements a publish-subscribe pattern: - -- **Instrumentations** (e.g., Servlet, Spring) fire events like "request started", "request header received", - "response body committed" through the gateway. -- **Product modules** (AppSec, IAST) subscribe to these events via `SubscriptionService` and react - (e.g., run WAF checks, track tainted data). -- `RequestContext` carries per-request state across products using `RequestContextSlot` - for type-safe storage. - -This design allows adding new products without modifying existing instrumentations. - ## Writer Pipeline When a trace completes, it flows through: From 733ef91927e0ef0a5c3ceaf66dade50c1d524fee Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:19:49 +0100 Subject: [PATCH 07/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 021050c98f2..265e4a003db 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -286,6 +286,9 @@ The core test hierarchy (Groovy/Spock) is: ## Instrumentation Pattern +TODO: This whole block should go under dd-java-agent/instrumentation. +TODO: Make it way smaller to keep few keywords and redirect to the two markdown document about how to write instrumentations + Every instrumentation follows the same pattern: 1. An **`InstrumenterModule`** subclass declares which product it serves (Tracing, AppSec, etc.), From 2a1ce8e5445d6ea91d9fe37714d90ae2fdd73674 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:24:44 +0100 Subject: [PATCH 08/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 265e4a003db..55d3f4b2767 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -84,8 +84,12 @@ unintended loading. See `docs/how_to_work_with_gradle.md` for build details. See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md` for details. - **`instrumentation/`** — All auto-instrumentations, organized as `{framework}/{framework}-{minVersion}/`. - About 186 framework directories. Each contains an `InstrumenterModule` subclass, one or more `Instrumenter` - implementations, advice classes, decorators, and helpers. See `docs/how_instrumentations_work.md` for details. + Nearly 200 framework directories. Each follows the same pattern: an `InstrumenterModule` declares the + target system and integration name, one or more `Instrumenter` implementations select target types + via matchers, advice classes inject bytecode via `@Advice.OnMethodEnter`/`@Advice.OnMethodExit`, + and decorator/helper classes contain the actual product logic. Instrumentations are discovered + via `@AutoService(InstrumenterModule.class)` (Java SPI) and validated by Muzzle at build time. + See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md` for details. - **`appsec/`** — Application Security. Entry point: `AppSecSystem.start()`. Integrates the Datadog WAF (Web Application Firewall) to detect and block attacks in real-time. @@ -174,8 +178,6 @@ instead. Core tracing abstractions: - `AgentPropagation` — Context propagation interfaces (`Getter`, `Setter`) that instrumentations implement to inject/extract trace context from framework-specific carriers (HTTP headers, message properties, etc.). -- `naming/` — Service and span operation naming schemas (v0, v1) for databases, messaging, - cloud services, etc. - `Config` / `InstrumenterConfig` — Master configuration class and instrumenter-specific config, centralizing settings for all products. `InstrumenterConfig` is separated from `Config` due to GraalVM native-image constraints: in native-image builds, all bytecode instrumentation must be @@ -193,6 +195,8 @@ Cross-product abstractions: instrumentations directly. - `cache/` — Shared caching primitives (`DDCache`, `FixedSizeCache`, `RadixTreeCache`) used throughout the agent. +- `naming/` — Service and span operation naming schemas (v0, v1) for databases, messaging, + cloud services, etc. - `telemetry/` — Multi-product telemetry collection interfaces (`MetricCollector`, `WafMetricCollector`, `LLMObsMetricCollector`, etc.). @@ -212,11 +216,17 @@ Product-specific APIs that also live here: ### `components/` +TODO: Those are low-level shared platform components. They are not tied to a product, don't bundle dependencies, and are safe to use in bootstrap. +TODO: Add a quick description for each component and feature they provide + Low-level shared components: `context` (context propagation primitives), `environment` (JVM/OS detection), `json` (lightweight JSON handling), `native-loader` (native library loading), `yaml`. ### `products/` +TODO: Give a quick explaintation of the product module design with api, lib, bootstrap, folders. +TODO: Add a quick description for each product. + Additional product modules: `metrics/` (StatsD client and monitoring abstraction) and `feature-flagging/` (server-side feature flag evaluation via remote config). @@ -284,30 +294,6 @@ The core test hierarchy (Groovy/Spock) is: port management, waits for the server port to open, and verifies expected trace output from a structured log file. -## Instrumentation Pattern - -TODO: This whole block should go under dd-java-agent/instrumentation. -TODO: Make it way smaller to keep few keywords and redirect to the two markdown document about how to write instrumentations - -Every instrumentation follows the same pattern: - -1. An **`InstrumenterModule`** subclass declares which product it serves (Tracing, AppSec, etc.), - its integration name, helper classes, and context stores. - -2. One or more **`Instrumenter`** implementations select target types via matchers - (`ForSingleType`, `ForKnownTypes`, `ForTypeHierarchy`) and register method advice. - -3. **Advice classes** use ByteBuddy's `@Advice.OnMethodEnter` / `@Advice.OnMethodExit` to inject - bytecode before/after matched methods. Advice code runs in the application's classloader context. - -4. **Decorator/helper classes** contain the actual tracing logic (start span, set tags, finish span). - These are injected into the application classloader at runtime. - -5. **Muzzle** validates at build time (and runtime) that the instrumented library's API matches - what the instrumentation expects, preventing `NoSuchMethodError` at runtime. - -Instrumentations are discovered via `@AutoService(InstrumenterModule.class)` (Java SPI). - ## Writer Pipeline When a trace completes, it flows through: From dea44da49f429d6b59f3af7c322738e04610e0eb Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:35:47 +0100 Subject: [PATCH 09/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 55d3f4b2767..a53fe426b5c 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -216,20 +216,37 @@ Product-specific APIs that also live here: ### `components/` -TODO: Those are low-level shared platform components. They are not tied to a product, don't bundle dependencies, and are safe to use in bootstrap. -TODO: Add a quick description for each component and feature they provide - -Low-level shared components: `context` (context propagation primitives), `environment` (JVM/OS detection), -`json` (lightweight JSON handling), `native-loader` (native library loading), `yaml`. +Low-level shared platform components. They are not tied to any product, don't bundle external +dependencies, and are safe to use from the bootstrap classloader: + +- `context` — Immutable context propagation framework. Provides `Context`, `ContextKey`, + and `Propagator` abstractions for storing and propagating key-value pairs across threads + and carrier objects. +- `environment` — JVM and OS detection utilities. `JavaVersion` for version parsing, + `JavaVirtualMachine` for JVM implementation detection (OpenJDK, Graal, J9), + `OperatingSystem` for OS/architecture detection, and `EnvironmentVariables`/`SystemProperties` + for safe access and mocking. +- `json` — Lightweight, dependency-free JSON serialization. `JsonWriter` for building JSON + with a fluent API, `JsonReader` for streaming parsing. +- `native-loader` — Platform-aware native library loading with pluggable strategies. + `NativeLoader` handles OS/architecture detection, resource extraction from JARs, + and temp file management. ### `products/` -TODO: Give a quick explaintation of the product module design with api, lib, bootstrap, folders. -TODO: Add a quick description for each product. +Self-contained product modules following a layered submodule pattern: +- `{product}-api/` — Public API interfaces, zero dependencies. +- `{product}-bootstrap/` — Data classes safe for the bootstrap classloader. +- `{product}-lib/` — Core implementation (shadow jar, excludes shared dependencies). +- `{product}-agent/` — Agent integration entry point (shadow jar). -Additional product modules: `metrics/` (StatsD client and monitoring abstraction) and -`feature-flagging/` (server-side feature flag evaluation via remote config). +Current products: +- `metrics/` — StatsD client and monitoring abstraction. Provides `Monitoring` interface with + counters, timers, and histograms for internal agent metrics collection. +- `feature-flagging/` — Server-side feature flag evaluation driven by remote configuration. + Implements the OpenFeature SDK, handles the Unified Feature Control (UFC) protocol, + and tracks flag exposure per user/session. ### `communication/` From 7f69250d3a8c57d387c675256a2483b80b27fefd Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:38:32 +0100 Subject: [PATCH 10/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 56 ------------------------------------------------- 1 file changed, 56 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index a53fe426b5c..b68779cea63 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -310,59 +310,3 @@ The core test hierarchy (Groovy/Spock) is: - `AbstractServerSmokeTest` extends `AbstractSmokeTest` — For HTTP server applications. Adds HTTP port management, waits for the server port to open, and verifies expected trace output from a structured log file. - -## Writer Pipeline - -When a trace completes, it flows through: - -1. `PendingTrace` collects all spans until the root span finishes. -2. `CoreTracer.write()` sends the trace to the `Writer`. -3. `DDAgentWriter` (the default writer) enqueues the trace in `TraceProcessingWorker`. -4. The worker serializes traces to MessagePack via `PayloadDispatcherImpl`. -5. The dispatcher sends batched payloads to the Datadog Agent's trace intake endpoint. -6. Sampling responses from the Agent are fed back to update sampling rates. - -## Architectural Invariants - -- **Bootstrap classloader isolation**: The agent jar is a shadow jar with all dependencies relocated - (shaded) under `datadog.` prefixes. This prevents classpath conflicts with application dependencies. - The agent classloader is separate from the application classloader. - -- **No premain side effects**: Code running during `premain` must not use `java.util.logging`, - `java.nio`, or `javax.management`. These trigger JVM initialization that can break applications - that configure these subsystems after `main`. See `docs/bootstrap_design_guidelines.md`. - -- **Advice is bytecode, not code**: Advice classes are templates whose bytecode gets copied into - target methods. They cannot reference methods on their own class or the instrumentation class. - They can only use bootstrap classpath types or injected helpers. - -- **Context stores are not maps**: `InstrumentationContext.get()` attaches data to objects by adding - fields via bytecode. The same object instance (identity, not equality) must be used for put and get. - -- **Instrumentations must be safe to skip**: Muzzle ensures any instrumentation can be silently - disabled if the target library version is incompatible. No instrumentation should cause the agent - to crash or the application to break. - -- **Product independence**: Each product (AppSec, IAST, Profiling, etc.) can be enabled/disabled - independently. Products communicate through the gateway, not direct dependencies. - -## Cross-Cutting Concerns - -- **Configuration**: The `Config` singleton reads from system properties, environment variables, - remote configuration, and config files. Keys are defined as constants in `dd-trace-api` - (e.g., `TracerConfig`, `GeneralConfig`). Configuration is immutable after startup, - except for values updated via remote configuration. - -- **Logging**: Uses a shaded SLF4J that redirects to an internal logger. Never use `java.util.logging` - in agent code. In advice classes, move logging to helper classes. - -- **Formatting**: google-java-format enforced via Spotless (`./gradlew spotlessApply`). - -- **Testing**: Unit tests use JUnit 5 or Spock 2. Instrumentation tests extend - `InstrumentationSpecification`. HTTP server integrations share base test classes - that enforce consistency. Smoke tests use the real agent jar against real applications. - Flaky tests are annotated with `@Flaky` and skipped in CI by default. - -- **Build**: Gradle with Kotlin DSL. The agent jar is built via `shadowJar` which relocates all - dependencies. Instrumentations declare framework dependencies as `compileOnly` so they don't leak - into the agent jar. Muzzle runs at build time to validate version compatibility. From be339a7c93964c113a852dd734af8d000d8491d9 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:44:27 +0100 Subject: [PATCH 11/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 205 ++++++++++++++++++++++-------------------------- 1 file changed, 93 insertions(+), 112 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index b68779cea63..4007ab5eb14 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,87 +1,77 @@ # Architecture of dd-trace-java -This document describes the high-level architecture of the Datadog Java APM agent. -If you want to familiarize yourself with the codebase, this is a good place to start. +High-level architecture of the Datadog Java APM agent. +Start here to orient yourself in the codebase. ## Bird's Eye View dd-trace-java is a Java agent that auto-instruments JVM applications at runtime via bytecode manipulation. It attaches to a running JVM using the `-javaagent` flag, intercepts class loading, and rewrites method bytecode -to inject tracing, security, profiling, and observability logic - all without requiring application code changes. +to inject tracing, security, profiling, and observability logic. No application code changes required. -The agent ships roughly 120 integrations (about 200 instrumentations) covering popular frameworks -(Spring, Servlet, gRPC, JDBC, Kafka, etc.) and supports multiple Datadog products through a single agent jar: +Ships ~120 integrations (~200 instrumentations) covering major frameworks +(Spring, Servlet, gRPC, JDBC, Kafka, etc.) and supports multiple Datadog products through a single jar: **Tracing**, **Profiling**, **Application Security (AppSec)**, **IAST**, **CI Visibility**, **Dynamic Instrumentation**, **LLM Observability**, **Crash Tracking**, **Data Streams**, **Feature Flagging**, and **USM**. -The agent communicates with a local Datadog Agent process (or directly with the Datadog intake APIs) +Communicates with a local Datadog Agent process (or directly with the Datadog intake APIs) to send collected telemetry. ## Startup Sequence -Understanding the startup sequence is key to understanding the project: +1. **`AgentBootstrap.premain()`** — JVM entry point. Runs on the application classloader + with minimal logic: locates the agent jar, creates an isolated classloader, jumps to `Agent.start()`. + Must remain tiny and side-effect-free. -1. **`AgentBootstrap.premain()`** — The JVM calls this entry point. It runs on the application classloader - with minimal logic: it locates the agent jar, creates an isolated classloader, and jumps to `Agent.start()`. - This class must remain tiny and side-effect-free. - -2. **`Agent.start()`** — Running on the bootstrap classloader, this method orchestrates everything: - creates the agent classloader, reads configuration, determines which products are enabled - (tracing, AppSec, IAST, profiling, etc.), and starts each subsystem on dedicated threads. +2. **`Agent.start()`** — Runs on the bootstrap classloader. Creates the agent classloader, + reads configuration, determines which products are enabled, starts each subsystem on dedicated threads. 3. **`AgentInstaller`** — Installs the ByteBuddy `ClassFileTransformer` that intercepts all class loading. - It discovers all `InstrumenterModule` implementations via service loading and registers their - type matchers and advice classes with ByteBuddy. + Discovers all `InstrumenterModule` implementations via service loading, registers their + type matchers and advice classes. -4. **Product subsystems start** — Each enabled product (AppSec, IAST, CI Visibility, Profiling, Debugger, etc.) - is started via its own `*System.start()` method, receiving shared communication objects. +4. **Product subsystems start** — Each enabled product is started via its own `*System.start()` method, + receiving shared communication objects. ## Codemap ### `dd-java-agent/` -The main agent module. Its build produces the final shadow jar (`dd-java-agent.jar`) using a -composite shadow jar strategy. Each product module (instrumentation, profiling, AppSec, IAST, -debugger, CI Visibility, LLM Obs, etc.) builds its own shadow jar, which is then embedded as a -nested directory inside the main jar (`inst/`, `profiling/`, `appsec/`, `iast/`, `debugger/`, -`ci-visibility/`, `llm-obs/`, `shared/`, `trace/`, etc.). A dedicated `sharedShadowJar` bundles -common transitive dependencies (OkHttp, JCTools, LZ4, etc.) so they are not duplicated across -feature jars. All dependencies are relocated under `datadog.` prefixes to prevent classpath conflicts -with application libraries. Class files inside feature jars are renamed to `.classdata` to prevent -unintended loading. See `docs/how_to_work_with_gradle.md` for build details. - -- **`src/`** — Contains `AgentBootstrap` and `AgentJar`, the true entry point loaded by the JVM's - `-javaagent` mechanism. Deliberately minimal. - -- **`agent-bootstrap/`** — Classes loaded on the bootstrap classloader. Contains `Agent` (the real startup - orchestrator), decorator base classes (`HttpServerDecorator`, `DatabaseClientDecorator`, etc.), - and bootstrap-safe utilities. Because these classes are on the bootstrap classloader, they are - visible to all classloaders and can be injected into and used by instrumentation advice and helpers - at runtime. +Main agent module. Produces the final shadow jar (`dd-java-agent.jar`) using a composite shadow jar +strategy. Each product module builds its own shadow jar, embedded as a nested directory inside the +main jar (`inst/`, `profiling/`, `appsec/`, `iast/`, `debugger/`, `ci-visibility/`, `llm-obs/`, +`shared/`, `trace/`, etc.). A dedicated `sharedShadowJar` bundles common transitive dependencies +(OkHttp, JCTools, LZ4, etc.) to avoid duplication across feature jars. All dependencies are relocated +under `datadog.` prefixes to prevent classpath conflicts. Class files inside feature jars are renamed +to `.classdata` to prevent unintended loading. See `docs/how_to_work_with_gradle.md`. + +- **`src/`** — `AgentBootstrap` and `AgentJar`, the entry point loaded by `-javaagent`. + Deliberately minimal. + +- **`agent-bootstrap/`** — Classes on the bootstrap classloader: `Agent` (startup orchestrator), + decorator base classes (`HttpServerDecorator`, `DatabaseClientDecorator`, etc.), and bootstrap-safe + utilities. Visible to all classloaders, so instrumentation advice and helpers can use them directly. See `docs/boostrap_design_guidelines.md` -- **`agent-builder/`** — ByteBuddy integration layer. Contains the class transformer pipeline: - `DDClassFileTransformer` intercepts every class being loaded, `GlobalIgnoresMatcher` applies - early filtering, `CombiningMatcher` evaluates all instrumentation matchers, and - `SplittingTransformer` applies the matched transformations. The `ignored_class_name.trie` is - a compiled trie built at build time that acts as the first and most efficient filter in this - pipeline — it short-circuits expensive matcher evaluation for known non-transformable classes - (JVM internals, agent infrastructure, monitoring libraries, large framework packages). - When a class is unexpectedly not instrumented, the trie is the first place to check: it may - be matched by a system-level ignore or an optimization ignore pattern. - -- **`agent-tooling/`** — The instrumentation framework. Key types: - - `InstrumenterModule` — Base class for all instrumentation modules. Each declares a target system +- **`agent-builder/`** — ByteBuddy integration layer. Class transformer pipeline: + `DDClassFileTransformer` intercepts every class load, `GlobalIgnoresMatcher` applies early + filtering, `CombiningMatcher` evaluates instrumentation matchers, `SplittingTransformer` + applies matched transformations. The `ignored_class_name.trie` is a compiled trie built at + build time that short-circuits matcher evaluation for known non-transformable classes (JVM + internals, agent infrastructure, monitoring libraries, large framework packages). When a class + is unexpectedly not instrumented, check the trie first. + +- **`agent-tooling/`** — Instrumentation framework. Key types: + - `InstrumenterModule` — Base class for all instrumentation modules. Declares a target system (Tracing, AppSec, IAST, Profiling, CiVisibility, USM, etc.) and one or more instrumentations. - - `Instrumenter` — Interface with variants for type matching: `ForSingleType`, `ForKnownTypes`, + - `Instrumenter` — Type matching interface: `ForSingleType`, `ForKnownTypes`, `ForTypeHierarchy`, `ForBootstrap`. - - `muzzle/` — Build-time and runtime safety checks. Verifies that the types and methods an - instrumentation expects actually exist in the library version present at runtime. - If they don't, the instrumentation is silently skipped. + - `muzzle/` — Build-time and runtime safety checks. Verifies that expected types and methods + exist in the library version at runtime. If not, the instrumentation is silently skipped. - See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md` for details. + See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md`. - **`instrumentation/`** — All auto-instrumentations, organized as `{framework}/{framework}-{minVersion}/`. Nearly 200 framework directories. Each follows the same pattern: an `InstrumenterModule` declares the @@ -91,9 +81,8 @@ unintended loading. See `docs/how_to_work_with_gradle.md` for build details. via `@AutoService(InstrumenterModule.class)` (Java SPI) and validated by Muzzle at build time. See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md` for details. -- **`appsec/`** — Application Security. Entry point: `AppSecSystem.start()`. Integrates the Datadog WAF - (Web Application Firewall) to detect and block attacks in real-time. - Hooks into the gateway event system to intercept HTTP requests. +- **`appsec/`** — Application Security. Entry point: `AppSecSystem.start()`. Runs the Datadog WAF + to detect and block attacks in real-time. Hooks into the gateway to intercept HTTP requests. - **`agent-iast/`** — Interactive Application Security Testing. Entry point: `IastSystem.start()`. Performs taint tracking: marks user input as tainted, propagates taint through string operations, @@ -108,40 +97,36 @@ unintended loading. See `docs/how_to_work_with_gradle.md` for build details. Uploads profiles to the Datadog backend. - **`agent-debugger/`** — Dynamic Instrumentation. Entry point: `DebuggerAgent`. - Enables live debugging (set breakpoints, capture snapshots), exception replay, code origin mapping, - and distributed debugging — all without restarting the JVM. Driven by remote configuration. + Live breakpoints, snapshot capture, exception replay, code origin mapping. + Driven by remote configuration. - **`agent-llmobs/`** — LLM Observability. Entry point: `LLMObsSystem.start()`. - Monitors LLM API calls (OpenAI, LangChain, etc.), tracking token usage, model inference, and evaluations. + Monitors LLM API calls (OpenAI, LangChain, etc.): token usage, model inference, evaluations. - **`agent-crashtracking/`** — Crash Tracking. Detects JVM crashes and fatal exceptions, collects system metadata, and uploads crash reports to Datadog's error tracking intake. -- **`agent-otel/`** — OpenTelemetry compatibility shim. Provides `OtelTracerProvider`, `OtelSpan`, - `OtelContext`, and other wrapper classes that implement the OTel API by delegating to the Datadog - tracer. Works in tandem with the OpenTelemetry instrumentations in `instrumentation/opentelemetry/`, - which use ByteBuddy advice to intercept OTel API calls (e.g., `OpenTelemetry.getTracerProvider()`) - and redirect them to the shim instances. This allows applications and libraries using the OTel API - to have their spans captured by the Datadog agent transparently. +- **`agent-otel/`** — OpenTelemetry compatibility shim. `OtelTracerProvider`, `OtelSpan`, + `OtelContext` and other wrappers implement the OTel API by delegating to the Datadog tracer. + Paired with instrumentations in `instrumentation/opentelemetry/` that intercept OTel API calls + and redirect them to shim instances. ### `dd-trace-core/` -Originally the core tracing engine, this module grew organically and now also hosts several -product-specific features that depend on tight integration with span creation, interception, -or serialization. New module code should prefer `products/` or `components/` over adding to -this module. Core tracing types: +Core tracing engine. Grew organically and now also hosts product-specific features that depend on +tight integration with span creation, interception, or serialization. New code should go in +`products/` or `components/` instead. Core tracing types: -- `CoreTracer` — The tracer implementation. Creates spans, manages sampling, drives the writer pipeline. +- `CoreTracer` — Tracer implementation. Creates spans, manages sampling, drives the writer pipeline. Implements `AgentTracer.TracerAPI`. - `DDSpan` / `DDSpanContext` — Concrete span and context implementations with Datadog-specific metadata. -- `PendingTrace` — Tracks all spans belonging to a single trace. When all spans finish, flushes the trace - to the writer. -- `scopemanager/` — `ContinuableScopeManager`, `ContinuableScope`, `ScopeContinuation`. Manages the - active span on each thread and supports async context propagation via continuations. +- `PendingTrace` — Collects all spans in a trace. Flushes to the writer when the root span finishes. +- `scopemanager/` — `ContinuableScopeManager`, `ContinuableScope`, `ScopeContinuation`. Active span + per thread, async context propagation via continuations. - `propagation/` — Trace context propagation codecs: Datadog, W3C TraceContext, B3, Haystack, X-Ray. -- `common/writer/` — The writer pipeline. `DDAgentWriter` buffers traces and dispatches them via - `PayloadDispatcherImpl` to the Datadog Agent's `/v0.4/traces` endpoint. Also: `DDIntakeWriter` for - direct API submission, and `TraceProcessingWorker` for async trace processing. +- `common/writer/` — Writer pipeline. `DDAgentWriter` buffers traces and dispatches via + `PayloadDispatcherImpl` to the Datadog Agent's `/v0.4/traces` endpoint. `DDIntakeWriter` for + direct API submission. `TraceProcessingWorker` for async processing. - `common/sampling/` — Sampling logic: `RuleBasedTraceSampler`, `RateByServiceTraceSampler`, `SingleSpanSampler`. Supports both head-based and rule-based sampling. - `tagprocessor/` — Post-processing of span tags: peer service calculation, base service naming, @@ -149,8 +134,7 @@ this module. Core tracing types: Non-tracing code that also lives here due to organic growth: -- `datastreams/` — Data Streams Monitoring. Tracks message pipeline latency across Kafka, RabbitMQ, - SQS, etc. Core infrastructure shared across many instrumentations. +- `datastreams/` — Data Streams Monitoring. Tracks message pipeline latency across Kafka, RabbitMQ, SQS, etc. - `civisibility/` — CI Visibility trace interceptors and protocol adapters. Hooks into the trace completion pipeline to filter and reformat test spans for the CI Test Cycle intake. - `lambda/` — AWS Lambda support. Coordinates span creation with the serverless extension, @@ -160,19 +144,20 @@ Non-tracing code that also lives here due to organic growth: ### `dd-trace-api/` -The public API. Contains types that application developers may interact with directly: -`Tracer`, `GlobalTracer`, `DDTags`, `DDSpanTypes`, `Trace` (annotation), `ConfigDefaults`. -Also houses all configuration key constants organized by domain: `TracerConfig`, `GeneralConfig`, -`AppSecConfig`, `ProfilingConfig`, `CiVisibilityConfig`, `IastConfig`, `DebuggerConfig`, etc. +Public API. Types application developers may use directly: `Tracer`, `GlobalTracer`, `DDTags`, +`DDSpanTypes`, `Trace` (annotation), `ConfigDefaults`. Also houses all configuration key constants +by domain: `TracerConfig`, `GeneralConfig`, `AppSecConfig`, `ProfilingConfig`, `CiVisibilityConfig`, +`IastConfig`, `DebuggerConfig`, etc. ### `internal-api/` -Internal shared API used across all agent modules but not part of the public API. -Similarly to `dd-trace-core`, this module grew organically and now hosts internal interfaces -for many products beyond tracing. New product APIs should consider `products/` or `components/` -instead. Core tracing abstractions: +Internal shared API across all agent modules (not public). Like `dd-trace-core`, grew organically +and now hosts interfaces for many products beyond tracing. New product APIs should go in +`products/` or `components/`. + +Core tracing abstractions: -- `AgentTracer` — Static facade for the tracer. Instrumentations call `AgentTracer.startSpan()`, +- `AgentTracer` — Static tracer facade. Instrumentations call `AgentTracer.startSpan()`, `AgentTracer.activateSpan()`, etc. - `AgentSpan` / `AgentScope` / `AgentSpanContext` — Internal span/scope/context interfaces. - `AgentPropagation` — Context propagation interfaces (`Getter`, `Setter`) that instrumentations @@ -188,11 +173,10 @@ instead. Core tracing abstractions: Cross-product abstractions: -- `gateway/` — The Instrumentation Gateway: an event bus (`InstrumentationGateway`, - `SubscriptionService`, `Events`, `CallbackProvider`, `RequestContext`) that decouples - instrumentations from product modules. Despite living in `internal-api`, this is primarily - an abstraction for AppSec and IAST to hook into the HTTP request lifecycle without modifying - instrumentations directly. +- `gateway/` — Instrumentation Gateway: event bus (`InstrumentationGateway`, + `SubscriptionService`, `Events`, `CallbackProvider`, `RequestContext`) decoupling + instrumentations from product modules. Primarily used by AppSec and IAST to hook into + the HTTP request lifecycle without modifying instrumentations. - `cache/` — Shared caching primitives (`DDCache`, `FixedSizeCache`, `RadixTreeCache`) used throughout the agent. - `naming/` — Service and span operation naming schemas (v0, v1) for databases, messaging, @@ -216,8 +200,8 @@ Product-specific APIs that also live here: ### `components/` -Low-level shared platform components. They are not tied to any product, don't bundle external -dependencies, and are safe to use from the bootstrap classloader: +Low-level shared platform components. Not tied to any product, no external dependencies, +bootstrap-safe: - `context` — Immutable context propagation framework. Provides `Context`, `ContextKey`, and `Propagator` abstractions for storing and propagating key-value pairs across threads @@ -235,6 +219,7 @@ dependencies, and are safe to use from the bootstrap classloader: ### `products/` Self-contained product modules following a layered submodule pattern: + - `{product}-api/` — Public API interfaces, zero dependencies. - `{product}-bootstrap/` — Data classes safe for the bootstrap classloader. - `{product}-lib/` — Core implementation (shadow jar, excludes shared dependencies). @@ -250,10 +235,9 @@ Current products: ### `communication/` -HTTP transport to the Datadog Agent and intake APIs. Key type: `SharedCommunicationObjects`, -which holds shared `OkHttpClient` instances (with Unix domain socket and named pipe support), -agent URL, feature discovery, and the configuration poller. All product modules receive this -at startup. +HTTP transport to the Datadog Agent and intake APIs. `SharedCommunicationObjects` holds shared +`OkHttpClient` instances (Unix domain socket and named pipe support), agent URL, feature discovery, +and the configuration poller. All product modules receive this at startup. ### `remote-config/` @@ -297,16 +281,13 @@ bytecode advice. ### `dd-smoke-tests/` -End-to-end smoke tests. Each test boots a real application with the agent jar attached and verifies -traces, spans, and product behavior. Covers Spring Boot, Play, Vert.x, Quarkus, WildFly, and more. -The core test hierarchy (Groovy/Spock) is: -- `ProcessManager` — Base class. Manages forked JVM processes: spawns the application with the agent - jar via `ProcessBuilder`, captures stdout to log files, and tears down processes on cleanup. - Provides `assertNoErrorLogs()` to scan logs for errors. -- `AbstractSmokeTest` extends `ProcessManager` — Adds a mock Datadog Agent (`TestHttpServer`) that - receives traces (v0.4/v0.5), telemetry, remote config, and EVP proxy requests. Provides polling - helpers (`waitForTraceCount`, `waitForSpan`, `waitForTelemetryFlat`) and decoded trace/telemetry - storage. -- `AbstractServerSmokeTest` extends `AbstractSmokeTest` — For HTTP server applications. Adds HTTP - port management, waits for the server port to open, and verifies expected trace output from a - structured log file. +End-to-end smoke tests. Each boots a real application with the agent jar and verifies traces, spans, +and product behavior. Covers Spring Boot, Play, Vert.x, Quarkus, WildFly, and more. +Core test hierarchy (Groovy/Spock): +- `ProcessManager` — Base. Spawns forked JVM processes with the agent via `ProcessBuilder`, + captures stdout to log files, tears down on cleanup. `assertNoErrorLogs()` scans logs for errors. +- `AbstractSmokeTest` extends `ProcessManager` — Adds a mock Datadog Agent (`TestHttpServer`) + receiving traces (v0.4/v0.5), telemetry, remote config, and EVP proxy requests. Polling helpers: + `waitForTraceCount`, `waitForSpan`, `waitForTelemetryFlat`. +- `AbstractServerSmokeTest` extends `AbstractSmokeTest` — For HTTP server apps. Adds port + management, waits for server port to open, verifies expected trace output. From 92c79b36fef64f3c0468766fa10165e2f44dd053 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:50:24 +0100 Subject: [PATCH 12/15] feat(doc): Update agents.md to refer to the architecture file --- AGENTS.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fe7de8531d0..ef91103f717 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,26 +7,20 @@ It ships ~120 integrations (~200 instrumentations) for tracing, profiling, AppSe ## Project layout +See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed module descriptions. + ``` -dd-java-agent/ Main agent - instrumentation/ All auto-instrumentations (one dir per framework) - agent-bootstrap/ Bootstrap classloader classes - agent-builder/ Agent build & bytecode weaving - agent-tooling/ Shared tooling for instrumentations - agent-{product}/ Product-specific modules (ci-visibility, iast, profiling, debugger, llmobs, aiguard, ...) - appsec/ Application Security (WAF, threat detection) +dd-java-agent/ Main agent (shadow jar, instrumentations, product modules) dd-trace-api/ Public API & configuration constants dd-trace-core/ Core tracing engine (spans, propagation, writer) -dd-trace-ot/ OpenTracing compatibility layer +dd-trace-ot/ Legacy OpenTracing compatibility library internal-api/ Internal shared API across modules +components/ Shared low-level components (context, environment, json) products/ Sub-products (feature flagging, metrics) communication/ HTTP transport to Datadog Agent -components/ Shared low-level components remote-config/ Remote configuration support telemetry/ Agent telemetry utils/ Shared utility modules (config, time, socket, test, etc.) -metadata/ Supported configurations metadata & requirements -benchmark/ Performance benchmarks dd-smoke-tests/ Smoke tests (real apps + agent) docs/ Developer documentation (see below) ``` @@ -35,6 +29,7 @@ docs/ Developer documentation (see below) | Topic | File | |---|---| +| Architecture & design | [ARCHITECTURE.md](ARCHITECTURE.md) | | Building from source | [BUILDING.md](BUILDING.md) | | Contributing & PR guidelines | [CONTRIBUTING.md](CONTRIBUTING.md) | | How instrumentations work | [docs/how_instrumentations_work.md](docs/how_instrumentations_work.md) | From 6cd0b03fd79914f9a1fe23d3765e271cb7b724e8 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:53:21 +0100 Subject: [PATCH 13/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4007ab5eb14..52c6bcbb9d5 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -44,7 +44,7 @@ main jar (`inst/`, `profiling/`, `appsec/`, `iast/`, `debugger/`, `ci-visibility `shared/`, `trace/`, etc.). A dedicated `sharedShadowJar` bundles common transitive dependencies (OkHttp, JCTools, LZ4, etc.) to avoid duplication across feature jars. All dependencies are relocated under `datadog.` prefixes to prevent classpath conflicts. Class files inside feature jars are renamed -to `.classdata` to prevent unintended loading. See `docs/how_to_work_with_gradle.md`. +to `.classdata` to prevent unintended loading. See [`docs/how_to_work_with_gradle.md`](docs/how_to_work_with_gradle.md). - **`src/`** — `AgentBootstrap` and `AgentJar`, the entry point loaded by `-javaagent`. Deliberately minimal. @@ -53,7 +53,7 @@ to `.classdata` to prevent unintended loading. See `docs/how_to_work_with_gradle decorator base classes (`HttpServerDecorator`, `DatabaseClientDecorator`, etc.), and bootstrap-safe utilities. Visible to all classloaders, so instrumentation advice and helpers can use them directly. - See `docs/boostrap_design_guidelines.md` + See [`docs/bootstrap_design_guidelines.md`](docs/bootstrap_design_guidelines.md) - **`agent-builder/`** — ByteBuddy integration layer. Class transformer pipeline: `DDClassFileTransformer` intercepts every class load, `GlobalIgnoresMatcher` applies early @@ -71,7 +71,7 @@ to `.classdata` to prevent unintended loading. See `docs/how_to_work_with_gradle - `muzzle/` — Build-time and runtime safety checks. Verifies that expected types and methods exist in the library version at runtime. If not, the instrumentation is silently skipped. - See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md`. + See [`docs/how_instrumentations_work.md`](docs/how_instrumentations_work.md) and [`docs/add_new_instrumentation.md`](docs/add_new_instrumentation.md). - **`instrumentation/`** — All auto-instrumentations, organized as `{framework}/{framework}-{minVersion}/`. Nearly 200 framework directories. Each follows the same pattern: an `InstrumenterModule` declares the @@ -79,7 +79,7 @@ to `.classdata` to prevent unintended loading. See `docs/how_to_work_with_gradle via matchers, advice classes inject bytecode via `@Advice.OnMethodEnter`/`@Advice.OnMethodExit`, and decorator/helper classes contain the actual product logic. Instrumentations are discovered via `@AutoService(InstrumenterModule.class)` (Java SPI) and validated by Muzzle at build time. - See `docs/how_instrumentations_work.md` and `docs/add_new_instrumentation.md` for details. + See [`docs/how_instrumentations_work.md`](docs/how_instrumentations_work.md) and [`docs/add_new_instrumentation.md`](docs/add_new_instrumentation.md) for details. - **`appsec/`** — Application Security. Entry point: `AppSecSystem.start()`. Runs the Datadog WAF to detect and block attacks in real-time. Hooks into the gateway to intercept HTTP requests. From a2323ee84e3b6fca011922cb41173ea1522ac6c2 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Wed, 18 Feb 2026 17:56:42 +0100 Subject: [PATCH 14/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 52c6bcbb9d5..a7dc25c6dc3 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -52,8 +52,7 @@ to `.classdata` to prevent unintended loading. See [`docs/how_to_work_with_gradl - **`agent-bootstrap/`** — Classes on the bootstrap classloader: `Agent` (startup orchestrator), decorator base classes (`HttpServerDecorator`, `DatabaseClientDecorator`, etc.), and bootstrap-safe utilities. Visible to all classloaders, so instrumentation advice and helpers can use them directly. - - See [`docs/bootstrap_design_guidelines.md`](docs/bootstrap_design_guidelines.md) + See [`docs/bootstrap_design_guidelines.md`](docs/bootstrap_design_guidelines.md). - **`agent-builder/`** — ByteBuddy integration layer. Class transformer pipeline: `DDClassFileTransformer` intercepts every class load, `GlobalIgnoresMatcher` applies early @@ -70,8 +69,7 @@ to `.classdata` to prevent unintended loading. See [`docs/how_to_work_with_gradl `ForTypeHierarchy`, `ForBootstrap`. - `muzzle/` — Build-time and runtime safety checks. Verifies that expected types and methods exist in the library version at runtime. If not, the instrumentation is silently skipped. - - See [`docs/how_instrumentations_work.md`](docs/how_instrumentations_work.md) and [`docs/add_new_instrumentation.md`](docs/add_new_instrumentation.md). + See [`docs/how_instrumentations_work.md`](docs/how_instrumentations_work.md) and [`docs/add_new_instrumentation.md`](docs/add_new_instrumentation.md). - **`instrumentation/`** — All auto-instrumentations, organized as `{framework}/{framework}-{minVersion}/`. Nearly 200 framework directories. Each follows the same pattern: an `InstrumenterModule` declares the @@ -170,6 +168,7 @@ Core tracing abstractions: decisions (which classes to instrument, which integrations to enable, resolver behavior, field injection flags) must be frozen into the native image binary. Runtime-only settings (agent endpoints, service names, sampling rates) remain in `Config`. + See [`docs/add_new_configurations.md`](docs/add_new_configurations.md). Cross-product abstractions: From 514ce9250ae77cb2d4210a8a6bc739c6eff7666b Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Thu, 19 Feb 2026 10:34:50 +0100 Subject: [PATCH 15/15] feat(doc): Iterate on content --- ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index a7dc25c6dc3..3d2b3bd4caf 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -95,7 +95,7 @@ to `.classdata` to prevent unintended loading. See [`docs/how_to_work_with_gradl Uploads profiles to the Datadog backend. - **`agent-debugger/`** — Dynamic Instrumentation. Entry point: `DebuggerAgent`. - Live breakpoints, snapshot capture, exception replay, code origin mapping. + Probes, snapshot capture, exception replay, code origin mapping. Driven by remote configuration. - **`agent-llmobs/`** — LLM Observability. Entry point: `LLMObsSystem.start()`.