Files
janssen/CentralLogging

CentralLogging — centrální logování (Loki + Grafana + FastAPI gateway)

Verze: 1.0 · Datum: 2026-06-08 · Autor: Vladimír Buzalka

Řešení pro sjednocení logů z rozházených skriptů projektu Janssen do jednoho centrálního místa na Unraidu, bez zrušení stávajícího souborového logování. Soubory a centrál běží paralelně; po ~měsíci ověřování se souborové logování vypne jedním přepínačem.


1. Architektura

  ┌────────────────┐     HTTP POST /log/batch      ┌──────────────┐   push   ┌────────┐
  │  Python skript │  ── Bearer token, JSON ──────▶ │ Log Gateway  │ ───────▶ │  Loki  │
  │  (central_     │      (na pozadí, v dávkách)    │  (FastAPI)   │  /push   │ (90 d) │
  │   logging.py)  │                                └──────────────┘          └────┬───┘
  │                │                                                                │
  │  + soubor .log │  (stávající RotatingFileHandler — zatím zůstává)               │
  └────────────────┘                                                          ┌─────▼────┐
                                                                              │ Grafana  │
   Při výpadku gateway → lokální spool .ndjson, přehraje se po obnovení.      │ (dashbrd)│
                                                                              └──────────┘

Proč takhle:

  • Loki — průmyslový standard pro centrální logy, levné úložiště (chunky na Unraid share), retence vynucená automaticky, vizualizace v Grafaně.
  • FastAPI gateway (jako tvůj msgreceiver) — skripty neznají interní detaily Loki ani DB hesla, jen jednoduchý JSON + sdílený token. Backend lze kdykoli vyměnit beze změny skriptů.
  • Klient jen stdlib (urllib) — žádné pip install do desítek skriptů.
  • Neblokující + odolné — emit jen vloží do fronty, odesílá vlákno na pozadí v dávkách; při výpadku spool soubor → žádný log se neztratí.

2. Adresářová struktura

CentralLogging/
├── README.md                       ← tento soubor
├── docker/
│   ├── docker-compose.yml          Loki + Grafana + Gateway
│   ├── loki-config.yml             Loki, retence 90 dní
│   └── grafana-datasource.yml      auto-přidání Loki do Grafany
├── gateway/
│   ├── log_gateway_v1.0.py         FastAPI brána
│   ├── log_gateway_v1.0.md         dokumentace brány
│   ├── requirements.txt
│   └── Dockerfile
└── client/
    ├── central_logging.py          stabilní import shim
    ├── central_logging_v1.0.py     implementace (verze ve jméně)
    ├── central_logging_v1.0.md     dokumentace knihovny
    └── example_usage_v1.0.py       ukázka integrace

3. Nasazení na Unraid

  1. Zkopíruj adresář CentralLogging/ na Unraid (např. do /mnt/user/appdata/central-logging/src).
  2. Uprav cesty volumes v docker-compose.yml (výchozí /mnt/user/appdata/central-logging/{loki,grafana}).
  3. Nastav tajemství (soubor .env vedle compose, NE do gitu):
    LOG_TOKEN=nejaky-dlouhy-nahodny-retezec
    GRAFANA_PASSWORD=silne-heslo
    
  4. Spusť:
    cd docker
    docker compose up -d
    docker compose ps
    
  5. Kontrola:
    • Gateway health: curl http://192.168.1.76:8770/health → očekávané {"status":"ok","loki":"ready",...}
    • Grafana: http://192.168.1.76:3001 (admin / GRAFANA_PASSWORD) → Explore → datasource Loki → dotaz {app="..."}

Porty: Loki 3100 (interní), Grafana 3001 (3000 drží Gitea), Gateway 8770. Uprav, pokud kolidují (msgreceiver běží na 8765).


4. Integrace do stávajících skriptů

Typický skript dnes obsahuje:

import logging
logging.basicConfig(filename=str(LOG_FILE), level=logging.ERROR,
                    format="%(asctime)s | %(message)s",
                    datefmt="%Y-%m-%d %H:%M:%S", encoding="utf-8")

Nahradíš celý blok basicConfig(...) jedním voláním — zbytek skriptu (logging.error(...), log.info(...)) zůstává beze změny:

import sys
sys.path.insert(0, r"U:\PythonProject\Janssen\CentralLogging\client")
from central_logging import setup_logging

log = setup_logging("nazev_skriptu")    # label aplikace v Loki

Konfigurace přes ENV (nebo argumenty setup_logging):

ENV Default Význam
CENTRAL_LOG_GATEWAY http://192.168.1.76:8770 URL brány
CENTRAL_LOG_TOKEN change-this-shared-secret sdílené tajemství (musí sedět s bránou)
CENTRAL_LOG_ENV prod label prostředí
CENTRAL_LOG_KEEP_FILE 1 psát i do souboru (po měsíci → 0)
CENTRAL_LOG_LEVEL INFO min. úroveň

5. Plán migrace (souběh → vypnutí souborů)

  1. Fáze A — souběh (cca 1 měsíc): keep_file=True (default). Logy jdou do souboru i do Loki. Ověřuješ úplnost, ladíš dashboardy, labely, úrovně.
  2. Fáze B — ověření: porovnáš soubor vs. Loki na vybraných skriptech, že nic nechybí (spool funguje i při výpadcích).
  3. Fáze C — vypnutí souborů: nastav globálně CENTRAL_LOG_KEEP_FILE=0 (nebo setup_logging(..., keep_file=False)). Skripty pak píší jen do centrálu. Staré .log soubory přesuň do TRASH/ (nemazat — konvence).

6. Dotazy v Grafaně (LogQL)

{app="parse_emails_graph"}                       # vše z jednoho skriptu
{app="parse_emails_graph", level="ERROR"}        # jen chyby
{env="prod"} |= "bulk_write"                     # fulltext napříč skripty
{app="edc_import"} | json | line > 100           # parsování JSON pole z těla
sum by (app) (count_over_time({level="ERROR"}[1h]))   # počet chyb / skript / h

Labely (nízká kardinalita): app, host, level, env. Vše ostatní (logger, func, line, exc, extra) je v těle řádku jako JSON → v Grafaně dostupné přes | json.


7. Bezpečnost a poznámky

  • Token je sdílené tajemství; drž ho v .env / ENV, ne v gitu.
  • Gateway běží v interní docker síti; ven publikuje jen port 8770. Pokud má být dostupná i mimo LAN, dej před ni reverzní proxy s TLS.
  • Loki má auth_enabled: false (single-tenant, interní). Pro veřejné vystavení přidej autentizaci na proxy.
  • Spool soubory (_log_spool/*.ndjson) vznikají jen při výpadku brány a samy se po obnovení spojení vyprázdní.