diff --git a/Cargo.lock b/Cargo.lock index 22d8213..b201b60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -917,7 +917,7 @@ dependencies = [ [[package]] name = "libdd-capabilities" version = "2.1.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "bytes", @@ -941,8 +941,9 @@ dependencies = [ [[package]] name = "libdd-capabilities-impl" version = "3.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ + "anyhow", "bytes", "http", "http-body-util", @@ -989,7 +990,7 @@ dependencies = [ [[package]] name = "libdd-common" version = "5.1.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "bytes", @@ -1030,7 +1031,7 @@ dependencies = [ "libc", "libdd-common 5.0.0", "libdd-libunwind-sys", - "libdd-telemetry", + "libdd-telemetry 5.0.1", "nix 0.29.0", "num-derive", "num-traits", @@ -1052,13 +1053,14 @@ dependencies = [ [[package]] name = "libdd-data-pipeline" version = "7.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "arc-swap", "async-trait", "bytes", "either", + "futures", "getrandom 0.2.17", "http", "http-body-util", @@ -1068,6 +1070,7 @@ dependencies = [ "libdd-ddsketch 1.1.0", "libdd-dogstatsd-client", "libdd-shared-runtime 2.0.0", + "libdd-telemetry 6.0.0", "libdd-tinybytes", "libdd-trace-normalization", "libdd-trace-protobuf 4.0.0", @@ -1081,6 +1084,7 @@ dependencies = [ "tokio-util", "tracing", "uuid", + "web-time", ] [[package]] @@ -1094,7 +1098,7 @@ dependencies = [ [[package]] name = "libdd-ddsketch" version = "1.1.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "prost", ] @@ -1102,7 +1106,7 @@ dependencies = [ [[package]] name = "libdd-dogstatsd-client" version = "4.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "cadence", @@ -1174,7 +1178,7 @@ dependencies = [ [[package]] name = "libdd-shared-runtime" version = "2.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "async-trait", "futures", @@ -1215,10 +1219,39 @@ dependencies = [ "winver", ] +[[package]] +name = "libdd-telemetry" +version = "6.0.0" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" +dependencies = [ + "anyhow", + "async-trait", + "base64", + "bytes", + "futures", + "getrandom 0.2.17", + "hashbrown 0.15.5", + "http", + "libc", + "libdd-capabilities 2.1.0", + "libdd-common 5.1.0", + "libdd-ddsketch 1.1.0", + "libdd-shared-runtime 2.0.0", + "serde", + "serde_json", + "sys-info", + "tokio", + "tokio-util", + "tracing", + "uuid", + "web-time", + "winver", +] + [[package]] name = "libdd-tinybytes" version = "1.1.1" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "serde", ] @@ -1226,7 +1259,7 @@ dependencies = [ [[package]] name = "libdd-trace-normalization" version = "3.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "libdd-trace-protobuf 4.0.0", @@ -1235,7 +1268,7 @@ dependencies = [ [[package]] name = "libdd-trace-obfuscation" version = "5.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "fluent-uri", @@ -1261,7 +1294,7 @@ dependencies = [ [[package]] name = "libdd-trace-protobuf" version = "4.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "prost", "serde", @@ -1271,7 +1304,7 @@ dependencies = [ [[package]] name = "libdd-trace-stats" version = "6.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "arc-swap", @@ -1285,6 +1318,7 @@ dependencies = [ "libdd-ddsketch 1.1.0", "libdd-dogstatsd-client", "libdd-shared-runtime 2.0.0", + "libdd-telemetry 6.0.0", "libdd-trace-obfuscation", "libdd-trace-protobuf 4.0.0", "libdd-trace-utils", @@ -1293,12 +1327,13 @@ dependencies = [ "tokio", "tokio-util", "tracing", + "web-time", ] [[package]] name = "libdd-trace-utils" version = "9.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=8cd68ab922fb7aade0f089ccfc91291d874673af#8cd68ab922fb7aade0f089ccfc91291d874673af" +source = "git+https://github.com/DataDog/libdatadog.git?rev=73f23a2c03be39971c966e444785d63b6fd52e81#73f23a2c03be39971c966e444785d63b6fd52e81" dependencies = [ "anyhow", "base64", @@ -1310,6 +1345,7 @@ dependencies = [ "http-body", "http-body-util", "indexmap", + "itoa", "libdd-capabilities 2.1.0", "libdd-capabilities-impl 3.0.0", "libdd-common 5.1.0", @@ -1816,6 +1852,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test", + "web-time", ] [[package]] @@ -2757,6 +2794,16 @@ dependencies = [ "semver", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-root-certs" version = "1.0.8" diff --git a/crates/capabilities/Cargo.toml b/crates/capabilities/Cargo.toml index cbb376e..6fb0ace 100644 --- a/crates/capabilities/Cargo.toml +++ b/crates/capabilities/Cargo.toml @@ -16,8 +16,8 @@ bytes = "1.4" futures-core = "0.3" anyhow = "1" # TODO: Replace this temporary libdatadog PR rev with the official release/tag -# that contains DataDog/libdatadog#2235, then regenerate Cargo.lock. -libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af" } +# that contains DataDog/libdatadog#2172, then regenerate Cargo.lock. +libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81" } [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/pipeline/Cargo.toml b/crates/pipeline/Cargo.toml index f8e318a..fdc3b06 100644 --- a/crates/pipeline/Cargo.toml +++ b/crates/pipeline/Cargo.toml @@ -15,17 +15,18 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1" libdatadog-nodejs-capabilities = { path = "../capabilities" } # TODO: Replace these temporary libdatadog PR revs with the official release/tag -# that contains DataDog/libdatadog#2235, then regenerate Cargo.lock. -libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af" } -libdd-common = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af", default-features = false } -libdd-data-pipeline = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af", default-features = false } -libdd-trace-utils = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af", default-features = false, features = ["change-buffer"] } -libdd-trace-stats = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af", default-features = false } -libdd-trace-protobuf = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af", default-features = false } -libdd-shared-runtime = { git = "https://github.com/DataDog/libdatadog.git", rev = "8cd68ab922fb7aade0f089ccfc91291d874673af", default-features = false } +# that contains DataDog/libdatadog#2172, then regenerate Cargo.lock. +libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81" } +libdd-common = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81", default-features = false } +libdd-data-pipeline = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81", default-features = false, features = ["telemetry"] } +libdd-trace-utils = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81", default-features = false, features = ["change-buffer"] } +libdd-trace-stats = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81", default-features = false } +libdd-trace-protobuf = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81", default-features = false } +libdd-shared-runtime = { git = "https://github.com/DataDog/libdatadog.git", rev = "73f23a2c03be39971c966e444785d63b6fd52e81", default-features = false } rmp-serde = "1" bytes = "1" http = "1" +web-time = "1" console_error_panic_hook = "0.1" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/pipeline/src/lib.rs b/crates/pipeline/src/lib.rs index 31188af..d913f2a 100644 --- a/crates/pipeline/src/lib.rs +++ b/crates/pipeline/src/lib.rs @@ -1,7 +1,7 @@ use libdatadog_nodejs_capabilities::WasmCapabilities; use libdd_data_pipeline::trace_exporter::agent_response::AgentResponse; use libdd_data_pipeline::trace_exporter::{ - TraceExporter, TraceExporterBuilder, TraceExporterOutputFormat, + TelemetryConfig, TraceExporter, TraceExporterBuilder, TraceExporterOutputFormat, }; use libdd_data_pipeline::OtlpProtocol; use libdd_shared_runtime::LocalRuntime; @@ -204,6 +204,11 @@ pub struct WasmSpanState { /// Extra HTTP headers for OTLP export (e.g. collector auth), as key/value /// pairs. Only applied when `otlp_endpoint` is set. otlp_headers: RefCell>, + /// When set, the lazily-built exporter has telemetry enabled with this + /// config (`heartbeat`/`runtime_id`/`debug_enabled` — see libdatadog's + /// `TelemetryConfig`). Only takes effect if set before the first send + /// (when the exporter is built). + telemetry_config: RefCell>, /// Latched message from a failed lazy `build_async`. Building is one-shot and /// a failure is fatal (bad config), so once set every send returns it (as a /// distinguishable error) instead of a misleading "builder already consumed", @@ -338,6 +343,7 @@ impl WasmSpanState { otlp_endpoint: RefCell::new(None), otlp_protocol: Cell::new(None), otlp_headers: RefCell::new(Vec::new()), + telemetry_config: RefCell::new(None), build_error: RefCell::new(None), }) } @@ -374,6 +380,29 @@ impl WasmSpanState { Ok(()) } + /// Enable telemetry on the lazily-built trace exporter. Off by default — + /// dd-trace-js opts in from JS. `heartbeat_ms`sets the metric-flush cadence + /// (0 defers to libdatadog's default interval), `runtime_id` tags telemetry + /// payloads with the tracer's runtime id when provided, and `debug_enabled` + /// toggles libdd-telemetry's verbose logging. + /// + /// Must be called before the first `sendPreparedChunk` — the exporter is + /// built lazily on first send and telemetry config is fixed at build time, + /// so later calls have no effect. + #[wasm_bindgen(js_name = "enableTelemetry")] + pub fn enable_telemetry( + &self, + heartbeat_ms: u32, + runtime_id: Option, + debug_enabled: bool, + ) { + *self.telemetry_config.borrow_mut() = Some(TelemetryConfig { + heartbeat: heartbeat_ms as u64, + runtime_id, + debug_enabled, + }); + } + /// Set extra HTTP headers for OTLP export as a flat `[key, value, ...]` /// array (the host flattens its key/value map). Only takes effect with an /// OTLP endpoint set, before the first send. A trailing unpaired element on @@ -530,6 +559,9 @@ impl WasmSpanState { builder.set_otlp_headers(headers.clone()); } } + if let Some(cfg) = self.telemetry_config.borrow().clone() { + builder.enable_telemetry(cfg); + } match builder.build_async::().await { Ok(built) => *exporter_slot = Some(built), Err(e) => { diff --git a/crates/pipeline/src/stats.rs b/crates/pipeline/src/stats.rs index 127a21e..0a20f22 100644 --- a/crates/pipeline/src/stats.rs +++ b/crates/pipeline/src/stats.rs @@ -7,13 +7,14 @@ //! HTTP transport for flushing stats to the Datadog agent's `/v0.6/stats` //! endpoint. -use std::time::{Duration, SystemTime}; +use std::time::Duration; +use web_time::SystemTime; -/// Wall-clock now() for wasm. `std::time::SystemTime::now()` is unimplemented on -/// `wasm32-unknown-unknown` (it panics/traps), so derive the time from JS -/// `Date.now()` (milliseconds since the Unix epoch). +/// Wall-clock now() for wasm. Delegates to `web_time::SystemTime::now()`, +/// which routes to JS `Date.now()` on `wasm32-unknown-unknown` (native +/// `std::time::SystemTime::now()` is unimplemented on that target and traps). fn now() -> SystemTime { - SystemTime::UNIX_EPOCH + Duration::from_millis(js_sys::Date::now() as u64) + SystemTime::now() } use bytes::Bytes;