Skip to content

Commit

Permalink
WASM Support (#57)
Browse files Browse the repository at this point in the history
## 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.
  • Loading branch information
jesseditson authored Aug 30, 2023
1 parent 6149863 commit 80ae321
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 4 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ tracing-subscriber = { version = "0.3.0", default-features = false, features = [
[target.'cfg(not(target_os = "windows"))'.dev-dependencies]
pprof = { version = "0.11.1", features = ["flamegraph", "criterion"] }

[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies]
js-sys = "0.3.64"
web-time = "0.2.0"

[lib]
bench = false

Expand Down
11 changes: 7 additions & 4 deletions src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ use std::any::TypeId;
use std::fmt;
use std::marker;
use std::thread;
use std::time::{Instant, SystemTime};
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
use tracing_core::span::{self, Attributes, Id, Record};
use tracing_core::{field, Event, Subscriber};
#[cfg(feature = "tracing-log")]
use tracing_log::NormalizeEvent;
use tracing_subscriber::layer::Context;
use tracing_subscriber::registry::LookupSpan;
use tracing_subscriber::Layer;
#[cfg(target_arch = "wasm32")]
use web_time::Instant;

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

Expand Down Expand Up @@ -839,7 +842,7 @@ where

let mut otel_event = otel::Event::new(
String::new(),
SystemTime::now(),
crate::time::now(),
vec![Key::new("level").string(meta.level().as_str()), target],
0,
);
Expand Down Expand Up @@ -924,7 +927,7 @@ where

// Assign end time, build and start span, drop span to export
builder
.with_end_time(SystemTime::now())
.with_end_time(crate::time::now())
.start_with_context(&self.tracer, &parent_cx);
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,17 @@ pub struct OtelData {
/// The otel span data recorded during the current tracing span.
pub builder: opentelemetry::trace::SpanBuilder,
}

pub(crate) mod time {
use std::time::SystemTime;

#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn now() -> SystemTime {
SystemTime::now()
}

#[cfg(target_arch = "wasm32")]
pub(crate) fn now() -> SystemTime {
SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(js_sys::Date::now() as u64)
}
}

0 comments on commit 80ae321

Please sign in to comment.