The problem
Every time I wanted to test OpenTelemetry instrumentation locally, I had to spin up Jaeger or a full collector stack. docker-compose up, wait, configure exporters, hope nothing clashes on port 4317... It felt like too much ceremony for a "does my trace look right?" check.
So I built otel-front: a single binary that receives OTLP data and shows it in a web UI. No Docker, no external database, no config files.
brew tap mesaglio/otel-front
brew install mesaglio/otel-front/otel-front
otel-front
# → opens http://localhost:8000
Point your app at localhost:4318 (HTTP) or localhost:4317 (gRPC) and that's it.
What it does
- Traces — waterfall view, flame graph, side-by-side trace comparison, search by operation or trace ID
- Logs — full-text search, severity/service filters, correlation with traces via trace_id
- Metrics — query builder, time series charts, aggregations (avg, sum, min, max, count)
Traces
Side-by-side comparison to spot regressions between two runs:
Logs correlated by trace_id directly from a trace view:
Logs
Metrics
How it's built
The interesting constraint was: single binary, zero external dependencies.
Go + embedded frontend
The backend is Go (Gin). The React frontend is built with Vite and then embedded directly into the binary using Go's embed.FS:
//go:embed static/*
var staticFiles embed.FS
One go build, one binary that serves everything.
DuckDB as in-memory store
I needed SQL (for flexible filtering and aggregations) without shipping a database. DuckDB fits perfectly — it runs entirely in-process, zero setup, and handles analytical queries well.
Traces, spans, logs, and metrics all land in DuckDB tables with JSON columns for attributes:
CREATE TABLE spans (
trace_id TEXT,
span_id TEXT,
name TEXT,
start_time_unix_nano BIGINT,
end_time_unix_nano BIGINT,
attributes JSON,
...
)
Instead of writing protobuf parsers from scratch, I reused the OpenTelemetry Collector's pdata library. It handles deserialization; I just transform the result into my internal models.
Quick start
Homebrew
brew tap mesaglio/otel-front
brew install otel-front
otel-front
Docker
docker run -p 8000:8000 -p 4317:4317 -p 4318:4318 \
ghcr.io/mesaglio/otel-front:latest
Binary (macOS / Linux, x86_64 & ARM64)
https://github.com/mesaglio/otel-front/releases/latest
Configure your app:
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_LOGS_EXPORTER="otlp"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
The UI includes a copy-paste helper for these env vars.
Source
GitHub: mesaglio/otel-front
PRs and feedback welcome. If you're working with OpenTelemetry locally and
find it useful (or broken), let me know in the comments.






Top comments (0)