Skip to content

Commit 80ae321

Browse files
authored
WASM Support (#57)
## Motivation I was attempting to use this library with a wasm target in a browser. If you call `std::time::{Instant, SystemTime}::now` in a wasm target, it will panic at runtime. This library makes use of both `::now()` calls, which will result in a panic when attempting to record a trace. ## Solution In the library that this library calls (`opentelemetry-api`), this is resolved by replacing calls to `SystemTime::now()` with an implementation that returns a `SystemTime` constructed from `js_sys::Date`. To preserve the ability to pass `SystemTime`-typed args to `opentelemetry_api` methods, I just added the same mechanism to this library. Because `Instant` is never used in `opentelemetry_api`, we can instead replace the implementation entirely with the api-compatible "polyfill" from `web_time`. All of these changes are behind `cfg` and automatically enabled when building for `wasm32` targets, so this will not change any behavior/performance when built for other targets.
1 parent 6149863 commit 80ae321

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ tracing-subscriber = { version = "0.3.0", default-features = false, features = [
5656
[target.'cfg(not(target_os = "windows"))'.dev-dependencies]
5757
pprof = { version = "0.11.1", features = ["flamegraph", "criterion"] }
5858

59+
[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies]
60+
js-sys = "0.3.64"
61+
web-time = "0.2.0"
62+
5963
[lib]
6064
bench = false
6165

src/layer.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ use std::any::TypeId;
88
use std::fmt;
99
use std::marker;
1010
use std::thread;
11-
use std::time::{Instant, SystemTime};
11+
#[cfg(not(target_arch = "wasm32"))]
12+
use std::time::Instant;
1213
use tracing_core::span::{self, Attributes, Id, Record};
1314
use tracing_core::{field, Event, Subscriber};
1415
#[cfg(feature = "tracing-log")]
1516
use tracing_log::NormalizeEvent;
1617
use tracing_subscriber::layer::Context;
1718
use tracing_subscriber::registry::LookupSpan;
1819
use tracing_subscriber::Layer;
20+
#[cfg(target_arch = "wasm32")]
21+
use web_time::Instant;
1922

2023
const SPAN_NAME_FIELD: &str = "otel.name";
2124
const SPAN_KIND_FIELD: &str = "otel.kind";
@@ -680,7 +683,7 @@ where
680683
let mut builder = self
681684
.tracer
682685
.span_builder(attrs.metadata().name())
683-
.with_start_time(SystemTime::now())
686+
.with_start_time(crate::time::now())
684687
// Eagerly assign span id so children have stable parent id
685688
.with_span_id(self.tracer.new_span_id());
686689

@@ -839,7 +842,7 @@ where
839842

840843
let mut otel_event = otel::Event::new(
841844
String::new(),
842-
SystemTime::now(),
845+
crate::time::now(),
843846
vec![Key::new("level").string(meta.level().as_str()), target],
844847
0,
845848
);
@@ -924,7 +927,7 @@ where
924927

925928
// Assign end time, build and start span, drop span to export
926929
builder
927-
.with_end_time(SystemTime::now())
930+
.with_end_time(crate::time::now())
928931
.start_with_context(&self.tracer, &parent_cx);
929932
}
930933
}

src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,17 @@ pub struct OtelData {
150150
/// The otel span data recorded during the current tracing span.
151151
pub builder: opentelemetry::trace::SpanBuilder,
152152
}
153+
154+
pub(crate) mod time {
155+
use std::time::SystemTime;
156+
157+
#[cfg(not(target_arch = "wasm32"))]
158+
pub(crate) fn now() -> SystemTime {
159+
SystemTime::now()
160+
}
161+
162+
#[cfg(target_arch = "wasm32")]
163+
pub(crate) fn now() -> SystemTime {
164+
SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(js_sys::Date::now() as u64)
165+
}
166+
}

0 commit comments

Comments
 (0)