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 = "2"
# add `emit_opentelemetry` with the same major/minor as the OpenTelemetry SDK
[dependencies.emit_opentelemetry]
version = "0.32"
[dependencies.opentelemetry_sdk]
version = "0.32"
features = ["trace", "logs"]
[dependencies.opentelemetry]
version = "0.32"
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.
§Span lifecycle
Spans created by emit’s #[emit::span] attribute will be created through the configured opentelemetry::trace::TracerProvider.
The following well-known emit properties are interpreted during span creation:
span_name: Sets the name of the span. Otherwise a default name derived from the span’s message template will be used.span_kind: Sets the kind of the span. Otherwise the default kind of internal will be used.span_links: Populates a set of links on the span.
Spans created through emit don’t carry additional attributes on them until completion.
Spans are completed when the function annotated with #[emit::span] completes.
At this point if the event is a span, and its context matches the current OpenTelemetry span context, it’ll be emitted as a span.
The following well-known emit properties are interpreted during span completion:
err: Mapped onto the semanticexceptionevent on the span, and the span’s status will be set toError.lvl: If its value iserror, the span’s status will be set toError.span_links: Populates a set of links on the span.
If the span doesn’t have a meaningful name configured already, then the rendered message will be used.
§Sampling
emit will respect the sampling decision in OpenTelemetry’s context. Spans outside of sampled OpenTelemetry traces will not be emitted.
That means the root span must be created by the OpenTelemetry SDK, not by emit.
§Span links
emit doesn’t track trace flags, trace state, or whether links are remote in its model.
This information will be populated from the current span context.
You can add span links through the OpenTelemetry SDK itself, even to spans created by emit, if you need to configure these.
§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 not be emitted.
Spans produced outside of a sampled OpenTelemetry trace will not be emitted. That means the root span must be created by the OpenTelemetry SDK.
§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 setup = emit_opentelemetry::setup(logger_provider, tracer_provider);
// 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(setup.metric_source());
let rt = setup.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§
- Emit
Open Telemetry Metrics - Metrics produced by the
emitto the OpenTelemetry SDK integration itself. - Setup
- A partly initialized OpenTelemetry provider.
Functions§
- setup
- Start a builder for the
emitto OpenTelemetry SDK integration.