Everything the Virtual Registry measures leaves through one OpenTelemetry pipeline, configured under otel and either pushed to an OTLP collector or served on a Prometheus scrape endpoint. Varnish counters, the Supervisor’s own metrics and, where it is enabled, the Artifact Firewall’s all arrive together under the same service.name.
Two intervals govern the cadence, and they are independent. scrape_interval (10 seconds by default) is how often Varnish counters are polled. export_interval (60 seconds) is how often they are pushed, and it has no effect on the Prometheus exporter, where the scraping server sets the pace.
Every varnishstat counter is exported, renamed to follow the OpenTelemetry conventions, which mostly means moving what varnishstat puts in the counter name into attributes. MAIN.cache_hit becomes varnish.main.cache.hits, and the per-backend counters collapse into one metric carrying a backend.name attribute rather than one metric per backend.
The full mapping from varnishstat name to exported name is in the varnish-otel metric reference, and important metrics picks out the ones worth alerting on.
Request histograms, traces and logs come from the transaction stream rather than the counters, so they are not bound to scrape_interval.
Varnish accounting counts each request against a namespace and a key, and the Virtual Registry sets the key to the request’s package type. Requests and bytes, hits and misses are therefore broken down by ecosystem without any configuration, on the varnish.accounting.* metrics, with accounting.key naming the type:
sum by (accounting_key) (rate(varnish_accounting_client_hits[5m]))
Two namespaces are used, on the accounting.namespace attribute. Package traffic is counted in default. The service endpoints /healthz, /readyz and /purgez are counted in other, so probe traffic does not distort the request rate.
The Supervisor reports on itself under the supervisor scope:
| Metric | Type | Description |
|---|---|---|
supervisor_uptime_seconds |
gauge | Seconds since the Supervisor started. |
supervisor_services_running |
gauge | Number of managed services currently running. |
supervisor_memory_usage_bytes |
gauge | Memory used by the Supervisor process itself, not by Varnish. |
supervisor_goroutines |
gauge | Goroutines in the Supervisor process. |
supervisor_alert_level |
gauge | Current alert level per managed service. Attributes: service, level_name. |
Reported when ACME is configured, under the acme scope:
| Metric | Type | Description |
|---|---|---|
acme_certificate_count |
gauge | Certificates currently held. |
acme_certificate_expiry_seconds |
gauge | Seconds until a certificate expires. Attribute: domain. |
acme_certificate_renewals_total |
counter | Renewals performed. Attributes: domain, status. |
acme_renewal_errors_total |
counter | Renewals that failed. Attribute: domain. |
acme_renewal_duration_seconds |
histogram | Time taken by a renewal. |
acme_validations_total |
counter | Challenge validations attempted. Attributes: domain, status. |
acme_validation_duration_seconds |
histogram | Time taken by a challenge validation. |
acme_certificate_expiry_seconds is the one to alert on. A renewal that keeps failing shows up there long before the certificate actually expires, whereas acme_renewal_errors_total also rises for a transient failure that the next attempt recovers from.
The Grafana tutorial sets up a Prometheus and Grafana stack against a Virtual Registry and imports a dashboard built on these metrics.