otelstor

command module
v0.0.0-...-7199d20 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 4, 2026 License: LGPL-2.1 Imports: 21 Imported by: 0

README

oteldash

otelstor

A lightweight OpenTelemetry trace collector and storage backend. Receives spans over OTLP (gRPC and HTTP/protobuf), stores them in a local bbolt database, and exposes a gRPC stats API and a Svelte web dashboard.

Building

# Build the server
go build -o otelstor .

# Build the test client
go build -o testclient ./cmd/testclient

# Build the Svelte UI (requires Node.js)
cd cmd/dashboard/ui && npm install && npm run build

# Build the dashboard bridge
go build -o dashboard ./cmd/dashboard

Running the server

./otelstor
# or with a custom config file
./otelstor -config /etc/otelstor/prod.cfg
Server flags
Flag Default Description
-config otelstor.cfg Path to textproto config file
Configuration file (otelstor.cfg)

The config file uses textproto format. All fields are optional; missing values use the defaults shown.

port: 4317
http_port: 4318
data_dir: "."
retention_days: 60
Field Default Description
port 4317 OTLP gRPC listen port
http_port 4318 OTLP HTTP/protobuf listen port (0 to disable)
data_dir "." Directory where traces.db is stored
retention_days 60 Days to retain trace data; older month buckets are deleted hourly

If otelstor.cfg is absent the server starts with the defaults above and logs a warning. An explicit -config path that does not exist is a fatal error.

OTLP endpoints

gRPC (port 4317)

Standard OTLP gRPC — compatible with any OpenTelemetry SDK or collector configured with an otlp/grpc exporter:

# OpenTelemetry Collector config example
exporters:
  otlp:
    endpoint: localhost:4317
    tls:
      insecure: true
HTTP/protobuf (port 4318)

Standard OTLP HTTP/protobuf — compatible with any SDK or collector configured with an otlp/http exporter:

# Manual example
curl -X POST http://localhost:4318/v1/traces \
  -H "Content-Type: application/x-protobuf" \
  --data-binary @export_request.pb

Running the dashboard

The dashboard is a separate Go binary that bridges the browser to the otelstor gRPC server.

./dashboard
# or
./dashboard -grpc-addrs localhost:4317,localhost:4327 -port 10731

Then open http://localhost:10731.

Dashboard flags
Flag Default Description
-grpc-addrs localhost:4317 Comma-separated list of otelstor gRPC server addresses to connect to
-port 10731 HTTP port for the dashboard

Each service card has a Drilldown button. Clicking it fetches the last 50 spans for that service and displays them inline — showing operation name, trace ID, start time, duration, and status. Click again to collapse.

Dashboard UI development
cd cmd/dashboard/ui
npm install
npm run dev     # Vite dev server on :5173, proxies /api to :10731
npm run build   # production build → dist/

Test client

The test client sends synthetic OTLP spans to the server, or dumps stored spans for a service. Spans have random start times up to 1 hour in the past and random durations up to 2 seconds.

Send spans
./testclient
./testclient -service payment-svc -count 500
./testclient -addr localhost:4317 -service worker -count 50
Dump stored spans
# Dump last 50 spans for the default service ("frontend")
./testclient -dump

# Dump last 50 spans for a specific service
./testclient -service payment-svc -dump
List trace IDs
# List the last 100 unique trace IDs for the default service
./testclient -traces

# List trace IDs for a specific service
./testclient -service payment-svc -traces
Show a trace by trace ID
./testclient -trace <hex-trace-id>

Fetches all spans for the given trace ID and prints them as an indented tree (root spans at the top, children indented under their parent, each group sorted by start time). The OFFSET column shows time elapsed since the earliest span in the trace.

Output example:

Trace 4bf92f3577b34da6a3ce929d0e0e4736 — 4 span(s)

  SPAN                                              SPAN ID              OFFSET  DURATION  STATUS
  ------------------------------------------------  ------------------  ------  --------  ------
  GET /api/orders                                   a2fb4a1d1a96d31…       0µs    120ms  OK
    POST /api/payments                              c9a0c77e2d19b7b…      10ms     80ms  OK
      db.query                                      b14f87cce43d191…      12ms     60ms  OK
    cache.get                                       f3e9a245301e9b2…     100ms      5ms  OK
List all services
# Show all services with trace count, span count, and last-updated time
./testclient -services

Output example:

3 service(s)

  SERVICE                          TRACES     SPANS  LAST UPDATED
  -------                          ------     -----  ------------
  frontend                            42       1024  2026-02-22 10:30:05 UTC
  payment-svc                         17        380  2026-02-21 18:14:22 UTC
  worker                               5         95  2026-02-20 09:00:01 UTC
Test client flags
Flag Default Description
-addr localhost:4317 otelstor gRPC server address
-service frontend Service name
-count 100 Number of spans to send (send mode only)
-dump false Dump last 50 stored entries instead of sending
-traces false List last 100 unique trace IDs instead of sending
-services false List all services with trace count, span count, and last-updated time
-trace "" Hex trace ID to fetch and display as an indented span tree

gRPC Stats API

The otelstor.StatsService is available on the same gRPC port as the OTLP endpoint.

GetStats

Returns effective server configuration and the full bucket tree (services → months → span counts).

GetSpans

Returns the most recent spans for a named service.

Field Description
service Service name to query
limit Max spans to return (default 50)
GetSpanTree

Given any span_id (hex), returns all spans that share the same trace_id within a ±2-minute window. Spans are returned with parent_span_id set so the caller can reconstruct the full trace tree.

Field Description
span_id Hex-encoded span ID of any span in the trace
GetTraceByID

Given a hex-encoded trace_id, returns all spans belonging to that trace by scanning every service and month bucket. Results are returned as a GetSpanTreeResponse (same shape as GetSpanTree). Returns NOT_FOUND if no spans match.

Field Description
trace_id Hex-encoded trace ID
GetTraceIDs

Returns the last N unique trace IDs for a named service, ordered most-recent first.

Field Description
service Service name to query
limit Max trace IDs to return (default 100)
ListServices

Returns a summary for every stored service in one call.

Each ServiceSummary contains:

Field Description
name Service name
trace_count Distinct trace IDs across all stored spans
span_count Total stored spans
last_updated_unix_nano Start time of the most recently stored span (from ULID key)

Storage layout

traces.db  (bbolt)
└── <service-name>/          ← top-level bucket per service
    └── <YYYY-MM>/           ← sub-bucket per month
        └── <24-byte key>    ← ULID(startTime)[16] || spanId[8]
            → zlib-compressed ResourceSpans protobuf (single span)

Month buckets older than retention_days are automatically removed on an hourly schedule.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
dashboard command
testclient command
testclient generates synthetic OTLP trace spans and sends them to an otelstor gRPC server.
testclient generates synthetic OTLP trace spans and sends them to an otelstor gRPC server.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL