unkin-agent 09f8fcd83d
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
Split CI into pre-commit/test/build workflows for branch protection
Branch protection on this repo will require the contexts
ci/woodpecker/pr/pre-commit, ci/woodpecker/pr/test and
ci/woodpecker/pr/build, mirroring the node-lookup workflow layout.

- Adds .woodpecker/pre-commit.yaml running pre-commit via uvx
- Adds .pre-commit-config.yaml mirroring node-lookup (vendored
  web/static assets excluded)
- Adds .woodpecker/test.yaml with vet + gofmt check + race tests
- Reworks build.yaml to compile via make build plus the existing
  buildx dry-run image check, PR events only
- Renames docker.yaml to release.yaml per node-lookup convention
  (tag-driven docker release unchanged)
2026-08-23 16:44:19 +10:00

logviewer

Web UI for the ClickHouse log store (logs.raw). Single Go binary with an embedded Bootstrap 3 + jQuery UI — no CDN assets, no build step.

logviewer does no authentication itself. It runs behind oauth2-proxy at logviewer.unkin.net; the proxy is the auth boundary. Query safety relies on the readonly ClickHouse user (logreader) plus server-side guardrails:

  • Time bounds are always enforced. Missing since/until default to a 15m window ending now; windows wider than 72h (the table TTL) are rejected. No request can scan the store unbounded.
  • Everything is parameterized (ClickHouse param_* bound parameters) except the explicit raw sql fragment, which is parenthesised and ANDed into the outer query — the enforced time bounds and LIMIT still apply, and the readonly user can't write.
  • max_execution_time=30 is set on every query.

Configuration

Env Default
CH_URL http://clickhouse-logs.logging.svc.cluster.local:8123 ClickHouse HTTP endpoint
CH_USER logreader readonly ClickHouse user
CH_PASSWORD (empty) password for CH_USER
LISTEN_ADDR :8080 HTTP listen address

API

  • GET /api/querysince/until (RFC3339, unix, or relative 15m/6h/1d), filters namespace/host/pod/container/app/severity/stream/source, q (space-separated case-insensitive substring terms, all must match), sql (raw WHERE fragment), limit (max 1000) / offset. Newest first.
  • GET /api/tail — same filters plus cursor (exclusive lower bound, unix ms). Returns ascending rows and the next cursor. Stale cursors are clamped to the last 15m.
  • GET /api/facets — top 20 namespaces / apps (labels['app']) / hosts by row count in the window.
  • GET /healthz — ClickHouse ping.

UI

Time-range picker (15m/1h/6h/1d/custom), facet dropdowns, debounced fuzzy search, toggleable raw-SQL box, paged log table with expandable rows (labels/fields), and a Tail mode (1s polling, autoscroll, pauses when you scroll up).

Development

make build   # dist/logviewer
make test    # go test -race ./...
make patch   # tag + push next vX.Y.Z → CI builds+pushes the image

Releases: pushing a v* tag builds the container and pushes it to artifactapi.k8s.syd1.au.unkin.net/docker-internal/logviewer.

S
Description
Web UI for the ClickHouse log store: fuzzy find, tail and SQL-filter logs (logviewer.unkin.net)
Readme 123 KiB
Languages
Go 63.5%
JavaScript 18.4%
HTML 12.2%
Makefile 3.4%
CSS 1.5%
Other 1%