Crate emit_opentelemetry

Crate emit_opentelemetry 

Source
Expand description

Integrate emit with the OpenTelemetry SDK.

This library forwards diagnostic events from emit through the OpenTelemetry SDK as log records and spans. This library is for applications that already use the OpenTelemetry SDK. It’s also intended for applications that need to unify multiple instrumentation libraries, like emit, log, and tracing, into a shared pipeline. If you’d just like to send emit diagnostics via OTLP to the OpenTelemetry Collector or other compatible service, then consider emit_otlp.

emit_opentelemetry version x.y.z is compatible with opentelemetry_sdk version x.y.*.

§Getting started

Configure the OpenTelemetry SDK as per its documentation, then add emit and emit_opentelemetry to your Cargo.toml:

[dependencies.emit]
version = "1"

# add `emit_openetelemetry` with the same major/minor as the OpenTelemetry SDK
[dependencies.emit_opentelemetry]
version = "0.30"

[dependencies.opentelemetry_sdk]
version = "0.30"
features = ["trace", "logs"]

[dependencies.opentelemetry]
version = "0.30"
features = ["trace", "logs"]

Initialize emit to send diagnostics to the OpenTelemetry SDK using setup:

fn main() {
    // Configure the OpenTelemetry SDK
    // See the OpenTelemetry SDK docs for details on configuration
    let logger_provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder()
        .with_simple_exporter(opentelemetry_stdout::LogExporter::default())
        .build();

    let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
        .with_simple_exporter(opentelemetry_stdout::SpanExporter::default())
        .build();

    // Configure `emit` to point to the OpenTelemetry SDK
    let rt = emit_opentelemetry::setup(logger_provider, tracer_provider).init();

    // Your app code goes here

    rt.blocking_flush(std::time::Duration::from_secs(30));

    // Shutdown the OpenTelemetry SDK
}

Diagnostic events produced by the 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::LogRecords.

§Mapping

emit events are mapped into the OpenTelemetry data model as follows:

  • When emit::Ctxt::open_push is called, which is done at the start of functions annotated with #[emit::span], a span is created in the configured opentelemetry::trace::TracerProvider.
    • If the properties include a span_name then it will be used as the name of the created span, otherwise emit_span will be used unil the span is emitted.
    • If the properties include a span_kind then it will be used as the kind of the created span.
  • When emit::Emitter::emit is called, which is done at the end of functions annotated with #[emit::span], then the emit event will be mapped to either an OpenTelemetry log record or span.
    • If the event has a span id and it matches the currently active span in the OpenTelemetry context then it will be completed as a span.
      • If the span doesn’t have a meaningful name configured already, then the rendered message will be used.
      • If the emit event contains the well-known err property, it will be mapped onto the semantic exception event on the span, and the span’s status will be set to Error.
      • If the emit event contains the well-known lvl property, and its value is error, the span’s status will be set to Error.
    • If the event isn’t for a span, then it will be emitted as a log record. emit events aren’t ever added as events on OpenTelemetry spans.
    • Properties on the emit event are mapped onto attributes on the resulting OpenTelemetry item.

§Sampling

By 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.

You can change this behavior by overriding the filter using emit::Setup::emit_when on the value returned by setup.

§Limitations

This library doesn’t support emit’s metrics as OpenTelemetry metrics. Any metric samples produced by emit will be emitted as log records.

Spans 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.

§Troubleshooting

If 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:

use emit::metric::Source;

fn main() {
    let logger_provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder()
        .with_simple_exporter(opentelemetry_stdout::LogExporter::default())
        .build();

    let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
        .with_simple_exporter(opentelemetry_stdout::SpanExporter::default())
        .build();

    // 1. Initialize the internal logger
    //    Diagnostics produced by `emit_opentelemetry` itself will go here
    let internal = emit::setup()
        .emit_to(emit_term::stdout())
        .init_internal();

    let mut reporter = emit::metric::Reporter::new();

    let rt = emit_opentelemetry::setup(logger_provider, tracer_provider)
        .map_emitter(|emitter| {
            // 2. Add `emit_opentelemetry`'s metrics to a reporter so we can see what it's up to
            //    You can do this independently of the internal emitter
            reporter.add_source(emitter.metric_source());

            emitter
        })
        .init();

    // Your app code goes here

    rt.blocking_flush(std::time::Duration::from_secs(30));

    // 3. Report metrics after attempting to flush
    //    You could also do this periodically as your application runs
    reporter.emit_metrics(&internal.emitter());
}

Also see the opentelemetry docs for any details on getting diagnostics out of it.

Structs§

EmitOpenTelemetryMetrics
Metrics produced by the emit to the OpenTelemetry SDK integration itself.
OpenTelemetryCtxt
An emit::Ctxt created during setup for integrating emit with the OpenTelemetry SDK.
OpenTelemetryEmitter
An emit::Emitter creating during setup for integrating emit with the OpenTelemetry SDK.
OpenTelemetryFrame
The emit::Ctxt::Frame used by OpenTelemetryCtxt.
OpenTelemetryIsSampledFilter
A filter that excludes events inside an unsampled trace.
OpenTelemetryProps
The emit::Ctxt::Current used by OpenTelemetryCtxt.

Functions§

setup
Start a builder for the emit to OpenTelemetry SDK integration.