otel_bridge is a small adapter layer for teams that already describe metrics with Telemetry.Metrics, but want to export them through OpenTelemetry.

It does not try to replace opentelemetry, opentelemetry_api, or opentelemetry_exporter. Instead, it sits on top of them and provides:

  • a small public API
  • a behaviour for metric spec modules
  • a bridge from Telemetry.Metrics to OpenTelemetry instruments
  • backend-specific profile helpers such as VictoriaMetrics

Installation

Add otel_bridge to your dependencies:

def deps do
  [
    {:otel_bridge, "~> 0.1.0"}
  ]
end

Design goals

  • keep business integration code small
  • prefer Elixir behaviours over framework-specific DSLs
  • keep backend policy out of business modules
  • stay compatible with standard OpenTelemetry packages

Supported scope

otel_bridge currently focuses on one job:

What it supports today:

What it does not support today:

Define metrics

Create a module that uses OtelBridge.Spec and returns ordinary Telemetry.Metrics definitions:

defmodule MyApp.Metrics do
  use OtelBridge.Spec

  @impl OtelBridge.Spec
  def metrics(meta) do
    [
      summary("http.server.duration",
        event_name: [:my_app, :http, :stop],
        measurement: :duration,
        unit: {:native, :millisecond},
        tags: [:route, :status_code],
        tag_values: fn metadata ->
          metadata
          |> Map.put(:route, metadata[:route] || "unknown")
          |> Map.put(:status_code, metadata[:status_code] || 500)
          |> Map.put(:service, Keyword.get(meta, :service))
        end
      )
    ]
  end
end

Start the bridge

Use OtelBridge directly in your supervision tree:

children = [
  {OtelBridge,
   specs: [MyApp.Metrics],
   optional_specs: [MyApp.OptionalMetrics],
   measurements: [{MyApp.Measurements, :dispatch, []}],
   meta: [service: "my_app"],
   poller: [period: 5_000]}
]

Accepted options:

  • :metrics - raw Telemetry.Metrics definitions
  • :specs - spec modules implementing OtelBridge.Spec
  • :optional_specs - spec modules that may or may not be available
  • :measurements - :telemetry_poller measurements
  • :meta - keyword metadata passed to spec modules
  • :poller - :telemetry_poller options
  • :observer_children - custom observer children for gauge-like metrics

Configure metric export

otel_bridge does not own the whole OpenTelemetry SDK configuration. It only helps you build metric reader config for a chosen backend profile.

For VictoriaMetrics:

config :opentelemetry_experimental,
  readers: [
    OtelBridge.metric_reader!(:victoria_metrics,
      export_interval_ms: 5_000,
      endpoint: "http://localhost:4318"
    )
  ]

The VictoriaMetrics profile exports synchronous metrics with cumulative temporality for:

  • counter
  • histogram
  • updown_counter

Complete examples

See the runnable examples in:

The first shows the smallest business integration shape. The second shows how to wire the VictoriaMetrics profile into config/runtime.exs.

Contract guarantees

otel_bridge aims to keep these behaviors stable within a compatible minor release line:

  • use OtelBridge.Spec remains the standard way to define spec modules
  • {OtelBridge, ...} remains the standard supervision entrypoint
  • OtelBridge.metric_reader!/2 remains the profile-based metric reader helper
  • Telemetry.Metrics.LastValue continues to be filtered out by the bridge
  • the :victoria_metrics profile keeps cumulative temporality for synchronous counters, histograms, and updown counters

These guarantees are backed by tests in test/.

Versioning policy

otel_bridge follows semantic versioning.

  • patch releases fix bugs and documentation without changing supported public API
  • minor releases may add new profiles, new helpers, and new supported metric shapes in a backwards-compatible way
  • major releases may change public APIs, profile names, or contract guarantees

Behavior that is not documented in this README or module docs should be treated as internal and may change between minor releases.

See CHANGELOG.md for release history.

Scope

otel_bridge is intentionally focused on metrics bridging and export policy.

It does not:

  • replace OpenTelemetry.Tracer
  • replace the OpenTelemetry SDK
  • provide business-specific metric definitions

Use the standard OpenTelemetry packages for tracing APIs and SDK setup, and use otel_bridge where you need a clean Telemetry.Metrics to OTel migration path.