Add provisioned Grafana dashboard for Yealink IP phones

Phones are ~99% of this Loki's log volume and nothing surfaced them. Adds a
file-provisioned dashboard (uid yealink-phones, folder "Network") plus the
provider config and the two grafana bind mounts it needs.

Built against a 24h baseline of real handset traffic; all 14 panel queries were
executed against live Loki before commit. Three findings shaped it, each of
which contradicts the obvious reading of the data:

- severity=emergency is NOT an emergency. All 24 emergency lines are the phone
  printing its own log-level table at boot ("sys log :type=1,E=3,W=4,N=5,I=6,D=7")
  — Yealink emits its logging config at level 0. Alerting on it would be 100%
  false positive. Filtered out.
- "LSYS<3+error> rtpcap get len not enough" is 467 of 830 error lines (56%) — a
  noise floor, not a fault. Excluded from every "actionable" panel.
- The hostname label cannot identify a device: its values are Yealink subsystems
  (sua, GUI, sys, cfg, ipp, dev, WEB, ATP), because the phones put the subsystem
  in the RFC3164 HOSTNAME field. Everything keys on source_ip. Yealink lines are
  separated from switch/router traffic on the same Loki by the |~ "<[0-7][+]"
  module marker (26,450 Yealink vs 33 non-Yealink lines in the baseline).

Thresholds are seeded from measured 24h counts: check passwd err 21 (auth),
data_task schedule time out 117 (handset scheduler overrunning its 30s
threshold — the best "phone is unwell" proxy), tftp/provisioning failures 3,
Register: update server 175 (SIP beat, 120s period), DHCP lease 9.

Caveat: only two handsets report today, so thresholds are baselined on a
2-phone sample and want revisiting once the fleet is onboarded.

Dashboards are file-provisioned, so UI edits are not persisted — change the
JSON here and redeploy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 15:53:11 +03:00
co-authored by Claude Opus 4.8
parent 9809cddbdf
commit 13b1887a16
3 changed files with 559 additions and 0 deletions
@@ -0,0 +1,17 @@
apiVersion: 1
# Loads every dashboard JSON from /var/lib/grafana/dashboards (bind-mounted from
# this repo's logging/grafana-dashboards/). Dashboards are file-provisioned, so
# they are recreated on every container start and edits made in the UI are not
# persisted — change the JSON in git and redeploy instead.
providers:
- name: 'logging-dashboards'
orgId: 1
folder: 'Network'
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: false