tsirysndr/otelview-skills/otelview-operate

Claude Code and agent skill by tsirysndr/otelview-skills

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Run and configure an otelview instance — choosing a storage backend (memory, duckdb, jaeger, remote), setting retention, securing OTLP ingest and the query API with tokens, enabling and locking down the MCP endpoint, deploying with Docker, systemd or Nix, and composing instances so one otelview stores for another. Use when asked to deploy, configure, secure, size or troubleshoot an otelview server rather than to query or instrument one.

Install

npx vskill@latest install tsirysndr/otelview-skills/otelview-operate

SKILL.md

Running an otelview

One binary, four processes' worth of job: OTLP receivers on :4317 (gRPC) and :4318 (HTTP), storage, the web UI and query API on :4319, and an MCP endpoint at /mcp on that same port. No cluster, no JVM, no sidecar.

sh
otelview # in-memory, UI on http://127.0.0.1:4319
otelview --storage duckdb # persist to ./otelview.duckdb
otelview -c otelview.yaml # everything else
otelview --print-config # every default, as YAML — the reference

--print-config is the honest source of truth for what a version accepts. Reach for it before writing config from memory.

Configuration

YAML or TOML, decided by the file extension. Every field is optional, so a config only needs what differs from the defaults:

yaml
receivers:
grpc: { enabled: true, listen: "0.0.0.0:4317" }
http: { enabled: true, listen: "0.0.0.0:4318" }
auth:
header: x-otelview-token # metadata key / HTTP header
token: sekret # unset = ingest is open
protect_api: false # also require it on the query API
storage:
backend: duckdb # memory | duckdb | jaeger | remote
retention: 7d # 36h / 7d / 2w / 1mo; unset keeps forever
retention_sweep_interval: 1h
duckdb:
path: otelview.duckdb # or ":memory:"
ui:
listen: "127.0.0.1:4319"
cors: true
# token: ui-sekret # require a token to use the web UI and API
mcp:
enabled: true # MCP for AI agents, at /mcp on the UI port
path: /mcp
# token: agent-sekret # OTELVIEW_MCP_TOKEN overrides this
log_level: info

ui.listen defaults to 127.0.0.1, so nothing is reachable from another machine until you say 0.0.0.0 — and the moment you do, read Securing it before anything else.

Choosing a backend

BackendUse it when
memoryLocal work, CI, a demo. Bounded ring buffers; gone on restart.
duckdbAnything you want to keep. One file, analytical, fast, embedded.
jaegerTraces already live in a Jaeger v2 remote-storage backend.
remoteAnother otelview holds all three signals; this one is just a face.

duckdb is the default answer. It is linked statically from the official release binaries, so there is nothing to install, and one file holds everything — back it up by copying it. It is also single-writer: one process may hold the database. A second otelview on the same path, or otelview mcp --storage duckdb while a server runs, will fail to open it.

jaeger keeps traces in an external jaeger.storage.v2.TraceReader backend and puts logs and metrics in a local fallback (memory or duckdb), because that API does not carry them.

remote makes this instance a thin reader of another otelview over gRPC — which is how you give a team a local UI onto a central store, and how otelviews compose:

yaml
storage:
backend: remote
remote:
endpoint: "http://otelview-central:4317"
auth_header: x-otelview-token
auth_token: sekret

Every otelview also serves jaeger.storage.v2.TraceReader plus otelview.storage.v1.{LogReader, MetricReader, Diagnostics} on its gRPC port, so it can back Jaeger v2 as well.

Retention

storage.retention ("36h", "7d", "2w", "1mo") deletes anything older on a sweep every retention_sweep_interval. Unset means keep forever, which on a busy instance means a file that grows until the disk says no.

It is honoured by backends that own their data — duckdb. With memory the ring buffers already bound themselves; with jaeger or remote the storage server behind it manages its own retention, and otelview says so once, loudly, at startup rather than pretending to delete. A bad duration is refused at startup, because a typo that silently keeps everything defeats the point.

Securing it

Three independent doors, which is worth being deliberate about:

DoorOpened byGuarded by
OTLP ingestauth.tokenauth.header (default x-otelview-token)
Web UI + REST APIui.token, or auth.protect_api + auth.tokenthat header, or Authorization: Bearer
MCP endpointmcp.token → ui.token → auth.tokenthe same, plus an Origin check

The MCP token falls back through that chain, so locking the UI locks MCP with the same key — there is no second setting to forget. OTELVIEW_MCP_TOKEN overrides it, which is how to keep the secret out of the config file:

sh
OTELVIEW_MCP_TOKEN=$(openssl rand -hex 32) otelview -c otelview.yaml

Two refusals are built in rather than left to the operator: serving MCP on a non-loopback address with no token fails at startup, and an MCP request carrying a browser Origin from anywhere but loopback is rejected (the DNS-rebinding mitigation — without it a web page could read a local instance). Set mcp.enabled: false to remove the endpoint entirely.

Telemetry is not innocuous: spans and logs carry URLs, user ids, SQL and whatever an exception message happened to include. Treat an open 0.0.0.0:4319 as publishing it. Put TLS in front (a reverse proxy) for anything crossing a network you do not own — otelview speaks plain HTTP itself.

Deploying

Docker — the image is ghcr.io/tsirysndr/otelview, multi-arch:

sh
docker run -p 4317:4317 -p 4318:4318 -p 4319:4319 \
-v otelview-data:/data ghcr.io/tsirysndr/otelview --storage duckdb

Inside a container, ui.listen must be 0.0.0.0:4319 to be reachable from outside it — which is exactly when to set a token. Keep the DuckDB file on a volume, or a restart is a fresh start.

systemd — one binary, no working directory to speak of. Give it a user, a WorkingDirectory where the DuckDB file lives, Restart=always, and the token via Environment= or EnvironmentFile=.

Nix — nix run github:tsirysndr/otelview, or install the flake; binaries come from the otelview cachix cache, so nothing compiles.

Package managers — Homebrew, APT (apt.fury.io/tsiry), DNF (yum.fury.io/tsiry), bun/npm, or the install script. The desktop app (Tauri) ships alongside and points at any remote otelview API.

Sizing

From the benchmarks on the DuckDB backend, on a laptop: ~400k spans/s and ~600k logs/s ingested, trace search in single-digit milliseconds, an attribute search across a million spans in tens of milliseconds, and a retention sweep at ~2M rows/s. Reads do not queue behind ingest: writes serialize on one connection while queries run on a pool of their own.

In practice the constraints are disk (JSON attributes on every row; set retention) and the sampled analytics (service_stats, service_graph and field discovery read up to 250 recent traces per request, which is what keeps them fast and what makes them a sample rather than a count).

When something is off

  • "binding OTLP HTTP receiver to 0.0.0.0:4318" — the port is taken, very

often by another otelview. Change the listen, or disable that receiver with enabled: false. The first server task to fail takes the process down by design, so one bad port stops everything.

  • DuckDB will not open — another process holds it. One writer per file.
  • The UI loads but is empty — nothing is arriving. Check /api/stats, then

the sender: that is the otelview-instrument skill.

  • `401` on ingest — the sender is not sending auth.header. On the API,

ui.token or protect_api is set and the browser or client has no token.

  • "storage.retention is set but this backend does not own its data" — a

jaeger or remote backend cannot delete on your behalf. Configure retention where the data actually lives.

  • The desktop app cannot reach the API — ui.cors must be true for a

non-browser origin, and the address must not be loopback-only if the app is on another machine.

  • Config rejected at startup — unknown fields are refused rather than

ignored, so a typo names itself. --print-config shows the accepted shape.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
1
7-day trend score
3

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/tsirysndr/otelview-skills/otelview-operate/badge)](https://verified-skill.com/skills/tsirysndr/otelview-skills/otelview-operate)

Something wrong with this skill or its page? Tell us.