À quoi ça sert

Loguru est une lib externe (pip install loguru) avec une philosophie : il existe un seul logger global déjà configuré et coloré, prêt à l'emploi. Tu importes, tu loggues, c'est tout.

python
from loguru import logger

logger.info("démarrage")
logger.warning("attention")
logger.error("raté")

Aucune config, sortie déjà colorée, timestamp inclus. Le contrat est : 1 ligne pour démarrer, 1 ligne par option supplémentaire.

Loguru vs stdlib logging

logging est plus flexible et universel (toutes les libs Python l'utilisent), mais sa config initiale est verbeuse. Loguru est plus simple, mais c'est une dépendance externe et ses paramètres ne sont pas reconnus par les libs tierces. En pratique : Loguru pour ton code, et on intercepte les libs externes pour qu'elles passent par Loguru aussi (voir how-to).

Le concept : sinks

Loguru appelle « sink » (puits) chaque destination où écrire un log : la console, un fichier, un service distant, une fonction Python… Tu en ajoutes autant que tu veux, et chaque sink peut filtrer par niveau et formater à sa manière.

  • 1 sink console est créé par défaut au démarrage.
  • Tu en ajoutes avec logger.add(...).
  • Tu retires le sink par défaut avec logger.remove() si tu veux tout reconfigurer.

Un exemple d'usage

Logger en console et dans un fichier qui tourne tous les jours, garde 7 jours, et compressé en zip :

python
from loguru import logger

logger.add(
    "app_{time:YYYY-MM-DD}.log",
    rotation="00:00",        # nouveau fichier à minuit
    retention="7 days",      # supprime les + vieux que 7 jours
    compression="zip",       # compresse les anciens
    level="INFO",
)

logger.info("prêt")
logger.debug("pas affiché car niveau INFO sur ce sink")

Voilà. En 3 lignes utiles tu as la rotation par date, la rétention, et l'archivage compressé — soit ~50 lignes à écrire en stdlib.

How-to : utiliser Loguru

  1. Installer

    bash
    uv add loguru
  2. Configurer en un point d'entrée

    Au début de ton main.py : on remove le sink par défaut puis on en ajoute deux (console + fichier) avec des niveaux et formats spécifiques.

    python
    import sys
    from loguru import logger
    
    logger.remove()                         # enlève la config par défaut
    
    logger.add(sys.stderr, level="INFO",
        format="<green>{time:HH:mm:ss}</green> <level>{level}</level> {message}")
    
    logger.add("logs/app.log",
        level="DEBUG",
        rotation="10 MB",
        retention=10,                 # garder 10 fichiers
        encoding="utf-8")

    Le format Loguru utilise des balises <color> pour la console, et {name} au lieu du %(name)s de stdlib.

  3. Logger en JSON pour Loki / Elasticsearch

    En prod, on veut souvent du JSON pour pouvoir parser/rechercher. Loguru le fait avec serialize=True :

    python
    logger.add("logs/app.jsonl", serialize=True)

    Chaque ligne devient un objet JSON avec { "text": ..., "record": { "time": ..., "level": ..., "message": ..., "extra": {...} } }, prêt à être ingéré par Loki ou un agent Fluent Bit.

  4. Capturer automatiquement les exceptions

    Le décorateur @logger.catch logge automatiquement toute exception qui sort de la fonction, avec stack trace, sans avoir à écrire un try/except.

    python
    from loguru import logger
    
    @logger.catch
    def traitement(x):
        return 1 / x
    
    traitement(0)   # loggue l'exception en ERROR avec stack trace, n'arrête pas le programme

    Pratique pour les tâches d'arrière-plan où tu veux logger le crash mais continuer à tourner.

  5. Ajouter du contexte avec bind

    On veut souvent enrichir les logs avec une info récurrente : l'ID utilisateur, l'ID de requête, le nom du job… logger.bind() crée un logger « pré-rempli » :

    python
    req_logger = logger.bind(request_id="abc-123", user="olivier")
    req_logger.info("requête traitée")
    # Avec un format qui inclut {extra}, le contexte apparaîtra dans chaque ligne
  6. Intercepter les logs de la stdlib

    Les libs externes (FastAPI, SQLAlchemy, requests…) utilisent logging de la stdlib. Pour qu'elles passent aussi par Loguru, on installe un handler intercepteur au démarrage. Snippet officiel à copier-coller :

    python
    import logging
    from loguru import logger
    
    class InterceptHandler(logging.Handler):
        def emit(self, record):
            try:
                level = logger.level(record.levelname).name
            except ValueError:
                level = record.levelno
            logger.opt(depth=6, exception=record.exc_info).log(
                level, record.getMessage()
            )
    
    logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)

    À partir de là, logging.getLogger("uvicorn").info(...) passe par Loguru et hérite de tes formatages.

  7. Formats temporels et rotations possibles

    rotation et retention acceptent plusieurs syntaxes — un des points forts de Loguru :

    python
    # rotation
    rotation="10 MB"          # par taille
    rotation="1 day"           # par durée
    rotation="00:00"           # à une heure précise
    rotation="monday at 12:00" # par jour de semaine
    
    # retention
    retention="7 days"        # supprimer après 7 jours
    retention=10                # garder 10 fichiers max
    
    # compression
    compression="zip"         # ou "gz", "tar.gz", "bz2"...

Aide-mémoire

python (essentiel)
from loguru import logger

logger.debug("...")
logger.info("...")
logger.warning("...")
logger.error("...")
logger.critical("...")
logger.success("opé OK")              # niveau spécifique Loguru
python (sinks)
logger.remove()                            # reset
logger.add(sys.stderr, level="INFO")
logger.add("app.log", rotation="10 MB",
           retention="7 days", compression="zip")
logger.add("app.jsonl", serialize=True)        # JSON pour Loki
python (extras)
@logger.catch                          # auto-log les exceptions
def f(): ...

logger.bind(user="X").info("action") # contexte
logger.opt(colors=True).info("<green>ok</green>")
python (placeholders dans le format)
"{time:YYYY-MM-DD HH:mm:ss}"
"{level}" "{message}"
"{name}:{function}:{line}"
"{extra}"                          # dict des données bind()

Loguru et le reste de l'écosystème

  • logging (stdlib) — la lib de base de Python. Loguru peut intercepter ses appels (voir how-to) pour que toutes les libs externes passent par lui.
  • Loki — combo classique : Loguru écrit en JSON (serialize=True), un agent (Promtail, Fluent Bit) lit le fichier, l'envoie à Loki, et Grafana affiche.
  • FastAPI — on intercepte les logs uvicorn et fastapi pour les unifier avec Loguru. Combiné avec un middleware qui appelle logger.bind(request_id=...), on a des logs corrélés par requête.
  • Celery — même chose : on intercepte le logger Celery pour que les logs de tâches sortent au même format que le reste.
  • Prefect — Prefect a son propre système de logs intégré à son UI ; on garde Loguru pour le code métier à l'intérieur des tâches.
Quand préférer stdlib à Loguru

Trois cas où la stdlib reste plus adaptée : 1) une lib ou un framework que tu publies (ne pas imposer Loguru à tes utilisateurs), 2) des envs contraints qui interdisent les dépendances (CI minimal, lambdas custom), 3) un projet d'équipe où la convention est déjà stdlib. Partout ailleurs, Loguru gagne le ratio confort/coût.

Pour aller plus loin