relay_event_schema/protocol/span_v2/
container.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Deserialize, Serialize)]
7pub struct ContainerMetadata {
8 #[serde(skip_serializing_if = "Option::is_none")]
16 pub version: Option<u16>,
17 #[serde(skip_serializing_if = "Option::is_none")]
21 pub ingest_settings: Option<IngestSettings>,
22}
23
24#[derive(Debug, Clone, Deserialize, Serialize)]
28pub struct IngestSettings {
29 #[serde(
31 default,
32 skip_serializing_if = "Option::is_none",
33 deserialize_with = "none_on_error"
34 )]
35 pub infer_ip: Option<InferIp>,
36 #[serde(
38 default,
39 skip_serializing_if = "Option::is_none",
40 deserialize_with = "none_on_error"
41 )]
42 pub infer_user_agent: Option<InferUserAgent>,
43}
44
45#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
49pub enum InferIp {
50 #[serde(rename = "auto")]
52 Auto,
53 #[serde(rename = "never")]
55 Never,
56}
57
58impl InferIp {
59 pub fn is_auto(&self) -> bool {
61 matches!(self, Self::Auto)
62 }
63}
64
65#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
70pub enum InferUserAgent {
71 #[serde(rename = "auto")]
73 Auto,
74 #[serde(rename = "never")]
76 Never,
77}
78
79impl InferUserAgent {
80 pub fn is_auto(&self) -> bool {
82 matches!(self, Self::Auto)
83 }
84}
85
86fn none_on_error<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
87where
88 D: serde::de::Deserializer<'de>,
89 T: serde::de::DeserializeOwned + std::fmt::Debug,
90{
91 #[derive(Deserialize)]
92 #[serde(untagged)]
93 enum Try<T> {
94 T(T),
95 Err(serde::de::IgnoredAny),
96 }
97
98 Ok(match Try::<T>::deserialize(deserializer)? {
99 Try::T(t) => Some(t),
100 Try::Err(_) => None,
101 })
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn test_valid_round_trip() {
110 let m: ContainerMetadata = serde_json::from_str(
111 r#"{
112 "version": 123,
113 "ingest_settings": {
114 "infer_ip": "auto",
115 "infer_user_agent": "never"
116 }
117 }"#,
118 )
119 .unwrap();
120
121 insta::assert_json_snapshot!(&m, @r#"
122 {
123 "version": 123,
124 "ingest_settings": {
125 "infer_ip": "auto",
126 "infer_user_agent": "never"
127 }
128 }
129 "#);
130 }
131
132 #[test]
133 fn test_ingest_settings_invalid() {
134 let m: ContainerMetadata = serde_json::from_str(
135 r#"{"ingest_settings": {
136 "infer_ip": "unknown",
137 "infer_user_agent": 123
138 }}"#,
139 )
140 .unwrap();
141
142 insta::assert_json_snapshot!(&m, @r#"
143 {
144 "ingest_settings": {}
145 }
146 "#);
147 }
148
149 #[test]
150 fn test_version_invalid_fails() {
151 let _ = serde_json::from_str::<ContainerMetadata>(r#"{"version": {}}"#).unwrap_err();
152 }
153}