Skip to main content

libdd_telemetry/data/
payloads.rs

1// Copyright 2021-Present Datadog, Inc. https://www.datadoghq.com/
2// SPDX-License-Identifier: Apache-2.0
3
4use std::collections::HashMap;
5use std::hash::Hasher;
6
7use crate::data::metrics;
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone, Default)]
12pub struct Dependency {
13    pub name: String,
14    pub version: Option<String>,
15    pub hash: Option<String>,
16    pub metadata: Option<Vec<DependencyMetadata>>,
17}
18
19/// SCA metadata may be attached to a dependency after it was first reported; keying the store
20/// by this instead of the full struct means that update refreshes the existing entry instead of
21/// being stored (and re-sent) as a second entry for the same package/version.
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
23pub struct DependencyKey {
24    name: String,
25    version: Option<String>,
26    hash: Option<String>,
27}
28
29impl crate::worker::store::Keyed<DependencyKey> for Dependency {
30    fn key(&self) -> DependencyKey {
31        DependencyKey {
32            name: self.name.clone(),
33            version: self.version.clone(),
34            hash: self.hash.clone(),
35        }
36    }
37}
38
39#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone, Default)]
40pub struct DependencyMetadata {
41    pub r#type: String,
42    pub value: String,
43}
44
45#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone, Default)]
46pub struct Integration {
47    pub name: String,
48    pub enabled: bool,
49    pub version: Option<String>,
50    pub compatible: Option<bool>,
51    pub auto_enabled: Option<bool>,
52    #[serde(default)]
53    pub error: Option<String>,
54}
55
56#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone)]
57pub struct Configuration {
58    pub name: String,
59    pub value: Option<String>, // distinguish `null` from ""
60    pub origin: ConfigurationOrigin,
61    pub config_id: Option<String>,
62    pub seq_id: Option<u64>,
63}
64
65#[derive(
66    Serialize,
67    Deserialize,
68    Debug,
69    Hash,
70    PartialEq,
71    Eq,
72    Clone,
73    Copy,
74    strum_macros::Display,
75    strum_macros::EnumIter,
76    strum_macros::IntoStaticStr,
77)]
78#[repr(C)]
79#[serde(rename_all = "snake_case")]
80#[strum(serialize_all = "snake_case")]
81pub enum ConfigurationOrigin {
82    EnvVar,
83    Code,
84    DdConfig,
85    RemoteConfig,
86    Default,
87    LocalStableConfig,
88    FleetStableConfig,
89    Calculated,
90    OtelEnvVar,
91    Ini,
92    Unknown,
93}
94
95#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
96pub struct Error {
97    pub code: Option<i64>,
98    pub message: Option<String>,
99}
100
101#[derive(Serialize, Debug)]
102pub struct AppStarted {
103    pub configuration: Vec<Configuration>,
104    pub dependencies: Vec<Dependency>,
105    pub integrations: Vec<Integration>,
106    #[serde(skip_serializing_if = "Option::is_none")]
107    pub install_signature: Option<InstallSignature>,
108    #[serde(skip_serializing_if = "HashMap::is_empty")]
109    pub products: HashMap<String, ProductState>,
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub error: Option<Error>,
112}
113
114#[derive(Serialize, Debug, Clone)]
115pub struct InstallSignature {
116    pub install_id: Option<String>,
117    pub install_type: Option<String>,
118    pub install_time: Option<String>,
119}
120
121#[derive(Serialize, Debug)]
122pub struct AppDependenciesLoaded {
123    pub dependencies: Vec<Dependency>,
124}
125
126#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
127pub struct ProductState {
128    pub enabled: bool,
129    pub version: Option<String>,
130    pub error: Option<Error>,
131}
132
133#[derive(Serialize, Debug)]
134pub struct AppProductChange {
135    pub products: HashMap<String, ProductState>,
136}
137
138#[derive(Serialize, Debug)]
139pub struct AppIntegrationsChange {
140    pub integrations: Vec<Integration>,
141}
142
143#[derive(Debug, Serialize)]
144pub struct AppClientConfigurationChange {
145    pub configuration: Vec<Configuration>,
146}
147
148#[derive(Debug, Serialize)]
149pub struct AppEndpoints {
150    pub is_first: bool,
151    pub endpoints: Vec<serde_json::Value>,
152}
153
154#[derive(Serialize, Debug)]
155pub struct GenerateMetrics {
156    pub series: Vec<metrics::Serie>,
157}
158
159#[derive(Serialize, Debug)]
160pub struct Distributions {
161    pub series: Vec<metrics::Distribution>,
162}
163
164#[derive(Serialize, Deserialize, Debug, Clone)]
165pub struct Log {
166    pub message: String,
167    pub level: LogLevel,
168    pub count: u32,
169
170    #[serde(default)]
171    pub stack_trace: Option<String>,
172    #[serde(default)]
173    pub tags: String,
174    #[serde(default)]
175    pub is_sensitive: bool,
176    #[serde(default)]
177    pub is_crash: bool,
178}
179
180#[derive(
181    Serialize,
182    Deserialize,
183    Debug,
184    PartialEq,
185    Eq,
186    Hash,
187    Clone,
188    Copy,
189    strum_macros::Display,
190    strum_macros::EnumIter,
191    // IntoStaticStr: required by the pre-9488 `ConvertToPyO3Enum` macro; see metrics.rs.
192    strum_macros::IntoStaticStr,
193)]
194#[serde(rename_all = "UPPERCASE")]
195#[strum(serialize_all = "UPPERCASE")]
196#[repr(C)]
197pub enum LogLevel {
198    Error,
199    Warn,
200    Debug,
201}
202
203#[derive(Serialize, Debug)]
204pub struct Logs {
205    pub logs: Vec<Log>,
206}
207
208#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
209#[serde(rename_all = "UPPERCASE")]
210#[repr(C)]
211pub enum Method {
212    Get = 0,
213    Post = 1,
214    Put = 2,
215    Delete = 3,
216    Patch = 4,
217    Head = 5,
218    Options = 6,
219    Trace = 7,
220    Connect = 8,
221    // The OpenAPI spec uses "*" for this variant. Whether "Other" accurately
222    // describes the "*" concept (any method) or whether it should be a
223    // catch-all for unknown methods is unclear.
224    #[serde(rename = "*")]
225    Other = 9,
226}
227
228#[derive(Serialize, Deserialize, Debug, Clone, Default)]
229pub struct Endpoint {
230    #[serde(default)]
231    pub method: Option<Method>,
232    #[serde(default)]
233    pub path: Option<String>,
234    pub operation_name: String,
235    pub resource_name: String,
236    #[serde(default)]
237    pub request_body_type: Option<Vec<String>>,
238    #[serde(default)]
239    pub response_body_type: Option<Vec<String>>,
240    #[serde(default)]
241    pub response_code: Option<Vec<u32>>,
242}
243
244impl PartialEq for Endpoint {
245    fn eq(&self, other: &Self) -> bool {
246        self.resource_name == other.resource_name
247    }
248}
249
250impl Eq for Endpoint {}
251
252impl std::hash::Hash for Endpoint {
253    fn hash<H: Hasher>(&self, state: &mut H) {
254        self.resource_name.hash(state);
255    }
256}
257
258impl Endpoint {
259    pub fn to_json_value(&self) -> serde_json::Result<serde_json::Value> {
260        serde_json::to_value(self)
261    }
262}