Skip to main content

datadog_agent_runtime/
lib.rs

1//! Shared runtime infrastructure for a process that acts as a remote agent for the Datadog Agent.
2//!
3//! A remote agent is a process that runs alongside the Datadog Agent and attaches to it over the Remote Agent Registry
4//! (RAR): it registers itself, receives its configuration from the Agent, and serves the status, flare, and telemetry
5//! services that the Agent queries. This crate provides those pieces, so that each remote agent only supplies what is
6//! truly its own: its configuration system, its topology, its control plane supervisor, its status sections, its
7//! telemetry remapping rules, and any extra API handlers.
8//!
9//! # Getting started
10//!
11//! Most remote agents use the [`facade`] module, which drives the whole startup sequence. A binary bootstraps the
12//! process with `saluki_app::bootstrap::AppBootstrapper`, implements [`LocalConfiguration`][facade::LocalConfiguration]
13//! and [`AuthoritativeConfiguration`][facade::AuthoritativeConfiguration] for its configuration system, ties them
14//! together with [`RemoteAgentSpecification`][facade::RemoteAgentSpecification] on a marker type, and then walks
15//! through the stages:
16//!
17//! 1. [`RemoteAgent::start`][facade::RemoteAgent::start] registers with the Datadog Agent, waits for the initial
18//!    configuration from its configuration stream, and reloads logging to match. In standalone mode, the local
19//!    configuration becomes authoritative instead.
20//! 2. [`RemoteAgent::initialize`][facade::RemoteAgent::initialize] creates the component and health registries and the
21//!    [`RemoteAgentEnvironmentProvider`][env::RemoteAgentEnvironmentProvider], which connects to the Datadog Agent for
22//!    the hostname, autodiscovery, and workload metadata.
23//! 3. [`RemoteAgent::run`][facade::RemoteAgent::run] takes the binary's topology and control plane supervisor, creates
24//!    the rest of the supervisors, validates the memory bounds, and runs the supervision tree until the process is asked
25//!    to shut down.
26//!
27//! Each stage is a type parameter of [`RemoteAgent`][facade::RemoteAgent], so only the methods for the current stage
28//! are available. The binary regains control between stages: to check its configuration before anything starts, and to
29//! build its topology and its control plane. `examples/minimal_remote_agent.rs` shows a complete binary.
30//!
31//! # Supervision tree
32//!
33//! The facade builds this tree, where `{identifier}` is the identifier of the application details that the binary
34//! registers with `saluki_metadata::set_app_details`:
35//!
36//! ```text
37//! {identifier}-root                 one-for-one, no restarts
38//! ├── bootstrap supervisor          from AppBootstrapper
39//! ├── internal-sup
40//! │   ├── control plane             from the binary
41//! │   │   └── remote-agent          from RemoteAgent::create_remote_agent_supervisor
42//! │   ├── resource registry
43//! │   ├── config-updates            connected mode only
44//! │   └── env-provider              connected mode only
45//! │       ├── workload
46//! │       └── autodiscovery
47//! └── the binary's topology
48//! ```
49//!
50//! A configuration stream that closes fails `config-updates` on every restart, which escalates to the root and stops the
51//! process, rather than leaving it to run on a configuration that can no longer change.
52//!
53//! # Control plane
54//!
55//! Each remote agent builds its own control plane supervisor from the workers it needs. ADP's `ctrl-pln` runs on a
56//! dedicated single-threaded runtime and holds:
57//!
58//! - the health registry's worker, and [`ResourceTelemetryWorker`][saluki_app::accounting::ResourceTelemetryWorker]
59//! - [`InternalTelemetryAPIWorker`][saluki_core::observability::metrics::InternalTelemetryAPIWorker], for `/metrics`
60//!   and `/compat/metrics`
61//! - [`DynamicLogLevelWorker`][saluki_app::logging::DynamicLogLevelWorker], fed by
62//!   [`LoggingTranslator::translate_log_levels`][logging::LoggingTranslator::translate_log_levels]
63//! - [`ConfigWorker`][saluki_app::config::ConfigWorker] for `/config`, and
64//!   [`ConfigRuntimeWorker`][control_plane::ConfigRuntimeWorker] for `/config/runtime`
65//! - the unprivileged and privileged API endpoints, built with [`APIBuilder`][saluki_app::api::APIBuilder], where the
66//!   privileged endpoint requires the Agent IPC certificate
67//! - the `remote-agent` supervisor from [`RemoteAgent::create_remote_agent_supervisor`][facade::RemoteAgent::create_remote_agent_supervisor]
68//!
69//! These workers publish their routes as dynamic routes, so whichever API endpoint runs in the same supervision tree
70//! serves them.
71//!
72//! # Hooks
73//!
74//! A remote agent can:
75//!
76//! - add sections to the status output with [`StatusSectionProvider`][remote_agent::StatusSectionProvider]
77//! - select and rename the internal metrics reported to the Datadog Agent as telemetry
78//! - serve `/compat/metrics` with its own remapping rules
79//! - serve its own routes on the unprivileged and privileged API endpoints
80//!
81//! Its [`LoggingTranslator`][logging::LoggingTranslator] sets its default log file and adds its own crates to the
82//! first-party log targets that a plain log level applies to.
83//!
84//! # Building blocks
85//!
86//! Each module can also be used on its own, without the facade:
87//!
88//! - [`remote_agent`]: registration, the configuration stream, and the workers that serve the status, flare, and
89//!   telemetry services
90//! - [`logging`]: translation of the Datadog Agent's logging settings and runtime log level changes
91//! - [`env`](mod@env): the host, autodiscovery, and workload providers
92//! - [`control_plane`]: workers that serve the internal APIs and keep the configuration current
93//!
94//! # Conventions
95//!
96//! Constructors don't spawn tasks. Long-running work is returned as a
97//! [`Supervisable`][saluki_core::runtime::Supervisable] worker or [`Supervisor`][saluki_core::runtime::Supervisor] for
98//! the caller to place in its supervision tree.
99//!
100//! [`RemoteAgentBootstrap`][remote_agent::RemoteAgentBootstrap] is the one exception for now. Registration has to
101//! finish before the supervision tree exists, so [`RemoteAgentBootstrap::new`][remote_agent::RemoteAgentBootstrap::new]
102//! spawns the registration loop, and
103//! [`RemoteAgentBootstrap::create_config_stream`][remote_agent::RemoteAgentBootstrap::create_config_stream] spawns the
104//! configuration stream loop. Neither task is supervised, and neither stops on shutdown.
105//!
106//! Each subsystem that talks to the Datadog Agent opens its own connection with
107//! [`RemoteAgentClient::connect`][datadog_agent_commons::ipc::client::RemoteAgentClient::connect], rather than sharing a
108//! clone of another subsystem's client.
109//!
110//! Code in this crate logs under the `datadog_agent_runtime` target, which the `datadog_agent` prefix in
111//! [`FIRST_PARTY_LOG_TARGETS`][logging::FIRST_PARTY_LOG_TARGETS] covers.
112//!
113//! # Features
114//!
115//! - `taskdump`: includes a Tokio task dump (`runtime-dump.txt`) in flares. Tokio only supports task dumps on Linux, on
116//!   `aarch64`, `x86`, `x86_64`, and `s390x`, so the feature does nothing on any other target. On those targets, the
117//!   build also requires `--cfg tokio_unstable`.
118#![deny(missing_docs)]
119
120pub mod control_plane;
121
122pub mod env;
123
124pub mod facade;
125
126pub mod logging;
127
128pub mod remote_agent;