Monitoring
Relic exports Prometheus metrics, OpenTelemetry traces and structured logs.
deploy/observability/ holds seven Grafana dashboards and the alert rules,
which the Helm chart and the Compose stack can install: see
Kubernetes: Monitoring and
Compose: Observability profile.
Settings are in the configuration reference.
Metrics
The server and the worker serve /metrics on a separate port
(RELIC_METRICS_LISTEN_ADDRESS, default :8091), never on the API port. It has
no authentication: keep it inside your network. RELIC_PROFILING_ENABLED=true
adds Go's profiler at /debug/pprof/ on the same port.
Series start with relic_; the metrics reference
lists them. They cover:
| Area | Series |
|---|---|
| HTTP | per API family (relic, packages, container-registry, scanning, access, releases, evidence, ui, health), route, method and status class |
| Relic API | per service, method and Connect code |
| Auth | sign-in attempts, issued tokens, LDAP operations |
| Artifacts | uploads and downloads by format, repository class and source (local, cache, upstream); remote upstreams and cache results |
| Storage and database | object storage operations; the database pool and query latency by query name |
| Background work | jobs by kind and queue, Relic Scan, garbage collection, the trash can, replication, builds and releases |
| Inventory | counted every five minutes: repositories, stored and unreferenced bytes, blobs, users, builds, findings by severity, CVE feed ages |
Labels never hold a user, path, digest, token or address.
RELIC_METRICS_REPOSITORY_LABEL=true adds the repository name to the artifact,
upstream, cache and replication series.
Traces
Set OTEL_EXPORTER_OTLP_ENDPOINT (OTLP over HTTP) to trace every request
except health probes, down to database, object storage, upstream and LDAP calls.
Queued jobs get a span linked to the request. Relic honours and forwards
traceparent.
OTEL_TRACES_SAMPLER sets which traces are kept. The Helm chart keeps 10% of new
traces and follows a traced caller; Compose keeps all.
Logs
Relic writes JSON lines to stderr at RELIC_LOG_LEVEL; RELIC_LOG_FORMAT=text
suits a terminal. OTEL_LOGS_EXPORTER=otlp also sends records over OTLP.
- Request lines carry
request_id, also returned asX-Request-Id, and, when traced,trace_idandspan_id. - A request still running after 10 seconds logs a
slow requestwarning. - A failed telemetry export logs
telemetry export failedand counts inrelic_telemetry_errors_total.
Dashboards
| Dashboard | Shows |
|---|---|
| Relic / Overview | traffic, errors and latency per API family, saturation, logs by request or trace ID |
| Relic / Packages and repositories | uploads and downloads by format, cache hit ratio, upstream latency and errors, builds and releases |
| Relic / Storage and garbage collection | stored and unreferenced content, object storage operations, garbage collection, the trash can |
| Relic / Relic Scan | backlog, scan stages, findings, blocked downloads, database and feed ages |
| Relic / Jobs and worker | jobs by kind, queues, push replication |
| Relic / Database | the connection pool and the slowest queries |
| Relic / Go runtime | CPU, memory, goroutines, garbage collection |
Each has datasource, namespace and instance variables. A latency panel's
exemplar opens its trace in Tempo.
Alerts
| Alert | Fires when | Severity |
|---|---|---|
| RelicDown | no server has been scraped for 5 minutes | critical |
| RelicHighErrorRate | over 5% of an API family's requests answer 5xx for 10 minutes | critical |
| RelicDownloadLatencySLO | downloads burn the "99% within 2 s" budget fast (1 hour) or slowly (6 hours) | critical / warning |
| RelicUpstreamErrors | over 20% of a format's upstream requests fail for 15 minutes | warning |
| RelicDBPoolExhausted | every database connection is in use and requests wait, for 10 minutes | warning |
| RelicJobBacklog | a job kind's oldest job has waited over 30 minutes | warning |
| RelicScanBacklog | the scan backlog grows for an hour, or the vulnerability database is over 3 days old | warning |
| RelicCVEFeedStale | a CVE feed is older than 3 times its refresh interval | info |
| RelicGCFailing | no garbage collection run succeeded in 6 hours | warning |
| RelicReplicationFailing | a repository's last 3 replication runs failed | warning |
| RelicStorageErrors | over 1% of object storage operations fail for 10 minutes | critical |
| RelicContentIntegrity | stored content is missing or does not match its checksum | critical |
| RelicDiskSpaceLow | under 10% of a single node's volume is free for 15 minutes | warning |
| RelicServerCertificateExpiring | the server's certificate expires within 14 days | warning |
Runbooks
Each alert links to its section below.
RelicDown
- Check the pods or containers:
kubectl get pods -l app.kubernetes.io/component=serverordocker compose ps relic-server. - A server in a restart loop usually cannot reach PostgreSQL or object storage, or cannot apply a migration. Read its last log lines.
- If it runs, check that Prometheus reaches port
8091and that the ServiceMonitor selects the Service.
RelicHighErrorRate
- On Relic / Overview, find the failing routes in 5xx ratio and Slowest routes, and open an exemplar's trace.
- Filter the log panel by the trace ID; the
errorfield names the cause. - If RelicDBPoolExhausted or RelicStorageErrors fire, start there.
RelicDownloadLatencySLO
Critical burns the budget fast (1 hour of data); warning burns it slowly (6 hours).
- On Relic / Packages and repositories, check whether slow downloads come from remote repositories (upstream latency) or local ones.
- On Relic / Storage and garbage collection, check
getlatency. - On Relic / Database, check pool waits and slow queries.
RelicUpstreamErrors
Relic still serves cached content.
- Check that the upstream answers from Relic's network: egress, proxy, DNS.
- While an upstream is down, you can set its remote repositories offline.
RelicDBPoolExhausted
- On Relic / Database, find the queries holding connections in Time spent by query.
RELIC_DATABASE_STATEMENT_TIMEOUTcuts long queries. Check PostgreSQL locks and I/O on the CloudNativePG dashboard.- Add server replicas, or raise
RELIC_DATABASE_MAX_CONNECTIONS(default 20). Replicas × pool size, plus the worker's pool, must fit PostgreSQL'smax_connections.
RelicJobBacklog
- Check that a worker runs (
relic_build_info{component="worker"}). - On Relic / Jobs and worker, check which kinds wait and whether they fail.
- Long scans occupy the scan queue. Add worker replicas if the backlog grows.
RelicScanBacklog
The cause label says which condition fired.
- Backlog: see Relic / Relic Scan. Each worker runs at most two scans at a time. Add worker replicas, or check the worker logs for scan failures.
- Old database: the worker updates it every 12 hours, which needs outbound
access or, air-gapped, an imported archive. Check the
scan_dbjob's errors on the System page.
RelicCVEFeedStale
- The hourly
cve_refreshjob reads the EPSS and KEV feeds; its last error is on the System page. - Air-gapped sites point
RELIC_CVE_EPSS_URLandRELIC_CVE_KEV_URLat a generic repository. Update the files there.
RelicGCFailing
- The
gcjob's error is on the System page and in the worker's logs. - Usually object storage refuses deletes (credentials or bucket policy). See RelicStorageErrors.
RelicReplicationFailing
- The last error is on the repository's replication page.
- Check the target's URL and credentials, and that the worker reaches it.
RelicStorageErrors
Uploads and downloads fail with these operations.
- On Relic / Storage and garbage collection, check which operations fail.
- Check the S3 endpoint (SeaweedFS pods or the provider's status), the credentials and free space.
RelicContentIntegrity
Relic refuses to serve missing or damaged content until it is restored.
- A read logs
stored content is missingorstored content does not match its checksum, with the SHA-256, repository and path. - Run the storage check and print its report, which lists each missing or
damaged object:
relic storage check --wait - Upload the file again with any client; Relic replaces the stored object.
- If many objects are affected, check the store: a lost volume, a lifecycle
rule deleting from
artifacts, or a restore from an older backup.
RelicDiskSpaceLow
The volume holds the SQLite database (volume="database") or the filesystem
object store (volume="object_storage"). Writes fail when it fills.
relic_db_sqlite_file_bytesis the database's share; the rest is content.- Empty the trash and lower
RELIC_TRASH_RETENTION; garbage collection then reclaims unreferenced content afterRELIC_GARBAGE_COLLECTION_GRACE_PERIOD. - Grow the volume (in Helm,
data.sizeon an expandable storage class), or move to S3 and PostgreSQL withrelic server database copy.
RelicServerCertificateExpiring
source="operator" is your certificate (RELIC_TLS_CERTIFICATE_FILE,
RELIC_TLS_KEY_FILE); source="generated" is one Relic issued.
- Renew your certificate and replace the files; the server reloads them without a restart.
- With cert-manager, check the Certificate's status and the issuer's events.
- Relic renews a generated certificate 30 days before expiry. If the alert
fires for one, the server cannot write
RELIC_TLS_DIRECTORY: check the logs and its permissions.