Elixir OpenTelemetry instrumentation
Instrument a Phoenix application with OpenTelemetry using the opentelemetry_phoenix and opentelemetry_ecto libraries. They subscribe to the :telemetry events Phoenix and Ecto already emit and turn them into spans, so incoming requests and database queries are traced with no changes to your controllers.
Prerequisites
Section titled “Prerequisites”- A Phoenix application.
- Elixir 1.14 or newer with OTP 25+.
- Your Osuite ingest token and region.
Install and configure
Section titled “Install and configure”-
Add the OpenTelemetry packages to
depsinmix.exs, then runmix deps.get.{:opentelemetry_api, "~> 1.4"},{:opentelemetry, "~> 1.5"},{:opentelemetry_exporter, "~> 1.8"},{:opentelemetry_phoenix, "~> 2.0"},{:opentelemetry_cowboy, "~> 1.0"},{:opentelemetry_ecto, "~> 1.2"} -
Wire up the instrumentation in
application.ex, at the start ofstart/2before the supervisor children start. Pass your Ecto repo’s telemetry prefix toOpentelemetryEcto.setup/1.def start(_type, _args) do:opentelemetry_cowboy.setup()OpentelemetryPhoenix.setup(adapter: :cowboy2)OpentelemetryEcto.setup([:my_app, :repo])children = [# ... your existing children]Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)end -
Configure the OTLP exporter in
config/runtime.exsso it reads your ingest credentials at boot.config :opentelemetry, traces_exporter: :otlpconfig :opentelemetry_exporter,otlp_protocol: :grpc,otlp_endpoint: "https://ingest.<region>.osuite.io:443",otlp_headers: [{"x-osuite-ingest-token", "<your-ingest-token>"}]Set the service name and environment as resource attributes, either here or with the standard
OTEL_SERVICE_NAME=<service-name>andOTEL_RESOURCE_ATTRIBUTES=service.environment=productionenvironment variables. Thehttps://scheme onotlp_endpointis required — Osuite only accepts OTLP over TLS.
Verify in Osuite
Section titled “Verify in Osuite”What you should see
Send a request to any route. The service appears in APM within a minute with a trace per request, showing the Phoenix endpoint, the controller action, and Ecto queries as nested spans.
Troubleshooting
Section titled “Troubleshooting”If no traces appear, confirm the setup calls run at application start and that config/runtime.exs is evaluated in your release (it is, by default). A common miss is calling OpentelemetryEcto.setup/1 with the wrong telemetry prefix — it must match your repo’s [:otp_app, :repo], not the module name.
No data in Osuite after a few minutes? Work through these checks.
- Endpoint — confirm the exporter targets exactly
ingest.<region>.osuite.io:443for your region, over TLS. - Token — confirm the ingest header carries a valid
<your-ingest-token>and has not been rotated. - Pipeline — confirm the signal you expect (traces, logs, or metrics) is wired into an active pipeline with the
otlp/osuiteexporter attached. - Export errors — check the application or Collector logs for OTLP export failures (auth, DNS, TLS, connection refused).
- Network — confirm the host has outbound access to the ingest endpoint on port
443. - Timing — allow up to a minute for the first data to appear before assuming a failure.
Still stuck? Ask the Investigation Agent or contact support.