OpenTelemetry Erlang/Elixir

repository·main·Indexed 18 days ago

https://github.com/open-telemetry/opentelemetry-erlang

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

Tokens
28.8K
Snippets
113
Records
132
Agent score
63%

What's inside opentelemetry-erlang

  1. Configure the OpenTelemetry Protocol (OTLP) exporter

    main

    The opentelemetry_exporter is used to send traces and metrics to an OpenTelemetry Collector. It currently supports the Tracer protocol via grpc or http_protobuf. By default, it exports protobuf-encoded Spans to http://localhost:4318/v1/traces using HTTP.

    {opentelemetry_exporter,
      [{otlp_protocol, grpc}, 
       {otlp_compression, gzip}, 
       {otlp_endpoint, "https://api.honeycomb.io:443"}, 
       {otlp_headers, [{"x-honeycomb-dataset", "experiments"}]}]}
  2. Use the OpenTelemetry API in Erlang and Elixir

    main

    The opentelemetry_api library 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).
  3. Migrate to the new semantic conventions structure

    main

    The structure of OpenTelemetry Semantic Conventions has changed. All attributes are now organized under a common attribute registry and classified by stability:

    1. Stable: Standard attributes.
    2. 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.

  4. How Context and Spans work in OpenTelemetry

    main

    Context

    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_span macro/function, which:

    1. Automatically finds the Tracer for your Application.
    2. Starts the Span.
    3. Sets the Span as the active Span in the process dictionary.
    4. Ends the Span when the block finishes (even if an exception is raised).
    5. 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_span manually instead of with_span, you must call the corresponding end_span API to signal the operation has finished.

  5. Understand Metrics Aggregation in opentelemetry_experimental

    main

    Aggregations 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 TypeDefault Aggregator
    counterotel_aggregation_sum
    updown counterotel_aggregation_sum
    histogramotel_aggregation_histogram_explicit
    observable counterotel_aggregation_sum
    observable updown counterotel_aggregation_sum
    observable gaugeotel_aggregation_last_value
  6. Understand the OpenTelemetry Erlang/Elixir Architecture

    main

    The OpenTelemetry implementation for Erlang and Elixir is split into two primary components following the OpenTelemetry specification:

    1. 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.
    2. 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.

  7. How metrics components work together

    main

    The metrics system is composed of several layers:

    1. Meter Provider: The entry point (implemented as otel_meter_server in the SDK). It manages shared configuration and the Resource of the telemetry. Including the SDK ensures a default Provider is available.
    2. Meter: Used to create instruments (implemented as otel_meter_default in the SDK). Most users interact with Meters indirectly via macros.
    3. Instrument: The object used to capture data. Can be synchronous (immediate recording) or observable (callback-based).
    4. Measurement: An individual data point consisting of a value and associated attributes.
    5. Metric Reader: (Part of the SDK) Triggers the collection of metrics, including executing callbacks for observable instruments.
  8. Configure Samplers

    main

    Samplers 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_span or start_span are available to the Sampler.

    Built-in Sampler Types:

    • always_on
    • always_off
    • traceidratio
    • parentbased_always_on
    • parentbased_always_off
    • parentbased_traceidratio

    Configuration Options:

    OSApplicationDefaultType
    OTEL_TRACES_SAMPLERsamplerparentbased_always_on(See types above)
    OTEL_TRACES_SAMPLER_ARGsampler_argString

    To implement a custom sampler, implement the otel_sampler behaviour.

  9. Identify the correct OpenTelemetry package for your needs

    main

    OpenTelemetry 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.x versioning. Modules are removed from here when they graduate to the stable opentelemetry_api package.

    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 is v0.3.0, the SDK will be v0.3.x).

    OTLP Exporter (opentelemetry_exporter)

    Contains exporter implementations that are tied to the SDK's public API.

  10. Understand the OpenTelemetry Erlang module naming convention

    main

    All core OpenTelemetry Applications use the otel module 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_experimental to opentelemetry_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.

  11. Correlate Logs with Spans

    main

    When a Span is made active (e.g., via with_span), it is automatically added to the Erlang/Elixir logger metadata under the key otel_span_ctx.

    You can configure your logger formatter to include trace_id and span_id in 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, " "], []}, ...]}}}]}]}]}.