-
Notifications
You must be signed in to change notification settings - Fork 183
Expand file tree
/
Copy pathagent_info.rs
More file actions
142 lines (134 loc) · 5.12 KB
/
Copy pathagent_info.rs
File metadata and controls
142 lines (134 loc) · 5.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
// SPDX-License-Identifier: Apache-2.0
//! FFI wrappers that read from the agent /info SHM (`AgentInfoReader`) and propagate
//! the results to the concentrator and trace-filter subsystems.
//!
//! Both functions perform a single `reader.read()` call (advancing the internal SHM
//! position once) and use the returned `changed` flag to decide whether to rebuild
//! the concentrator and filter configuration.
use crate::stats::apply_concentrator_config;
use datadog_sidecar::service::agent_info::AgentInfoReader;
use libdd_common_ffi::slice::{AsBytes, CharSlice};
use libdd_data_pipeline::agent_info::schema::AgentInfoStruct;
use std::ffi::c_char;
use std::ffi::CString;
fn info_to_concentrator_config(info: &AgentInfoStruct) {
apply_concentrator_config(
info.peer_tags.as_deref().unwrap_or(&[]).to_owned(),
info.span_kinds_stats_computed
.as_deref()
.unwrap_or(&[])
.to_owned(),
info.filter_tags.require.to_owned(),
info.filter_tags.reject.to_owned(),
info.filter_tags_regex.require.to_owned(),
info.filter_tags_regex.reject.to_owned(),
info.ignore_resources.to_owned(),
info.client_drop_p0s.unwrap_or(false),
info.version.as_deref(),
);
}
/// Read all agent /info data in one SHM read and apply env, container-hash and concentrator
/// config atomically.
///
/// Fills `env_out` with the agent's `config.default_env` (zero-length slice if absent).
/// Fills `container_hash_out` with `container_tags_hash` (zero-length slice if absent).
/// Both slices borrow from the reader's cached info — valid until the next `reader.read()`.
///
/// Concentrator config (peer tags, span kinds, trace filters) is applied only when the
/// SHM has changed since the last read (`changed == true`). Calling this once at RINIT
/// ensures the config is always applied before the first span is processed, so the
/// per-span `ddog_apply_agent_info_concentrator_config` can safely rely on `changed` alone.
///
/// # Safety
/// `reader` must be a valid pointer to an `AgentInfoReader`.
#[no_mangle]
pub unsafe extern "C" fn ddog_apply_agent_info(
reader: &mut AgentInfoReader,
env_out: &mut CharSlice<'static>,
container_hash_out: &mut CharSlice<'static>,
) {
let (changed, info) = reader.read();
if let Some(info) = info {
if let Some(s) = info
.config
.as_ref()
.and_then(|c| c.default_env.as_deref())
.filter(|s| !s.is_empty())
{
*env_out = CharSlice::from_raw_parts(s.as_ptr() as *const c_char, s.len());
}
if changed {
if let Some(s) = info.container_tags_hash.as_deref().filter(|s| !s.is_empty()) {
*container_hash_out = CharSlice::from_raw_parts(s.as_ptr() as *const c_char, s.len());
} else {
*container_hash_out = CharSlice::empty();
}
info_to_concentrator_config(info);
}
}
}
/// Serialize the current cached agent info as a JSON string.
/// Returns NULL if no info has been read yet.
/// The returned pointer must be freed with `ddog_agent_info_json_free`.
#[no_mangle]
pub unsafe extern "C" fn ddog_agent_info_as_json(reader: &mut AgentInfoReader) -> *mut c_char {
let (changed, info) = reader.read();
if let Some(info) = info {
if changed {
info_to_concentrator_config(info);
}
CString::new(serde_json::to_string(info).unwrap()).unwrap().into_raw()
} else {
std::ptr::null_mut()
}
}
#[no_mangle]
pub extern "C" fn ddog_agent_info_json_free(ptr: *mut c_char) {
if !ptr.is_null() {
drop(unsafe { CString::from_raw(ptr) });
}
}
/// Returns whether the agent /info `endpoints` list advertises `endpoint` (e.g. `/v1.0/traces`);
/// false when no info has been received yet ("unknown" == "not advertised").
///
/// # Safety
/// `reader` must be a valid pointer to an `AgentInfoReader`.
#[no_mangle]
pub unsafe extern "C" fn ddog_agent_info_has_endpoint(
reader: &mut AgentInfoReader,
endpoint: CharSlice,
) -> bool {
let (changed, info) = reader.read();
if let Some(info) = info {
if changed {
info_to_concentrator_config(info);
}
let endpoint = endpoint.as_bytes();
return info
.endpoints
.as_deref()
.map_or(false, |eps| eps.iter().any(|e| e.as_bytes() == endpoint));
}
false
}
/// Apply concentrator config changes from the agent /info SHM.
///
/// Cheap no-op when the SHM has not changed (`changed == false`). Only applies when
/// new data has arrived mid-request — `ddog_apply_agent_info` at RINIT guarantees the
/// initial configuration is already in place, so `changed` alone is sufficient here.
///
/// # Safety
/// `reader` must be a valid pointer to an `AgentInfoReader`.
#[no_mangle]
pub unsafe extern "C" fn ddog_apply_agent_info_concentrator_config(
reader: &mut AgentInfoReader,
) {
let (changed, info) = reader.read();
if !changed {
return;
}
if let Some(info) = info {
info_to_concentrator_config(info);
}
}