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 (1)
Great article and thanks for your contribution. I totally tested this regarding OTel instrumentation and gave it a star. It was the most "plug and play" dev tool I tried about my project with OTel instrumentation and lightweight dev viewer of metrics, logs and traces. This has a good future!