MiregoElixirOtelAgent

Drop-in OpenTelemetry agent for Elixir apps.

This is not an official OTEL distribution. It's an opinionated drop-in library to quickly set up a standard Elixir/Phoenix application that follows semantic conventions. Traces are provided by the official opentelemetry_* libraries while metrics are provided by Telemetry.Metrics and exported by an internal OTLP metric exporter. Some default metrics are provided by this library.

Goal: this library is intended to be temporary. Once the official OpenTelemetry Elixir libraries include proper metrics support, and the official instrumentation libraries include their own metrics, this library should be deprecated in favor of those upstream solutions.

Installation

def deps do
[
{:mirego_elixir_otel_agent, "~> 0.1"}
]
end

Since the official :opentelemetry and :opentelemetry_exporter applications are configured directly by the host app, they can be started normally by the release. No special restart handling is required.

Configuration

Configure the official SDK and exporter directly, just as you would without this library:

# config/runtime.exs
if endpoint = System.get_env("OTEL_EXPORTER_OTLP_ENDPOINT") do
config :opentelemetry,
resource: [
{"service.name", "my-app"},
{"service.version", Application.spec(:my_app, :vsn) |> to_string()}
],
traces_exporter: :otlp,
span_processor: :batch
config :opentelemetry_exporter,
otlp_protocol: :http_protobuf,
otlp_endpoint: endpoint
config :mirego_elixir_otel_agent,
enabled: true,
metric_export_period: 30_000,
phoenix_adapter: :bandit,
metric_exporter: [
resource: %{"service.namespace" => "my-team"},
otlp_headers: %{"x-api-key" => System.fetch_env!("OTLP_API_KEY")},
otlp_timeout: 15_000
]
end

App module

defmodule MyApp.OpenTelemetry do
use MiregoElixirOtelAgent,
ecto_prefixes: [[:my_app, :repo]]
import Telemetry.Metrics
@impl true
def on_start do
# Phoenix, Ecto, Bandit/Cowboy, Absinthe, and Oban instrumentations are
# attached automatically when their modules are present. Use this callback
# for any custom setup that the automatic instrumentation does not cover.
:ok
end
@impl true
def extra_metrics do
[
counter("my_app.custom.metric",
event_name: [:my_app, :custom_metric],
measurement: :count,
tags: [:success]
)
]
end
end

Supervision tree

In MyApp.Application, start the agent as one of the first children:

children = [
MyApp.OpenTelemetry,
MyApp.Repo,
MyAppWeb.Endpoint
]

Callbacks

CallbackRequiredRole
on_start/0noCustom startup hook. The built-in Phoenix, Ecto, server adapter, Absinthe, and Oban instrumentations are attached automatically.
extra_metrics/0noApp-specific metrics defined with Telemetry.Metrics

use options

OptionDefaultPurpose
:ecto_prefixes[]Prefixes for baseline DB metrics andOpentelemetryEcto.setup/1 (e.g. [[:my_app, :repo]])
:baseline_metricstruetrue / false / [vm: true, http: true, ecto: true, graphql: true] when Absinthe is loaded, otherwise graphql: false
:auto_instrumenttrueWhen true, attaches Phoenix, Ecto, server adapter, Absinthe, and Oban instrumentations automatically. Set to false to do it yourself in on_start/0.

Agent config options

OptionDefaultPurpose
:enabledfalseWhen not true, start_link/1 returns :ignore
:metric_export_period30_000Metrics export interval in ms
:phoenix_adapter:banditAdapter passed to OpentelemetryPhoenix.setup/1 (:bandit or :cowboy2)
:metric_exporter[]Internal metrics-exporter options; see Metric exporter configuration

Instrumentations

The following instrumentation libraries are attached automatically when :auto_instrument is true (the default) and their modules are present in the host app. Automatic attachment does not necessarily mean automatic installation: opentelemetry_phoenix and opentelemetry_ecto are installed transitively with this library, while the optional instrumentations below must be added directly to the host application's dependencies.

Add the optional instrumentation libraries you need to your host app dependencies; the agent will detect and attach them on start:

def deps do
[
{:mirego_elixir_otel_agent, "~> 0.1"},
{:opentelemetry_oban, "~> 1.2"},
{:opentelemetry_absinthe, "~> 2.3"}
]
end

Set :auto_instrument to false and attach the instrumentations yourself in on_start/0 if you need custom setup options.

Metric exporter configuration

Metrics use the internal exporter vendored in this package. It reads connection settings from :opentelemetry_exporter, so the OTLP endpoint used for traces is also used for metrics. The agent passes those settings directly when it starts the exporter; it does not modify :opentelemetry_exporter application config.

Use :metric_exporter only for metric-specific overrides that cannot live in the official exporter config. For example:

config :mirego_elixir_otel_agent,
metric_exporter: [
resource: %{
"service.namespace" => "my-team",
"deployment.environment.name" => "production"
},
otlp_headers: %{"x-api-key" => System.fetch_env!("OTLP_API_KEY")},
otlp_timeout: 15_000,
otlp_compression: :gzip
]

Supported internal options are:

KeyDefaultPurpose
:resource%{}Additional OTLP resource attributes. Nested maps are flattened with dot-separated keys.
:otlp_headers%{}Request headers, merged with headers from the official exporter config.
:otlp_timeout10_000OTLP request timeout in milliseconds.
:otlp_compression:gzipRequest compression; :gzip or nil.

The exporter currently supports only OTLP/HTTP protobuf. Its fallback defaults are otlp_protocol: :http_protobuf and otlp_compression: :gzip.

License

MiregoElixirOtelAgent is © 2026 Mirego and may be freely distributed under the New BSD license. See the LICENSE.md file.

About Mirego

Mirego is a team of passionate people who believe that work is a place where you can innovate and have fun. We’re a team of talented people who imagine and build beautiful Web and mobile applications. We come together to share ideas and change the world.

We also love open-source software and we try to give back to the community as much as we can.