# Recommended LogQL alert rules for plex-language-sync, for Loki's ruler. # Ship the container's logs to Loki and load this file into Loki's ruler. # Firing alerts go through your Alertmanager like any Prometheus alert. # Thresholds and severity labels are starting points. Change the container # selector to the label your log collector sets, such as job or service. groups: - name: plex-language-sync rules: # This rule fires on silence, keyed on the deep scan's completion line. # If DEEP_SCAN_INTERVAL is off, drop it. See docs/monitoring.md. - alert: PlexLanguageSyncDeepScanStalled expr: | absent_over_time({container="plex-language-sync"} |= `deep analysis completed` [26h]) for: 1h labels: severity: warning annotations: summary: "no plex-language-sync deep-analysis heartbeat in 26h" description: > No `deep analysis completed` line has arrived in 26h, usually a stalled deep scan. Missed episodes then get no tracks. Rule out a stopped container or log pipeline, then find the last `scheduled deep analysis starting` line. - alert: PlexLanguageSyncErrorLog expr: | sum by (container) (count_over_time( {container="plex-language-sync"} |= `level=ERROR` [15m] )) >= 3 for: 5m labels: severity: warning annotations: summary: "plex-language-sync emitting repeated ERROR logs" description: > plex-language-sync logged 3 or more ERROR lines in 15m. A bad setting or an unwritable /config ends in a restart loop. A WebSocket that will not reconnect and a failed cache save on shutdown also log ERROR. Read the lines. - alert: PlexLanguageSyncResolutionStalled expr: | sum by (container) (count_over_time( {container="plex-language-sync"} |= `user resolution stalled` [30m] )) > 0 for: 0m labels: severity: warning annotations: summary: "plex-language-sync is attributing no playback to any user" description: > Playback events are skipped, so no language choices are saved. Read the `cause` field. For `sessions_unreadable`, check PLEX_TOKEN admin rights and the server. For `all_clients_absent`, session matching is failing.