Open-Source Wikis

/

Datadog Agent

/

How to contribute

/

Patterns and conventions

DataDog/datadog-agent

Patterns and conventions

The conventions a contributor needs in their head before opening the editor.

Use dda inv, never raw go

The single most important rule, repeated throughout AGENTS.md:

This project uses extensive custom Go build tags. Most source files are ignored by the standard Go toolchain unless the correct tags are passed.

Direct invocation:

Don't Do
go build ./... dda inv agent.build (or another *.build task)
go test ./pkg/... dda inv test --targets=./pkg/...
go mod tidy dda inv tidy
go vet ./... dda inv linter.go
golangci-lint run dda inv linter.go

If you only want a smoke test that the change compiles, build the smallest binary that includes the path you touched (dda inv dogstatsd.build, dda inv trace-agent.build, dda inv system-probe.build).

Build tags

Build tags drive compilation. The full computation lives in tasks/build_tags.py. A few you'll meet often:

Tag Effect
kubeapiserver Compiles in the Kubernetes API server plumbing (Cluster Agent and Cluster Checks).
containerd containerd integration.
docker Docker integration.
cri CRI runtime integration.
kubelet Kubelet client.
linux_bpf eBPF implementation files (Linux-only).
python Python check runtime.
jmx JMX-Fetch bridge.
serverless Stripped-down build for the serverless flavor.
iot Stripped-down IoT Agent build.
clusterchecks Cluster check dispatcher logic.
secrets The secret backend executor.
ec2, gce, azure, cloudfoundry Cloud-provider-specific integrations.

Always start a new file with explicit constraints when a feature is platform- or tag-specific:

//go:build linux && linux_bpf
// +build linux,linux_bpf

package mything

Mismatched tags between source and tests are a common cause of "works on my machine."

Component framework patterns

Every new piece of functionality should be added as a component under comp/. Read Components framework for the longer explanation.

Conventions:

  • Layout: comp/<bundle>/<component>/def/, <component>/impl/, <component>/fx/, optionally <component>/mock/.
  • Component interfaces go in def/. Implementations go in impl/. Fx wiring goes in fx/.
  • Bundles (comp/<bundle>/bundle.go) collect related components into a single fx.Option.
  • Mocks (<component>/mock/) are mandatory for components used in tests.
  • Mocks must be registered with mockery configuration in .mockery.yaml.

A component's interface should be:

  • Small. Focused on the one capability the component provides.
  • Stable. Other components depend on it; breaking changes are expensive.
  • Testable. Returning concrete types or interfaces other code can mock.

When migrating from pkg/ to comp/, the typical pattern is:

  1. Create comp/<bundle>/<component>/def/, copy or define the interface.
  2. Create comp/<bundle>/<component>/impl/. The first version often delegates to the existing pkg/ code.
  3. Create comp/<bundle>/<component>/fx/ with the Fx options.
  4. Update binaries (cmd/<binary>/subcommands/run/) to depend on the component instead of calling pkg/ directly.
  5. Eventually move the implementation into impl/ and delete the pkg/ package.

Error handling

  • Use fmt.Errorf("…: %w", err) for wrapping. Bare err returns lose context.

  • Reserve panic for truly unrecoverable situations. The Agent's job is to keep running even when subsystems fail.

  • Functions exposed to UIs and APIs must degrade gracefully when a dependency isn't ready. From AGENTS.md:

    Components initialize in stages — some dependencies may not be ready when others start. Functions exposed to UIs or APIs should return safe defaults when a dependency is unavailable, not propagate errors or panic.

Concurrency and lifecycle

Most components implement an explicit Start() / Stop(). Conventions:

  • Spawn goroutines from Start(), signal them via context cancellation in Stop().
  • Channels owned by the component are closed by the goroutine that writes to them, after they are confident no more writes will happen.
  • Send-on-closed-channel races at shutdown are the most common bug class. Tests must exercise the shutdown path.
  • golang.org/x/sync/errgroup and golang.org/x/sync/singleflight are commonly used in the codebase.

The relevant AGENTS.md section is reproduced verbatim:

The agent runs many concurrent goroutines with explicit Start()/Stop() lifecycles. The most common bugs are send-on-closed-channel during shutdown and goroutine leaks. Changes that introduce goroutines or modify component lifecycle should have tests exercising startup and graceful shutdown.

Logging

Conventions in docs/public/guidelines/conventions/logging.md and surfaced via pkg/util/log/ and comp/core/log/. Highlights:

  • Use the package's bound logger (log.Debug, log.Info, log.Warn, log.Error).
  • Don't log secrets. The flare scrubber redacts known patterns, but logs are not flares — they may go to disk regardless.
  • Prefer one log line per event with structured fields, rather than multi-line free-form output.
  • Per-package loggers (e.g., pkg/security/seclog/, pkg/trace/log/) exist for backwards compatibility; new code should use the canonical logger.

Configuration

  • Configuration goes through pkg/config/setup/ (legacy) and comp/core/config/ (component framework).
  • Every config key should have a default in pkg/config/setup/config.go (or its delegated callers) and a corresponding YAML key in the example datadog.yaml.
  • Environment variables follow the DD_<UPPERCASE_KEY> pattern automatically; you don't add them by hand.
  • New runtime-changeable settings go through comp/core/settings/ so they appear in agent config and agent config set.
  • The .claude/skills/create-config-field/ skill walks through the full procedure for adding a new config field.

Platform-specific code

  • Use *_linux.go, *_windows.go, *_darwin.go filenames for OS-specific implementations.
  • Stub the same symbols for unsupported platforms so packages still compile.
  • Take Windows seriously. The .claude/skills/, the build system (packages/agent/windows/), and the install scripts all have Windows variants. Drift between Linux and Windows is one of the most common bug classes.

Documentation in code

  • Every exported symbol should have a doc comment.
  • The component framework auto-generates comp/README.md from package docs (dda inv collector.generate). Keep package summaries up to date.
  • README files inside pkg/ and comp/ (e.g., pkg/aggregator/README.md, pkg/trace/README.md, comp/dogstatsd/README.md) are the canonical reference for those subsystems.
  • AGENTS.md files are scoped to a directory tree; keep their guidance accurate.

Naming and style

  • Use gofmt (enforced by dda inv linter.go).
  • Package names are lowercase, no underscores. Exception: generated *_string.go files for stringer.
  • Test packages are typically the same as the package under test (white-box). Black-box tests use <pkg>_test.
  • File names use lowercase with underscores when needed (time_sampler.go).
  • For new directories, mirror the existing style of the parent. The repo is large and consistency matters more than clever organization.

License headers

Every Go file starts with the standard header:

// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

The tasks/licenses.py task validates this. eBPF C code uses GPLv2; rtloader uses Apache.

Per-area AGENTS.md

Several subtrees have their own AGENTS.md files that refine the repo-wide conventions:

  • bazel/AGENTS.md — Bazel rules and conventions.
  • test/e2e-framework/AGENTS.md, test/fakeintake/AGENTS.md — E2E and fakeintake.
  • pkg/collector/corechecks/ebpf/AGENTS.md — eBPF-based core checks.
  • And many more across pkg/ and comp/.

Read the local AGENTS.md before making changes in an unfamiliar subtree. The root AGENTS.md explicitly asks contributors and AI agents to update these files when they go stale.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Patterns and conventions – Datadog Agent wiki | Factory