dd-trace-dotnet
AGENTS.md572 starsChanged 18 days agoApache-2.0View on GitHub
For AI Agents: This file provides a navigation hub and quick reference. Linked docs in each section can be loaded when their topic is relevant to your task. The Datadog.Trace NuGet package ships only the manual instrumentation API (Datadog.Trace.Manual.dll) — not auto-instrumentation code or native profiler binaries. Reference it in customer code for Tracer.Instance.StartActive() etc. The full managed tracer (Datadog.Trace.dll) contains all auto-instrumentation code and is delivered separately via the tracer "monitoring home" (installers, MSI, container images, or specialized packages:…
- Reads credentials
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository6 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- add-lint-ruleSkill
- analyze-azdo-buildSkill
- azure-functionsSkill
- bump-libdatadogSkill
- sdk-reviewSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
21 rules. About 0 are common, 4 are distinctive, and 17 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 94
Add [InstrumentMethod] attribute with assembly/type/method details and version range
- Very specific: line 96
Use duck typing constraints (where TReq : IMyShape, IDuckType) or obj.DuckCast<IMyShape>() for third-party types
- Very specific: line 101
When confirming instrumentation, neither CallTarget_RewriterCallback() Finished nor absence of ReJITError proves CLR acceptance or …
- Very specific: line 110
Setup: Use Azure App Services Site Extension on Windows Premium/Elastic Premium/Dedicated plans.
- Very specific: line 124
Add missing using directives instead of fully-qualified type names.
- Very specific: line 125
Use modern C# syntax, but avoid features requiring types unavailable in older runtimes (e.g., no ValueTuple syntax for .NET Framework 4.6.1)
- Very specific: line 127
Prefer modern collection expressions ([])
- Very specific: line 128
Use StringUtil.IsNullOrEmpty() instead of string.IsNullOrEmpty() for compatibility across all supported runtimes.
- Very specific: line 130
Never manually edit generated files (.g.
- Very specific: line 168
Use clear, customer-facing terminology in log messages to avoid confusion.
- Very specific: line 186
Never use ToString() on numeric types in log calls - use generic log methods instead:
- Distinctive: line 197
When implementing retry logic, use appropriate log levels:
- Very specific: line 213
Understanding code flow is critical: If inner methods already handle expected errors, outer catch blocks should use Log.Error since they …
- Distinctive: line 217
When logging final failures for network operations, include:
- Very specific: line 231
Zero-Allocation Provider Structs: Use readonly struct with generic type parameters and interface constraints to avoid boxing
- Very specific: line 233
Avoid Allocation in Logging: Use format strings (Log("value: {0}", x)) instead of interpolation (Log($"value: {x}"))
- Distinctive: line 250
Use struct implementations with generic constraints for zero-allocation production code
- Very specific: line 252
Prefer using [Theory] with input data rather than duplicating tests
- Very specific: line 298
Do not commit secrets; prefer env vars (DD_*).
- Very specific: line 299
Use global.json SDK; confirm with dotnet --version.
- Distinctive: line 300
Never mention a customer or user in a pull request.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Repository Guidelines
For AI Agents: This file provides a navigation hub and quick reference. Linked docs in each section can be loaded when their topic is relevant to your task.
Project Structure & Module Organization
- tracer/src — Managed tracer, analyzers, tooling.
- tracer/test — Unit/integration tests; sample apps under test/test-applications.
- profiler/src, profiler/test — Native profiler and tests.
- shared — Cross-cutting native libs/utilities.
- docs — Product and developer docs.
- docker-compose.yml — Test dependencies (databases, brokers, etc.).
- Solutions:
Datadog.Trace.sln,Datadog.Profiler.sln(IDE).
Architecture Overview
- Auto-instrumentation: Native CLR profiler hooks the runtime (CallTarget) and loads the managed tracer.
- Managed tracer:
Datadog.Tracehandles spans, context propagation, and library integrations. - Loader/home: Build outputs publish a "monitoring home"; the native loader boots the tracer from there.
- Build system: Nuke coordinates .NET builds and CMake/vcpkg for native components.
NuGet Package Architecture
The Datadog.Trace NuGet package ships only the manual instrumentation API (Datadog.Trace.Manual.dll) — not auto-instrumentation code or native profiler binaries. Reference it in customer code for Tracer.Instance.StartActive() etc.
The full managed tracer (Datadog.Trace.dll) contains all auto-instrumentation code and is delivered separately via the tracer "monitoring home" (installers, MSI, container images, or specialized packages: Datadog.Trace.Bundle for complete multi-runtime/multi-product distribution; Datadog.AzureFunctions for Azure Functions). The native profiler loads Datadog.Trace.dll into instrumented processes from the home.
Tracer Structure
tracer/src/Datadog.Trace— Core managed tracer library.Activity— System.Diagnostics.Activity bridge/helpers.Agent— Agent transport, payloads, health, serialization.AppSec— Application Security (WAF/RASP) components.AspNet— ASP.NET helpers/back-compat.Ci— CI Visibility (test/session/span) logic.ClrProfiler— Auto-instrumentation runtime (CallTarget, handlers, definitions).Configuration— Settings, sources, environment parsing.ContinuousProfiler— Hooks for CPU/wall profiler coordination.DataStreamsMonitoring— DSM utilities and checkpoints.DatabaseMonitoring— DBM helpers.Debugger— Dynamic Instrumentation (live debugger) plumbing.DiagnosticListeners— DiagnosticSource/Listener integrations.DogStatsd— StatsD metrics client integration.DuckTyping— Duck typing runtime and attributes.ExtensionMethods— Internal extension helpers.FaultTolerant— Retry/backoff/resiliency helpers.Generated— Generated sources (source generators output).Headers— HTTP header constants/parsing.HttpOverStreams— Socket/pipe HTTP transport to the agent.Iast— Interactive App Security Testing.LibDatadog— Native interop wrappers.Logging— Internal logging abstractions.OTelMetrics/OpenTelemetry— OTEL interop and exporters.PDBs— Symbol/PDB helpers.PlatformHelpers— OS/arch/runtime helpers.Processors— Pipelines and span processors.Propagators— Trace context inject/extract (Datadog, W3C, B3).RemoteConfigurationManagement— RCM polling/apply.RuntimeMetrics— Process/runtime metrics.Sampling— Samplers and priorities.ServiceFabric— Service Fabric integration helpers.Tagging— Strongly-typed tag sets.Telemetry— Product telemetry emission.Util— Common utilities.Vendors— Vendored third-party code.
- Other tracer modules under
tracer/srcDatadog.Trace.ClrProfiler.Managed.Loader— Managed bootstrapper loaded by the profiler.Datadog.Trace.Manual— Manual instrumentation shims/APIs.Datadog.Trace.SourceGenerators— Compile-time code generators.Datadog.Trace.OpenTracing— OpenTracing bridge.Datadog.Trace.MSBuild— MSBuild tasks/targets.Datadog.Trace.Tools.*— CLI tools, analyzers, shared libs, and dd_dotnet.Datadog.Trace.Trimming— Trimming/linker support.Datadog.AzureFunctions— Azure Functions support.Datadog.FleetInstaller— Fleet/installer utilities.Datadog.InstrumentedAssembly*— Pre-instrumented assembly tooling/verification.
- Tracer tools under
tracer/toolsDatadog.AutoInstrumentation— Instrumentation generator (GUI, CLI, and shared core); standaloneDatadog.AutoInstrumentation.slnx, not inDatadog.Trace.sln.
Datadog.Tracer.Native— Native interop glue and packaging metadata.
Build & Development
Quick start:
- Build:
./tracer/build.sh(Linux/macOS) or.\tracer\build.cmd(Windows) - Unit tests:
./tracer/build.sh BuildAndRunManagedUnitTests - Integration tests:
BuildAndRunIntegrationTests tracer/README.md— Complete development setup guide (VS requirements, Docker, Dev Containers, platform-specific build commands, and Nuke targets)
Creating Integrations
Quick reference:
- Location:
tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/<Area>/<Integration>.cs - Add
[InstrumentMethod]attribute with assembly/type/method details and version range - Implement
OnMethodBeginandOnMethodEnd/OnAsyncMethodEndhandlers - Use duck typing constraints (
where TReq : IMyShape, IDuckType) orobj.DuckCast<IMyShape>()for third-party types - Tests: Add under
tracer/test/Datadog.Trace.ClrProfiler.IntegrationTestswith samples intracer/test/test-applications/integrations - Generate boilerplate (GUI):
./tracer/build.ps1 RunInstrumentationGenerator - Generate boilerplate (CLI):
./tracer/build.ps1 RunInstrumentationGeneratorCli --assembly-path <dll> --type-name <type> --method-name <method> - Generators only scaffold code: copy GUI output or use CLI
--output-path <file>, then implement handlers and add samples/tests. - When confirming instrumentation, neither
CallTarget_RewriterCallback() Finishednor absence ofReJITErrorproves CLR acceptance or execution. Read Confirming runtime instrumentation for the evidence required at each stage. docs/development/AutomaticInstrumentation.md— Complete guide to creating integrations, CallTarget wiring, testing strategies, package version configuration, and CI testingdocs/development/InstrumentationGenerator.md— GUI and CLI instrumentation generator tools, Nuke integration, duck typing flags, JSON output, and two-tool workflow with dotnet-inspectdocs/development/DuckTyping.md— Duck typing patterns, proxy types, binding attributes, best practices, and performance benchmarks
Azure Functions & Serverless
Quick reference:
- Setup: Use Azure App Services Site Extension on Windows Premium/Elastic Premium/Dedicated plans; use
Datadog.AzureFunctionsNuGet package for Linux Consumption/Container Apps - Tests:
BuildAndRunWindowsAzureFunctionsTestsNuke target; samples undertracer/test/test-applications/azure-functions/ - External Repos: Azure Functions Host and .NET Worker
docs/development/AzureFunctions.md— Setup, testing, instrumentation specifics, and debugging guidedocs/development/for-ai/AzureFunctions-Architecture.md— Deep dive into Azure Functions Host and .NET Worker architecture, gRPC protocol, and instrumentation hook pointsdocs/development/AwsLambdaIntegrationTests.md— AWS Lambda integration test setup, architecture, and test patterns
Coding Standards
C# style:
- See
.editorconfig(auto-enforced). - Add missing
usingdirectives instead of fully-qualified type names. - Use modern C# syntax, but avoid features requiring types unavailable in older runtimes (e.g., no
ValueTuplesyntax for .NET Framework 4.6.1)- For instance, prefer
is not nullto!= null
- For instance, prefer
- Prefer modern collection expressions (
[]) - Use
StringUtil.IsNullOrEmpty()instead ofstring.IsNullOrEmpty()for compatibility across all supported runtimes. - StyleCop: see
tracer/stylecop.json; address warnings before pushing. - Never manually edit generated files (
.g.in the file extension). Read the file header for regeneration instructions instead.
C/C++ style:
- See
.clang-format; keep consistent naming.
Windows Command Line Best Practices
CRITICAL: Avoid >nul and 2>nul redirections on Windows
On Windows, redirecting to nul can create a literal file named "nul" instead of redirecting to the NUL device. These files are extremely difficult to delete and cause repository issues.
Problem commands:
findstr /s /i "pattern" "*.cpp" "*.h" 2>nul
command 2>nul | head -20
any-command >nulSafe alternatives:
- Don't suppress errors - Let error output show naturally
- Use full device path:
2>\\.\NUL(works reliably but verbose) - Use PowerShell for cross-platform compatibility where applicable
- Prefer dedicated tools over piped bash commands (use Grep, Glob, Read tools instead)
Examples of safe patterns:
# Bad: Creates nul file
findstr /s /i "DD_TRACE" "*.cpp" 2>nul
# Good: Let errors show
findstr /s /i "DD_TRACE" "*.cpp"
# Good: Use full device path if suppression is essential
findstr /s /i "DD_TRACE" "*.cpp" 2>\\.\NULLogging Guidelines
Use clear, customer-facing terminology in log messages to avoid confusion. Profiler is ambiguous — it can refer to the .NET profiling APIs we use internally or the Continuous Profiler product.
Customer-facing terminology (high-level logs):
- Datadog SDK — When disabling the entire product or referring to the whole monitoring solution
- Example:
"The Datadog SDK has been disabled"
- Example:
- Instrumentation or Instrumentation component — For the native tracer auto-instrumentation
- Example:
"Instrumentation has been disabled"or"The Instrumentation component failed to initialize"
- Example:
- Continuous Profiler — Always use full name for the profiling product
- Example:
"The Continuous Profiler has been disabled"
- Example:
- Datadog.Trace.dll — For the managed tracer assembly (avoid "managed profiler")
- Example:
"Unable to initialize: Datadog.Trace.dll was not yet loaded into the App Domain"
- Example:
Internal/technical naming (still valid):
- Native loader, Native tracer, Managed tracer loader, Managed tracer, Libdatadog, Continuous Profiler
CorProfiler/ICorProfiler/COR Profilerfor runtime components
Log Argument Formatting
Never use ToString() on numeric types in log calls - use generic log methods instead:
// BAD - allocates a string unnecessarily
Log.Debug(ex, "Error (attempt {Attempt})", (attempt + 1).ToString());
// GOOD - uses generic method, no allocation
Log.Debug<int>(ex, "Error (attempt {Attempt})", attempt + 1);Log Levels for Retry Operations
When implementing retry logic, use appropriate log levels:
- Debug: Intermediate retry attempts (transient errors are expected)
- Error: Final failure after all retries exhausted
- Error: Non-retryable errors (e.g., 400 Bad Request indicates a bug)
ErrorSkipTelemetry Usage
Log.ErrorSkipTelemetry logs locally but does NOT send to Datadog telemetry. Use it for:
- Expected environmental errors: Network connectivity issues, endpoint unavailability
- Transient failures: Errors that are expected in production and self-resolve
Do NOT use ErrorSkipTelemetry for:
- Errors in outer catch blocks that would only catch unexpected exceptions
- HTTP 400 Bad Request (indicates a bug in our payload)
- Errors that indicate bugs in the tracer code
Understanding code flow is critical: If inner methods already handle expected errors, outer catch blocks should use Log.Error since they would only catch unexpected exceptions (bugs).
Error Messages for Network Failures
When logging final failures for network operations, include:
- The endpoint that failed
- Number of attempts made
- Link to troubleshooting documentation
Performance Guidelines
The tracer runs in-process with customer applications and must have minimal performance impact.
Critical code paths:
- Bootstrap/Startup Code: Managed loader, tracer initialization, static constructors, configuration loading, integration registration
- Hot Paths: Span creation/tagging, context propagation, sampling decisions, instrumentation callbacks, request/response pipeline
Key patterns:
- Zero-Allocation Provider Structs: Use
readonly structwith generic type parameters and interface constraints to avoid boxing- Example:
EnvironmentVariableProviderin managed loader
- Example:
- Avoid Allocation in Logging: Use format strings (
Log("value: {0}", x)) instead of interpolation (Log($"value: {x}")) - Avoid params Array Allocations: Provide overloads for common cases (0, 1, 2 args)
Debugger / Dynamic Instrumentation Safety
Debugger code runs inside customer processes while inspecting live customer objects. Before changing debugger capture, expression evaluation, redaction, Exception Replay, Code Origin, or symbol-resolution paths, check:
docs/development/DebuggerSafetyBoundaries.md— guidance for reflection paths that may resolve customer assemblies/types/members early, trigger type initializers, instantiate attributes, or execute customer code such as getters, enumerators, exception overrides, orToString(), and for redacting sensitive values before they leave the process.
Testing
Frameworks: xUnit (managed), GoogleTest (native)
Test style: Inline results in assertions: SomeMethod().Should().Be(expected)
Docker: Many integration tests require Docker; services in docker-compose.yml
Testing patterns:
- Extract interfaces for environment/filesystem dependencies (e.g.,
IEnvironmentVariableProvider) - Use struct implementations with generic constraints for zero-allocation production code
- Example: Managed loader tests use
MockEnvironmentVariableProvider(seetracer/test/Datadog.Trace.Tests/ClrProfiler/Managed/Loader/)
- Example: Managed loader tests use
- Prefer using
[Theory]with input data rather than duplicating tests docs/development/TracerDebugging.md— Local debugging techniques, launchSettings.json configuration, $(SolutionDir) path issues, IDE-specific tips, and troubleshooting common tracer loading problems
Commit & Pull Request Guidelines
- Commits: imperative mood, optional
[Area]prefix (e.g.[Debugger],[SymDB]). Keep messages concise — avoid full diffs or extensive explanation. - PRs: follow
.github/pull_request_template.md. Keep descriptions concise — focus on "what" and "why", brief "how" only when complex.
Documentation References
Core docs:
docs/README.md— Overview and linksdocs/CONTRIBUTING.md— Contribution process and external PR policiestracer/README.md— Dev setup, platform requirements, and build targetsdocs/RUNTIME_SUPPORT_POLICY.md— Supported runtimes
Development guides:
docs/development/AutomaticInstrumentation.md— Creating integrationsdocs/development/InstrumentationGenerator.md— GUI and CLI instrumentation generator toolsdocs/development/for-ai/InstrumentationGenerator-CLI.md— LLM reference for the CLI (commands, JSON schemas, error handling)docs/development/DuckTyping.md— Duck typing guidedocs/development/TracerDebugging.md— Local debugging, IDE configuration, path issues, and troubleshootingdocs/development/AzureFunctions.md— Azure Functions integrationdocs/development/InferredProxyServices.md— Inferred proxy spans (AWS API Gateway, Azure APIM, Azure Front Door)docs/development/for-ai/AzureFunctions-Architecture.md— Azure Functions architecture deep divedocs/development/AwsLambdaIntegrationTests.md— AWS Lambda integration testsdocs/development/DebuggerSafetyBoundaries.md— Debugger reflection/type-loading, customer-code execution, and redaction safety guidedocs/development/UpdatingTheSdk.md— SDK updatesdocs/development/QueryingDatadogAPIs.md— Querying Datadog APIs for debugging (spans, logs)docs/development/GitHubActionsSecurity.md— GitHub Actions SHA-pinning policy, action allowlist, and reviewer checklistdocs/development/FeatureFlagsOpenFeature.md— OpenFeature provider sync APIs, provider hook rules, and focused testsdocs/development/for-ai/Coding-Requirements/— Per-lens rules for planning changes and for code review
CI & Testing:
docs/development/CI/TroubleshootingCIFailures.md— Investigating build/test failures in Azure DevOpsdocs/development/CI/RunSmokeTestsLocally.md— Running smoke tests locally
Configuration
tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml— Human-readable config metadata, product categorization, key aliases, deprecations, and default values for allDD_*andOTEL_*environment variables (also consumed by source generators).docs/development/Configuration/AddingConfigurationKeys.md— Step-by-step guide for adding config keys: YAML definitions, source generators, aliases, telemetry normalization, and related analyzers
Security & Configuration
- Do not commit secrets; prefer env vars (
DD_*)..envshould not contain credentials. - Use
global.jsonSDK; confirm withdotnet --version. - Never mention a customer or user in a pull request. Do not include their name, any other identifying detail, PII, or their code in the diff, commit messages, or PR description.
Glossary
Common acronyms used in this repository:
- AAS — Azure App Services
- AAP — App and API Protection (formerly ASM, previously AppSec)
- AOT — Ahead-of-Time (compilation)
- APM — Application Performance Monitoring
- ASM — see AAP
- CI — Continuous Integration / CI Visibility
- CP — Continuous Profiler
- DBM — Database Monitoring
- DI — Dynamic Instrumentation
- DSM — Data Streams Monitoring
- IAST — Interactive Application Security Testing
- JIT — Just-in-Time (compiler)
- OTEL — OpenTelemetry
- R2R — ReadyToRun
- RASP — Runtime Application Self-Protection
- RCM — Remote Configuration Management
- RID — Runtime Identifier
- TFM — Target Framework Moniker
- WAF — Web Application Firewall
Code Review Rules
Before pushing code or creating a pull request, you must run the sdk-review skill on the committed changes unless the user specifically says not to. You must also do a standard self review (using the /review skill if available). All other required publication checks still apply.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

