Skip to content

Commit 47db742

Browse files
committed
Support adding events
Signed-off-by: Caleb Schoepp <[email protected]>
1 parent 045bcea commit 47db742

File tree

5 files changed

+143
-14
lines changed

5 files changed

+143
-14
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ test-components = { path = "tests/test-components" }
9696
test-environment = { workspace = true }
9797
testing-framework = { path = "tests/testing-framework" }
9898
which = "4.2.5"
99-
fake-opentelemetry-collector = "0.19.0"
99+
fake-opentelemetry-collector = { path = "../../davidB/tracing-opentelemetry-instrumentation-sdk/fake-opentelemetry-collector" }
100100

101101
[build-dependencies]
102102
cargo-target-dep = { git = "https://github.com/fermyon/cargo-target-dep", rev = "482f269eceb7b1a7e8fc618bf8c082dd24979cf1" }

crates/factor-observe/src/host.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
use std::time::Duration;
2+
use std::time::SystemTime;
3+
use std::time::UNIX_EPOCH;
4+
15
use anyhow::Result;
26
use opentelemetry::global::ObjectSafeSpan;
37
use opentelemetry::trace::TraceContextExt;
48
use opentelemetry::trace::Tracer;
59
use opentelemetry::Context;
610
use spin_core::async_trait;
711
use spin_core::wasmtime::component::Resource;
8-
use spin_world::wasi::clocks0_2_0::wall_clock::Datetime;
12+
use spin_world::wasi::clocks0_2_0::wall_clock;
13+
use spin_world::wasi::observe::traces::Datetime;
914
use spin_world::wasi::observe::traces::{self, KeyValue, Span as WitSpan};
1015
use tracing_opentelemetry::OpenTelemetrySpanExt;
1116

@@ -97,12 +102,39 @@ impl traces::HostSpan for InstanceState {
97102

98103
async fn add_event(
99104
&mut self,
100-
_resource: Resource<WitSpan>,
101-
_name: String,
102-
_timestamp: Option<Datetime>,
103-
_attributes: Option<Vec<KeyValue>>,
105+
resource: Resource<WitSpan>,
106+
name: String,
107+
timestamp: Option<Datetime>,
108+
attributes: Option<Vec<KeyValue>>,
104109
) -> Result<()> {
105-
todo!()
110+
if let Some(guest_span) = self
111+
.state
112+
.write()
113+
.unwrap()
114+
.guest_spans
115+
.get_mut(resource.rep())
116+
{
117+
let timestamp = if let Some(timestamp) = timestamp {
118+
UNIX_EPOCH
119+
+ Duration::from_secs(timestamp.seconds)
120+
+ Duration::from_nanos(timestamp.nanoseconds as u64)
121+
} else {
122+
SystemTime::now()
123+
};
124+
125+
let attributes = if let Some(attributes) = attributes {
126+
attributes.into_iter().map(|a| a.into()).collect()
127+
} else {
128+
vec![]
129+
};
130+
131+
guest_span
132+
.inner
133+
.add_event_with_timestamp(name.into(), timestamp, attributes)
134+
} else {
135+
tracing::debug!("can't find guest span to add events too")
136+
}
137+
Ok(())
106138
}
107139

108140
async fn add_link(&mut self, _resource: Resource<WitSpan>, _link: traces::Link) -> Result<()> {

tests/integration.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,83 @@ mod integration_tests {
505505
Ok(())
506506
}
507507

508+
#[tokio::test]
509+
async fn wasi_observe_events() -> anyhow::Result<()> {
510+
let collector = FakeCollectorServer::start()
511+
.await
512+
.expect("fake collector server should start");
513+
let collector_endpoint = collector.endpoint().clone();
514+
515+
tokio::task::spawn_blocking(|| {
516+
run_test_inited(
517+
"wasi-observe-tracing",
518+
SpinConfig {
519+
binary_path: spin_binary(),
520+
spin_up_args: Vec::new(),
521+
app_type: SpinAppType::Http,
522+
},
523+
ServicesConfig::none(),
524+
|env| {
525+
env.set_env_var("OTEL_EXPORTER_OTLP_ENDPOINT", collector_endpoint);
526+
env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc");
527+
env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5");
528+
Ok(())
529+
},
530+
move |env| {
531+
let spin = env.runtime_mut();
532+
assert_spin_request(
533+
spin,
534+
Request::new(Method::Get, "/events"),
535+
Response::new(200),
536+
)?;
537+
538+
let mut spans: Vec<ExportedSpan>;
539+
assert_eventually!(
540+
{
541+
spans = collector.exported_spans();
542+
!spans.is_empty()
543+
},
544+
5
545+
);
546+
547+
assert_eq!(spans.len(), 3);
548+
549+
let event_span = spans
550+
.iter()
551+
.find(|s| s.name == "events")
552+
.expect("'events' span should exist");
553+
554+
let events = event_span.events.clone();
555+
assert_eq!(events.len(), 3);
556+
557+
let basic_event = events
558+
.iter()
559+
.find(|e| e.name == "basic-event")
560+
.expect("'basic' event should exist");
561+
let event_with_attributes = events
562+
.iter()
563+
.find(|e| e.name == "event-with-attributes")
564+
.expect("'event_with_attributes' event should exist");
565+
let event_with_timestamp = events
566+
.iter()
567+
.find(|e| e.name == "event-with-timestamp")
568+
.expect("'event_with_timestamp' event should exist");
569+
570+
assert!(basic_event.time_unix_nano < event_with_attributes.time_unix_nano);
571+
assert_eq!(event_with_attributes.attributes.len(), 1);
572+
assert!(
573+
event_with_attributes.time_unix_nano < event_with_timestamp.time_unix_nano
574+
);
575+
576+
Ok(())
577+
},
578+
)
579+
})
580+
.await??;
581+
582+
Ok(())
583+
}
584+
508585
// TODO: wasi_observe_set_event
509586
// TODO: wasi_observe_update_name
510587
// TODO: wasi_observe_set_link

tests/test-components/components/wasi-observe-tracing/src/lib.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use spin_sdk::{
88
http::{Method, Params, Request, Response, Router},
99
http_component,
1010
};
11-
use wasi::observe::traces::{KeyValue, Span, SpanParent, Value};
11+
use wasi::{
12+
clocks0_2_0::wall_clock::now,
13+
observe::traces::{KeyValue, Span, SpanParent, Value},
14+
};
1215

1316
#[http_component]
1417
fn handle(req: http::Request<()>) -> Response {
@@ -17,6 +20,7 @@ fn handle(req: http::Request<()>) -> Response {
1720
router.get("/drop-semantics", drop_semantics);
1821
router.get("/setting-attributes", setting_attributes);
1922
router.get_async("/host-guest-host", host_guest_host);
23+
router.get("/events", events);
2024
router.handle(req)
2125
}
2226

@@ -70,3 +74,21 @@ async fn host_guest_host(_req: Request, _params: Params) -> Response {
7074

7175
Response::new(200, "")
7276
}
77+
78+
fn events(_req: Request, _params: Params) -> Response {
79+
let span = Span::start("events", &SpanParent::Implicit, None);
80+
span.add_event("basic-event", None, None);
81+
span.add_event(
82+
"event-with-attributes",
83+
None,
84+
Some(&[KeyValue {
85+
key: "foo".to_string(),
86+
value: Value::Bool(true),
87+
}]),
88+
);
89+
let mut now_plus = now();
90+
now_plus.seconds += 1;
91+
span.add_event("event-with-timestamp", Some(now_plus), None);
92+
span.end(None);
93+
Response::new(200, "")
94+
}

0 commit comments

Comments
 (0)