saluki_components/common/datadog/
protocol.rs

1//! Protocol version types for Datadog payloads.
2
3use std::collections::{BTreeSet, HashMap};
4
5use agent_data_plane_config::shared::{
6    MetricsEncoding as TypedMetricsEncoding, V3ApiEncoding as TypedV3ApiEncoding, V3ApiSettings as TypedV3ApiSettings,
7    V3SeriesMode,
8};
9use serde::{Deserialize, Serialize};
10
11/// How an encoded metric payload is targeted within the normal Datadog endpoint set.
12///
13/// Endpoint names match the configured primary or additional endpoint identity. A metrics-only primary override
14/// inherits the normal primary's policy identity, while retaining its own destination and protocol settings.
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub enum MetricsEndpointRouting {
17    /// The full metric stream goes to endpoints without an allowlist policy.
18    AllExcept(BTreeSet<String>),
19    /// A filtered metric stream goes only to the endpoints sharing its allowlist.
20    Only(BTreeSet<String>),
21}
22
23impl MetricsEndpointRouting {
24    /// Returns whether this payload targets the given configured endpoint.
25    pub(crate) fn should_route_to(&self, configured_endpoint: &str) -> bool {
26        match self {
27            Self::AllExcept(endpoints) => !endpoints.contains(configured_endpoint),
28            Self::Only(endpoints) => endpoints.contains(configured_endpoint),
29        }
30    }
31}
32
33/// The type of metrics payload.
34#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
35pub enum MetricsPayloadType {
36    /// Series metrics (counters, gauges, rates, sets).
37    Series,
38
39    /// Sketch metrics (histograms, distributions).
40    Sketches,
41}
42
43/// Protocol version for metrics payloads.
44#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
45pub enum MetricsProtocolVersion {
46    /// V2 protocol (legacy format).
47    V2,
48
49    /// V3 protocol (columnar format).
50    V3,
51}
52
53/// Combined payload info for metrics, encoding both protocol version and metric type.
54///
55/// This is stored in `PayloadMetadata` and used by the I/O layer to filter payloads
56/// based on endpoint V3 settings.
57#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
58pub struct MetricsPayloadInfo {
59    /// The protocol version (V2 or V3).
60    pub version: MetricsProtocolVersion,
61
62    /// The type of metrics (series or sketches).
63    pub payload_type: MetricsPayloadType,
64}
65
66impl MetricsPayloadInfo {
67    /// Creates a new V2 series payload info.
68    pub const fn v2_series() -> Self {
69        Self {
70            version: MetricsProtocolVersion::V2,
71            payload_type: MetricsPayloadType::Series,
72        }
73    }
74
75    /// Creates a new V2 sketches payload info.
76    pub const fn v2_sketches() -> Self {
77        Self {
78            version: MetricsProtocolVersion::V2,
79            payload_type: MetricsPayloadType::Sketches,
80        }
81    }
82
83    /// Creates a new V3 series payload info.
84    pub const fn v3_series() -> Self {
85        Self {
86            version: MetricsProtocolVersion::V3,
87            payload_type: MetricsPayloadType::Series,
88        }
89    }
90
91    /// Creates a new V3 sketches payload info.
92    pub const fn v3_sketches() -> Self {
93        Self {
94            version: MetricsProtocolVersion::V3,
95            payload_type: MetricsPayloadType::Sketches,
96        }
97    }
98
99    /// Returns true if this is a sketch payload.
100    pub const fn is_sketch(&self) -> bool {
101        matches!(self.payload_type, MetricsPayloadType::Sketches)
102    }
103}
104
105/// V3 API settings for a specific metric type (series or sketches).
106#[derive(Clone, Debug, Default, PartialEq)]
107pub struct V3ApiSettings {
108    /// Endpoints that should receive V3 payloads for this metric type.
109    ///
110    /// Each entry should be a configured endpoint name, such as `https://app.datadoghq.com`.
111    /// If empty, no V3 payloads are generated for this metric type.
112    pub endpoints: Vec<String>,
113}
114
115impl V3ApiSettings {
116    /// Returns true if V3 is enabled for any endpoint.
117    pub fn is_enabled(&self) -> bool {
118        !self.endpoints.is_empty()
119    }
120}
121
122/// V3 API configuration for per-endpoint V3 support.
123#[derive(Clone, Debug, Default, PartialEq)]
124pub struct V3ApiConfig {
125    /// V3 settings for sketch metrics (histograms, distributions).
126    pub sketches: V3ApiSettings,
127
128    /// Override compression level for V3 payloads.
129    ///
130    /// A value of `0` uses the normal serializer compression level.
131    pub compression_level: i32,
132}
133
134impl V3ApiConfig {
135    /// Returns true if V3 is enabled for sketch metrics.
136    pub fn use_v3_sketches(&self) -> bool {
137        self.sketches.is_enabled()
138    }
139}
140
141impl From<&TypedV3ApiSettings> for V3ApiSettings {
142    fn from(settings: &TypedV3ApiSettings) -> Self {
143        Self {
144            endpoints: settings.endpoints.clone(),
145        }
146    }
147}
148
149impl From<&TypedV3ApiEncoding> for V3ApiConfig {
150    fn from(config: &TypedV3ApiEncoding) -> Self {
151        Self {
152            sketches: (&config.sketches).into(),
153            compression_level: config.compression_level,
154        }
155    }
156}
157
158/// The Datadog Agent's `use_v3_api` configuration section.
159#[derive(Clone, Debug, Default, PartialEq)]
160pub struct UseV3ApiConfig {
161    /// Agent-compatible V3 API configuration for series metrics.
162    pub series: UseV3ApiSeriesConfig,
163}
164
165/// Agent-compatible `use_v3_api.series` configuration.
166#[derive(Clone, Debug, Default, PartialEq)]
167pub struct UseV3ApiSeriesConfig {
168    /// Global V3 series mode.
169    pub enabled: V3SeriesMode,
170
171    /// Per-endpoint V3 series mode overrides.
172    pub endpoints: HashMap<String, V3SeriesMode>,
173}
174
175impl From<&TypedMetricsEncoding> for UseV3ApiSeriesConfig {
176    fn from(config: &TypedMetricsEncoding) -> Self {
177        Self {
178            enabled: config.v3_series_mode,
179            endpoints: config.v3_series_endpoint_modes.clone(),
180        }
181    }
182}