Health, metrics, logs and build identity
Viking exposes telemetry without requiring an observability backend. Administrators connect a scraper, log collector and dashboards from their platform. Admin listeners are unauthenticated and must remain inside the trusted network. Monitoring is not proof that every page renders correctly.
Endpoints and what readiness means
| Component | Default listener | /healthz |
/readyz |
/metrics |
|---|---|---|---|---|
| Frontend | :8081 |
Process alive | Root resolves to a readable directory | Frontend HTTP registry |
| CMS | :8081 |
Process alive | Writable private project, readable project metadata, usable auth manager | CMS HTTP/publish registry |
| Controller | :8080 |
Ping | Ping | Controller-runtime registry |
The controller's probes are pings; they do not aggregate Website health or prove
leader status, successful reconciliation, storage binding or publication.
Frontend readiness does not require an index.html at /; a readable release
directory can still give a homepage 404. CMS readiness does not verify every
page or guarantee the next publication will have enough disk space.
Standard probes return JSON and Cache-Control: no-store, for example
{"status":"ready","version":"dev"}. Use HTTP status for success/failure;
CMS/frontend unavailable readiness is 503. Health status is ok, successful
readiness status is ready. Errors can include an error string. The optional
controller --health-probe-addr listener uses the native probe format instead
of this JSON but still carries the Viking Server header.
To inspect a CMS without exposing admin ports, run from a workstation:
kubectl port-forward -n websites-example deployment/example-cms 18081:8081
In another terminal, use curl -i http://127.0.0.1:18081/readyz or
curl http://127.0.0.1:18081/metrics; stop forwarding with Ctrl+C. Use a
frontend Deployment instead for frontend telemetry, and forward port 8080
for controller telemetry. Forwarding one Deployment selects one pod, not an
aggregate across replicas.
Metrics
| Component | Metric | Meaning |
|---|---|---|
| Frontend | http_requests_total{method,code} |
Completed public requests |
| Frontend | http_request_duration_seconds |
Request duration histogram |
| Frontend | http_response_size_bytes |
Response size histogram |
| Frontend | http_requests_in_flight |
Concurrent public requests |
| CMS | http_requests_total{method,code} |
Requests reaching API/editor instrumentation |
| CMS | http_request_duration_seconds |
Duration of those instrumented requests |
| CMS | publish_total{result} |
Publish attempts, success or error |
| CMS | publish_duration_seconds |
Publish duration histogram |
| CMS | current_release{release} |
1 for the currently recorded active release |
| Controller | controller_runtime_*, process/Go metrics |
Runtime reconciliation/queue and process telemetry; inspect the running endpoint for exact series |
Histograms expose _bucket, _sum and _count samples. Frontend/CMS method
labels use only GET, HEAD, POST, PUT, DELETE, PATCH, OPTIONS and OTHER. They do
not use request URLs or Host as labels. Add namespace/site labels in your
scrape configuration instead of assuming they are intrinsic application labels.
Use API counters for requests that reach the editing API; use ingress and
identity-provider logs to investigate authentication attempts and login failures.
Admin scrapes sit outside ordinary public/API counters. publish_total measures
publication attempts; track rollback activity through release status and logs.
Both CMS and frontend use generic HTTP metric names: retain a distinguishing job/component/site label when querying. Scrape each desired pod's internal port using your platform's discovery configuration and monitoring resources. Configure alerting for sustained failed readiness, restarts, reconciliation errors, failed publishing and storage capacity through your existing monitoring stack. Choose thresholds from your workload.
Running application version
The editor shows the CMS version; authenticated GET /api/version returns
{"version":"dev"} for an unstamped build. Standard health JSON also includes
version. Every listener returns Server: Viking <Component> <version>:
CMS, Frontend or Controller, followed by the binary's build-stamped version.
This includes successful and rejected requests, OAuth redirects, metrics,
probes and unknown paths. A site content release such as 000003 and a theme
version such as 1.0.0 are different identifiers.
Check the running image's header, health response or API value when verifying an upgrade. The editor displays the backend version; image tags and the editor's package version are separate identifiers.
Ingress/reverse proxies must preserve the upstream Server header. If an external response advertises a proxy or library, compare a direct response to determine whether the proxy is replacing the upstream header. Configure the proxy to preserve the component identity.
Logs and issue evidence
CMS and controller use JSON production logs; frontend writes JSON access logs to stdout and operational logs to stderr. Access records include method, path, status, duration and other component-specific fields. CMS API logs do not represent every authentication response for the same layering reason as metrics. Use Kubernetes container logs and ingress/provider logs together for login issues.
Frontend --trust-proxy enables forwarded client addresses only when every
request comes through a trusted proxy which replaces client-supplied forwarding
headers. The CMS does not expose that frontend flag. Never enable proxy trust
on a publicly reachable pod merely to improve log addresses.
When escalating, capture component/version, Website namespace/name, time, request path/status, release ID and sanitized relevant logs. Do not include session cookies, access tokens, Secret data or database passwords. Storage snapshots and published-release history require separate retention from logs; see backup/restore.
