From 172033a9b80ef0f011f98386a83713253ca8e171 Mon Sep 17 00:00:00 2001 From: Jules Wiriath Date: Mon, 29 Jun 2026 14:52:13 +0200 Subject: [PATCH] feat(css): enabled for wasm --- Cargo.lock | 12 ++++++++++ LICENSE-3rdparty.csv | 1 + libdd-data-pipeline/Cargo.toml | 1 + libdd-data-pipeline/src/otlp/metrics.rs | 3 ++- .../src/trace_exporter/builder.rs | 6 +---- libdd-data-pipeline/src/trace_exporter/mod.rs | 11 ---------- .../src/trace_exporter/stats.rs | 22 +++---------------- libdd-trace-stats/Cargo.toml | 2 ++ libdd-trace-stats/src/lib.rs | 1 - .../src/span_concentrator/mod.rs | 6 +++-- 10 files changed, 26 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 727a4f2560..16cfb25df3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3046,6 +3046,7 @@ dependencies = [ "tokio-util", "tracing", "uuid", + "web-time", ] [[package]] @@ -3519,6 +3520,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", + "web-time", ] [[package]] @@ -6595,6 +6597,16 @@ dependencies = [ "wasm-bindgen", ] +[[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.5" diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 0e794bc021..ef04646f30 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -498,6 +498,7 @@ wasm-bindgen-macro,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/m wasm-bindgen-macro-support,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro-support,MIT OR Apache-2.0,The wasm-bindgen Developers wasm-bindgen-shared,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/shared,MIT OR Apache-2.0,The wasm-bindgen Developers web-sys,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/web-sys,MIT OR Apache-2.0,The wasm-bindgen Developers +web-time,https://github.com/daxpedda/web-time,MIT OR Apache-2.0,The web-time Authors webpki-root-certs,https://github.com/rustls/webpki-roots,CDLA-Permissive-2.0,The webpki-root-certs Authors webpki-roots,https://github.com/rustls/webpki-roots,CDLA-Permissive-2.0,The webpki-roots Authors widestring,https://github.com/VoidStarKat/widestring-rs,MIT OR Apache-2.0,The widestring Authors diff --git a/libdd-data-pipeline/Cargo.toml b/libdd-data-pipeline/Cargo.toml index 6425345d22..dad7288fa6 100644 --- a/libdd-data-pipeline/Cargo.toml +++ b/libdd-data-pipeline/Cargo.toml @@ -46,6 +46,7 @@ libdd-tinybytes = { version = "1.1.1", path = "../libdd-tinybytes", features = [ "bytes_string", "serialization", ] } +web-time = "1" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tokio = { version = "1.23", features = ["time", "test-util"], default-features = false } diff --git a/libdd-data-pipeline/src/otlp/metrics.rs b/libdd-data-pipeline/src/otlp/metrics.rs index 21c30c1785..2fb67b0b9b 100644 --- a/libdd-data-pipeline/src/otlp/metrics.rs +++ b/libdd-data-pipeline/src/otlp/metrics.rs @@ -16,8 +16,9 @@ use libdd_trace_utils::otlp_encoder::mapper::status_code; use libdd_trace_utils::otlp_encoder::OtlpResourceInfo; use serde_json::{json, Value}; use std::sync::{Arc, Mutex}; -use std::time::{Duration, SystemTime}; +use std::time::Duration; use tracing::error; +use web_time::SystemTime; const METRIC_NAME: &str = "traces.span.sdk.metrics.duration"; const NANOS_PER_SECOND: f64 = 1_000_000_000.0; diff --git a/libdd-data-pipeline/src/trace_exporter/builder.rs b/libdd-data-pipeline/src/trace_exporter/builder.rs index 049a592dd9..c4695a8dbe 100644 --- a/libdd-data-pipeline/src/trace_exporter/builder.rs +++ b/libdd-data-pipeline/src/trace_exporter/builder.rs @@ -647,9 +647,7 @@ impl TraceExporterBuilder { #[cfg(target_arch = "wasm32")] drop(info_fetcher_handle); - #[allow(unused_mut)] let mut stats = StatsComputationStatus::Disabled; - #[cfg(not(target_arch = "wasm32"))] if let Some(bucket_size) = self.stats_bucket_size { stats = StatsComputationStatus::DisabledByAgent { bucket_size }; } @@ -752,9 +750,7 @@ impl TraceExporterBuilder { // OTLP metrics + stats bucket size: start the concentrator unconditionally (bypass the // agent gate) so `check_agent_info` cannot later disable stats. - #[allow(unused_mut)] let mut otlp_stats_enabled = false; - #[cfg(not(target_arch = "wasm32"))] if let (Some(metrics_config), Some(bucket_size)) = (otlp_metrics_config.clone(), self.stats_bucket_size) { @@ -767,7 +763,7 @@ impl TraceExporterBuilder { .collect(); let concentrator = Arc::new(Mutex::new(SpanConcentrator::new( bucket_size, - std::time::SystemTime::now(), + web_time::SystemTime::now(), span_kinds, self.peer_tags.clone(), None, diff --git a/libdd-data-pipeline/src/trace_exporter/mod.rs b/libdd-data-pipeline/src/trace_exporter/mod.rs index 90f6bd1b08..1cbae36114 100644 --- a/libdd-data-pipeline/src/trace_exporter/mod.rs +++ b/libdd-data-pipeline/src/trace_exporter/mod.rs @@ -257,7 +257,6 @@ pub struct TraceExporter< common_stats_tags: Vec, client_computed_top_level: bool, client_side_stats: StatsComputationConfig, - #[cfg_attr(target_arch = "wasm32", allow(dead_code))] previous_info_state: ArcSwapOption, info_response_observer: ResponseObserver, #[cfg(all(not(target_arch = "wasm32"), feature = "telemetry"))] @@ -276,7 +275,6 @@ pub struct TraceExporter< /// When true, span stats are computed and exported as OTLP metrics. The concentrator is /// started at build time, so agent-driven stats (de)activation in `check_agent_info` is /// skipped. - #[cfg_attr(target_arch = "wasm32", allow(dead_code))] otlp_stats_enabled: bool, /// When `Some(max_line_size)`, traces are written as newline-delimited JSON /// through the [`LogWriterCapability`] (the Datadog Forwarder "log exporter" @@ -421,7 +419,6 @@ impl< Ok(res) } - #[cfg(not(target_arch = "wasm32"))] /// Check if agent info state has changed fn has_agent_info_state_changed(&self, agent_info: &Arc) -> bool { Some(agent_info.state_hash.as_str()) @@ -434,7 +431,6 @@ impl< /// Reconcile in-process stats state with the latest agent info. /// Async so the `Enabled` arm can await a stats-worker shutdown without `block_on`. - #[cfg(not(target_arch = "wasm32"))] async fn check_agent_info(&self) { let Some(agent_info) = agent_info::get_agent_info() else { return; @@ -500,18 +496,11 @@ impl< .store(Some(agent_info.state_hash.clone().into())) } - #[cfg(target_arch = "wasm32")] - async fn check_agent_info(&self) { - // No background workers on wasm — agent info is never fetched, stats are - // never computed. This is intentionally a no-op. - } - /// Reconcile `v1_active` with the agent's currently-advertised endpoints. Called only when /// V1 is configured and the agent info state has changed, so transitions are logged at most /// once per change. Note: `v1_active` can also transition `true → false` outside this path, /// via the fail-closed hook in `send_trace_chunks_inner` when the agent returns 404 on /// `/v1.0/traces` (the agent does not bump its state hash on 404). - #[cfg(not(target_arch = "wasm32"))] fn refresh_v1_active(&self, agent_info: &Arc) { let supports_v1 = agent_info .info diff --git a/libdd-data-pipeline/src/trace_exporter/stats.rs b/libdd-data-pipeline/src/trace_exporter/stats.rs index eaff519d3d..d477c9a54d 100644 --- a/libdd-data-pipeline/src/trace_exporter/stats.rs +++ b/libdd-data-pipeline/src/trace_exporter/stats.rs @@ -7,14 +7,11 @@ //! including starting/stopping stats workers, managing the span concentrator, //! and processing traces for stats collection. -#[cfg(not(target_arch = "wasm32"))] use super::add_path; use super::TracerMetadata; -#[cfg(not(target_arch = "wasm32"))] use crate::agent_info::schema::AgentInfo; use arc_swap::ArcSwap; use libdd_capabilities::{HttpClientCapability, MaybeSend, SleepCapability}; -#[cfg(not(target_arch = "wasm32"))] use libdd_common::Endpoint; use libdd_common::MutexExt; use libdd_shared_runtime::{SharedRuntime, WorkerHandle}; @@ -23,18 +20,16 @@ use libdd_trace_stats::span_concentrator::SpanConcentrator; use libdd_trace_stats::span_concentrator::{ SharedStatsComputationObfuscationConfig, StatsComputationObfuscationConfig, }; -#[cfg(not(target_arch = "wasm32"))] use libdd_trace_stats::stats_exporter::{StatsExporter, StatsMetadata}; use libdd_trace_utils::trace_filter::TraceFilterer; use std::sync::{Arc, Mutex}; use std::time::Duration; -#[cfg(not(target_arch = "wasm32"))] use tracing::{debug, error}; +// std::time::SystemTime::now() panics on wasm32. +use web_time::SystemTime; -#[cfg(not(target_arch = "wasm32"))] pub(crate) const DEFAULT_STATS_ELIGIBLE_SPAN_KINDS: [&str; 4] = ["client", "server", "producer", "consumer"]; -#[cfg(not(target_arch = "wasm32"))] pub(crate) const STATS_ENDPOINT: &str = "/v0.6/stats"; /// The maximum obfuscation version this tracer supports. @@ -43,7 +38,6 @@ pub(crate) const SUPPORTED_OBFUSCATION_VERSION: u32 = 1; #[cfg(feature = "stats-obfuscation")] pub(crate) const SUPPORTED_OBFUSCATION_VERSION_STR: &str = "1"; -#[cfg(not(target_arch = "wasm32"))] /// Context struct that groups immutable parameters used by stats functions pub(crate) struct StatsContext<'a, R: SharedRuntime> { pub metadata: &'a TracerMetadata, @@ -58,7 +52,6 @@ pub(crate) struct StatsContext<'a, R: SharedRuntime> { } #[derive(Debug)] -#[cfg_attr(target_arch = "wasm32", allow(dead_code))] pub(crate) enum StatsComputationStatus { /// Client-side stats has been disabled by the tracer Disabled, @@ -74,7 +67,6 @@ pub(crate) enum StatsComputationStatus { } #[derive(Debug)] -#[cfg_attr(target_arch = "wasm32", allow(dead_code))] pub(crate) struct StatsComputationConfig { pub(crate) status: ArcSwap, pub(crate) stats_cardinality_limit: Option, @@ -91,7 +83,6 @@ pub(crate) struct StatsComputationConfig { /// This requires: /// - `client_drop_p0s` to be enabled on the agent, /// - the `/v0.6/stats` endpoint to be advertised by the agent. -#[cfg(not(target_arch = "wasm32"))] fn is_stats_computation_supported(agent_info: &AgentInfo) -> bool { agent_info.info.client_drop_p0s.is_some_and(|v| v) && agent_info @@ -110,7 +101,6 @@ fn is_obfuscation_active(agent_info: &AgentInfo) -> bool { .is_some_and(|v| v >= 1 && v == SUPPORTED_OBFUSCATION_VERSION) } -#[cfg(not(target_arch = "wasm32"))] /// Get span kinds for stats computation with default fallback fn get_span_kinds_for_stats(agent_info: &Arc) -> Vec { agent_info @@ -120,7 +110,6 @@ fn get_span_kinds_for_stats(agent_info: &Arc) -> Vec { .unwrap_or_else(|| DEFAULT_STATS_ELIGIBLE_SPAN_KINDS.map(String::from).to_vec()) } -#[cfg(not(target_arch = "wasm32"))] /// Start the stats exporter and enable stats computation /// /// Should only be used if the agent enabled stats computation @@ -139,7 +128,7 @@ pub(crate) fn start_stats_computation< { let stats_concentrator = Arc::new(Mutex::new(SpanConcentrator::new( bucket_size, - std::time::SystemTime::now(), + SystemTime::now(), span_kinds, peer_tags, ctx.stats_cardinality_limit, @@ -151,7 +140,6 @@ pub(crate) fn start_stats_computation< Ok(()) } -#[cfg(not(target_arch = "wasm32"))] /// Create stats exporter and worker, start the worker, and update the state fn create_and_start_stats_worker< C: HttpClientCapability + SleepCapability + MaybeSend + Sync + 'static, @@ -191,7 +179,6 @@ fn create_and_start_stats_worker< Ok(()) } -#[cfg(not(target_arch = "wasm32"))] /// Transition from `Enabled` to `DisabledByAgent`, awaiting the stats worker shutdown. pub(crate) async fn stop_stats_computation(client_side_stats: &ArcSwap) { // load_full() avoids holding an ArcSwap Guard (!Send) across .await. @@ -212,7 +199,6 @@ pub(crate) async fn stop_stats_computation(client_side_stats: &ArcSwap, client_side_stats: &StatsComputationConfig, @@ -276,7 +261,6 @@ fn update_obfuscation_config( } } -#[cfg(not(target_arch = "wasm32"))] pub(crate) async fn handle_stats_enabled( agent_info: &Arc, stats_concentrator: &Arc>, diff --git a/libdd-trace-stats/Cargo.toml b/libdd-trace-stats/Cargo.toml index bb87e1ee0f..6f817c808f 100644 --- a/libdd-trace-stats/Cargo.toml +++ b/libdd-trace-stats/Cargo.toml @@ -30,6 +30,8 @@ tokio-util = "0.7.11" tracing = { version = "0.1", default-features = false } async-trait = "0.1.85" futures = { version = "0.3.32", default-features = false, features = ["alloc"] } +# Cross-platform `SystemTime`; `std::time::SystemTime::now()` panics on wasm32. +web-time = "1" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] libdd-capabilities-impl = { version = "3.0.0", path = "../libdd-capabilities-impl", default-features = false } diff --git a/libdd-trace-stats/src/lib.rs b/libdd-trace-stats/src/lib.rs index 8e5793c8bb..855e8ce088 100644 --- a/libdd-trace-stats/src/lib.rs +++ b/libdd-trace-stats/src/lib.rs @@ -10,5 +10,4 @@ //! This crate provides utilities to compute stats from traces. pub mod span_concentrator; -#[cfg(not(target_arch = "wasm32"))] pub mod stats_exporter; diff --git a/libdd-trace-stats/src/span_concentrator/mod.rs b/libdd-trace-stats/src/span_concentrator/mod.rs index 0f233daca2..dcfe9451f1 100644 --- a/libdd-trace-stats/src/span_concentrator/mod.rs +++ b/libdd-trace-stats/src/span_concentrator/mod.rs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 //! This module implements the SpanConcentrator used to aggregate spans into stats use std::collections::HashMap; -use std::time::{self, Duration, SystemTime}; +use std::time::Duration; use tracing::debug; +// std::time::SystemTime panics on wasm32. +use web_time::{SystemTime, UNIX_EPOCH}; use libdd_trace_protobuf::pb; @@ -59,7 +61,7 @@ impl FlushableConcentrator for SpanConcentrator { /// Return a Duration between t and the unix epoch /// If t is before the unix epoch return 0 fn system_time_to_unix_duration(t: SystemTime) -> Duration { - t.duration_since(time::UNIX_EPOCH) + t.duration_since(UNIX_EPOCH) .unwrap_or(Duration::from_nanos(0)) }