Monitoring and notifications¶
dzo is built to be watched from another machine: Prometheus scrapes metrics, Icinga checks a status endpoint, and Discord gets notifications.
The exporter¶
dzo-exporter.service serves
GET /metricsin Prometheus format,GET /statusandGET /status/<instance>as JSON for Icinga.
It listens on :9464 over plain HTTP by default. It exposes no secrets and no
player IP addresses.
exporter:
listen: ":9464"
tls:
cert_file: /etc/dzo/tls/cert.pem # default: empty (plain HTTP); with key_file
key_file: /etc/dzo/tls/key.pem # default: empty
client_ca_file: /etc/dzo/tls/ca.pem # default: empty; set for mutual TLS (needs cert_file)
allow: ["192.0.2.0/24"] # default: none = every address; otherwise a CIDR allow-list
bearer_token_file: /var/lib/dzo/secrets/exporter.token # default: empty = no token
Certificates are reloaded without restarts. Replace the files (for example
from a certbot or lego deploy hook) and run
systemctl --user reload dzo-exporter, or just wait: changed files are picked
up automatically. Game servers are never involved, so a certificate change never
restarts a server. An invalid new certificate is rejected and the old one stays
active.
Run it with dzo exporter (the unit does that). It answers from a snapshot that is
refreshed every 15 seconds in the background, so a scrape never waits for a game
server; the expensive values, the size of the cache and the mission drift count, are
refreshed every 10 minutes. dzo status [<instance>] [--json] prints what the
exporter would report, and dzo status --write /run/dzo/status also writes the
local status files, one per instance, for debugging.
What it reads: systemd (ActiveState, restart count, start time), podman (the
container’s health), the Steam query on the instance’s query port (players, round
trip), the manifest and the failed-render gate of the instance (last render), the
snapshot index (backups) and the Steam login status. The restart counter is
systemd’s own, reported as reason="all": the reasons crash, health,
scheduled, update and manual are not told apart yet. In-game metrics from
MetricZ are not included.
Main metrics¶
Metric |
Meaning |
|---|---|
|
server running and answering |
|
|
|
players online |
|
restarts by |
|
0 when the last render failed |
|
managed mission files changed outside dzo |
|
mod updates waiting for a restart |
|
complete snapshots |
|
time of the newest snapshot per reason |
|
size of the archive of rotated profile logs |
|
large files in |
|
a new server build is available (manual upgrade needed) |
|
0 when a Steam login is needed |
|
disk usage |
Icinga¶
Install the dzo package on the Icinga host or satellite as well. It provides
monitoring plugins that follow the usual OK/WARNING/CRITICAL/UNKNOWN rules:
# everything dzo knows about one instance, with players/uptime/restarts as perfdata
dzo check remote --url https://<game host>:9464/status --instance deerisle
# global checks
dzo check remote --url https://<game host>:9464/status --updates
dzo check remote --url https://<game host>:9464/status --steam
dzo check remote --url https://<game host>:9464/status --disk
# the game server itself, independent of dzo
dzo check a2s <game host>:8716
Icinga 2 CheckCommand definitions and example services are shipped in
/usr/share/doc/dzo/examples/icinga2/.
Discord¶
Configure a default webhook and, optionally, named webhooks with event filters
in /etc/dzo/config.yaml. Each instance uses the default unless its
notify.discord lists other targets ([] disables notifications).
Events include mod updates, available server builds, restarts, health changes, crash loops, failed renders, mission drift, Steam login required, and failed jobs. Bursts are combined into one message (“12 mods updated, 3 servers restarting”).
No Discord message pings anyone: dzo sends allowed_mentions: {parse: []}, so a player name or a
chat line with @everyone in it shows as text. The webhook calls have a timeout of 10 seconds.
The killfeed, which posts the kills of a game server, is a separate setting of the instance
(killfeed, see Configuration) and uses the same webhooks. Give it its own webhook for
the public channel; notify.discord stays for the operator.
dzo notify test [--target admins]
Logs in Loki¶
dzo does not ship logs itself. It writes them to stable places that a log agent (Grafana Alloy, promtail, vector) can collect:
journald:
dzo-<name>.service(server console) anddzo-*jobs, as structured JSON withinstance,jobandeventfields.
For the game’s own logs we recommend the dzo_logz mod together with a Loki installation, so that the logs are searchable and kept for as long as you want. This is a setup you do yourself:
install and configure the dzo_logz mod as described on its Workshop page;
run Loki (with the retention and disk space that the log volume needs) and a log agent that ships the mod’s log files, plus the journald logs above, to it.
dzo does not configure the mod, does not generate any agent or Loki configuration, and does not read these logs.
Operator jobs (update check, download, render, restart) can also be exported as OpenTelemetry traces if an OTLP endpoint is configured.