Logowanie do journald z poziomu Pythona
Tworząc narzędzia systemowe, daemony lub usługi działające na systemach opartych o systemd
, warto logować zdarzenia bezpośrednio do journald
. Dzięki temu logi trafiają do centralnego dziennika systemowego.
W tym artykule pokażę, jak logować do journald
w Pythonie - zarówno przy użyciu modułu systemd
, jak i standardowej biblioteki logging
z obsługą journald
.
Instalacja modułu systemd-python
Aby korzystać z bezpośredniego API journald, zainstaluj bibliotekę:
Metoda 1: systemd.journal.send()
Najprostszy sposób logowania. Przykład:
from systemd import journal
journal.send("Something happened",
SYSLOG_IDENTIFIER="my_app",
PRIORITY=5)
Parametry:
MESSAGE
- pierwszy argument funkcji, treść logaSYSLOG_IDENTIFIER
- identyfikator źródła logu (np. nazwa aplikacji lub unit file)PRIORITY
- poziom ważności (cyfra od 0 do 7)
Poziomy PRIORITY
:
Liczba | Nazwa | Opis |
---|---|---|
0 | emerg |
Krytyczny - system nie działa |
1 | alert |
Wymaga natychmiastowej reakcji |
2 | crit |
Krytyczny błąd |
3 | err |
Błąd |
4 | warning |
Ostrzeżenie |
5 | notice |
Istotna informacja |
6 | info |
Informacyjny |
7 | debug |
Debugowanie |
Uwaga: PRIORITY
powinno być liczbą, np. PRIORITY=3
, a nie tekstem typu "err"
. Podanie stringa może nie zadziałać.
Odczyt logów w journalctl 🔍
Przykład logowania:
Sprawdzenie logów:
Z filtrowaniem po poziomie:
Wyświetlenie pełnych danych (w tym PRIORITY
):
Metoda 2: standardowy logging
z JournalHandler
W większych aplikacjach Pythonowych zaleca się logowanie przez wbudowany moduł logging
z wykorzystaniem handlera JournalHandler
. Taki sposób:
- umożliwia centralne zarządzanie logowaniem w całej aplikacji,
- pozwala elastycznie dodawać różne backendy logujące (do pliku, stdout, journald, itp.),
- jest zgodny z frameworkami (Django, Flask, Celery, FastAPI itp.),
- daje możliwość konfiguracji zewnętrznej (np. przez plik
logging.conf
lub YAML).
Przykład użycia:
import logging
from systemd.journal import JournalHandler
logger = logging.getLogger("my_app")
logger.addHandler(JournalHandler())
logger.setLevel(logging.DEBUG)
logger.debug("App debug")
logger.info("Info")
logger.warning("Warning!")
logger.error("Error occurred")
logger.critical("Critical failure")
- Domyślnie
SYSLOG_IDENTIFIER
wjournald
to nazwa loggera (my_app
). - W
journalctl
możesz odczytać te logi za pomocą:
Poziomy logowania 🔎
JournalHandler
automatycznie mapuje poziomy logging
na poziomy syslog (PRIORITY
):
logging level |
journald PRIORITY |
Nazwa syslog |
---|---|---|
DEBUG |
7 | debug |
INFO |
6 | info |
WARNING |
4 | warning |
ERROR |
3 | err |
CRITICAL |
2 | crit |
🛑 Nie ma wsparcia dla PRIORITY=1
(alert
) ani 0
(emerg
).
Jeśli potrzebujesz tych poziomów, skorzystaj z journal.send()
.
Dlaczego warto używać logging
+ JournalHandler
w większych aplikacjach?
- ✅ Centralizacja logiki logowania - konfigurujesz raz, działa wszędzie.
- ✅ Elastyczność - możesz dodać dodatkowe handlery (pliki, syslog, e-mail).
- ✅ Zgodność z frameworkami - wiele bibliotek i frameworków Pythona używa
logging
. - ✅ Zewnętrzna konfiguracja - możliwość ładowania ustawień z pliku.
Jeśli Twoja aplikacja to prosty skrypt CLI lub pojedynczy daemon, możesz używać journal.send()
bezpośrednio. Ale jeśli budujesz coś większego - zdecydowanie polecam korzystać z logging
+ JournalHandler
Rozwiązywanie problemów (brak logów) 🛠️
1. Brak logów w journalctl -p emerg
?
Sprawdź, czy:
journal.send("Test", PRIORITY=0) # ✅ poprawnie
journal.send("Test", PRIORITY="emerg") # ❌ NIE zadziała
2. Używaj -t
zamiast -p
do testów
To pokaże logi niezależnie od poziomu.
3. Uruchom jako root (jeśli trzeba)
Niektóre poziomy mogą być pomijane w sandboxie lub przy ograniczonych uprawnieniach:
✅ Podsumowanie
systemd.journal.send()
umożliwia szybkie logowaniePRIORITY
to liczba od 0 do 7- standardowe
logging
można podpiąć do journald journalctl
pozwala filtrować logi po identyfikatorze (-t
) i poziomie (-p
)- do debugowania używaj
-o verbose