{"id":50818306,"url":"https://github.com/mashiro/otelop","last_synced_at":"2026-06-13T11:33:47.669Z","repository":{"id":350695831,"uuid":"1205875553","full_name":"mashiro/otelop","owner":"mashiro","description":"Local OTel viewer for dev loops — single binary, in-memory, browser UI.","archived":false,"fork":false,"pushed_at":"2026-06-09T01:44:44.000Z","size":2270,"stargazers_count":11,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T03:22:42.109Z","etag":null,"topics":["developer-tools","go","logs","metrics","observability","opentelemetry","otel","otlp","react","traces"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mashiro.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-09T11:14:43.000Z","updated_at":"2026-06-08T01:58:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mashiro/otelop","commit_stats":null,"previous_names":["mashiro/otelop"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/mashiro/otelop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mashiro%2Fotelop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mashiro%2Fotelop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mashiro%2Fotelop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mashiro%2Fotelop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mashiro","download_url":"https://codeload.github.com/mashiro/otelop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mashiro%2Fotelop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34283390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["developer-tools","go","logs","metrics","observability","opentelemetry","otel","otlp","react","traces"],"created_at":"2026-06-13T11:33:44.537Z","updated_at":"2026-06-13T11:33:47.658Z","avatar_url":"https://github.com/mashiro.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"frontend/public/favicon.svg\" width=\"80\" height=\"80\" alt=\"otelop\" /\u003e\n\n# otelop\n\nA local OpenTelemetry viewer for traces, metrics, and logs.\nSingle binary, in-memory, browser UI.\n\n[![Go](https://img.shields.io/badge/go-1.26-00ADD8?logo=go\u0026logoColor=white)](go.mod)\n[![React](https://img.shields.io/badge/react-19-61DAFB?logo=react\u0026logoColor=white)](frontend/package.json)\n[![License](https://img.shields.io/badge/license-MIT-black)](LICENSE)\n\n\u003c/div\u003e\n\n---\n\n## What it is\n\n`otelop` runs a local OTLP receiver and shows whatever it gets in a browser. No Docker, no database, no Jaeger/Prometheus/Loki to wire up. Start the binary, point your app at it, open the page.\n\nIt's meant for the loop where you're writing instrumentation and just want to see what came through.\n\n\u003cdiv align=\"center\"\u003e\n\n![otelop trace view](docs/images/trace.png)\n\n\u003c/div\u003e\n\n## Features\n\n- Single binary with the frontend embedded\n- OTLP gRPC and HTTP receivers (built-in OpenTelemetry Collector)\n- Optional OTLP forwarding to one upstream endpoint\n- Traces, metrics, and logs in one UI\n- Live updates over WebSocket\n- GraphQL API at `/graphql`\n- MCP server, so agents can query the same data\n- In-memory ring buffers — no persistence, no setup\n\n## Install\n\nWith Go:\n\n```bash\ngo install github.com/mashiro/otelop/cmd/otelop@latest\n```\n\nWith mise:\n\n```bash\nmise use -g github:mashiro/otelop\n```\n\nWith Docker:\n\n```bash\ndocker run --rm -p 4317:4317 -p 4318:4318 -p 4319:4319 ghcr.io/mashiro/otelop:latest\n```\n\n## Quick start\n\n```bash\notelop start\n```\n\nThis detaches into the background so your terminal stays free. Use `otelop status` to see what it is listening on and `otelop stop` to shut it down. Pass `--foreground` (or `-f`) if you want logs in the current terminal.\n\nThen point your app at it:\n\n```bash\nOTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 your-app\n```\n\nAnd open \u003chttp://localhost:4319\u003e.\n\n### With AI coding agents\n\nAny AI coding agent that supports OpenTelemetry can export to `otelop`, so you can watch the agent's API calls, tool runs, and prompts live. For example:\n\n- [Claude Code](https://docs.claude.com/en/docs/claude-code/monitoring-usage)\n- [Codex](https://developers.openai.com/codex/config-advanced)\n\n## Endpoints\n\n| Port | Purpose |\n|---|---|\n| `4319` | Web UI + GraphQL |\n| `4317` | OTLP gRPC receiver |\n| `4318` | OTLP HTTP receiver |\n\n## Commands\n\n```\notelop start [flags]   # launch in the background (default), or foreground with -f\notelop stop            # stop the background server\notelop status          # show PID, listen addresses, and buffered counts\notelop version\n```\n\n`start` flags:\n\n```\n  --foreground, -f   run in the foreground instead of detaching\n  --http             Web UI listen address           (default :4319)\n  --otlp-grpc        OTLP gRPC receiver endpoint     (default 0.0.0.0:4317)\n  --otlp-http        OTLP HTTP receiver endpoint     (default 0.0.0.0:4318)\n  --proxy-url        upstream OTLP endpoint for forwarding\n  --proxy-protocol   upstream OTLP protocol          (grpc|http)\n  --proxy-auth-type  upstream OTLP auth type         (bearer|basic|headers)\n  --proxy-auth-token upstream bearer token\n  --proxy-auth-username upstream basic auth username\n  --proxy-auth-password upstream basic auth password\n  --proxy-header     upstream header                 (repeatable key=value)\n  --trace-cap        max traces in memory            (default 1000)\n  --metric-cap       max metric series in memory     (default 3000)\n  --log-cap          max log entries in memory       (default 5000)\n  --max-data-points  max data points per series      (default 1000)\n  --log-level        debug|info|warn|error           (default warn)\n```\n\nPID, log, and metadata files live in `$XDG_STATE_HOME/otelop/` (defaults to `~/.local/state/otelop/`).\n\n## Configuration\n\nEvery `start` flag can be set three ways. Higher precedence wins:\n\n1. CLI flag (`otelop start --http :4319`)\n2. Environment variable (`OTELOP_HTTP=:4319 otelop start`)\n3. TOML config file at `$XDG_CONFIG_HOME/otelop/config.toml` (defaults to `~/.config/otelop/config.toml`; override with `OTELOP_CONFIG_FILE=/path/to/config.toml`)\n\nExample `~/.config/otelop/config.toml`:\n\n```toml\nhttp = \":4319\"\notlp_grpc = \"0.0.0.0:4317\"\notlp_http = \"0.0.0.0:4318\"\ntrace_cap = 1000\nmetric_cap = 3000\nlog_cap = 5000\nmax_data_points = 1000\nlog_level = \"warn\"\ndebug = false\n\n[proxy]\nurl = \"https://collector.internal:4318\"\nprotocol = \"http\"\n\n[proxy.auth]\ntype = \"bearer\"\ntoken = \"replace-me\"\n```\n\nThe matching environment variables are `OTELOP_HTTP`, `OTELOP_OTLP_GRPC`, `OTELOP_OTLP_HTTP`, `OTELOP_PROXY_URL`, `OTELOP_PROXY_PROTOCOL`, `OTELOP_PROXY_AUTH_TYPE`, `OTELOP_PROXY_AUTH_TOKEN`, `OTELOP_PROXY_AUTH_USERNAME`, `OTELOP_PROXY_AUTH_PASSWORD`, `OTELOP_PROXY_HEADERS`, `OTELOP_TRACE_CAP`, `OTELOP_METRIC_CAP`, `OTELOP_LOG_CAP`, `OTELOP_MAX_DATA_POINTS`, `OTELOP_LOG_LEVEL`, and `OTELOP_DEBUG`.\n\nWhen proxying is enabled, `otelop` still buffers incoming telemetry locally for the UI and also forwards the same traces, metrics, and logs to the configured upstream OTLP endpoint.\n\n`proxy.auth.type` supports:\n\n- `bearer`: sends `Authorization: Bearer \u003ctoken\u003e`\n- `basic`: sends `Authorization: Basic \u003cbase64(username:password)\u003e`\n- `headers`: sends the exact headers configured under `[proxy.auth.headers]` or `--proxy-header`\n\nDo not embed credentials in `proxy.url`; `otelop` rejects URLs with userinfo such as `https://user:pass@example.com`.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmashiro%2Fotelop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmashiro%2Fotelop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmashiro%2Fotelop/lists"}