datadog_agent_config_testing/config_registry/mod.rs
1/// Datadog Agent configuration annotations, generated from `schema_overlay.yaml`.
2///
3/// Type definitions live here (hand-written); generated annotation constants and statics
4/// live in `annotations_index.rs` (generated in-tree by `build.rs`).
5pub use datadog_agent_config::classifier::{structs, Pipeline, PipelineAffinity, Severity};
6
7/// Support level for a configuration key, as recorded in the testing annotation layer.
8///
9/// Unlike the prod [`datadog_agent_config::classifier::SupportLevel`], this enum includes
10/// [`Full`][SupportLevel::Full] so that generated annotation constants can express keys that work
11/// identically to the core agent. The prod classifier omits `Full` because fully supported keys
12/// require no diagnostic action.
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub enum SupportLevel {
15 /// Fully supported with identical behavior to the core agent.
16 Full,
17 /// Supported but with behavioral or default-value differences.
18 Partial,
19 /// Explicitly incompatible; ADP does not support this key.
20 Incompatible(Severity),
21 /// Intentionally ignored.
22 #[allow(unused)]
23 Ignored,
24 /// Unrecognized by ADP.
25 #[allow(unused)]
26 Unrecognized,
27}
28
29/// Declares a set of [`SalukiAnnotation`] constants and generates a companion `ALL` slice.
30///
31/// Each entry declares one named `pub const` annotation. The macro also emits:
32///
33/// ```ignore
34/// pub const ALL: &[&SalukiAnnotation] = &[&NAME1, &NAME2, ...];
35/// ```
36///
37/// so that `annotations_index.rs` can aggregate submodules with a single
38/// `v.extend_from_slice(my_module::ALL)` line rather than listing every constant by name.
39#[macro_export]
40macro_rules! declare_annotations {
41 ( $( $(#[$attr:meta])* $name:ident = $val:expr ;)+ ) => {
42 $(
43 $(#[$attr])*
44 pub const $name: $crate::config_registry::SalukiAnnotation = $val;
45 )+
46
47 /// All annotations declared in this module, in declaration order.
48 pub const ALL: &[$crate::config_registry::SalukiAnnotationRef] = &[
49 $( &$name, )+
50 ];
51 };
52}
53
54/// The shape of a configuration value.
55#[derive(Clone, Copy, Debug, PartialEq, Eq)]
56pub enum ValueType {
57 /// A boolean (`true` / `false`).
58 Bool,
59 /// A UTF-8 string.
60 String,
61 /// An unsigned integer.
62 Integer,
63 /// A floating-point number.
64 Float,
65 /// A list of strings (YAML sequence or space-separated env var string).
66 StringList,
67 /// A duration, expressed as a Go duration string (for example, `10s`) or integer nanoseconds.
68 Duration,
69}
70
71/// Which schema source of truth defined the `SchemaEntry`
72#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
73#[repr(u8)]
74pub(crate) enum Schema {
75 /// Saluki defined the `SchemaEntry`.
76 Saluki,
77 /// The vendored Datadog config schema defines the `SchemaEntry`.
78 Datadog,
79}
80
81/// Schema-derived metadata for a single configuration key.
82#[derive(Debug)]
83pub struct SchemaEntry {
84 /// The source of truth from which this entry was derived.
85 #[allow(dead_code)]
86 pub(crate) schema: Schema,
87
88 /// Canonical dot-separated YAML path for this key (for example, `"proxy.http"`).
89 pub yaml_path: &'static str,
90
91 /// Environment variables that deliver this value, as declared in the schema.
92 pub env_vars: &'static [&'static str],
93
94 /// Shape of the value.
95 pub value_type: ValueType,
96
97 /// JSON-encoded default value from the Agent schema, if present.
98 pub default: Option<&'static str>,
99}
100
101/// Saluki-specific annotation for a single configuration key.
102#[derive(Debug)]
103pub struct SalukiAnnotation {
104 /// The schema entry this annotation enriches.
105 pub schema: &'static SchemaEntry,
106
107 /// How well saluki supports this key.
108 pub support_level: SupportLevel,
109
110 /// Additional YAML paths beyond the canonical one in the schema (aliases).
111 pub additional_yaml_paths: &'static [&'static str],
112
113 /// Overrides the schema's `env_vars` list entirely when `Some`.
114 pub env_var_override: Option<&'static [&'static str]>,
115
116 /// Config structs that incorporate this key, as [`structs`] constants.
117 pub used_by: &'static [&'static str],
118
119 /// Overrides the schema's `value_type` when `Some`.
120 pub value_type_override: Option<ValueType>,
121
122 /// Overrides the smoke-test injected value entirely when `Some`.
123 pub test_json: Option<&'static str>,
124
125 /// Which pipelines this key affects.
126 pub pipeline_affinity: PipelineAffinity,
127}
128
129/// A reference to a [`SalukiAnnotation`], used as the element type of `ALL` slices generated by
130/// [`declare_annotations!`].
131pub type SalukiAnnotationRef = &'static SalukiAnnotation;
132
133impl SalukiAnnotation {
134 /// The canonical YAML path for this key (from the schema).
135 pub fn yaml_path(&self) -> &'static str {
136 self.schema.yaml_path
137 }
138
139 /// All YAML paths for this key: canonical first, then any aliases.
140 pub fn all_yaml_paths(&self) -> impl Iterator<Item = &'static str> {
141 std::iter::once(self.schema.yaml_path).chain(self.additional_yaml_paths.iter().copied())
142 }
143
144 /// Effective env vars: the override list if set, otherwise the schema's list.
145 pub fn effective_env_vars(&self) -> &'static [&'static str] {
146 self.env_var_override.unwrap_or(self.schema.env_vars)
147 }
148
149 /// Shape of the value: override if set, otherwise from the schema.
150 pub fn value_type(&self) -> ValueType {
151 self.value_type_override.unwrap_or(self.schema.value_type)
152 }
153}
154
155/// A fully resolved configuration key.
156#[derive(Debug)]
157pub struct ConfigKey {
158 /// All dot-separated YAML paths that deliver this value.
159 pub yaml_paths: Vec<&'static str>,
160
161 /// All environment variables that deliver this value.
162 pub env_vars: Vec<&'static str>,
163
164 /// Shape of the value.
165 pub value_type: ValueType,
166
167 /// Config structs that incorporate this key, as [`structs`] constants.
168 pub used_by: &'static [&'static str],
169}
170
171impl From<&SalukiAnnotation> for ConfigKey {
172 fn from(a: &SalukiAnnotation) -> Self {
173 ConfigKey {
174 yaml_paths: a.all_yaml_paths().collect(),
175 env_vars: a.effective_env_vars().to_vec(),
176 value_type: a.value_type(),
177 used_by: a.used_by,
178 }
179 }
180}
181
182// Generated module containing all annotation constants and the aggregation statics.
183include!("annotations_index.rs");