OpenTelemetry Erlang/Elixir
repository·main·Indexed 18 days ago
https://github.com/open-telemetry/opentelemetry-erlangA distributed tracing and metrics framework for Erlang and Elixir applications implementing the OpenTelemetry specification. It provides the opentelemetry_api for lightweight instrumentation of spans and context, and an experimental metrics API (opentelemetry_api_experimental) supporting synchronous and observable instruments. The library separates the API from the SDK, requiring the OpenTelemetry SDK for actual data export and the opentelemetry_experimental package for metrics recording and aggregation.
What's inside opentelemetry-erlang
- The Erlang/Elixir OpenTelemetry SDK is an implementation of the OpenTelemetry API. It is designed to be included in your final deployable artifact, typically an OTP Release, to provide tracing and observability capabilities within Erlang or Elixir applications.
Configure the OpenTelemetry Protocol (OTLP) exporter
mainThe
opentelemetry_exporteris used to send traces and metrics to an OpenTelemetry Collector. It currently supports the Tracer protocol viagrpcorhttp_protobuf. By default, it exports protobuf-encoded Spans tohttp://localhost:4318/v1/tracesusing HTTP.{opentelemetry_exporter, [{otlp_protocol, grpc}, {otlp_compression, gzip}, {otlp_endpoint, "https://api.honeycomb.io:443"}, {otlp_headers, [{"x-honeycomb-dataset", "experiments"}]}]}Use the OpenTelemetry API in Erlang and Elixir
mainThe
opentelemetry_apilibrary provides the API portion of the OpenTelemetry specification for Erlang and Elixir. It is a lightweight library that does not start any processes.To simplify usage, the library provides macros (Erlang) and functions (Elixir) that automatically look up a Named Tracer based on the current OTP Application name. This ensures that spans are correctly associated with the appropriate Instrumentation Library and version.
Important: This library is the API only. To actually export traces, you must include the OpenTelemetry SDK in your release. If only the API is present, a no-op Tracer is used and no data is exported.
%% Erlang Example -include_lib("opentelemetry_api/include/otel_tracer.hrl"). some_fun() -> ?with_span(<<"some_fun/0">>, #{}, fun(_SpanCtx) -> ?set_attribute(<<"key">>, <<"value">>), ... end).Migrate to the new semantic conventions structure
mainThe structure of OpenTelemetry Semantic Conventions has changed. All attributes are now organized under a common attribute registry and classified by stability:
- Stable: Standard attributes.
- Experimental (Incubating): Attributes that are subject to change.
Attributes are organized by attribute group and stability. Previous code patterns are kept in a deprecated status to facilitate migration, but it is recommended to move to the new organized structure.
How Context and Spans work in OpenTelemetry
mainContext
Context is used to pass values (like Span Context and Baggage) associated with the current execution unit. In this library, if a Context is not explicitly passed to an API function, it is retrieved from the process dictionary. If no Context exists in the process dictionary, one is created.
Spans
A Span represents a single operation. The recommended way to manage Spans is using the
with_spanmacro/function, which:- Automatically finds the Tracer for your Application.
- Starts the Span.
- Sets the Span as the active Span in the process dictionary.
- Ends the Span when the block finishes (even if an exception is raised).
- Resets the Context in the process dictionary to its previous state after the Span ends, ensuring proper lineage for child Spans.
If you use
start_spanmanually instead ofwith_span, you must call the correspondingend_spanAPI to signal the operation has finished.Understand Metrics Aggregation in opentelemetry_experimental
mainAggregations define how measurements over time are combined into exact or statistical metrics. Each Instrument has a default aggregator based on its type, but you can override this using a View or Reader configuration.
Supported Aggregators
otel_aggregation_sum: Arithmetic sum of values.otel_aggregation_drop: Ignores measurement values.otel_aggregation_last_value: Collects only the last value and its timestamp.otel_aggregation_histogram_explicit: Collects a histogram with static bucket boundaries.
Default Aggregators by Instrument Type
Instrument Type Default Aggregator counterotel_aggregation_sumupdown counterotel_aggregation_sumhistogramotel_aggregation_histogram_explicitobservable counterotel_aggregation_sumobservable updown counterotel_aggregation_sumobservable gaugeotel_aggregation_last_valueUnderstand the OpenTelemetry Erlang/Elixir Architecture
mainThe OpenTelemetry implementation for Erlang and Elixir is split into two primary components following the OpenTelemetry specification:
- API (
opentelemetry_api): Defines the interfaces for tracing and instrumentation. Your application code should only depend on the API. If the SDK is not present, the API functions as a no-op implementation. - SDK (
opentelemetry): The actual implementation of the API. This should be included in your production release along with an exporter to process and send telemetry data.
To capture distributed traces, you should use officially supported instrumentation libraries (found in
opentelemetry-erlang-contrib) rather than manual instrumentation where possible.- API (
How metrics components work together
mainThe metrics system is composed of several layers:
- Meter Provider: The entry point (implemented as
otel_meter_serverin the SDK). It manages shared configuration and the Resource of the telemetry. Including the SDK ensures a default Provider is available. - Meter: Used to create instruments (implemented as
otel_meter_defaultin the SDK). Most users interact with Meters indirectly via macros. - Instrument: The object used to capture data. Can be synchronous (immediate recording) or observable (callback-based).
- Measurement: An individual data point consisting of a value and associated attributes.
- Metric Reader: (Part of the SDK) Triggers the collection of metrics, including executing callbacks for observable instruments.
- Meter Provider: The entry point (implemented as
Configure Samplers
mainSamplers control the number of traces collected and sent to the backend. The sampling decision is made when a span starts, meaning only the initial attributes passed to
with_spanorstart_spanare available to the Sampler.Built-in Sampler Types:
always_onalways_offtraceidratioparentbased_always_onparentbased_always_offparentbased_traceidratio
Configuration Options:
OS Application Default Type OTEL_TRACES_SAMPLERsamplerparentbased_always_on(See types above) OTEL_TRACES_SAMPLER_ARGsampler_argString To implement a custom sampler, implement the
otel_samplerbehaviour.Identify the correct OpenTelemetry package for your needs
mainOpenTelemetry Erlang is split into several distinct OTP Applications. Choose the package based on the stability and type of signal you are using:
Stable APIs (
opentelemetry_api)Contains stable signal APIs. At version 1.0, this includes:
- Tracing
- Baggage
- Context
Experimental APIs (
opentelemetry_api_experimental)Contains APIs that are not yet stable (e.g., Metrics and Logging prior to 1.0). This package always uses
0.xversioning. Modules are removed from here when they graduate to the stableopentelemetry_apipackage.Stable SDK (
opentelemetry)The main implementation package. The API is dynamically configured to use this SDK implementation.
Experimental SDK (
opentelemetry_sdk_experimental)Contains implementations for the APIs found in
opentelemetry_api_experimental. It is versioned in lockstep with the experimental API (e.g., if the API isv0.3.0, the SDK will bev0.3.x).OTLP Exporter (
opentelemetry_exporter)Contains exporter implementations that are tied to the SDK's public API.
Understand the OpenTelemetry Erlang module naming convention
mainAll core OpenTelemetry Applications use the
otelmodule prefix (e.g.,otel_trace,otel_meter).Because Erlang uses a flat namespace, this prefix allows modules to move between different packages (such as from
opentelemetry_api_experimentaltoopentelemetry_api) without requiring users to change their code. If you are using the latest version of an experimental API, your code will continue to work seamlessly once that API graduates to a stable package.Correlate Logs with Spans
mainWhen a Span is made active (e.g., via
with_span), it is automatically added to the Erlang/Elixir logger metadata under the keyotel_span_ctx.You can configure your logger formatter to include
trace_idandspan_idin your logs by accessing these values from the metadata.%% Example logger configuration to include trace/span IDs {kernel, [{logger_level, debug}, {logger, [{handler, default, logger_std_h, #{formatter => #{template => [..., {otel_trace_id, ["trace_id=", otel_trace_id, " "], []}, {otel_span_id, ["span_id=", otel_span_id, " "], []}, ...]}}}]}]}]}.