OTLP Exporter Configuration for OpenTelemetry Erlang/Elixir
This document shows how to configure the OpenTelemetry Erlang/Elixir SDK to export telemetry data to Uptrace using the OTLP exporter. For the getting started guide, see Monitor OpenTelemetry Erlang/Elixir with Uptrace.
OTLP exporter configuration
The OpenTelemetry Erlang/Elixir SDK uses the OTLP exporter to send telemetry data to Uptrace. You can configure it using application configuration or environment variables.
For more details on the OpenTelemetry APIs, see:
- OpenTelemetry Erlang/Elixir Tracing API - creating spans, recording errors, adding attributes
- OpenTelemetry Erlang/Elixir Metrics API - counters, histograms, and gauges
- OpenTelemetry Erlang/Elixir Resource detectors - service name, environment, and deployment metadata
Exporting traces
Configure the OTLP trace exporter to send distributed traces to Uptrace:
# config/config.exs or config/runtime.exs
config :opentelemetry,
span_processor: :batch,
traces_exporter: :otlp
config :opentelemetry_exporter,
otlp_protocol: :grpc,
otlp_compression: :gzip,
otlp_endpoint: "https://api.uptrace.dev:4317",
otlp_headers: [{"uptrace-dsn", System.get_env("UPTRACE_DSN")}]
HTTP/protobuf protocol
You can also use the HTTP/protobuf protocol instead of gRPC:
config :opentelemetry_exporter,
otlp_protocol: :http_protobuf,
otlp_compression: :gzip,
otlp_endpoint: "https://api.uptrace.dev",
otlp_headers: [{"uptrace-dsn", System.get_env("UPTRACE_DSN")}]
Exporting metrics
Configure the OTLP metrics exporter to send OpenTelemetry metrics to Uptrace:
# config/runtime.exs
config :opentelemetry_experimental,
metrics_exporter: :otlp
config :opentelemetry_exporter,
otlp_protocol: :grpc,
otlp_compression: :gzip,
otlp_endpoint: "https://api.uptrace.dev:4317",
otlp_headers: [{"uptrace-dsn", System.get_env("UPTRACE_DSN")}]
Environment variables
You can configure the OTLP exporter using environment variables, which is particularly useful for containerized deployments:
# gRPC protocol (recommended)
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.uptrace.dev:4317"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
export OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<YOUR_UPTRACE_DSN>"
# HTTP/protobuf protocol
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.uptrace.dev"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
export OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<YOUR_UPTRACE_DSN>"
Signal-specific configuration
You can configure different endpoints for traces and metrics:
# Traces
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://api.uptrace.dev:4317"
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_TRACES_COMPRESSION="gzip"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="uptrace-dsn=<YOUR_UPTRACE_DSN>"
# Metrics
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="https://api.uptrace.dev:4317"
export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_METRICS_COMPRESSION="gzip"
export OTEL_EXPORTER_OTLP_METRICS_HEADERS="uptrace-dsn=<YOUR_UPTRACE_DSN>"
Batch processor configuration
The batch processor buffers spans before sending them to the exporter. Configure it for optimal performance:
config :opentelemetry,
span_processor: :batch,
bsp_scheduled_delay_ms: 5000, # Delay between exports (default: 5000)
bsp_max_queue_size: 10000, # Max spans in queue (default: 2048)
bsp_max_export_batch_size: 512, # Max spans per batch (default: 512)
bsp_exporting_timeout_ms: 30000 # Export timeout (default: 30000)
Complete example
Here's a complete configuration example for a Phoenix application:
# config/runtime.exs
import Config
# OpenTelemetry SDK configuration
config :opentelemetry,
span_processor: :batch,
traces_exporter: :otlp,
resource: %{
service: %{
name: System.get_env("OTEL_SERVICE_NAME", "my-phoenix-app"),
version: "1.0.0"
},
deployment: %{
environment: System.get_env("MIX_ENV", "development")
}
}
# OTLP exporter configuration
config :opentelemetry_exporter,
otlp_protocol: :grpc,
otlp_compression: :gzip,
otlp_endpoint: System.get_env("OTEL_EXPORTER_OTLP_ENDPOINT", "https://api.uptrace.dev:4317"),
otlp_headers: [
{"uptrace-dsn", System.get_env("UPTRACE_DSN")}
]
# lib/my_app/application.ex
defmodule MyApp.Application do
use Application
def start(_type, _args) do
# Setup OpenTelemetry instrumentations before starting supervision tree
:opentelemetry_cowboy.setup()
OpentelemetryPhoenix.setup(adapter: :cowboy2)
OpentelemetryEcto.setup([:my_app, :repo])
children = [
MyApp.Repo,
{Phoenix.PubSub, name: MyApp.PubSub},
MyAppWeb.Endpoint
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
Troubleshooting
Testing with stdout exporter
Use the stdout exporter to verify spans are being created correctly:
# config/dev.exs
config :opentelemetry,
traces_exporter: {:otel_exporter_stdout, []}
Connection issues
If traces don't appear in Uptrace:
- Verify DSN: Check that your Uptrace DSN is correctly set
- Check connectivity: Ensure your application can reach
api.uptrace.dev:4317(gRPC) orapi.uptrace.dev(HTTP) - Review logs: Look for OpenTelemetry error messages in your application logs
- Check firewall: Ensure outbound connections on port 4317 (gRPC) or 443 (HTTP) are allowed
Verifying export
Add logging to confirm spans are being exported:
# In application.ex, add after OpenTelemetry setup
require Logger
Logger.info("OpenTelemetry configured with exporter: #{inspect(Application.get_env(:opentelemetry, :traces_exporter))}")