Skip to content

Commit a8fcca4

Browse files
committed
WIP: Broken attempt to back wasi-otel. Failing on the propagator. Something to do with tracing::Span::current()
Signed-off-by: Caleb Schoepp <[email protected]>
1 parent 49fe245 commit a8fcca4

File tree

13 files changed

+334
-375
lines changed

13 files changed

+334
-375
lines changed

Cargo.lock

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

crates/factor-observe/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ anyhow = { workspace = true }
99
indexmap = "2.2.6"
1010
opentelemetry = { workspace = true }
1111
opentelemetry_sdk = { workspace = true }
12+
opentelemetry-otlp = { version = "0.27", features = ["http-proto", "http", "reqwest-client"] }
1213
spin-core = { path = "../core" }
1314
spin-factors = { path = "../factors" }
1415
spin-resource-table = { path = "../table" }
16+
spin-telemetry = { path = "../telemetry" }
1517
spin-world = { path = "../world" }
1618
tracing = { workspace = true }
1719
tracing-opentelemetry = { workspace = true }

crates/factor-observe/src/host.rs

Lines changed: 83 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -1,244 +1,117 @@
1-
use std::time::SystemTime;
1+
// use std::time::SystemTime;
22

33
use anyhow::anyhow;
44
use anyhow::Result;
5-
use opentelemetry::global::ObjectSafeSpan;
65
use opentelemetry::trace::TraceContextExt;
7-
use opentelemetry::trace::Tracer;
86
use opentelemetry::Context;
7+
use opentelemetry_sdk::trace::SpanProcessor;
98
use spin_core::async_trait;
10-
use spin_core::wasmtime::component::Resource;
11-
use spin_world::wasi::observe::tracer;
9+
use spin_world::wasi::otel::tracing as wasi_otel;
10+
use spin_world::wasi::otel::tracing::SpanContext;
11+
use tracing::span;
12+
1213
use tracing_opentelemetry::OpenTelemetrySpanExt;
1314

14-
use crate::{GuestSpan, InstanceState};
15+
use crate::InstanceState;
1516

1617
#[async_trait]
17-
impl tracer::Host for InstanceState {
18-
async fn start(
18+
impl wasi_otel::Host for InstanceState {
19+
async fn on_start(
1920
&mut self,
20-
name: String,
21-
options: Option<tracer::StartOptions>,
22-
) -> Result<Resource<tracer::Span>> {
21+
span_data: wasi_otel::SpanData,
22+
_parent: wasi_otel::SpanContext,
23+
) -> Result<()> {
2324
let mut state = self.state.write().unwrap();
24-
let options = options.unwrap_or_default();
2525

2626
// Before we ever create any new spans make sure we track the original host span ID
2727
if state.original_host_span_id.is_none() {
28-
state.original_host_span_id = Some(
29-
tracing::Span::current()
30-
.context()
31-
.span()
32-
.span_context()
33-
.span_id(),
34-
);
28+
// TODO: Note this is also failing to get anything meaningful through tracing::Span::current()
29+
let context = dbg!(tracing::Span::current().context());
30+
let span = dbg!(context.span());
31+
let span_context = dbg!(span.span_context());
32+
state.original_host_span_id = dbg!(Some(span_context.span_id()));
3533
}
3634

37-
// Get span's parent based on whether it's a new root and whether there are any active spans
38-
let parent_context = match (options.new_root, state.active_spans.is_empty()) {
39-
// Not a new root && Active spans -> Last active guest span is parent
40-
(false, false) => {
41-
let span_context = state
42-
.guest_spans
43-
.get(*state.active_spans.last().unwrap())
44-
.unwrap()
45-
.inner
46-
.span_context()
47-
.clone();
48-
Context::new().with_remote_span_context(span_context)
49-
}
50-
// Not a new root && No active spans -> Current host span is parent
51-
(false, true) => tracing::Span::current().context(),
52-
// New root && n/a -> No parent
53-
(true, _) => Context::new(),
54-
};
35+
// // Get span's parent based on whether it's a new root and whether there are any active spans
36+
// let parent_context = match (false, state.active_spans.is_empty()) {
37+
// // Not a new root && Active spans -> Last active guest span is parent
38+
// (false, false) => {
39+
// let span_context = state
40+
// .guest_spans
41+
// .get(*state.active_spans.last().unwrap())
42+
// .unwrap()
43+
// .inner
44+
// .span_context()
45+
// .clone();
46+
// Context::new().with_remote_span_context(span_context)
47+
// }
48+
// // Not a new root && No active spans -> Current host span is parent
49+
// (false, true) => tracing::Span::current().context(),
50+
// // New root && n/a -> No parent
51+
// (true, _) => Context::new(),
52+
// };
5553

5654
// Create the underlying opentelemetry span
57-
let mut builder = self.tracer.span_builder(name);
58-
if let Some(kind) = options.span_kind {
59-
builder = builder.with_kind(kind.into());
60-
}
61-
if let Some(attributes) = options.attributes {
62-
builder = builder.with_attributes(attributes.into_iter().map(Into::into));
63-
}
64-
if let Some(links) = options.links {
65-
builder = builder.with_links(links.into_iter().map(Into::into).collect());
66-
}
67-
if let Some(timestamp) = options.timestamp {
68-
builder = builder.with_start_time(timestamp);
69-
}
70-
let otel_span = builder.start_with_context(&self.tracer, &parent_context);
71-
72-
// Wrap it in a GuestSpan for our own bookkeeping purposes
73-
let guest_span = GuestSpan { inner: otel_span };
74-
75-
// Put the GuestSpan in our resource table and push it on to our stack of active spans
76-
let resource_id = state.guest_spans.push(guest_span).unwrap();
77-
state.active_spans.insert(resource_id);
78-
79-
Ok(Resource::new_own(resource_id))
80-
}
81-
}
82-
83-
#[async_trait]
84-
impl tracer::HostSpan for InstanceState {
85-
async fn span_context(
86-
&mut self,
87-
resource: Resource<tracer::Span>,
88-
) -> Result<tracer::SpanContext> {
89-
if let Some(guest_span) = self.state.read().unwrap().guest_spans.get(resource.rep()) {
90-
Ok(guest_span.inner.span_context().clone().into())
91-
} else {
92-
Err(anyhow!("BUG: cannot find resource in table"))
93-
}
94-
}
95-
96-
async fn is_recording(&mut self, resource: Resource<tracer::Span>) -> Result<bool> {
97-
if let Some(guest_span) = self.state.read().unwrap().guest_spans.get(resource.rep()) {
98-
Ok(guest_span.inner.is_recording())
99-
} else {
100-
Err(anyhow!("BUG: cannot find resource in table"))
101-
}
102-
}
103-
104-
async fn set_attributes(
105-
&mut self,
106-
resource: Resource<tracer::Span>,
107-
attributes: Vec<tracer::KeyValue>,
108-
) -> Result<()> {
109-
if let Some(guest_span) = self
110-
.state
111-
.write()
112-
.unwrap()
113-
.guest_spans
114-
.get_mut(resource.rep())
115-
{
116-
for attribute in attributes {
117-
guest_span.inner.set_attribute(attribute.into());
118-
}
119-
Ok(())
120-
} else {
121-
Err(anyhow!("BUG: cannot find resource in table"))
122-
}
123-
}
124-
125-
async fn add_event(
126-
&mut self,
127-
resource: Resource<tracer::Span>,
128-
name: String,
129-
timestamp: Option<tracer::Datetime>,
130-
attributes: Option<Vec<tracer::KeyValue>>,
131-
) -> Result<()> {
132-
if let Some(guest_span) = self
133-
.state
134-
.write()
135-
.unwrap()
136-
.guest_spans
137-
.get_mut(resource.rep())
138-
{
139-
let timestamp = timestamp.map(Into::into).unwrap_or_else(SystemTime::now);
140-
let attributes = if let Some(attributes) = attributes {
141-
attributes.into_iter().map(Into::into).collect()
142-
} else {
143-
vec![]
144-
};
145-
146-
guest_span
147-
.inner
148-
.add_event_with_timestamp(name.into(), timestamp, attributes);
55+
// let builder = self.tracer.span_builder(span_data.name);
56+
// if let Some(kind) = options.span_kind {
57+
// builder = builder.with_kind(kind.into());
58+
// }
59+
// if let Some(attributes) = options.attributes {
60+
// builder = builder.with_attributes(attributes.into_iter().map(Into::into));
61+
// }
62+
// if let Some(links) = options.links {
63+
// builder = builder.with_links(links.into_iter().map(Into::into).collect());
64+
// }
65+
// if let Some(timestamp) = options.timestamp {
66+
// builder = builder.with_start_time(timestamp);
67+
// }
68+
// let otel_span = builder.start_with_context(
69+
// &self.tracer,
70+
// &Context::new().with_remote_span_context(parent.into()),
71+
// );
72+
// let span_id = otel_span.span_context().span_id();
73+
74+
// Put the span in our map and push it on to our stack of active spans
75+
let span_context =
76+
std::convert::Into::<opentelemetry::trace::SpanContext>::into(span_data.span_context);
77+
let span_id = span_context.span_id();
78+
state.guest_span_contexts.insert(span_id, span_context);
79+
state.active_spans.insert(span_id);
14980

150-
Ok(())
151-
} else {
152-
Err(anyhow!("BUG: cannot find resource in table"))
153-
}
154-
}
155-
156-
async fn add_link(
157-
&mut self,
158-
resource: Resource<tracer::Span>,
159-
link: tracer::Link,
160-
) -> Result<()> {
161-
if let Some(guest_span) = self
162-
.state
163-
.write()
164-
.unwrap()
165-
.guest_spans
166-
.get_mut(resource.rep())
167-
{
168-
guest_span.inner.add_link(
169-
link.span_context.into(),
170-
link.attributes.into_iter().map(Into::into).collect(),
171-
);
172-
Ok(())
173-
} else {
174-
Err(anyhow!("BUG: cannot find resource in table"))
175-
}
176-
}
177-
178-
async fn set_status(
179-
&mut self,
180-
resource: Resource<tracer::Span>,
181-
status: tracer::Status,
182-
) -> Result<()> {
183-
if let Some(guest_span) = self
184-
.state
185-
.write()
186-
.unwrap()
187-
.guest_spans
188-
.get_mut(resource.rep())
189-
{
190-
guest_span.inner.set_status(status.into());
191-
Ok(())
192-
} else {
193-
Err(anyhow!("BUG: cannot find resource in table"))
194-
}
195-
}
196-
197-
async fn update_name(&mut self, resource: Resource<tracer::Span>, name: String) -> Result<()> {
198-
if let Some(guest_span) = self
199-
.state
200-
.write()
201-
.unwrap()
202-
.guest_spans
203-
.get_mut(resource.rep())
204-
{
205-
guest_span.inner.update_name(name.into());
206-
Ok(())
207-
} else {
208-
Err(anyhow!("BUG: cannot find resource in table"))
209-
}
81+
Ok(())
21082
}
21183

212-
async fn end(
213-
&mut self,
214-
resource: Resource<tracer::Span>,
215-
timestamp: Option<tracer::Datetime>,
216-
) -> Result<()> {
84+
async fn on_end(&mut self, span_data: wasi_otel::SpanData) -> Result<()> {
21785
let mut state = self.state.write().unwrap();
218-
if let Some(guest_span) = state.guest_spans.get_mut(resource.rep()) {
219-
if let Some(timestamp) = timestamp {
220-
guest_span.inner.end_with_timestamp(timestamp.into());
221-
} else {
222-
guest_span.inner.end();
223-
}
86+
87+
let span_id = std::convert::Into::<opentelemetry::trace::SpanContext>::into(
88+
span_data.span_context.clone(),
89+
)
90+
.span_id();
91+
self.processor.on_end(span_data.into());
92+
if let Some(_guest_span) = state.guest_span_contexts.get_mut(&span_id) {
93+
// // TODO: Transfer all the data
94+
// guest_span.end_with_timestamp(span_data.end_time.into());
22495

22596
// Remove the span from active_spans
226-
state.active_spans.shift_remove(&resource.rep());
97+
state.active_spans.shift_remove(&span_id);
22798

22899
Ok(())
229100
} else {
101+
// TODO: This seems to be wrong
230102
Err(anyhow!("BUG: cannot find resource in table"))
231103
}
104+
// Ok(())
232105
}
233106

234-
async fn drop(&mut self, resource: Resource<tracer::Span>) -> Result<()> {
235-
// Dropping the resource automatically calls drop on the Span which ends itself with the
236-
// current timestamp if the Span is not already ended.
237-
238-
// Ensure that the span has been removed from active_spans
239-
let mut state = self.state.write().unwrap();
240-
state.active_spans.shift_remove(&resource.rep());
241-
242-
Ok(())
107+
async fn current_span_context(&mut self) -> Result<wasi_otel::SpanContext> {
108+
// TODO: The bug is that tracing::Span::current() is not returning anything
109+
let context = tracing::Span::current().context();
110+
let span = context.span();
111+
let span_context = span.span_context();
112+
let out: SpanContext = span_context.clone().into();
113+
Ok(out)
243114
}
244115
}
116+
117+
// TODO: Rename module to otel

0 commit comments

Comments
 (0)