Skip to main content

emit_opentelemetry/
lib.rs

1/*!
2Integrate `emit` with the OpenTelemetry SDK.
3
4This library forwards diagnostic events from `emit` through the OpenTelemetry SDK as log records and spans.
5This library is for applications that already use the OpenTelemetry SDK.
6It's also intended for applications that need to unify multiple instrumentation libraries, like `emit`, `log`, and `tracing`, into a shared pipeline.
7If you'd just like to send `emit` diagnostics via OTLP to the OpenTelemetry Collector or other compatible service, then consider [`emit_otlp`](https://docs.rs/emit_otlp).
8
9`emit_opentelemetry` version `x.y.z` is compatible with `opentelemetry_sdk` version `x.y.*`.
10
11# Getting started
12
13Configure the OpenTelemetry SDK as per its documentation, then add `emit` and `emit_opentelemetry` to your Cargo.toml:
14
15```toml
16[dependencies.emit]
17version = "1"
18
19# add `emit_opentelemetry` with the same major/minor as the OpenTelemetry SDK
20[dependencies.emit_opentelemetry]
21version = "0.31"
22
23[dependencies.opentelemetry_sdk]
24version = "0.31"
25features = ["trace", "logs"]
26
27[dependencies.opentelemetry]
28version = "0.31"
29features = ["trace", "logs"]
30```
31
32Initialize `emit` to send diagnostics to the OpenTelemetry SDK using [`setup`]:
33
34```
35fn main() {
36    // Configure the OpenTelemetry SDK
37    // See the OpenTelemetry SDK docs for details on configuration
38    let logger_provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder()
39        .with_simple_exporter(opentelemetry_stdout::LogExporter::default())
40        .build();
41
42    let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
43        .with_simple_exporter(opentelemetry_stdout::SpanExporter::default())
44        .build();
45
46    // Configure `emit` to point to the OpenTelemetry SDK
47    let rt = emit_opentelemetry::setup(logger_provider, tracer_provider).init();
48
49    // Your app code goes here
50
51    rt.blocking_flush(std::time::Duration::from_secs(30));
52
53    // Shutdown the OpenTelemetry SDK
54}
55```
56
57Diagnostic events produced by the [`macro@emit::span`] macro are sent to an [`opentelemetry::trace::Tracer`] as an [`opentelemetry::trace::Span`] on completion. All other emitted events are sent to an [`opentelemetry::logs::Logger`] as [`opentelemetry::logs::LogRecord`]s.
58
59# Span lifecycle
60
61Spans created by `emit`'s `#[emit::span]` attribute will be created through the configured [`opentelemetry::trace::TracerProvider`].
62The following well-known `emit` properties are interpreted during span creation:
63
64- `span_id`: Sets the id of the span. If the id matches the current span then no new span will be created.
65- `trace_id`: Sets the trace id of the span. Otherwise the current trace id will be used.
66- `span_name`: Sets the name of the span. Otherwise a default name derived from the span's message template will be used.
67- `span_kind`: Sets the kind of the span. Otherwise the default kind of _internal_ will be used.
68- `span_links`: Populates a set of links on the span.
69
70Spans created through `emit` don't carry additional attributes on them until completion.
71
72Spans are completed either by emitting an event manually, or when the function annotated with `#[emit::span]` completes.
73At this point if the event is a span, and its context matches the current OpenTelemetry span context, it'll be emitted as a span.
74Otherwise it'll be emitted as a regular log event.
75The following well-known `emit` properties are interpreted during span completion:
76
77- `err`: Mapped onto the semantic `exception` event on the span, and the span's status will be set to `Error`.
78- `lvl`: If its value is `error`, the span's status will be set to `Error`.
79
80If the span doesn't have a meaningful name configured already, then the rendered message will be used.
81
82# Sampling
83
84By default, `emit` events will be excluded if they are inside an unsampled OpenTelemetry trace, even if that trace is marked as recorded. OpenTelemetry will still propagate sampling decisions, but `emit`'s own spans will not be constructed within the unsampled trace.
85
86You can change this behavior by overriding the filter using [`emit::Setup::emit_when`] on the value returned by [`setup`].
87
88# Span links
89
90`emit` doesn't track trace flags, trace state, or whether links are remote in its model.
91This information will be populated from the current span context.
92
93# Span parents
94
95When using `emit_opentelemetry`, any `SpanCtxt` pulled from ambient context won't carry a parent span id, even for non-root spans.
96This is because the OpenTelemetry SDK doesn't have an API for accessing the parent-child relationship of a span after its construction.
97
98# Limitations
99
100This library doesn't support `emit`'s metrics as OpenTelemetry metrics. Any metric samples produced by `emit` will be emitted as log records.
101
102Spans produced manually (without adding their trace ids and span ids to the shared [`emit::Ctxt`]) will be emitted as log events instead of as spans.
103
104# Troubleshooting
105
106If you're not seeing `emit` diagnostics flow as expected through the OpenTelemetry SDK, you can try configuring `emit`'s internal logger, and collect metrics from the integration:
107
108```
109# mod emit_term {
110#     pub fn stdout() -> impl emit::runtime::InternalEmitter + Send + Sync + 'static {
111#        emit::runtime::AssertInternal(emit::emitter::from_fn(|_| {}))
112#     }
113# }
114use emit::metric::Source;
115
116fn main() {
117    let logger_provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder()
118        .with_simple_exporter(opentelemetry_stdout::LogExporter::default())
119        .build();
120
121    let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
122        .with_simple_exporter(opentelemetry_stdout::SpanExporter::default())
123        .build();
124
125    // 1. Initialize the internal logger
126    //    Diagnostics produced by `emit_opentelemetry` itself will go here
127    let internal = emit::setup()
128        .emit_to(emit_term::stdout())
129        .init_internal();
130
131    let mut reporter = emit::metric::Reporter::new();
132
133    let rt = emit_opentelemetry::setup(logger_provider, tracer_provider)
134        .map_emitter(|emitter| {
135            // 2. Add `emit_opentelemetry`'s metrics to a reporter so we can see what it's up to
136            //    You can do this independently of the internal emitter
137            reporter.add_source(emitter.metric_source());
138
139            emitter
140        })
141        .init();
142
143    // Your app code goes here
144
145    rt.blocking_flush(std::time::Duration::from_secs(30));
146
147    // 3. Report metrics after attempting to flush
148    //    You could also do this periodically as your application runs
149    reporter.emit_metrics(&internal.emitter());
150}
151```
152
153Also see the [`opentelemetry`] docs for any details on getting diagnostics out of it.
154*/
155
156#![doc(html_logo_url = "https://raw.githubusercontent.com/emit-rs/emit/main/asset/logo.svg")]
157#![deny(missing_docs)]
158
159use emit::well_known::KEY_SPAN_LINKS;
160use emit::{
161    well_known::{
162        KEY_ERR, KEY_EVT_KIND, KEY_LVL, KEY_SPAN_ID, KEY_SPAN_KIND, KEY_SPAN_NAME, KEY_SPAN_PARENT,
163        KEY_TRACE_ID, LVL_DEBUG, LVL_ERROR, LVL_INFO, LVL_WARN,
164    },
165    Filter, Props,
166};
167use opentelemetry::trace::{Link, SamplingDecision, SamplingResult, TraceState};
168use opentelemetry::{
169    logs::{AnyValue, LogRecord, Logger, LoggerProvider, Severity},
170    trace::{
171        SpanContext, SpanId, SpanKind, Status, TraceContextExt, TraceId, Tracer, TracerProvider,
172    },
173    Context, ContextGuard, Key, KeyValue, TraceFlags, Value,
174};
175use std::fmt::{Display, Formatter};
176use std::{borrow::Cow, cell::RefCell, fmt, ops::ControlFlow, sync::Arc};
177
178mod internal_metrics;
179
180pub use internal_metrics::*;
181
182/**
183Start a builder for the `emit` to OpenTelemetry SDK integration.
184
185```
186fn main() {
187    // Configure the OpenTelemetry SDK
188    // See the OpenTelemetry SDK docs for details on configuration
189    let logger_provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder()
190        .with_simple_exporter(opentelemetry_stdout::LogExporter::default())
191        .build();
192
193    let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
194        .with_simple_exporter(opentelemetry_stdout::SpanExporter::default())
195        .build();
196
197    let rt = emit_opentelemetry::setup(logger_provider, tracer_provider).init();
198
199    // Your app code goes here
200
201    rt.blocking_flush(std::time::Duration::from_secs(30));
202
203    // Shutdown the OpenTelemetry SDK
204}
205```
206
207Use [`emit::Setup::map_emitter`] and [`emit::Setup::map_ctxt`] on the returned value to customize the integration:
208
209```
210fn main() {
211    // Configure the OpenTelemetry SDK
212    // See the OpenTelemetry SDK docs for details on configuration
213    let logger_provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder()
214        .with_simple_exporter(opentelemetry_stdout::LogExporter::default())
215        .build();
216
217    let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
218        .with_simple_exporter(opentelemetry_stdout::SpanExporter::default())
219        .build();
220
221    let rt = emit_opentelemetry::setup(logger_provider, tracer_provider)
222        .map_emitter(|emitter| emitter
223            .with_log_body(|evt, f| write!(f, "{}", evt.tpl()))
224            .with_span_name(|evt, f| write!(f, "{}", evt.tpl()))
225        )
226        .init();
227
228    // Your app code goes here
229
230    rt.blocking_flush(std::time::Duration::from_secs(30));
231
232    // Shutdown the OpenTelemetry SDK
233}
234```
235*/
236pub fn setup<L: Logger + Send + Sync + 'static, T: Tracer + Send + Sync + 'static>(
237    logger_provider: impl LoggerProvider<Logger = L>,
238    tracer_provider: impl TracerProvider<Tracer = T>,
239) -> emit::Setup<
240    OpenTelemetryEmitter<L>,
241    OpenTelemetryIsSampledFilter,
242    OpenTelemetryCtxt<emit::setup::DefaultCtxt, T>,
243>
244where
245    T::Span: Send + Sync + 'static,
246{
247    let name = "emit";
248    let metrics = Arc::new(InternalMetrics::default());
249
250    emit::setup()
251        .emit_to(OpenTelemetryEmitter::new(
252            metrics.clone(),
253            logger_provider.logger(name),
254        ))
255        .emit_when(OpenTelemetryIsSampledFilter {})
256        .map_ctxt(|ctxt| {
257            OpenTelemetryCtxt::wrap(metrics.clone(), tracer_provider.tracer(name), ctxt)
258        })
259}
260
261/**
262An [`emit::Ctxt`] created during [`setup`] for integrating `emit` with the OpenTelemetry SDK.
263
264This type is responsible for intercepting calls that push span state to `emit`'s ambient context and forwarding them to the OpenTelemetry SDK's own context.
265
266When [`macro@emit::span`] is called, an [`opentelemetry::trace::Span`] is started using the given trace and span ids. The span doesn't carry any other ambient properties until it's completed either through [`emit::span::SpanGuard::complete`], or at the end of the scope the [`macro@emit::span`] macro covers.
267*/
268pub struct OpenTelemetryCtxt<C, T> {
269    tracer: T,
270    metrics: Arc<InternalMetrics>,
271    inner: C,
272}
273
274/**
275The [`emit::Ctxt::Frame`] used by [`OpenTelemetryCtxt`].
276*/
277pub struct OpenTelemetryFrame<F> {
278    // Holds the OpenTelemetry context fetched when the span was started
279    // If this field is `None`, and `active` is true then the slot has been
280    // moved into the thread-local stack
281    slot: Option<Context>,
282    // Whether `slot` has been moved into the thread-local stack
283    // If this field is false and `active` is `None` then the frame doesn't
284    // hold an OpenTelemetry span
285    active: bool,
286    options: OpenTelemetryFrameOptions,
287    // The frame from the wrapped `Ctxt`
288    inner: F,
289}
290
291#[derive(Debug, Clone, Copy, Default)]
292struct OpenTelemetryFrameOptions {
293    // Whether to try end the span upon closing the frame
294    // Normally, this should be false by the time `close` is called because
295    // the emitter will have ended the span
296    end_on_close: bool,
297    // Whether to build a default span name on close
298    // This value will be `true` if the span was originally started with a default name
299    update_default_name_on_close: bool,
300}
301
302/**
303The [`emit::Ctxt::Current`] used by [`OpenTelemetryCtxt`].
304*/
305pub struct OpenTelemetryProps<P: ?Sized> {
306    ctxt: emit::span::SpanCtxt,
307    // Props from the wrapped `Ctxt`
308    inner: *const P,
309}
310
311impl<C, T> OpenTelemetryCtxt<C, T> {
312    fn wrap(metrics: Arc<InternalMetrics>, tracer: T, ctxt: C) -> Self {
313        OpenTelemetryCtxt {
314            tracer,
315            inner: ctxt,
316            metrics,
317        }
318    }
319
320    /**
321    Get an [`emit::metric::Source`] for instrumentation produced by the `emit` to OpenTelemetry SDK integration.
322
323    These metrics are shared by [`OpenTelemetryEmitter::metric_source`].
324
325    These metrics can be used to monitor the running health of your diagnostic pipeline.
326    */
327    pub fn metric_source(&self) -> EmitOpenTelemetryMetrics {
328        EmitOpenTelemetryMetrics {
329            metrics: self.metrics.clone(),
330        }
331    }
332}
333
334impl<P: emit::Props + ?Sized> emit::Props for OpenTelemetryProps<P> {
335    fn for_each<'kv, F: FnMut(emit::Str<'kv>, emit::Value<'kv>) -> ControlFlow<()>>(
336        &'kv self,
337        mut for_each: F,
338    ) -> ControlFlow<()> {
339        self.ctxt.for_each(&mut for_each)?;
340
341        // SAFETY: This type is only exposed for arbitrarily short (`for<'a>`) lifetimes
342        // so inner it's guaranteed to be valid for `'kv`, which must be shorter than its
343        // original lifetime
344        unsafe { &*self.inner }.for_each(|k, v| {
345            if k != emit::well_known::KEY_TRACE_ID && k != emit::well_known::KEY_SPAN_ID {
346                for_each(k, v)?;
347            }
348
349            ControlFlow::Continue(())
350        })
351    }
352}
353
354thread_local! {
355    static ACTIVE_FRAME_STACK: RefCell<Vec<ActiveFrame>> = RefCell::new(Vec::new());
356}
357
358struct ActiveFrame {
359    _guard: ContextGuard,
360    options: OpenTelemetryFrameOptions,
361}
362
363fn push(guard: ActiveFrame) {
364    ACTIVE_FRAME_STACK.with(|stack| stack.borrow_mut().push(guard));
365}
366
367fn pop() -> Option<ActiveFrame> {
368    ACTIVE_FRAME_STACK.with(|stack| stack.borrow_mut().pop())
369}
370
371fn with_current(f: impl FnOnce(&mut ActiveFrame)) {
372    ACTIVE_FRAME_STACK.with(|stack| {
373        if let Some(frame) = stack.borrow_mut().last_mut() {
374            f(frame);
375        }
376    })
377}
378
379impl<C: emit::Ctxt, T: Tracer> emit::Ctxt for OpenTelemetryCtxt<C, T>
380where
381    T::Span: Send + Sync + 'static,
382{
383    type Current = OpenTelemetryProps<C::Current>;
384
385    type Frame = OpenTelemetryFrame<C::Frame>;
386
387    fn open_root<P: emit::Props>(&self, props: P) -> Self::Frame {
388        let (incoming, props) = incoming_span_ctxt(&self.tracer, props, false);
389
390        let (slot, options) = match incoming {
391            // An empty root context should unset any active OTel context
392            IncomingSpanCtxt::None => (Some(Context::new()), Default::default()),
393            // If the context is the same then don't track anything in this frame
394            IncomingSpanCtxt::Same => (None, Default::default()),
395            // If the context is different then track it in this frame
396            IncomingSpanCtxt::Different(context, options) => (Some(context), options),
397        };
398
399        OpenTelemetryFrame {
400            active: false,
401            options,
402            slot,
403            inner: self.inner.open_root(props),
404        }
405    }
406
407    fn open_disabled<P: Props>(&self, props: P) -> Self::Frame {
408        let (incoming, props) = incoming_span_ctxt(&self.tracer, props, true);
409
410        let (slot, options) = match incoming {
411            // An empty context and the same context are equivalent; neither track anything in this frame
412            IncomingSpanCtxt::None => (None, Default::default()),
413            IncomingSpanCtxt::Same => (None, Default::default()),
414            // If the context is different then track it in this frame
415            IncomingSpanCtxt::Different(context, options) => (Some(context), options),
416        };
417
418        OpenTelemetryFrame {
419            active: false,
420            options,
421            slot,
422            inner: self.inner.open_disabled(props),
423        }
424    }
425
426    fn open_push<P: Props>(&self, props: P) -> Self::Frame {
427        let (incoming, props) = incoming_span_ctxt(&self.tracer, props, false);
428
429        let (slot, options) = match incoming {
430            // An empty context and the same context are equivalent; neither track anything in this frame
431            // Note that if the sampling decision changed without the span context changing we'll ignore it
432            IncomingSpanCtxt::None => (None, Default::default()),
433            IncomingSpanCtxt::Same => (None, Default::default()),
434            // If the context is different then track it in this frame
435            // The context will be unsampled, so any downstream spans will also be unsampled
436            IncomingSpanCtxt::Different(context, options) => (Some(context), options),
437        };
438
439        OpenTelemetryFrame {
440            active: false,
441            options,
442            slot,
443            inner: self.inner.open_push(props),
444        }
445    }
446
447    fn enter(&self, local: &mut Self::Frame) {
448        self.inner.enter(&mut local.inner);
449
450        if let Some(ctxt) = local.slot.take() {
451            let guard = ctxt.attach();
452
453            push(ActiveFrame {
454                _guard: guard,
455                options: local.options,
456            });
457            local.active = true;
458        }
459    }
460
461    fn with_current<R, F: FnOnce(&Self::Current) -> R>(&self, with: F) -> R {
462        let ctxt = Context::current();
463        let span = ctxt.span();
464
465        // Use the trace and span ids from OpenTelemetry
466        // If an OpenTelemetry span is created between calls to `enter`
467        // and `exit` then these values won't match what's on the frame
468        // We need to observe that to keep `emit`'s diagnostics aligned
469        // with other OpenTelemetry consumers in the same application
470        let trace_id = span.span_context().trace_id().to_bytes();
471        let span_id = span.span_context().span_id().to_bytes();
472
473        self.inner.with_current(|props| {
474            let props = OpenTelemetryProps {
475                ctxt: emit::span::SpanCtxt::new(
476                    emit::TraceId::from_bytes(trace_id),
477                    // Span parents are tracked by OTel internally, we can't access them
478                    None,
479                    emit::SpanId::from_bytes(span_id),
480                ),
481                inner: props as *const C::Current,
482            };
483
484            with(&props)
485        })
486    }
487
488    fn exit(&self, frame: &mut Self::Frame) {
489        self.inner.exit(&mut frame.inner);
490
491        if frame.active {
492            frame.slot = Some(Context::current());
493
494            if let Some(active) = pop() {
495                frame.options = active.options;
496            }
497            frame.active = false;
498        }
499    }
500
501    fn close(&self, mut frame: Self::Frame) {
502        // If the span hasn't been closed through an event, then close it now
503        if frame.options.end_on_close {
504            // This will only be `None` if `close` is called out-of-order
505            // with `exit`
506            if let Some(ctxt) = frame.slot.take() {
507                self.metrics.span_unexpected_close.increment();
508
509                let span = ctxt.span();
510                span.end();
511            }
512        }
513    }
514}
515
516fn incoming_span_ctxt<T: Tracer>(
517    tracer: &T,
518    props: impl emit::Props,
519    suppress: bool,
520) -> (IncomingSpanCtxt, impl Props)
521where
522    T::Span: Send + Sync + 'static,
523{
524    let span_id = props.pull::<emit::SpanId, _>(KEY_SPAN_ID);
525
526    let Some(span_id) = span_id else {
527        return (
528            IncomingSpanCtxt::None,
529            ExcludeSpanCtxtProps { inner: props },
530        );
531    };
532
533    let ctxt = Context::current();
534
535    let span_id = otel_span_id(span_id);
536
537    // Only open a span if the id has changed
538    if span_id == ctxt.span().span_context().span_id() {
539        return (
540            IncomingSpanCtxt::Same,
541            ExcludeSpanCtxtProps { inner: props },
542        );
543    }
544
545    // Map `emit`'s well-known span properties into the OTel context
546    // Note that only properties that are needed on span construction are
547    // handled here. Other span properties will be mapped when the span is emitted
548
549    let span_links = props
550        .get(KEY_SPAN_LINKS)
551        .map(|links| {
552            otel_span_links(
553                links,
554                ctxt.span().span_context().trace_flags(),
555                ctxt.span().span_context().is_remote(),
556                ctxt.span().span_context().trace_state(),
557            )
558        })
559        .unwrap_or_default();
560
561    let span_kind = props
562        .pull::<emit::span::SpanKind, _>(KEY_SPAN_KIND)
563        .map(|kind| match kind {
564            emit::span::SpanKind::Client => SpanKind::Client,
565            emit::span::SpanKind::Server => SpanKind::Server,
566            emit::span::SpanKind::Producer => SpanKind::Producer,
567            emit::span::SpanKind::Consumer => SpanKind::Consumer,
568            _ => SpanKind::Internal,
569        })
570        .unwrap_or(SpanKind::Internal);
571
572    let span_name = props.pull::<String, _>(KEY_SPAN_NAME).map(Cow::Owned);
573
574    // If the props include a span name then don't change it when completing the span
575    // We need to track this in our own frame type because the OTel SDK doesn't expose
576    // the name after construction
577    let update_default_name_on_close = span_name.is_none();
578
579    let trace_id = props.pull::<emit::TraceId, _>(KEY_TRACE_ID);
580
581    let trace_id = trace_id.map(otel_trace_id);
582
583    let mut span = tracer
584        .span_builder(span_name.unwrap_or(Cow::Borrowed("emit_span")))
585        .with_kind(span_kind)
586        .with_span_id(span_id);
587
588    if let Some(trace_id) = trace_id {
589        span = span.with_trace_id(trace_id);
590    }
591
592    span = span.with_links(span_links);
593
594    // If the context was discarded by `emit`'s filter then open it as disabled
595    if suppress {
596        span = span.with_sampling_result(SamplingResult {
597            decision: SamplingDecision::Drop,
598            attributes: vec![],
599            trace_state: Default::default(),
600        });
601    }
602
603    let ctxt = ctxt.with_span(span.start(tracer));
604
605    (
606        IncomingSpanCtxt::Different(
607            ctxt,
608            OpenTelemetryFrameOptions {
609                update_default_name_on_close,
610                end_on_close: true,
611            },
612        ),
613        ExcludeSpanCtxtProps { inner: props },
614    )
615}
616
617enum IncomingSpanCtxt {
618    None,
619    Same,
620    Different(Context, OpenTelemetryFrameOptions),
621}
622
623/**
624A filter used when pushing properties into `emit`'s context that removes properties
625tracked by the OpenTelemetry SDK.
626*/
627struct ExcludeSpanCtxtProps<P> {
628    inner: P,
629}
630
631impl<P: emit::Props> emit::Props for ExcludeSpanCtxtProps<P> {
632    fn for_each<'kv, F: FnMut(emit::Str<'kv>, emit::Value<'kv>) -> ControlFlow<()>>(
633        &'kv self,
634        mut for_each: F,
635    ) -> ControlFlow<()> {
636        self.inner.for_each(|key, value| match key.get() {
637            // Properties that come from the OTel context
638            KEY_TRACE_ID | KEY_SPAN_ID | KEY_SPAN_PARENT | KEY_SPAN_NAME | KEY_SPAN_KIND
639            | KEY_SPAN_LINKS => ControlFlow::Continue(()),
640            // Properties to pass through to the underlying context
641            _ => for_each(key, value),
642        })
643    }
644}
645
646/**
647An [`emit::Emitter`] creating during [`setup`] for integrating `emit` with the OpenTelemetry SDK.
648
649This type is responsible for emitting diagnostic events as log records through the OpenTelemetry SDK and completing spans created through the integration.
650*/
651pub struct OpenTelemetryEmitter<L> {
652    logger: L,
653    span_name: Box<MessageFormatter>,
654    log_body: Box<MessageFormatter>,
655    metrics: Arc<InternalMetrics>,
656}
657
658type MessageFormatter = dyn Fn(&emit::event::Event<&dyn emit::props::ErasedProps>, &mut fmt::Formatter) -> fmt::Result
659    + Send
660    + Sync;
661
662fn default_span_name() -> Box<MessageFormatter> {
663    Box::new(|evt, f| {
664        if let Some(name) = evt.props().get(KEY_SPAN_NAME) {
665            write!(f, "{}", name)
666        } else {
667            write!(f, "{}", evt.msg())
668        }
669    })
670}
671
672fn default_log_body() -> Box<MessageFormatter> {
673    Box::new(|evt, f| write!(f, "{}", evt.msg()))
674}
675
676struct MessageRenderer<'a, P> {
677    pub fmt: &'a MessageFormatter,
678    pub evt: &'a emit::event::Event<'a, P>,
679}
680
681impl<'a, P: emit::props::Props> fmt::Display for MessageRenderer<'a, P> {
682    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
683        (self.fmt)(&self.evt.erase(), f)
684    }
685}
686
687impl<L> OpenTelemetryEmitter<L> {
688    fn new(metrics: Arc<InternalMetrics>, logger: L) -> Self {
689        OpenTelemetryEmitter {
690            logger,
691            span_name: default_span_name(),
692            log_body: default_log_body(),
693            metrics,
694        }
695    }
696
697    /**
698    Specify a function that gets the name of a span from a diagnostic event.
699
700    The default implementation uses the [`KEY_SPAN_NAME`] property on the event, or [`emit::Event::msg`] if it's not present.
701    */
702    pub fn with_span_name(
703        mut self,
704        writer: impl Fn(
705                &emit::event::Event<&dyn emit::props::ErasedProps>,
706                &mut fmt::Formatter,
707            ) -> fmt::Result
708            + Send
709            + Sync
710            + 'static,
711    ) -> Self {
712        self.span_name = Box::new(writer);
713        self
714    }
715
716    /**
717    Specify a function that gets the body of a log record from a diagnostic event.
718
719    The default implementation uses [`emit::Event::msg`].
720    */
721    pub fn with_log_body(
722        mut self,
723        writer: impl Fn(
724                &emit::event::Event<&dyn emit::props::ErasedProps>,
725                &mut fmt::Formatter,
726            ) -> fmt::Result
727            + Send
728            + Sync
729            + 'static,
730    ) -> Self {
731        self.log_body = Box::new(writer);
732        self
733    }
734
735    /**
736    Get an [`emit::metric::Source`] for instrumentation produced by the `emit` to OpenTelemetry SDK integration.
737
738    These metrics are shared by [`OpenTelemetryCtxt::metric_source`].
739
740    These metrics can be used to monitor the running health of your diagnostic pipeline.
741    */
742    pub fn metric_source(&self) -> EmitOpenTelemetryMetrics {
743        EmitOpenTelemetryMetrics {
744            metrics: self.metrics.clone(),
745        }
746    }
747}
748
749impl<L: Logger> emit::Emitter for OpenTelemetryEmitter<L> {
750    fn emit<E: emit::event::ToEvent>(&self, evt: E) {
751        let evt = evt.to_event();
752
753        // If the event is for a span then attempt to end it
754        // The typical case is the span was created through `#[span]`
755        // and so is the currently active frame. If it isn't the active frame
756        // then it's been created manually or spans are being completed out of order
757        if emit::kind::is_span_filter().matches(&evt) {
758            let mut emitted = false;
759            with_current(|frame| {
760                if frame.options.end_on_close {
761                    let ctxt = Context::current();
762                    let span = ctxt.span();
763
764                    let span_id = span.span_context().span_id();
765
766                    let evt_span_id = evt
767                        .props()
768                        .pull::<emit::SpanId, _>(KEY_SPAN_ID)
769                        .map(otel_span_id);
770
771                    // If the event is for the current span then complete it
772                    if Some(span_id) == evt_span_id {
773                        let mut status = Status::Ok;
774                        let mut status_is_descriptive_err = false;
775                        let mut span_links = Vec::new();
776
777                        let _ = evt.props().for_each(|k, v| {
778                            if k == KEY_LVL {
779                                if let Some(emit::Level::Error) = v.by_ref().cast::<emit::Level>() {
780                                    // Only set the status if we haven't given it a more descriptive value already
781                                    if !status_is_descriptive_err {
782                                        status = Status::error("error");
783                                    }
784
785                                    return ControlFlow::Continue(());
786                                }
787                            }
788
789                            if k == KEY_ERR {
790                                span.add_event(
791                                    "exception",
792                                    vec![KeyValue::new("exception.message", v.to_string())],
793                                );
794
795                                status = Status::error(v.to_string());
796                                status_is_descriptive_err = true;
797
798                                return ControlFlow::Continue(());
799                            }
800
801                            if k == KEY_SPAN_LINKS {
802                                span_links = otel_span_links(
803                                    v,
804                                    span.span_context().trace_flags(),
805                                    span.span_context().is_remote(),
806                                    span.span_context().trace_state(),
807                                );
808
809                                return ControlFlow::Continue(());
810                            }
811
812                            // Ignored; these are all handled during span construction
813                            if k == KEY_TRACE_ID
814                                || k == KEY_SPAN_ID
815                                || k == KEY_SPAN_PARENT
816                                || k == KEY_EVT_KIND
817                                || k == KEY_SPAN_KIND
818                                || k == KEY_SPAN_NAME
819                            {
820                                return ControlFlow::Continue(());
821                            }
822
823                            if let Some(v) = otel_span_value(v) {
824                                span.set_attribute(KeyValue::new(k.to_cow(), v));
825                            }
826
827                            ControlFlow::Continue(())
828                        });
829
830                        if frame.options.update_default_name_on_close {
831                            span.update_name(
832                                MessageRenderer {
833                                    fmt: &self.span_name,
834                                    evt: &evt,
835                                }
836                                .to_string(),
837                            );
838                        }
839
840                        span.set_status(status);
841
842                        for link in span_links {
843                            span.add_link(link.span_context, Default::default());
844                        }
845
846                        if let Some(extent) = evt.extent().and_then(|ex| ex.as_range()) {
847                            span.end_with_timestamp(extent.end.to_system_time());
848                        } else {
849                            span.end();
850                        }
851
852                        frame.options.end_on_close = false;
853                        emitted = true;
854                    }
855                }
856            });
857
858            if emitted {
859                return;
860            } else {
861                self.metrics.span_unexpected_emit.increment();
862            }
863        }
864
865        // If the event wasn't emitted as a span then emit it as a log record
866        let mut record = self.logger.create_log_record();
867
868        let body = format!(
869            "{}",
870            MessageRenderer {
871                fmt: &self.log_body,
872                evt: &evt,
873            }
874        );
875
876        record.set_body(AnyValue::String(body.into()));
877
878        let mut trace_id = None;
879        let mut span_id = None;
880        let mut attributes = Vec::new();
881        {
882            let _ = evt.props().for_each(|k, v| {
883                if k == KEY_LVL {
884                    match v.by_ref().cast::<emit::Level>() {
885                        Some(emit::Level::Debug) => {
886                            record.set_severity_number(Severity::Debug);
887                            record.set_severity_text(LVL_DEBUG);
888                        }
889                        Some(emit::Level::Info) => {
890                            record.set_severity_number(Severity::Info);
891                            record.set_severity_text(LVL_INFO);
892                        }
893                        Some(emit::Level::Warn) => {
894                            record.set_severity_number(Severity::Warn);
895                            record.set_severity_text(LVL_WARN);
896                        }
897                        Some(emit::Level::Error) => {
898                            record.set_severity_number(Severity::Error);
899                            record.set_severity_text(LVL_ERROR);
900                        }
901                        None => {
902                            record.set_severity_text("unknown");
903                        }
904                    }
905
906                    return ControlFlow::Continue(());
907                }
908
909                if k == KEY_TRACE_ID {
910                    if let Some(id) = v.by_ref().cast::<emit::TraceId>() {
911                        trace_id = Some(otel_trace_id(id));
912
913                        return ControlFlow::Continue(());
914                    }
915                }
916
917                if k == KEY_SPAN_ID {
918                    if let Some(id) = v.by_ref().cast::<emit::SpanId>() {
919                        span_id = Some(otel_span_id(id));
920
921                        return ControlFlow::Continue(());
922                    }
923                }
924
925                if k == KEY_SPAN_PARENT {
926                    if v.by_ref().cast::<emit::SpanId>().is_some() {
927                        return ControlFlow::Continue(());
928                    }
929                }
930
931                // Ignored
932                if k == KEY_SPAN_NAME || k == KEY_SPAN_KIND || k == KEY_SPAN_LINKS {
933                    return ControlFlow::Continue(());
934                }
935
936                if let Some(v) = otel_log_value(v) {
937                    attributes.push((Key::new(k.to_cow()), v));
938                }
939
940                ControlFlow::Continue(())
941            });
942        }
943
944        record.add_attributes(attributes);
945
946        if let Some(extent) = evt.extent() {
947            record.set_timestamp(extent.as_point().to_system_time());
948        }
949
950        let context = Context::current();
951        let span = context.span();
952        let span = span.span_context();
953
954        let trace_id = trace_id.unwrap_or_else(|| span.trace_id());
955        let span_id = span_id.unwrap_or_else(|| span.span_id());
956        let trace_flags = Some(span.trace_flags());
957
958        record.set_trace_context(trace_id, span_id, trace_flags);
959
960        self.logger.emit(record);
961    }
962
963    fn blocking_flush(&self, _: std::time::Duration) -> bool {
964        false
965    }
966}
967
968/**
969A filter that excludes span events inside an unsampled trace.
970*/
971pub struct OpenTelemetryIsSampledFilter {}
972
973impl emit::Filter for OpenTelemetryIsSampledFilter {
974    fn matches<E: emit::event::ToEvent>(&self, evt: E) -> bool {
975        let evt = evt.to_event();
976
977        // If the event is a span then only include it if it matches the current OTel span context
978        if emit::kind::is_span_filter().matches(&evt) {
979            let ctxt = Context::current();
980            let span = ctxt.span();
981            let span_ctxt = span.span_context();
982
983            span_ctxt == &SpanContext::NONE || span_ctxt.is_sampled()
984        } else {
985            // If the event is not a span then include it
986            true
987        }
988    }
989}
990
991fn otel_trace_id(trace_id: emit::TraceId) -> TraceId {
992    TraceId::from_bytes(trace_id.to_bytes())
993}
994
995fn otel_span_id(span_id: emit::SpanId) -> SpanId {
996    SpanId::from_bytes(span_id.to_bytes())
997}
998
999fn otel_span_value(v: emit::Value) -> Option<Value> {
1000    match any_value::serialize(&v) {
1001        Ok(Some(av)) => match av {
1002            AnyValue::Int(v) => Some(Value::I64(v)),
1003            AnyValue::Double(v) => Some(Value::F64(v)),
1004            AnyValue::String(v) => Some(Value::String(v)),
1005            AnyValue::Boolean(v) => Some(Value::Bool(v)),
1006            // Variants not supported by `Value`
1007            _ => Some(Value::String(v.to_string().into())),
1008        },
1009        Ok(None) => None,
1010        Err(()) => Some(Value::String(v.to_string().into())),
1011    }
1012}
1013
1014fn otel_log_value(v: emit::Value) -> Option<AnyValue> {
1015    match any_value::serialize(&v) {
1016        Ok(v) => v,
1017        Err(()) => Some(AnyValue::String(v.to_string().into())),
1018    }
1019}
1020
1021fn otel_span_links(
1022    v: emit::Value,
1023    trace_flags: TraceFlags,
1024    is_remote: bool,
1025    trace_state: &TraceState,
1026) -> Vec<Link> {
1027    // A `serde::Serializer` that extracts span links in `emit`'s `["{traceid}-{spanid}"]`
1028    // format and converts them into OpenTelemetry links
1029
1030    use serde::ser::{
1031        Error, Impossible, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
1032        SerializeTupleVariant, Serializer, StdError,
1033    };
1034
1035    struct Extract<'a> {
1036        links: Vec<Link>,
1037        trace_flags: TraceFlags,
1038        is_remote: bool,
1039        trace_state: &'a TraceState,
1040    }
1041
1042    #[derive(Debug)]
1043    struct ExtractError;
1044
1045    impl fmt::Display for ExtractError {
1046        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1047            f.write_str("unsupported value for span links")
1048        }
1049    }
1050
1051    impl StdError for ExtractError {}
1052
1053    impl Error for ExtractError {
1054        fn custom<T>(_: T) -> Self
1055        where
1056            T: Display,
1057        {
1058            ExtractError
1059        }
1060    }
1061
1062    impl<'a> Serializer for Extract<'a> {
1063        type Ok = Vec<Link>;
1064        type Error = ExtractError;
1065        type SerializeSeq = Self;
1066        type SerializeTuple = Self;
1067        type SerializeTupleStruct = Self;
1068        type SerializeTupleVariant = Self;
1069        type SerializeMap = Impossible<Self::Ok, Self::Error>;
1070        type SerializeStruct = Impossible<Self::Ok, Self::Error>;
1071        type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
1072
1073        fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
1074            Err(ExtractError)
1075        }
1076
1077        fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
1078            Err(ExtractError)
1079        }
1080
1081        fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
1082            Err(ExtractError)
1083        }
1084
1085        fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
1086            Err(ExtractError)
1087        }
1088
1089        fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
1090            Err(ExtractError)
1091        }
1092
1093        fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
1094            Err(ExtractError)
1095        }
1096
1097        fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
1098            Err(ExtractError)
1099        }
1100
1101        fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
1102            Err(ExtractError)
1103        }
1104
1105        fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
1106            Err(ExtractError)
1107        }
1108
1109        fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
1110            Err(ExtractError)
1111        }
1112
1113        fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
1114            Err(ExtractError)
1115        }
1116
1117        fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
1118            Err(ExtractError)
1119        }
1120
1121        fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
1122            Err(ExtractError)
1123        }
1124
1125        fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
1126            Err(ExtractError)
1127        }
1128
1129        fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
1130            Err(ExtractError)
1131        }
1132
1133        fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
1134        where
1135            T: ?Sized + Serialize,
1136        {
1137            value.serialize(self)
1138        }
1139
1140        fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
1141            Err(ExtractError)
1142        }
1143
1144        fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
1145            Err(ExtractError)
1146        }
1147
1148        fn serialize_unit_variant(
1149            self,
1150            _: &'static str,
1151            _: u32,
1152            _: &'static str,
1153        ) -> Result<Self::Ok, Self::Error> {
1154            Err(ExtractError)
1155        }
1156
1157        fn serialize_newtype_struct<T>(
1158            self,
1159            _: &'static str,
1160            value: &T,
1161        ) -> Result<Self::Ok, Self::Error>
1162        where
1163            T: ?Sized + Serialize,
1164        {
1165            value.serialize(self)
1166        }
1167
1168        fn serialize_newtype_variant<T>(
1169            self,
1170            _: &'static str,
1171            _: u32,
1172            _: &'static str,
1173            value: &T,
1174        ) -> Result<Self::Ok, Self::Error>
1175        where
1176            T: ?Sized + Serialize,
1177        {
1178            value.serialize(self)
1179        }
1180
1181        fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
1182            Ok(self)
1183        }
1184
1185        fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
1186            Ok(self)
1187        }
1188
1189        fn serialize_tuple_struct(
1190            self,
1191            _: &'static str,
1192            _: usize,
1193        ) -> Result<Self::SerializeTupleStruct, Self::Error> {
1194            Ok(self)
1195        }
1196
1197        fn serialize_tuple_variant(
1198            self,
1199            _: &'static str,
1200            _: u32,
1201            _: &'static str,
1202            _: usize,
1203        ) -> Result<Self::SerializeTupleVariant, Self::Error> {
1204            Ok(self)
1205        }
1206
1207        fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
1208            Err(ExtractError)
1209        }
1210
1211        fn serialize_struct(
1212            self,
1213            _: &'static str,
1214            _: usize,
1215        ) -> Result<Self::SerializeStruct, Self::Error> {
1216            Err(ExtractError)
1217        }
1218
1219        fn serialize_struct_variant(
1220            self,
1221            _: &'static str,
1222            _: u32,
1223            _: &'static str,
1224            _: usize,
1225        ) -> Result<Self::SerializeStructVariant, Self::Error> {
1226            Err(ExtractError)
1227        }
1228    }
1229
1230    impl<'a> SerializeSeq for Extract<'a> {
1231        type Ok = Vec<Link>;
1232        type Error = ExtractError;
1233
1234        fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
1235        where
1236            T: ?Sized + Serialize,
1237        {
1238            self.links.push(value.serialize(ParseLink {
1239                trace_flags: self.trace_flags,
1240                is_remote: self.is_remote,
1241                trace_state: self.trace_state,
1242            })?);
1243
1244            Ok(())
1245        }
1246
1247        fn end(self) -> Result<Self::Ok, Self::Error> {
1248            Ok(self.links)
1249        }
1250    }
1251
1252    impl<'a> SerializeTuple for Extract<'a> {
1253        type Ok = Vec<Link>;
1254        type Error = ExtractError;
1255
1256        fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
1257        where
1258            T: ?Sized + Serialize,
1259        {
1260            self.links.push(value.serialize(ParseLink {
1261                trace_flags: self.trace_flags,
1262                is_remote: self.is_remote,
1263                trace_state: self.trace_state,
1264            })?);
1265
1266            Ok(())
1267        }
1268
1269        fn end(self) -> Result<Self::Ok, Self::Error> {
1270            Ok(self.links)
1271        }
1272    }
1273
1274    impl<'a> SerializeTupleStruct for Extract<'a> {
1275        type Ok = Vec<Link>;
1276        type Error = ExtractError;
1277
1278        fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
1279        where
1280            T: ?Sized + Serialize,
1281        {
1282            self.links.push(value.serialize(ParseLink {
1283                trace_flags: self.trace_flags,
1284                is_remote: self.is_remote,
1285                trace_state: self.trace_state,
1286            })?);
1287
1288            Ok(())
1289        }
1290
1291        fn end(self) -> Result<Self::Ok, Self::Error> {
1292            Ok(self.links)
1293        }
1294    }
1295
1296    impl<'a> SerializeTupleVariant for Extract<'a> {
1297        type Ok = Vec<Link>;
1298        type Error = ExtractError;
1299
1300        fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
1301        where
1302            T: ?Sized + Serialize,
1303        {
1304            self.links.push(value.serialize(ParseLink {
1305                trace_flags: self.trace_flags,
1306                is_remote: self.is_remote,
1307                trace_state: &self.trace_state,
1308            })?);
1309
1310            Ok(())
1311        }
1312
1313        fn end(self) -> Result<Self::Ok, Self::Error> {
1314            Ok(self.links)
1315        }
1316    }
1317
1318    struct ParseLink<'a> {
1319        trace_flags: TraceFlags,
1320        is_remote: bool,
1321        trace_state: &'a TraceState,
1322    }
1323
1324    impl<'a> Serializer for ParseLink<'a> {
1325        type Ok = Link;
1326        type Error = ExtractError;
1327        type SerializeSeq = Impossible<Self::Ok, Self::Error>;
1328        type SerializeTuple = Impossible<Self::Ok, Self::Error>;
1329        type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
1330        type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
1331        type SerializeMap = Impossible<Self::Ok, Self::Error>;
1332        type SerializeStruct = Impossible<Self::Ok, Self::Error>;
1333        type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
1334
1335        fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
1336            Err(ExtractError)
1337        }
1338
1339        fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
1340            Err(ExtractError)
1341        }
1342
1343        fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
1344            Err(ExtractError)
1345        }
1346
1347        fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
1348            Err(ExtractError)
1349        }
1350
1351        fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
1352            Err(ExtractError)
1353        }
1354
1355        fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
1356            Err(ExtractError)
1357        }
1358
1359        fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
1360            Err(ExtractError)
1361        }
1362
1363        fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
1364            Err(ExtractError)
1365        }
1366
1367        fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
1368            Err(ExtractError)
1369        }
1370
1371        fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
1372            Err(ExtractError)
1373        }
1374
1375        fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
1376            Err(ExtractError)
1377        }
1378
1379        fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
1380            Err(ExtractError)
1381        }
1382
1383        fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
1384            let link = emit::span::SpanLink::try_from_str(v).map_err(|_| ExtractError)?;
1385
1386            Ok(Link::new(
1387                SpanContext::new(
1388                    otel_trace_id(*link.trace_id()),
1389                    otel_span_id(*link.span_id()),
1390                    self.trace_flags,
1391                    self.is_remote,
1392                    self.trace_state.clone(),
1393                ),
1394                Vec::new(),
1395                0,
1396            ))
1397        }
1398
1399        fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
1400            Err(ExtractError)
1401        }
1402
1403        fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
1404            Err(ExtractError)
1405        }
1406
1407        fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
1408        where
1409            T: ?Sized + Serialize,
1410        {
1411            value.serialize(self)
1412        }
1413
1414        fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
1415            Err(ExtractError)
1416        }
1417
1418        fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
1419            Err(ExtractError)
1420        }
1421
1422        fn serialize_unit_variant(
1423            self,
1424            _: &'static str,
1425            _: u32,
1426            _: &'static str,
1427        ) -> Result<Self::Ok, Self::Error> {
1428            Err(ExtractError)
1429        }
1430
1431        fn serialize_newtype_struct<T>(
1432            self,
1433            _: &'static str,
1434            value: &T,
1435        ) -> Result<Self::Ok, Self::Error>
1436        where
1437            T: ?Sized + Serialize,
1438        {
1439            value.serialize(self)
1440        }
1441
1442        fn serialize_newtype_variant<T>(
1443            self,
1444            _: &'static str,
1445            _: u32,
1446            _: &'static str,
1447            value: &T,
1448        ) -> Result<Self::Ok, Self::Error>
1449        where
1450            T: ?Sized + Serialize,
1451        {
1452            value.serialize(self)
1453        }
1454
1455        fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
1456            Err(ExtractError)
1457        }
1458
1459        fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
1460            Err(ExtractError)
1461        }
1462
1463        fn serialize_tuple_struct(
1464            self,
1465            _: &'static str,
1466            _: usize,
1467        ) -> Result<Self::SerializeTupleStruct, Self::Error> {
1468            Err(ExtractError)
1469        }
1470
1471        fn serialize_tuple_variant(
1472            self,
1473            _: &'static str,
1474            _: u32,
1475            _: &'static str,
1476            _: usize,
1477        ) -> Result<Self::SerializeTupleVariant, Self::Error> {
1478            Err(ExtractError)
1479        }
1480
1481        fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
1482            Err(ExtractError)
1483        }
1484
1485        fn serialize_struct(
1486            self,
1487            _: &'static str,
1488            _: usize,
1489        ) -> Result<Self::SerializeStruct, Self::Error> {
1490            Err(ExtractError)
1491        }
1492
1493        fn serialize_struct_variant(
1494            self,
1495            _: &'static str,
1496            _: u32,
1497            _: &'static str,
1498            _: usize,
1499        ) -> Result<Self::SerializeStructVariant, Self::Error> {
1500            Err(ExtractError)
1501        }
1502    }
1503
1504    v.serialize(Extract {
1505        links: Vec::new(),
1506        trace_flags,
1507        is_remote,
1508        trace_state,
1509    })
1510    .unwrap_or_default()
1511}
1512
1513mod any_value {
1514    use std::{collections::HashMap, fmt};
1515
1516    use opentelemetry::{logs::AnyValue, Key, StringValue};
1517    use serde::ser::{
1518        Error, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
1519        SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer, StdError,
1520    };
1521
1522    /// Serialize an arbitrary `serde::Serialize` into an `AnyValue`.
1523    ///
1524    /// This method performs the following translations when converting between `serde`'s data model and OpenTelemetry's:
1525    ///
1526    /// - Integers that don't fit in a `i64` are converted into strings.
1527    /// - Unit types and nones are discarded (effectively treated as undefined).
1528    /// - Struct and tuple variants are converted into an internally tagged map.
1529    /// - Unit variants are converted into strings.
1530    pub(crate) fn serialize(value: impl Serialize) -> Result<Option<AnyValue>, ()> {
1531        value.serialize(ValueSerializer).map_err(|_| ())
1532    }
1533
1534    struct ValueSerializer;
1535
1536    struct ValueSerializeSeq {
1537        value: Vec<AnyValue>,
1538    }
1539
1540    struct ValueSerializeTuple {
1541        value: Vec<AnyValue>,
1542    }
1543
1544    struct ValueSerializeTupleStruct {
1545        value: Vec<AnyValue>,
1546    }
1547
1548    struct ValueSerializeMap {
1549        key: Option<Key>,
1550        value: HashMap<Key, AnyValue>,
1551    }
1552
1553    struct ValueSerializeStruct {
1554        value: HashMap<Key, AnyValue>,
1555    }
1556
1557    struct ValueSerializeTupleVariant {
1558        variant: &'static str,
1559        value: Vec<AnyValue>,
1560    }
1561
1562    struct ValueSerializeStructVariant {
1563        variant: &'static str,
1564        value: HashMap<Key, AnyValue>,
1565    }
1566
1567    #[derive(Debug)]
1568    struct ValueError(String);
1569
1570    impl fmt::Display for ValueError {
1571        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1572            fmt::Display::fmt(&self.0, f)
1573        }
1574    }
1575
1576    impl Error for ValueError {
1577        fn custom<T>(msg: T) -> Self
1578        where
1579            T: fmt::Display,
1580        {
1581            ValueError(msg.to_string())
1582        }
1583    }
1584
1585    impl StdError for ValueError {}
1586
1587    impl Serializer for ValueSerializer {
1588        type Ok = Option<AnyValue>;
1589
1590        type Error = ValueError;
1591
1592        type SerializeSeq = ValueSerializeSeq;
1593
1594        type SerializeTuple = ValueSerializeTuple;
1595
1596        type SerializeTupleStruct = ValueSerializeTupleStruct;
1597
1598        type SerializeTupleVariant = ValueSerializeTupleVariant;
1599
1600        type SerializeMap = ValueSerializeMap;
1601
1602        type SerializeStruct = ValueSerializeStruct;
1603
1604        type SerializeStructVariant = ValueSerializeStructVariant;
1605
1606        fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
1607            Ok(Some(AnyValue::Boolean(v)))
1608        }
1609
1610        fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
1611            self.serialize_i64(v as i64)
1612        }
1613
1614        fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
1615            self.serialize_i64(v as i64)
1616        }
1617
1618        fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
1619            self.serialize_i64(v as i64)
1620        }
1621
1622        fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
1623            Ok(Some(AnyValue::Int(v)))
1624        }
1625
1626        fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
1627            if let Ok(v) = v.try_into() {
1628                self.serialize_i64(v)
1629            } else {
1630                self.collect_str(&v)
1631            }
1632        }
1633
1634        fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
1635            self.serialize_i64(v as i64)
1636        }
1637
1638        fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
1639            self.serialize_i64(v as i64)
1640        }
1641
1642        fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
1643            self.serialize_i64(v as i64)
1644        }
1645
1646        fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
1647            if let Ok(v) = v.try_into() {
1648                self.serialize_i64(v)
1649            } else {
1650                self.collect_str(&v)
1651            }
1652        }
1653
1654        fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
1655            if let Ok(v) = v.try_into() {
1656                self.serialize_i64(v)
1657            } else {
1658                self.collect_str(&v)
1659            }
1660        }
1661
1662        fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
1663            self.serialize_f64(v as f64)
1664        }
1665
1666        fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
1667            Ok(Some(AnyValue::Double(v)))
1668        }
1669
1670        fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
1671            self.collect_str(&v)
1672        }
1673
1674        fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
1675            Ok(Some(AnyValue::String(StringValue::from(v.to_owned()))))
1676        }
1677
1678        fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
1679            Ok(Some(AnyValue::Bytes(Box::new(v.to_owned()))))
1680        }
1681
1682        fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
1683            Ok(None)
1684        }
1685
1686        fn serialize_some<T: serde::Serialize + ?Sized>(
1687            self,
1688            value: &T,
1689        ) -> Result<Self::Ok, Self::Error> {
1690            value.serialize(self)
1691        }
1692
1693        fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
1694            Ok(None)
1695        }
1696
1697        fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
1698            name.serialize(self)
1699        }
1700
1701        fn serialize_unit_variant(
1702            self,
1703            _: &'static str,
1704            _: u32,
1705            variant: &'static str,
1706        ) -> Result<Self::Ok, Self::Error> {
1707            variant.serialize(self)
1708        }
1709
1710        fn serialize_newtype_struct<T: serde::Serialize + ?Sized>(
1711            self,
1712            _: &'static str,
1713            value: &T,
1714        ) -> Result<Self::Ok, Self::Error> {
1715            value.serialize(self)
1716        }
1717
1718        fn serialize_newtype_variant<T: serde::Serialize + ?Sized>(
1719            self,
1720            _: &'static str,
1721            _: u32,
1722            variant: &'static str,
1723            value: &T,
1724        ) -> Result<Self::Ok, Self::Error> {
1725            let mut map = self.serialize_map(Some(1))?;
1726            map.serialize_entry(variant, value)?;
1727            map.end()
1728        }
1729
1730        fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
1731            Ok(ValueSerializeSeq { value: Vec::new() })
1732        }
1733
1734        fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
1735            Ok(ValueSerializeTuple { value: Vec::new() })
1736        }
1737
1738        fn serialize_tuple_struct(
1739            self,
1740            _: &'static str,
1741            _: usize,
1742        ) -> Result<Self::SerializeTupleStruct, Self::Error> {
1743            Ok(ValueSerializeTupleStruct { value: Vec::new() })
1744        }
1745
1746        fn serialize_tuple_variant(
1747            self,
1748            _: &'static str,
1749            _: u32,
1750            variant: &'static str,
1751            _: usize,
1752        ) -> Result<Self::SerializeTupleVariant, Self::Error> {
1753            Ok(ValueSerializeTupleVariant {
1754                variant,
1755                value: Vec::new(),
1756            })
1757        }
1758
1759        fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
1760            Ok(ValueSerializeMap {
1761                key: None,
1762                value: HashMap::new(),
1763            })
1764        }
1765
1766        fn serialize_struct(
1767            self,
1768            _: &'static str,
1769            _: usize,
1770        ) -> Result<Self::SerializeStruct, Self::Error> {
1771            Ok(ValueSerializeStruct {
1772                value: HashMap::new(),
1773            })
1774        }
1775
1776        fn serialize_struct_variant(
1777            self,
1778            _: &'static str,
1779            _: u32,
1780            variant: &'static str,
1781            _: usize,
1782        ) -> Result<Self::SerializeStructVariant, Self::Error> {
1783            Ok(ValueSerializeStructVariant {
1784                variant,
1785                value: HashMap::new(),
1786            })
1787        }
1788    }
1789
1790    impl SerializeSeq for ValueSerializeSeq {
1791        type Ok = Option<AnyValue>;
1792
1793        type Error = ValueError;
1794
1795        fn serialize_element<T: serde::Serialize + ?Sized>(
1796            &mut self,
1797            value: &T,
1798        ) -> Result<(), Self::Error> {
1799            if let Some(value) = value.serialize(ValueSerializer)? {
1800                self.value.push(value);
1801            }
1802
1803            Ok(())
1804        }
1805
1806        fn end(self) -> Result<Self::Ok, Self::Error> {
1807            Ok(Some(AnyValue::ListAny(Box::new(self.value))))
1808        }
1809    }
1810
1811    impl SerializeTuple for ValueSerializeTuple {
1812        type Ok = Option<AnyValue>;
1813
1814        type Error = ValueError;
1815
1816        fn serialize_element<T: serde::Serialize + ?Sized>(
1817            &mut self,
1818            value: &T,
1819        ) -> Result<(), Self::Error> {
1820            if let Some(value) = value.serialize(ValueSerializer)? {
1821                self.value.push(value);
1822            }
1823
1824            Ok(())
1825        }
1826
1827        fn end(self) -> Result<Self::Ok, Self::Error> {
1828            Ok(Some(AnyValue::ListAny(Box::new(self.value))))
1829        }
1830    }
1831
1832    impl SerializeTupleStruct for ValueSerializeTupleStruct {
1833        type Ok = Option<AnyValue>;
1834
1835        type Error = ValueError;
1836
1837        fn serialize_field<T: serde::Serialize + ?Sized>(
1838            &mut self,
1839            value: &T,
1840        ) -> Result<(), Self::Error> {
1841            if let Some(value) = value.serialize(ValueSerializer)? {
1842                self.value.push(value);
1843            }
1844
1845            Ok(())
1846        }
1847
1848        fn end(self) -> Result<Self::Ok, Self::Error> {
1849            Ok(Some(AnyValue::ListAny(Box::new(self.value))))
1850        }
1851    }
1852
1853    impl SerializeTupleVariant for ValueSerializeTupleVariant {
1854        type Ok = Option<AnyValue>;
1855
1856        type Error = ValueError;
1857
1858        fn serialize_field<T: serde::Serialize + ?Sized>(
1859            &mut self,
1860            value: &T,
1861        ) -> Result<(), Self::Error> {
1862            if let Some(value) = value.serialize(ValueSerializer)? {
1863                self.value.push(value);
1864            }
1865
1866            Ok(())
1867        }
1868
1869        fn end(self) -> Result<Self::Ok, Self::Error> {
1870            Ok(Some(AnyValue::Map({
1871                let mut variant = HashMap::new();
1872                variant.insert(
1873                    Key::from(self.variant),
1874                    AnyValue::ListAny(Box::new(self.value)),
1875                );
1876                Box::new(variant)
1877            })))
1878        }
1879    }
1880
1881    impl SerializeMap for ValueSerializeMap {
1882        type Ok = Option<AnyValue>;
1883
1884        type Error = ValueError;
1885
1886        fn serialize_key<T: serde::Serialize + ?Sized>(
1887            &mut self,
1888            key: &T,
1889        ) -> Result<(), Self::Error> {
1890            let key = match key.serialize(ValueSerializer)? {
1891                Some(AnyValue::String(key)) => Key::from(String::from(key)),
1892                key => Key::from(format!("{:?}", key)),
1893            };
1894
1895            self.key = Some(key);
1896
1897            Ok(())
1898        }
1899
1900        fn serialize_value<T: serde::Serialize + ?Sized>(
1901            &mut self,
1902            value: &T,
1903        ) -> Result<(), Self::Error> {
1904            let key = self
1905                .key
1906                .take()
1907                .ok_or_else(|| Self::Error::custom("missing key"))?;
1908
1909            if let Some(value) = value.serialize(ValueSerializer)? {
1910                self.value.insert(key, value);
1911            }
1912
1913            Ok(())
1914        }
1915
1916        fn end(self) -> Result<Self::Ok, Self::Error> {
1917            Ok(Some(AnyValue::Map(Box::new(self.value))))
1918        }
1919    }
1920
1921    impl SerializeStruct for ValueSerializeStruct {
1922        type Ok = Option<AnyValue>;
1923
1924        type Error = ValueError;
1925
1926        fn serialize_field<T: serde::Serialize + ?Sized>(
1927            &mut self,
1928            key: &'static str,
1929            value: &T,
1930        ) -> Result<(), Self::Error> {
1931            let key = Key::from(key);
1932
1933            if let Some(value) = value.serialize(ValueSerializer)? {
1934                self.value.insert(key, value);
1935            }
1936
1937            Ok(())
1938        }
1939
1940        fn end(self) -> Result<Self::Ok, Self::Error> {
1941            Ok(Some(AnyValue::Map(Box::new(self.value))))
1942        }
1943    }
1944
1945    impl SerializeStructVariant for ValueSerializeStructVariant {
1946        type Ok = Option<AnyValue>;
1947
1948        type Error = ValueError;
1949
1950        fn serialize_field<T: serde::Serialize + ?Sized>(
1951            &mut self,
1952            key: &'static str,
1953            value: &T,
1954        ) -> Result<(), Self::Error> {
1955            let key = Key::from(key);
1956
1957            if let Some(value) = value.serialize(ValueSerializer)? {
1958                self.value.insert(key, value);
1959            }
1960
1961            Ok(())
1962        }
1963
1964        fn end(self) -> Result<Self::Ok, Self::Error> {
1965            Ok(Some(AnyValue::Map({
1966                let mut variant = HashMap::new();
1967                variant.insert(Key::from(self.variant), AnyValue::Map(Box::new(self.value)));
1968                Box::new(variant)
1969            })))
1970        }
1971    }
1972}
1973
1974#[cfg(test)]
1975mod tests {
1976    use std::io;
1977
1978    use super::*;
1979
1980    use emit::runtime::AmbientSlot;
1981
1982    use opentelemetry::trace::{SamplingDecision, SamplingResult, TraceState};
1983
1984    use opentelemetry_sdk::{
1985        logs::{in_memory_exporter::InMemoryLogExporter, SdkLoggerProvider},
1986        trace::{in_memory_exporter::InMemorySpanExporter, SdkTracerProvider},
1987    };
1988
1989    fn build(
1990        slot: &AmbientSlot,
1991    ) -> (
1992        InMemoryLogExporter,
1993        InMemorySpanExporter,
1994        SdkLoggerProvider,
1995        SdkTracerProvider,
1996    ) {
1997        let logger_exporter = InMemoryLogExporter::default();
1998
1999        let logger_provider = SdkLoggerProvider::builder()
2000            .with_simple_exporter(logger_exporter.clone())
2001            .build();
2002
2003        let tracer_exporter = InMemorySpanExporter::default();
2004
2005        let tracer_provider = SdkTracerProvider::builder()
2006            .with_simple_exporter(tracer_exporter.clone())
2007            .build();
2008
2009        let _ = setup(logger_provider.clone(), tracer_provider.clone()).init_slot(slot);
2010
2011        (
2012            logger_exporter,
2013            tracer_exporter,
2014            logger_provider,
2015            tracer_provider,
2016        )
2017    }
2018
2019    #[test]
2020    fn emit_log() {
2021        let slot = AmbientSlot::new();
2022        let (logs, _, _, _) = build(&slot);
2023
2024        emit::emit!(rt: slot.get(), "test {attr}", attr: "log");
2025
2026        let logs = logs.get_emitted_logs().unwrap();
2027
2028        assert_eq!(1, logs.len());
2029
2030        let Some(AnyValue::String(body)) = logs[0].record.body() else {
2031            panic!("unexpected log body value");
2032        };
2033
2034        assert_eq!("test log", body.as_str());
2035    }
2036
2037    #[test]
2038    fn emit_log_trace_context() {
2039        let slot = AmbientSlot::new();
2040        let (logs, _, _, _) = build(&slot);
2041
2042        emit::emit!(rt: slot.get(), "test log", trace_id: "4bf92f3577b34da6a3ce929d0e0e4736", span_id: "00f067aa0ba902b7");
2043
2044        let logs = logs.get_emitted_logs().unwrap();
2045
2046        assert_eq!(1, logs.len());
2047
2048        assert_eq!(
2049            "4bf92f3577b34da6a3ce929d0e0e4736",
2050            logs[0].record.trace_context().unwrap().trace_id.to_string()
2051        );
2052        assert_eq!(
2053            "00f067aa0ba902b7",
2054            logs[0].record.trace_context().unwrap().span_id.to_string()
2055        );
2056    }
2057
2058    #[test]
2059    fn emit_span() {
2060        static SLOT: AmbientSlot = AmbientSlot::new();
2061        let (_, spans, _, _) = build(&SLOT);
2062
2063        #[emit::span(rt: SLOT.get(), "emit {attr}", attr: "span")]
2064        fn emit_span() -> emit::span::SpanCtxt {
2065            emit::span::SpanCtxt::current(SLOT.get().ctxt())
2066        }
2067
2068        let ctxt = emit_span();
2069
2070        let spans = spans.get_finished_spans().unwrap();
2071
2072        assert_eq!(1, spans.len());
2073
2074        assert_eq!("emit {attr}", spans[0].name);
2075
2076        assert_eq!(
2077            ctxt.trace_id().unwrap().to_bytes(),
2078            spans[0].span_context.trace_id().to_bytes()
2079        );
2080        assert_eq!(
2081            ctxt.span_id().unwrap().to_bytes(),
2082            spans[0].span_context.span_id().to_bytes()
2083        );
2084        assert!(ctxt.span_parent().is_none());
2085        assert_eq!(
2086            opentelemetry::trace::SpanId::INVALID,
2087            spans[0].parent_span_id
2088        );
2089    }
2090
2091    #[test]
2092    fn emit_span_direct() {
2093        let slot = AmbientSlot::new();
2094        let (logs, spans, _, _) = build(&slot);
2095
2096        emit::emit!(
2097            rt: slot.get(),
2098            evt: emit::Span::new(
2099                emit::mdl!(),
2100                "test",
2101                "2024-01-01T00:00:00.000Z".parse::<emit::Timestamp>().unwrap().."2024-01-01T00:00:01.000Z".parse::<emit::Timestamp>().unwrap(),
2102                emit::span::SpanCtxt::new_root(slot.get().rng()),
2103            ),
2104        );
2105
2106        let logs = logs.get_emitted_logs().unwrap();
2107        let spans = spans.get_finished_spans().unwrap();
2108
2109        assert_eq!(1, logs.len());
2110        assert_eq!(0, spans.len());
2111    }
2112
2113    #[test]
2114    fn emit_span_otel_span() {
2115        static SLOT: AmbientSlot = AmbientSlot::new();
2116        let (_, spans, _, tracer_provider) = build(&SLOT);
2117
2118        #[emit::span(rt: SLOT.get(), "emit span")]
2119        fn emit_span(tracer_provider: &SdkTracerProvider) -> (SpanContext, emit::span::SpanCtxt) {
2120            fn otel_span(tracer_provider: &SdkTracerProvider) -> SpanContext {
2121                use opentelemetry::trace::TracerProvider;
2122
2123                tracer_provider
2124                    .tracer("otel_span")
2125                    .in_span("otel span", |cx| cx.span().span_context().clone())
2126            }
2127
2128            (
2129                otel_span(&tracer_provider),
2130                emit::span::SpanCtxt::current(SLOT.get().ctxt()),
2131            )
2132        }
2133
2134        let (otel_ctxt, emit_ctxt) = emit_span(&tracer_provider);
2135
2136        let spans = spans.get_finished_spans().unwrap();
2137
2138        assert_eq!(2, spans.len());
2139
2140        assert_eq!(
2141            otel_ctxt.trace_id().to_bytes(),
2142            emit_ctxt.trace_id().unwrap().to_bytes()
2143        );
2144
2145        assert_eq!("otel span", spans[0].name);
2146
2147        assert_eq!(
2148            otel_ctxt.trace_id().to_bytes(),
2149            spans[0].span_context.trace_id().to_bytes()
2150        );
2151        assert_eq!(
2152            otel_ctxt.span_id().to_bytes(),
2153            spans[0].span_context.span_id().to_bytes()
2154        );
2155        assert_eq!(
2156            emit_ctxt.span_id().unwrap().to_bytes(),
2157            spans[0].parent_span_id.to_bytes()
2158        );
2159
2160        assert_eq!("emit span", spans[1].name);
2161
2162        assert_eq!(
2163            emit_ctxt.trace_id().unwrap().to_bytes(),
2164            spans[1].span_context.trace_id().to_bytes()
2165        );
2166        assert_eq!(
2167            emit_ctxt.span_id().unwrap().to_bytes(),
2168            spans[1].span_context.span_id().to_bytes()
2169        );
2170        assert!(emit_ctxt.span_parent().is_none());
2171    }
2172
2173    #[test]
2174    fn emit_span_otel_log() {
2175        static SLOT: AmbientSlot = AmbientSlot::new();
2176        let (logs, _, logger_provider, _) = build(&SLOT);
2177
2178        #[emit::span(rt: SLOT.get(), "emit span")]
2179        fn emit_span(logger_provider: &SdkLoggerProvider) -> emit::span::SpanCtxt {
2180            use opentelemetry::logs::LoggerProvider;
2181
2182            let logger = logger_provider.logger("otel_logger");
2183
2184            let mut log = logger.create_log_record();
2185
2186            log.set_body(AnyValue::String("test log".into()));
2187
2188            logger.emit(log);
2189
2190            emit::span::SpanCtxt::current(SLOT.get().ctxt())
2191        }
2192
2193        let ctxt = emit_span(&logger_provider);
2194
2195        let logs = logs.get_emitted_logs().unwrap();
2196
2197        assert_eq!(1, logs.len());
2198
2199        assert!(logs[0]
2200            .record
2201            .trace_context()
2202            .unwrap()
2203            .trace_flags
2204            .unwrap()
2205            .is_sampled());
2206
2207        assert_eq!(
2208            ctxt.trace_id().unwrap().to_bytes(),
2209            logs[0].record.trace_context().unwrap().trace_id.to_bytes()
2210        );
2211        assert_eq!(
2212            ctxt.span_id().unwrap().to_bytes(),
2213            logs[0].record.trace_context().unwrap().span_id.to_bytes()
2214        );
2215    }
2216
2217    #[test]
2218    fn emit_span_span_name() {
2219        static SLOT: AmbientSlot = AmbientSlot::new();
2220        let (_, spans, _, _) = build(&SLOT);
2221
2222        #[emit::span(rt: SLOT.get(), "emit span", span_name: "custom name")]
2223        fn emit_span() {}
2224
2225        emit_span();
2226
2227        let spans = spans.get_finished_spans().unwrap();
2228
2229        assert_eq!(1, spans.len());
2230
2231        assert_eq!("custom name", spans[0].name);
2232    }
2233
2234    #[test]
2235    fn emit_span_span_kind() {
2236        static SLOT: AmbientSlot = AmbientSlot::new();
2237        let (_, spans, _, _) = build(&SLOT);
2238
2239        #[emit::span(rt: SLOT.get(), "emit span", span_kind: "producer")]
2240        fn emit_span() {}
2241
2242        emit_span();
2243
2244        let spans = spans.get_finished_spans().unwrap();
2245
2246        assert_eq!(1, spans.len());
2247
2248        assert_eq!(SpanKind::Producer, spans[0].span_kind);
2249    }
2250
2251    #[test]
2252    fn emit_span_span_links() {
2253        static SLOT: AmbientSlot = AmbientSlot::new();
2254        let (_, spans, _, _) = build(&SLOT);
2255
2256        #[emit::span(
2257            rt: SLOT.get(),
2258            "emit span",
2259            #[emit::as_serde]
2260            span_links: [
2261                "4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7",
2262            ],
2263        )]
2264        fn emit_span() {}
2265
2266        emit_span();
2267
2268        let spans = spans.get_finished_spans().unwrap();
2269
2270        assert_eq!(1, spans.len());
2271
2272        assert_eq!(1, spans[0].links.links.len());
2273
2274        assert_eq!(
2275            "4bf92f3577b34da6a3ce929d0e0e4736",
2276            spans[0].links.links[0].span_context.trace_id().to_string()
2277        );
2278        assert_eq!(
2279            "00f067aa0ba902b7",
2280            spans[0].links.links[0].span_context.span_id().to_string()
2281        );
2282    }
2283
2284    #[test]
2285    fn emit_span_ok() {
2286        static SLOT: AmbientSlot = AmbientSlot::new();
2287        let (_, spans, _, _) = build(&SLOT);
2288
2289        #[emit::span(rt: SLOT.get(), ok_lvl: "info", "emit span")]
2290        fn emit_span() -> Result<(), io::Error> {
2291            Ok(())
2292        }
2293
2294        let _ = emit_span();
2295
2296        let spans = spans.get_finished_spans().unwrap();
2297
2298        assert_eq!(1, spans.len());
2299
2300        assert_eq!(Status::Ok, spans[0].status);
2301    }
2302
2303    #[test]
2304    fn emit_span_err() {
2305        static SLOT: AmbientSlot = AmbientSlot::new();
2306        let (_, spans, _, _) = build(&SLOT);
2307
2308        #[emit::span(rt: SLOT.get(), err_lvl: "error", "emit span")]
2309        fn emit_span() -> Result<(), io::Error> {
2310            Err(io::Error::new(io::ErrorKind::Other, "something failed!"))
2311        }
2312
2313        let _ = emit_span();
2314
2315        let spans = spans.get_finished_spans().unwrap();
2316
2317        assert_eq!(1, spans.len());
2318
2319        assert_eq!(Status::error("something failed!"), spans[0].status);
2320    }
2321
2322    #[test]
2323    fn emit_span_lvl_err() {
2324        static SLOT: AmbientSlot = AmbientSlot::new();
2325        let (_, spans, _, _) = build(&SLOT);
2326
2327        #[emit::span(rt: SLOT.get(), ok_lvl: "error", "emit span")]
2328        fn emit_span() -> Result<(), io::Error> {
2329            Ok(())
2330        }
2331
2332        let _ = emit_span();
2333
2334        let spans = spans.get_finished_spans().unwrap();
2335
2336        assert_eq!(1, spans.len());
2337
2338        assert_eq!(Status::error("error"), spans[0].status);
2339    }
2340
2341    #[test]
2342    fn emit_span_unsampled_otel_span() {
2343        static SLOT: AmbientSlot = AmbientSlot::new();
2344        let (_, spans, _, tracer_provider) = build(&SLOT);
2345
2346        #[emit::span(rt: SLOT.get(), when: emit::filter::from_fn(|_| false), "emit span")]
2347        fn emit_span(tracer_provider: &SdkTracerProvider) -> SpanContext {
2348            fn otel_span(tracer_provider: &SdkTracerProvider) -> SpanContext {
2349                use opentelemetry::trace::TracerProvider;
2350
2351                tracer_provider
2352                    .tracer("otel_span")
2353                    .in_span("otel span", |cx| cx.span().span_context().clone())
2354            }
2355
2356            otel_span(&tracer_provider)
2357        }
2358
2359        let otel_ctxt = emit_span(&tracer_provider);
2360
2361        let spans = spans.get_finished_spans().unwrap();
2362
2363        assert_eq!(0, spans.len());
2364
2365        assert!(!otel_ctxt.is_sampled());
2366    }
2367
2368    #[test]
2369    fn emit_span_unsampled_emit_span() {
2370        static SLOT: AmbientSlot = AmbientSlot::new();
2371        let (_, spans, _, _) = build(&SLOT);
2372
2373        #[emit::span(rt: SLOT.get(), when: emit::filter::from_fn(|_| false), "emit span")]
2374        fn emit_span_outer() {
2375            #[emit::span(rt: SLOT.get(), "emit span")]
2376            fn emit_span_inner() {}
2377
2378            emit_span_inner()
2379        }
2380
2381        emit_span_outer();
2382
2383        let spans = spans.get_finished_spans().unwrap();
2384
2385        assert_eq!(0, spans.len());
2386    }
2387
2388    #[test]
2389    fn emit_span_unsampled_otel_log() {
2390        static SLOT: AmbientSlot = AmbientSlot::new();
2391        let (logs, _, logger_provider, _) = build(&SLOT);
2392
2393        #[emit::span(rt: SLOT.get(), when: emit::filter::from_fn(|_| false), "emit span")]
2394        fn emit_span(logger_provider: &SdkLoggerProvider) -> emit::span::SpanCtxt {
2395            use opentelemetry::logs::LoggerProvider;
2396
2397            let logger = logger_provider.logger("otel_logger");
2398
2399            let mut log = logger.create_log_record();
2400
2401            log.set_body(AnyValue::String("test log".into()));
2402
2403            logger.emit(log);
2404
2405            emit::span::SpanCtxt::current(SLOT.get().ctxt())
2406        }
2407
2408        let ctxt = emit_span(&logger_provider);
2409
2410        let logs = logs.get_emitted_logs().unwrap();
2411
2412        assert_eq!(1, logs.len());
2413
2414        assert!(!logs[0]
2415            .record
2416            .trace_context()
2417            .unwrap()
2418            .trace_flags
2419            .unwrap()
2420            .is_sampled());
2421
2422        assert_eq!(
2423            ctxt.trace_id().unwrap().to_bytes(),
2424            logs[0].record.trace_context().unwrap().trace_id.to_bytes()
2425        );
2426        assert_eq!(
2427            ctxt.span_id().unwrap().to_bytes(),
2428            logs[0].record.trace_context().unwrap().span_id.to_bytes()
2429        );
2430    }
2431
2432    #[test]
2433    fn emit_ctxt_clear_otel_ctxt() {
2434        static SLOT: AmbientSlot = AmbientSlot::new();
2435        let (_, _, _, tracer_provider) = build(&SLOT);
2436
2437        fn otel_span(tracer_provider: &SdkTracerProvider) -> SpanContext {
2438            use opentelemetry::trace::TracerProvider;
2439
2440            tracer_provider
2441                .tracer("otel_span")
2442                .in_span("otel span", |_| {
2443                    emit::Frame::root(SLOT.get().ctxt(), emit::Empty)
2444                        .call(|| Context::current().span().span_context().clone())
2445                })
2446        }
2447
2448        let cx = otel_span(&tracer_provider);
2449
2450        assert_eq!(SpanContext::NONE, cx);
2451    }
2452
2453    #[test]
2454    fn emit_ctxt_push_otel_ctxt() {
2455        static SLOT: AmbientSlot = AmbientSlot::new();
2456        let (_, _, _, tracer_provider) = build(&SLOT);
2457
2458        fn otel_span(tracer_provider: &SdkTracerProvider) -> (SpanContext, SpanContext) {
2459            use opentelemetry::trace::TracerProvider;
2460
2461            tracer_provider
2462                .tracer("otel_span")
2463                .in_span("otel span", |_| {
2464                    let outer = Context::current().span().span_context().clone();
2465
2466                    let inner = emit::Frame::push(SLOT.get().ctxt(), emit::Empty)
2467                        .call(|| Context::current().span().span_context().clone());
2468
2469                    (outer, inner)
2470                })
2471        }
2472
2473        let (outer, inner) = otel_span(&tracer_provider);
2474
2475        assert_eq!(outer.trace_id(), inner.trace_id());
2476        assert_eq!(outer.span_id(), inner.span_id());
2477        assert_eq!(outer.trace_flags(), inner.trace_flags());
2478    }
2479
2480    #[test]
2481    fn otel_span_emit_span() {
2482        static SLOT: AmbientSlot = AmbientSlot::new();
2483        let (_, spans, _, tracer_provider) = build(&SLOT);
2484
2485        fn otel_span(tracer_provider: &SdkTracerProvider) -> (SpanContext, emit::span::SpanCtxt) {
2486            use opentelemetry::trace::TracerProvider;
2487
2488            #[emit::span(rt: SLOT.get(), "emit span")]
2489            fn emit_span() -> emit::span::SpanCtxt {
2490                emit::span::SpanCtxt::current(SLOT.get().ctxt())
2491            }
2492
2493            tracer_provider
2494                .tracer("otel_span")
2495                .in_span("otel span", |cx| {
2496                    (cx.span().span_context().clone(), emit_span())
2497                })
2498        }
2499
2500        let (otel_ctxt, emit_ctxt) = otel_span(&tracer_provider);
2501
2502        let spans = spans.get_finished_spans().unwrap();
2503
2504        assert_eq!(2, spans.len());
2505
2506        assert_eq!(
2507            otel_ctxt.trace_id().to_bytes(),
2508            emit_ctxt.trace_id().unwrap().to_bytes()
2509        );
2510
2511        assert_eq!("emit span", spans[0].name);
2512
2513        assert_eq!(
2514            emit_ctxt.trace_id().unwrap().to_bytes(),
2515            spans[0].span_context.trace_id().to_bytes()
2516        );
2517        assert_eq!(
2518            emit_ctxt.span_id().unwrap().to_bytes(),
2519            spans[0].span_context.span_id().to_bytes()
2520        );
2521        assert!(emit_ctxt.span_parent().is_none(),);
2522        assert!(emit_ctxt.span_parent().is_none(),);
2523
2524        assert_eq!("otel span", spans[1].name);
2525
2526        assert_eq!(
2527            otel_ctxt.trace_id().to_bytes(),
2528            spans[1].span_context.trace_id().to_bytes()
2529        );
2530        assert_eq!(
2531            otel_ctxt.span_id().to_bytes(),
2532            spans[1].span_context.span_id().to_bytes()
2533        );
2534        assert_eq!(SpanId::INVALID, spans[1].parent_span_id);
2535    }
2536
2537    #[test]
2538    fn otel_span_emit_log() {
2539        static SLOT: AmbientSlot = AmbientSlot::new();
2540        let (logs, _, _, tracer_provider) = build(&SLOT);
2541
2542        fn otel_span(tracer_provider: &SdkTracerProvider) -> SpanContext {
2543            use opentelemetry::trace::TracerProvider;
2544
2545            tracer_provider
2546                .tracer("otel_span")
2547                .in_span("otel span", |cx| {
2548                    emit::emit!(rt: SLOT.get(), "emit event");
2549
2550                    cx.span().span_context().clone()
2551                })
2552        }
2553
2554        let ctxt = otel_span(&tracer_provider);
2555
2556        let logs = logs.get_emitted_logs().unwrap();
2557
2558        assert_eq!(1, logs.len());
2559
2560        assert!(logs[0]
2561            .record
2562            .trace_context()
2563            .unwrap()
2564            .trace_flags
2565            .unwrap()
2566            .is_sampled());
2567
2568        assert_eq!(
2569            ctxt.trace_id(),
2570            logs[0].record.trace_context().unwrap().trace_id
2571        );
2572        assert_eq!(
2573            ctxt.span_id(),
2574            logs[0].record.trace_context().unwrap().span_id
2575        );
2576    }
2577
2578    #[test]
2579    fn otel_span_unsampled_emit_span() {
2580        static SLOT: AmbientSlot = AmbientSlot::new();
2581        let (logs, spans, _, tracer_provider) = build(&SLOT);
2582
2583        #[emit::span(rt: SLOT.get(), "emit {attr}", attr: "span")]
2584        fn emit_span() {
2585            emit::emit!(rt: SLOT.get(), "emit event");
2586        }
2587
2588        fn otel_span(tracer_provider: &SdkTracerProvider) {
2589            use opentelemetry::trace::TracerProvider;
2590
2591            let tracer = tracer_provider.tracer("otel_span");
2592
2593            let span = tracer
2594                .span_builder("otel span")
2595                .with_sampling_result(SamplingResult {
2596                    decision: SamplingDecision::RecordOnly,
2597                    attributes: Vec::new(),
2598                    trace_state: TraceState::NONE,
2599                });
2600
2601            let span = span.start(&tracer);
2602            let cx = Context::current_with_span(span);
2603            let _guard = cx.attach();
2604
2605            emit_span();
2606        }
2607
2608        otel_span(&tracer_provider);
2609
2610        let logs = logs.get_emitted_logs().unwrap();
2611        let spans = spans.get_finished_spans().unwrap();
2612
2613        assert_eq!(1, logs.len());
2614        assert_eq!(0, spans.len());
2615
2616        assert!(!logs[0]
2617            .record
2618            .trace_context()
2619            .unwrap()
2620            .trace_flags
2621            .unwrap()
2622            .is_sampled());
2623    }
2624
2625    #[test]
2626    fn otel_span_unsampled_emit_log() {
2627        static SLOT: AmbientSlot = AmbientSlot::new();
2628        let (logs, _, _, tracer_provider) = build(&SLOT);
2629
2630        fn otel_span(tracer_provider: &SdkTracerProvider) -> SpanContext {
2631            use opentelemetry::trace::TracerProvider;
2632
2633            let tracer = tracer_provider.tracer("otel_span");
2634
2635            let span = tracer.span_builder("otel span");
2636
2637            let span = span
2638                .with_sampling_result(SamplingResult {
2639                    decision: SamplingDecision::Drop,
2640                    attributes: vec![],
2641                    trace_state: Default::default(),
2642                })
2643                .start(&tracer);
2644            let cx = Context::current_with_span(span);
2645            let _guard = cx.attach();
2646
2647            emit::emit!(rt: SLOT.get(), "emit event");
2648
2649            Context::current().span().span_context().clone()
2650        }
2651
2652        let ctxt = otel_span(&tracer_provider);
2653
2654        let logs = logs.get_emitted_logs().unwrap();
2655
2656        assert_eq!(1, logs.len());
2657
2658        assert!(!logs[0]
2659            .record
2660            .trace_context()
2661            .unwrap()
2662            .trace_flags
2663            .unwrap()
2664            .is_sampled());
2665
2666        assert_eq!(
2667            ctxt.trace_id(),
2668            logs[0].record.trace_context().unwrap().trace_id
2669        );
2670        assert_eq!(
2671            ctxt.span_id(),
2672            logs[0].record.trace_context().unwrap().span_id
2673        );
2674    }
2675
2676    #[test]
2677    fn emit_value_to_otel_attribute() {
2678        use opentelemetry::Key;
2679        use std::collections::HashMap;
2680
2681        #[derive(serde::Serialize)]
2682        struct Struct {
2683            a: i32,
2684            b: i32,
2685            c: i32,
2686        }
2687
2688        #[derive(serde::Serialize)]
2689        struct Newtype(i32);
2690
2691        #[derive(serde::Serialize)]
2692        enum Enum {
2693            Unit,
2694            Newtype(i32),
2695            Struct { a: i32, b: i32, c: i32 },
2696            Tuple(i32, i32, i32),
2697        }
2698
2699        struct Bytes<B>(B);
2700
2701        impl<B: AsRef<[u8]>> serde::Serialize for Bytes<B> {
2702            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2703            where
2704                S: serde::Serializer,
2705            {
2706                serializer.serialize_bytes(self.0.as_ref())
2707            }
2708        }
2709
2710        struct Map {
2711            a: i32,
2712            b: i32,
2713            c: i32,
2714        }
2715
2716        impl serde::Serialize for Map {
2717            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2718            where
2719                S: serde::Serializer,
2720            {
2721                use serde::ser::SerializeMap;
2722
2723                let mut map = serializer.serialize_map(Some(3))?;
2724
2725                map.serialize_entry(&"a", &self.a)?;
2726                map.serialize_entry(&"b", &self.b)?;
2727                map.serialize_entry(&"c", &self.c)?;
2728
2729                map.end()
2730            }
2731        }
2732
2733        let slot = AmbientSlot::new();
2734        let (logs, _, _, _) = build(&slot);
2735
2736        emit::emit!(
2737            rt: slot.get(),
2738            "test log",
2739            str_value: "a string",
2740            u8_value: 1u8,
2741            u16_value: 2u16,
2742            u32_value: 42u32,
2743            u64_value: 2147483660u64,
2744            u128_small_value: 2147483660u128,
2745            u128_big_value: 9223372036854775820u128,
2746            i8_value: 1i8,
2747            i16_value: 2i16,
2748            i32_value: 42i32,
2749            i64_value: 2147483660i64,
2750            i128_small_value: 2147483660i128,
2751            i128_big_value: 9223372036854775820i128,
2752            f64_value: 4.2,
2753            bool_value: true,
2754            #[emit::as_serde]
2755            bytes_value: Bytes([1, 1, 1]),
2756            #[emit::as_serde]
2757            unit_value: (),
2758            #[emit::as_serde]
2759            some_value: Some(42),
2760            #[emit::as_serde]
2761            none_value: None::<i32>,
2762            #[emit::as_serde]
2763            slice_value: [1, 1, 1] as [i32; 3],
2764            #[emit::as_serde]
2765            map_value: Map { a: 1, b: 1, c: 1 },
2766            #[emit::as_serde]
2767            struct_value: Struct { a: 1, b: 1, c: 1 },
2768            #[emit::as_serde]
2769            tuple_value: (1, 1, 1),
2770            #[emit::as_serde]
2771            newtype_value: Newtype(42),
2772            #[emit::as_serde]
2773            unit_variant_value: Enum::Unit,
2774            #[emit::as_serde]
2775            unit_variant_value: Enum::Unit,
2776            #[emit::as_serde]
2777            newtype_variant_value: Enum::Newtype(42),
2778            #[emit::as_serde]
2779            struct_variant_value: Enum::Struct { a: 1, b: 1, c: 1 },
2780            #[emit::as_serde]
2781            tuple_variant_value: Enum::Tuple(1, 1, 1),
2782        );
2783
2784        let logs = logs.get_emitted_logs().unwrap();
2785
2786        let get = |needle: &str| -> Option<AnyValue> {
2787            logs[0].record.attributes_iter().find_map(|(k, v)| {
2788                if k.as_str() == needle {
2789                    Some(v.clone())
2790                } else {
2791                    None
2792                }
2793            })
2794        };
2795
2796        assert_eq!(
2797            AnyValue::String("a string".into()),
2798            get("str_value").unwrap()
2799        );
2800
2801        assert_eq!(AnyValue::Int(1), get("i8_value").unwrap());
2802        assert_eq!(AnyValue::Int(2), get("i16_value").unwrap());
2803        assert_eq!(AnyValue::Int(42), get("i32_value").unwrap());
2804        assert_eq!(AnyValue::Int(2147483660), get("i64_value").unwrap());
2805        assert_eq!(AnyValue::Int(2147483660), get("i128_small_value").unwrap());
2806        assert_eq!(
2807            AnyValue::String("9223372036854775820".into()),
2808            get("i128_big_value").unwrap()
2809        );
2810
2811        assert_eq!(AnyValue::Double(4.2), get("f64_value").unwrap());
2812
2813        assert_eq!(AnyValue::Boolean(true), get("bool_value").unwrap());
2814
2815        assert_eq!(None, get("unit_value"));
2816        assert_eq!(None, get("none_value"));
2817        assert_eq!(AnyValue::Int(42), get("some_value").unwrap());
2818
2819        assert_eq!(
2820            AnyValue::ListAny(Box::new(vec![
2821                AnyValue::Int(1),
2822                AnyValue::Int(1),
2823                AnyValue::Int(1)
2824            ])),
2825            get("slice_value").unwrap()
2826        );
2827
2828        assert_eq!(
2829            AnyValue::Map({
2830                let mut map = HashMap::<Key, AnyValue>::default();
2831
2832                map.insert(Key::from("a"), AnyValue::Int(1));
2833                map.insert(Key::from("b"), AnyValue::Int(1));
2834                map.insert(Key::from("c"), AnyValue::Int(1));
2835
2836                Box::new(map)
2837            }),
2838            get("map_value").unwrap()
2839        );
2840
2841        assert_eq!(
2842            AnyValue::Map({
2843                let mut map = HashMap::<Key, AnyValue>::default();
2844
2845                map.insert(Key::from("a"), AnyValue::Int(1));
2846                map.insert(Key::from("b"), AnyValue::Int(1));
2847                map.insert(Key::from("c"), AnyValue::Int(1));
2848
2849                Box::new(map)
2850            }),
2851            get("struct_value").unwrap()
2852        );
2853
2854        assert_eq!(
2855            AnyValue::ListAny(Box::new(vec![
2856                AnyValue::Int(1),
2857                AnyValue::Int(1),
2858                AnyValue::Int(1)
2859            ])),
2860            get("tuple_value").unwrap()
2861        );
2862
2863        assert_eq!(
2864            AnyValue::String("Unit".into()),
2865            get("unit_variant_value").unwrap()
2866        );
2867
2868        assert_eq!(
2869            AnyValue::Map({
2870                let mut map = HashMap::new();
2871
2872                map.insert(Key::from("Newtype"), AnyValue::Int(42));
2873
2874                Box::new(map)
2875            }),
2876            get("newtype_variant_value").unwrap()
2877        );
2878
2879        assert_eq!(
2880            AnyValue::Map({
2881                let mut map = HashMap::new();
2882
2883                map.insert(
2884                    Key::from("Struct"),
2885                    AnyValue::Map({
2886                        let mut map = HashMap::new();
2887                        map.insert(Key::from("a"), AnyValue::Int(1));
2888                        map.insert(Key::from("b"), AnyValue::Int(1));
2889                        map.insert(Key::from("c"), AnyValue::Int(1));
2890                        Box::new(map)
2891                    }),
2892                );
2893
2894                Box::new(map)
2895            }),
2896            get("struct_variant_value").unwrap()
2897        );
2898
2899        assert_eq!(
2900            AnyValue::Map({
2901                let mut map = HashMap::new();
2902
2903                map.insert(
2904                    Key::from("Tuple"),
2905                    AnyValue::ListAny(Box::new(vec![
2906                        AnyValue::Int(1),
2907                        AnyValue::Int(1),
2908                        AnyValue::Int(1),
2909                    ])),
2910                );
2911
2912                Box::new(map)
2913            }),
2914            get("tuple_variant_value").unwrap()
2915        );
2916    }
2917}