Skip to content

Commit acd5a0d

Browse files
dd-octo-sts[bot]github-actions[bot]bwoebi
authored
libdatadog update to 15899dfe (#4006)
* libdatadog update to 15899dfe Automated update by CI pipeline https://gitlab.ddbuild.io/DataDog/apm-reliability/dd-trace-php/-/pipelines/126695654 Full CI result: ❌ 148 job(s) failed * libdatadog update to 15899dfe [no-ci-feedback] Automated update by CI pipeline https://gitlab.ddbuild.io/DataDog/apm-reliability/dd-trace-php/-/pipelines/126697886 Full CI result: ❌ 248 job(s) failed * Avoid a dedicated socket for crashtracker Update for libdatadog changes. Signed-off-by: Bob Weinand <bob.weinand@datadoghq.com> Help distinguishing debug logs by url for parallel requests Signed-off-by: Bob Weinand <bob.weinand@datadoghq.com> * Fixup testsuite Signed-off-by: Bob Weinand <bob.weinand@datadoghq.com> * Fix windows Signed-off-by: Bob Weinand <bob.weinand@datadoghq.com> * libdatadog update --------- Signed-off-by: Bob Weinand <bob.weinand@datadoghq.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Bob Weinand <bob.weinand@datadoghq.com>
1 parent f068c9e commit acd5a0d

32 files changed

Lines changed: 348 additions & 176 deletions

Cargo.lock

Lines changed: 86 additions & 46 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ inherits = "release"
3333
# These are to satistfy the build with libdatadog as a path dependency inside
3434
# components-rs. There may be a better way to fix this, but I'm alreday two
3535
# tasks removed from what I'm trying to do, so pushing forward.
36+
#
37+
# Every dependency that a libdatadog crate inherits via `{ workspace = true }`
38+
# must be declared here, because those crates resolve their workspace
39+
# inheritance against this manifest when built as path dependencies. Keep this
40+
# list in sync with libdatadog's own `[workspace.dependencies]`; libdatadog
41+
# #2253 consolidated `anyhow`, `serde`, `tokio` and `tracing` to the workspace
42+
# level, so they are mirrored here too.
3643
[workspace.dependencies]
44+
anyhow = { version = "1.0", default-features = false }
3745
arc-swap = "1.7.1"
3846
hyper = { version = "1.6", features = [
3947
"http1",
@@ -44,6 +52,9 @@ hyper-util = { version = "0.1.10", features = [
4452
"client",
4553
"client-legacy",
4654
] }
55+
serde = { version = "1.0", default-features = false }
56+
tokio = { version = "1.36", default-features = false }
57+
tracing = { version = "0.1", default-features = false }
4758

4859
[workspace.lints]
4960
# empty for compat with libdatadog

cbindgen.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ rename_types = "PascalCase"
2424
"ZendString" = "_zend_string"
2525
"FILE" = "FILE"
2626
"EndpointConfig" = "ddog_crasht_EndpointConfig"
27+
"Metadata" = "ddog_crasht_Metadata"
2728
"MaybeOwnedZendString" = "_zend_string *"
2829

2930
[enum]

components-rs/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ libdd-data-pipeline = { path = "../libdatadog/libdd-data-pipeline" }
2323
libdd-tinybytes = { path = "../libdatadog/libdd-tinybytes" }
2424
libdd-trace-utils = { path = "../libdatadog/libdd-trace-utils" }
2525
libdd-trace-stats = { path = "../libdatadog/libdd-trace-stats" }
26+
libdd-trace-protobuf = { path = "../libdatadog/libdd-trace-protobuf" }
27+
libdd-crashtracker = { path = "../libdatadog/libdd-crashtracker", default-features = false, features = ["collector"] }
2628
libdd-crashtracker-ffi = { path = "../libdatadog/libdd-crashtracker-ffi", default-features = false, features = ["collector"] }
2729
libdd-library-config-ffi = { path = "../libdatadog/libdd-library-config-ffi", default-features = false }
2830
spawn_worker = { path = "../libdatadog/spawn_worker" }

components-rs/common.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@
5252

5353
typedef struct ddog_Endpoint ddog_Endpoint;
5454

55-
typedef struct ddog_Tag ddog_Tag;
56-
5755
/**
5856
* Holds the raw parts of a Rust Vec; it should only be created from Rust,
5957
* never from C.
@@ -412,8 +410,11 @@ typedef enum ddog_RemoteConfigCapabilities {
412410
DDOG_REMOTE_CONFIG_CAPABILITIES_APM_TRACING_ENABLE_LIVE_DEBUGGING = 41,
413411
DDOG_REMOTE_CONFIG_CAPABILITIES_ASM_DD_MULTICONFIG = 42,
414412
DDOG_REMOTE_CONFIG_CAPABILITIES_ASM_TRACE_TAGGING_RULES = 43,
413+
DDOG_REMOTE_CONFIG_CAPABILITIES_ASM_EXTENDED_DATA_COLLECTION = 44,
415414
DDOG_REMOTE_CONFIG_CAPABILITIES_APM_TRACING_MULTICONFIG = 45,
416415
DDOG_REMOTE_CONFIG_CAPABILITIES_FFE_FLAG_CONFIGURATION_RULES = 46,
416+
DDOG_REMOTE_CONFIG_CAPABILITIES_DD_DATA_STREAMS_TRANSACTION_EXTRACTORS = 47,
417+
DDOG_REMOTE_CONFIG_CAPABILITIES_LLM_OBS_ACTIVATION = 48,
417418
} ddog_RemoteConfigCapabilities;
418419

419420
typedef enum ddog_RemoteConfigProduct {
@@ -426,6 +427,7 @@ typedef enum ddog_RemoteConfigProduct {
426427
DDOG_REMOTE_CONFIG_PRODUCT_ASM_FEATURES,
427428
DDOG_REMOTE_CONFIG_PRODUCT_FFE_FLAGS,
428429
DDOG_REMOTE_CONFIG_PRODUCT_LIVE_DEBUGGER,
430+
DDOG_REMOTE_CONFIG_PRODUCT_LIVE_DEBUGGER_SYMBOL_DB,
429431
} ddog_RemoteConfigProduct;
430432

431433
typedef enum ddog_SpanProbeTarget {
@@ -1110,9 +1112,10 @@ typedef struct ddog_TelemetryWorkerBuilder ddog_TelemetryWorkerBuilder;
11101112
* The worker won't send data to the agent until you call `TelemetryWorkerHandle::send_start`
11111113
*
11121114
* To stop the worker, call `TelemetryWorkerHandle::send_stop` which trigger flush asynchronously
1113-
* then `TelemetryWorkerHandle::wait_for_shutdown`
1115+
* then `TelemetryWorkerHandle::wait_for_shutdown` (native only — wasm callers rely on the
1116+
* SharedRuntime worker JoinHandle instead).
11141117
*/
1115-
typedef struct ddog_TelemetryWorkerHandle ddog_TelemetryWorkerHandle;
1118+
typedef struct ddog_TelemetryWorkerHandle_NativeCapabilities ddog_TelemetryWorkerHandle_NativeCapabilities;
11161119

11171120
typedef enum ddog_Option_U64_Tag {
11181121
DDOG_OPTION_U64_SOME_U64,
@@ -1128,6 +1131,12 @@ typedef struct ddog_Option_U64 {
11281131
};
11291132
} ddog_Option_U64;
11301133

1134+
/**
1135+
* FFI-facing alias: the C ABI surface is native-only, so the worker handle is
1136+
* always pinned to [`NativeCapabilities`].
1137+
*/
1138+
typedef struct ddog_TelemetryWorkerHandle_NativeCapabilities ddog_TelemetryWorkerHandle;
1139+
11311140
typedef enum ddog_Option_Bool_Tag {
11321141
DDOG_OPTION_BOOL_SOME_BOOL,
11331142
DDOG_OPTION_BOOL_NONE_BOOL,

components-rs/datadog.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,26 @@ struct ddog_Endpoint *datadog_otel_metrics_endpoint_from_url(ddog_CharSlice url)
5555

5656
struct ddog_Endpoint *datadog_otel_metrics_endpoint_from_agent_url(ddog_CharSlice url);
5757

58-
void datadog_endpoint_as_crashtracker_config(const struct ddog_Endpoint *endpoint,
59-
void (*callback)(ddog_crasht_EndpointConfig, void*),
60-
void *userdata);
58+
/**
59+
* Initialize crashtracking, selecting the receiver strategy for this process:
60+
* - Linux, sidecar host (`master_pid == getpid()`): the in-process thread-mode sidecar can't
61+
* serve its own crash, so spawn a fork+exec subprocess receiver (like the standalone daemon),
62+
* resolving frames there since a crashing process can't reliably symbolize itself.
63+
* - Linux, worker/collector: connect to the sidecar IPC socket and upgrade it to a crashtracker
64+
* receiver on crash (`SOCK_SEQPACKET` + `enter_crashtracker_receiver`), streaming the report
65+
* over that single socket and resolving frames in-process.
66+
* - other unix (macOS): no sidecar upgrade; the default connector reaches the socket path.
67+
*
68+
* `master_pid` is the thread-mode master listener PID (0 if none): it keys the IPC socket and, on
69+
* Linux, distinguishes the host from a worker.
70+
*
71+
* # Safety
72+
* `endpoint` must point to a valid `Endpoint`; `metadata`'s borrowed strings/tags must outlive the
73+
* call (they are copied into owned storage before it returns).
74+
*/
75+
ddog_MaybeError datadog_crashtracker_init(const struct ddog_Endpoint *endpoint,
76+
ddog_crasht_Metadata metadata,
77+
int32_t master_pid);
6178

6279
ddog_Configurator *ddog_library_configurator_new_dummy(bool debug_logs, ddog_CharSlice language);
6380

@@ -189,7 +206,12 @@ void ddog_rshutdown_remote_config(struct ddog_RemoteConfigState *remote_config);
189206

190207
void ddog_shutdown_remote_config(struct ddog_RemoteConfigState*);
191208

192-
void ddog_drop_probe(struct ddog_Probe probe);
209+
/**
210+
* Free the FFI-owned allocations in a `Probe` (the `tags` vec and the nested
211+
* span-decoration / log allocations) by consuming it; borrowed `CharSlice`s are
212+
* left untouched. Called from `dd_probe_dtor` when a probe is uninstalled.
213+
*/
214+
void ddog_drop_probe(struct ddog_Probe);
193215

194216
void ddog_log_debugger_data(const struct ddog_Vec_DebuggerPayload *payloads);
195217

components-rs/lib.rs

Lines changed: 137 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use std::ffi::{c_char, OsStr};
2222
use std::path::Path;
2323
use std::ptr::null_mut;
2424
use uuid::Uuid;
25-
25+
#[cfg(unix)]
26+
use datadog_sidecar::crashtracker::crashtracker_receiver_request_bytes;
2627
pub use libdd_crashtracker_ffi::*;
2728
pub use libdd_library_config_ffi::*;
2829
pub use datadog_sidecar_ffi::*;
@@ -196,26 +197,144 @@ pub unsafe extern "C" fn datadog_otel_metrics_endpoint_from_agent_url(url: CharS
196197
}
197198
}
198199

199-
#[no_mangle]
200+
/// Initialize crashtracking, selecting the receiver strategy for this process:
201+
/// - Linux, sidecar host (`master_pid == getpid()`): the in-process thread-mode sidecar can't
202+
/// serve its own crash, so spawn a fork+exec subprocess receiver (like the standalone daemon),
203+
/// resolving frames there since a crashing process can't reliably symbolize itself.
204+
/// - Linux, worker/collector: connect to the sidecar IPC socket and upgrade it to a crashtracker
205+
/// receiver on crash (`SOCK_SEQPACKET` + `enter_crashtracker_receiver`), streaming the report
206+
/// over that single socket and resolving frames in-process.
207+
/// - other unix (macOS): no sidecar upgrade; the default connector reaches the socket path.
208+
///
209+
/// `master_pid` is the thread-mode master listener PID (0 if none): it keys the IPC socket and, on
210+
/// Linux, distinguishes the host from a worker.
211+
///
212+
/// # Safety
213+
/// `endpoint` must point to a valid `Endpoint`; `metadata`'s borrowed strings/tags must outlive the
214+
/// call (they are copied into owned storage before it returns).
200215
#[cfg(unix)]
201-
pub unsafe extern "C" fn datadog_endpoint_as_crashtracker_config(
216+
#[no_mangle]
217+
#[allow(clippy::missing_safety_doc)]
218+
pub unsafe extern "C" fn datadog_crashtracker_init(
202219
endpoint: &Endpoint,
203-
callback: unsafe extern "C" fn(EndpointConfig<'_>, *mut std::ffi::c_void),
204-
userdata: *mut std::ffi::c_void,
205-
) {
206-
let url_str = endpoint.url.to_string();
207-
unsafe {
208-
callback(
209-
EndpointConfig {
210-
url: CharSlice::from(url_str.as_str()),
211-
api_key: CharSlice::from(endpoint.api_key.as_deref().unwrap_or("")),
212-
test_token: CharSlice::from(endpoint.test_token.as_deref().unwrap_or("")),
213-
timeout: endpoint.timeout_ms,
214-
use_system_resolver: endpoint.use_system_resolver,
215-
},
216-
userdata,
217-
);
220+
metadata: Metadata,
221+
master_pid: i32,
222+
) -> MaybeError {
223+
use libdd_crashtracker::{CrashtrackerConfiguration, StacktraceCollection};
224+
225+
let result = (|| -> anyhow::Result<()> {
226+
let metadata: libdd_crashtracker::Metadata = metadata.try_into()?;
227+
228+
let mut builder = CrashtrackerConfiguration::builder()
229+
.collect_all_threads(true)
230+
.timeout(std::time::Duration::from_millis(5000))
231+
.endpoint_use_system_resolver(endpoint.use_system_resolver)
232+
.endpoint_url(&endpoint.url.to_string());
233+
if let Some(api_key) = endpoint.api_key.as_deref() {
234+
builder = builder.endpoint_api_key(api_key);
235+
}
236+
if let Some(test_token) = endpoint.test_token.as_deref() {
237+
builder = builder.endpoint_test_token(test_token);
238+
}
239+
if endpoint.timeout_ms != 0 {
240+
builder = builder.endpoint_timeout_ms(endpoint.timeout_ms);
241+
}
242+
243+
#[cfg(target_os = "linux")]
244+
{
245+
// Worker/collector: open a fresh connection to the sidecar IPC socket, upgrade it with
246+
// the SEQPACKET connector, and resolve frames in-process.
247+
if master_pid == 0 || master_pid != std::process::id() as i32 {
248+
let socket_path = datadog_sidecar::crashtracker::crashtracker_ipc_socket_path(
249+
master_pid as u32,
250+
datadog_sidecar::config::FromEnv::ipc_mode(),
251+
);
252+
// Prime the request bytes outside the crash handler so the connector never
253+
// allocates in signal context.
254+
let _ = crashtracker_receiver_request_bytes();
255+
let config = builder
256+
.resolve_frames(StacktraceCollection::EnabledWithInprocessSymbols)
257+
.unix_socket_path(socket_path.to_string_lossy().into_owned())
258+
.unix_socket_connector(
259+
datadog_sidecar::crashtracker::connect_to_sidecar_receiver,
260+
)
261+
.build()?;
262+
return libdd_crashtracker::init(
263+
config,
264+
libdd_crashtracker::CrashtrackerReceiverConfig::default(),
265+
metadata,
266+
);
267+
}
268+
// Thread-mode host: its in-process sidecar can't serve its own crash, so spawn a
269+
// transient fork+exec subprocess receiver and resolve frames there.
270+
let config = builder
271+
.resolve_frames(StacktraceCollection::EnabledWithSymbolsInReceiver)
272+
.build()?;
273+
let receiver_config =
274+
datadog_sidecar::build_crashtracker_receiver_config(None, None)?;
275+
libdd_crashtracker::init(config, receiver_config, metadata)
276+
}
277+
278+
// macOS can't open a fresh SOCK_SEQPACKET connection signal-safely, so reuse the
279+
// already-open sidecar fd and upgrade it at crash time (no-op if there's no connection).
280+
// The path is a placeholder the connector ignores; it just has to be non-empty so the
281+
// crashtracker takes the connector path.
282+
#[cfg(target_os = "macos")]
283+
{
284+
// Prime the request bytes outside the crash handler so the connector never
285+
// allocates in signal context.
286+
let _ = crashtracker_receiver_request_bytes();
287+
let config = builder
288+
.resolve_frames(StacktraceCollection::EnabledWithInprocessSymbols)
289+
.unix_socket_path("datadog-sidecar-crashtracker".to_string())
290+
.unix_socket_connector(reuse_sidecar_fd_connector)
291+
.build()?;
292+
libdd_crashtracker::init(
293+
config,
294+
libdd_crashtracker::CrashtrackerReceiverConfig::default(),
295+
metadata,
296+
)
297+
}
298+
299+
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
300+
{
301+
let _ = (master_pid, builder, metadata);
302+
Ok(())
303+
}
304+
})();
305+
match result {
306+
Ok(()) => MaybeError::None,
307+
Err(e) => {
308+
MaybeError::Some(Error::from(format!("{e:?}")))
309+
}
310+
}
311+
}
312+
313+
/// On macos we cannot easily create a new signal safe connection to the sidecar, so we reuse the
314+
/// already open fd from datadog_sidecar_for_signal.
315+
#[cfg(target_os = "macos")]
316+
fn reuse_sidecar_fd_connector(_unix_socket_path: &str) -> std::os::fd::RawFd {
317+
extern "C" {
318+
// Set by the sidecar connect path (sidecar.c) to the live transport for best-effort
319+
// signal-handler use; null when there is no connection. The transport pointer is stable
320+
// across transparent reconnects (only its inner sender is swapped), so reading the fd
321+
// through it stays current. Typed as an opaque pointer to keep the `extern` block FFI-safe;
322+
// cast to the real type below.
323+
static mut datadog_sidecar_for_signal: *mut std::ffi::c_void;
324+
}
325+
326+
// Best-effort, signal context: read the transport pointer and get its current fd via
327+
// SidecarTransport::signal_fd (which uses get_mut, never locking). Going through the raw
328+
// pointer knowingly bypasses aliasing checks — the crashing thread is the only realistic
329+
// accessor.
330+
let transport = unsafe { datadog_sidecar_for_signal }
331+
as *mut datadog_sidecar::service::blocking::SidecarTransport;
332+
if transport.is_null() {
333+
return -1;
218334
}
335+
let fd = unsafe { (*transport).as_raw_fd() };
336+
let bytes = crashtracker_receiver_request_bytes();
337+
let sent = unsafe { libc::send(dup, bytes.as_ptr() as *const libc::c_void, bytes.len(), 0) };
219338
}
220339

221340
// Hack: Without this, the PECL build of the tracer does not contain the ddog_library_* functions
57.8 KB
Binary file not shown.

components-rs/remote_config.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -650,13 +650,13 @@ pub extern "C" fn ddog_remote_configs_service_env_change(
650650
tags: &libdd_common_ffi::Vec<Tag>,
651651
process_tags: &libdd_common_ffi::Vec<Tag>,
652652
) -> bool {
653-
let new_target = Target {
654-
service: service.to_utf8_lossy().to_string(),
655-
env: env.to_utf8_lossy().to_string(),
656-
app_version: version.to_utf8_lossy().to_string(),
657-
tags: tags.as_slice().to_vec(),
658-
process_tags: process_tags.as_slice().to_vec(),
659-
};
653+
let new_target = Target::new(
654+
service.to_utf8_lossy().to_string(),
655+
env.to_utf8_lossy().to_string(),
656+
version.to_utf8_lossy().to_string(),
657+
tags.as_slice().iter().map(|t| t.to_string()).collect(),
658+
process_tags.as_slice().iter().map(|t| t.to_string()).collect(),
659+
);
660660

661661
if let Some(target) = remote_config.manager.get_target() {
662662
if **target == new_target {
@@ -798,7 +798,7 @@ pub unsafe extern "C" fn ddog_send_debugger_diagnostics<'a>(
798798
remote_config_state
799799
.manager
800800
.get_target()
801-
.map_or("", |t| t.service.as_str()),
801+
.map_or("", |t| t.service()),
802802
);
803803
let mut payload = ddog_debugger_diagnostics_create_unboxed(
804804
probe,

components-rs/sidecar.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -442,11 +442,6 @@ ddog_MaybeError ddog_sidecar_set_test_session_token(struct ddog_SidecarTransport
442442
void ddog_sidecar_reconnect(struct ddog_SidecarTransport **transport,
443443
struct ddog_SidecarTransport *(*factory)(void));
444444

445-
/**
446-
* Return the path of the crashtracker unix domain socket.
447-
*/
448-
ddog_CharSlice ddog_sidecar_get_crashtracker_unix_socket_path(void);
449-
450445
/**
451446
* Gets an agent info reader.
452447
*/

0 commit comments

Comments
 (0)