libdd_library_config/
tracer_metadata.rs1use libdd_trace_protobuf::opentelemetry::proto as otel_proto;
4use std::default::Default;
5
6#[derive(serde::Serialize, Debug)]
8pub struct TracerMetadata {
9 pub schema_version: u8,
11 #[serde(skip_serializing_if = "Option::is_none")]
13 pub runtime_id: Option<String>,
14 pub tracer_language: String,
17 pub tracer_version: String,
19 pub hostname: String,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub service_name: Option<String>,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub service_env: Option<String>,
27 #[serde(skip_serializing_if = "Option::is_none")]
29 pub service_version: Option<String>,
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub process_tags: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub container_id: Option<String>,
36}
37
38impl Default for TracerMetadata {
39 fn default() -> Self {
40 TracerMetadata {
41 schema_version: 2,
42 runtime_id: None,
43 tracer_language: String::new(),
44 tracer_version: String::new(),
45 hostname: String::new(),
46 service_name: None,
47 service_env: None,
48 service_version: None,
49 process_tags: None,
50 container_id: None,
51 }
52 }
53}
54
55impl TracerMetadata {
56 const OTEL_SDK_NAME: &str = "libdatadog";
58
59 pub fn to_otel_process_ctx(&self) -> otel_proto::common::v1::ProcessContext {
60 use otel_proto::common::v1::{any_value, AnyValue, KeyValue};
61
62 fn key_value(key: &'static str, val: String) -> KeyValue {
63 KeyValue {
64 key: key.to_owned(),
65 value: Some(AnyValue {
66 value: Some(any_value::Value::StringValue(val)),
67 }),
68 key_ref: 0,
69 }
70 }
71
72 fn key_value_opt(key: &'static str, val: &Option<String>) -> KeyValue {
75 key_value(key, val.as_ref().cloned().unwrap_or_default())
76 }
77
78 let TracerMetadata {
81 schema_version: _,
83 runtime_id,
84 tracer_language,
85 tracer_version,
86 hostname,
87 service_name,
88 service_env,
89 service_version,
90 process_tags,
91 container_id,
92 } = self;
93
94 otel_proto::common::v1::ProcessContext {
95 resource: Some(otel_proto::resource::v1::Resource {
96 attributes: vec![
97 key_value_opt("service.name", service_name),
98 key_value_opt("service.instance.id", runtime_id),
99 key_value_opt("service.version", service_version),
100 key_value_opt("deployment.environment.name", service_env),
101 key_value("telemetry.sdk.language", tracer_language.clone()),
102 key_value("telemetry.sdk.version", tracer_version.clone()),
103 key_value("telemetry.sdk.name", Self::OTEL_SDK_NAME.to_owned()),
104 key_value("host.name", hostname.clone()),
105 key_value_opt("container.id", container_id),
106 ],
107 dropped_attributes_count: 0,
108 entity_refs: vec![],
109 }),
110 extra_attributes: vec![key_value_opt("datadog.process_tags", process_tags)],
111 }
112 }
113}
114
115pub enum AnonymousFileHandle {
116 #[cfg(target_os = "linux")]
117 Linux(memfd::Memfd),
118 #[cfg(not(target_os = "linux"))]
119 Other(()),
120}
121
122#[cfg(target_os = "linux")]
123mod linux {
124 use anyhow::Context;
125 use rand::distributions::Alphanumeric;
126 use rand::Rng;
127 use std::io::Write;
128
129 pub fn store_tracer_metadata(
132 data: &super::TracerMetadata,
133 ) -> anyhow::Result<super::AnonymousFileHandle> {
134 let _ = crate::otel_process_ctx::linux::publish(&data.to_otel_process_ctx());
135
136 let uid: String = rand::thread_rng()
137 .sample_iter(&Alphanumeric)
138 .take(8)
139 .map(char::from)
140 .collect();
141
142 let mfd_name: String = format!("datadog-tracer-info-{uid}");
143
144 let mfd = memfd::MemfdOptions::default()
145 .close_on_exec(true)
146 .allow_sealing(true)
147 .create::<&str>(mfd_name.as_ref())
148 .context("unable to create memfd")?;
149
150 let buf = rmp_serde::to_vec_named(data).context("failed serialization")?;
151 mfd.as_file()
152 .write_all(&buf)
153 .context("unable to write into memfd")?;
154
155 mfd.add_seals(&[
156 memfd::FileSeal::SealShrink,
157 memfd::FileSeal::SealGrow,
158 memfd::FileSeal::SealSeal,
159 ])
160 .context("unable to seal memfd")?;
161
162 Ok(super::AnonymousFileHandle::Linux(mfd))
163 }
164}
165
166#[cfg(not(target_os = "linux"))]
167mod other {
168 pub fn store_tracer_metadata(
169 _data: &super::TracerMetadata,
170 ) -> anyhow::Result<super::AnonymousFileHandle> {
171 Ok(super::AnonymousFileHandle::Other(()))
172 }
173}
174
175#[cfg(target_os = "linux")]
176pub use linux::*;
177#[cfg(not(target_os = "linux"))]
178pub use other::*;