#[macro_export]
macro_rules! span_event {
($name:literal) => {{
use $crate::__private::opentelemetry::trace::TraceContextExt;
use $crate::__private::opentelemetry::Context;
Context::current().span().add_event($name, vec![]);
}};
($name:literal, $($key:literal = $value:tt),+ $(,)?) => {{
use $crate::__private::opentelemetry::trace::TraceContextExt;
use $crate::__private::opentelemetry::KeyValue;
use $crate::__private::opentelemetry::Context;
let __attrs = [$((
$key,
$crate::__attr_to_option!($value)
)),+];
Context::current().span().add_event(
$name,
__attrs
.into_iter()
.filter_map(|(k, v)| v.map(|v| KeyValue::new(k, v)))
.collect::<Vec<_>>()
);
}};
}
#[cfg(test)]
mod tests {
use crate::span;
use apollo_opentelemetry_test::{TelemetryContext, assert_spans_snapshot};
use opentelemetry::Context;
use opentelemetry::trace::{FutureExt as _, TraceContextExt};
#[test]
fn test_span_event_simple() {
let ctx = TelemetryContext::new();
let span = span!("parent");
let cx = Context::current_with_span(span);
let _guard = cx.attach();
span_event!("my-event");
drop(_guard);
assert_spans_snapshot!(ctx, @r#"
- name: parent
span_kind: Internal
is_sampled: true
events:
- name: my-event
"#);
}
#[test]
fn test_span_event_with_attributes() {
let ctx = TelemetryContext::new();
let span = span!("parent");
let cx = Context::current_with_span(span);
let _guard = cx.attach();
span_event!("my-event", "key" = "value", "count" = 42i64);
drop(_guard);
assert_spans_snapshot!(ctx, @r#"
- name: parent
span_kind: Internal
is_sampled: true
events:
- name: my-event
attributes:
count: "42"
key: value
"#);
}
#[tokio::test]
async fn test_span_event_in_async() {
let ctx = TelemetryContext::new();
let span = span!("async-parent");
let cx = Context::current_with_span(span);
async {
span_event!("async-event", "stage" = "processing");
}
.with_context(cx)
.await;
assert_spans_snapshot!(ctx, @r#"
- name: async-parent
span_kind: Internal
is_sampled: true
events:
- name: async-event
attributes:
stage: processing
"#);
}
}