logging.config.dictConfig centraliza a configuração de logs em um dicionário. Em vez de cada módulo criar handlers e formatos próprios, a aplicação define destinos, níveis e política de propagação uma vez. Isso reduz mensagens duplicadas e facilita mudar o comportamento entre desenvolvimento e produção.

Este artigo aprofunda o guia de logging em Python. Bibliotecas devem apenas emitir eventos com logging.getLogger(__name__); a aplicação é responsável por configurar a saída.

Configuração mínima com console

import logging
from logging.config import dictConfig

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "standard": {
            "format": "%(asctime)s %(levelname)s %(name)s %(message)s",
        },
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "standard",
            "level": "INFO",
        },
    },
    "root": {"handlers": ["console"], "level": "INFO"},
}

dictConfig(LOGGING)
logger = logging.getLogger(__name__)
logger.info("aplicação iniciada")

version é obrigatório e atualmente vale 1. Manter disable_existing_loggers como False evita silenciar loggers criados por bibliotecas antes da configuração. Ajuste o nível no handler e no logger conscientemente: ambos podem filtrar mensagens.

Loggers por módulo e propagação

"loggers": {
    "minha_app.db": {
        "level": "WARNING",
        "handlers": [],
        "propagate": True,
    },
    "urllib3": {
        "level": "WARNING",
        "handlers": [],
        "propagate": True,
    },
}

Um logger com propagate=True envia o registro aos ancestrais. Se ele também tiver um handler equivalente, a mensagem pode aparecer duas vezes. Concentre os handlers no logger raiz quando todos os módulos usam os mesmos destinos.

Rotacione arquivos sem crescer indefinidamente

"handlers": {
    "file": {
        "class": "logging.handlers.RotatingFileHandler",
        "filename": "logs/app.log",
        "maxBytes": 10_000_000,
        "backupCount": 5,
        "encoding": "utf-8",
        "formatter": "standard",
        "level": "INFO",
    },
}

Crie o diretório antes de configurar. Em contêineres e plataformas gerenciadas, normalmente é melhor escrever no console e deixar a infraestrutura coletar e rotacionar. Não dependa de arquivo local para auditoria persistente sem entender o ciclo de deploy.

Inclua contexto sem montar frases manualmente

logger.info(
    "pedido processado",
    extra={"request_id": request_id, "pedido_id": pedido.id},
)

Adicione os campos ao formatter quando usar a biblioteca padrão. Garanta que toda mensagem tenha esses atributos ou use um filtro que forneça defaults, caso contrário a formatação falhará. Nunca registre senha, token, cookie de sessão ou dado pessoal desnecessário.

Configure uma vez e teste

Chame dictConfig no ponto de entrada, antes de criar workers. Reconfigurações repetidas tornam o comportamento difícil de prever. Em testes, pytest e caplog podem observar eventos sem depender do arquivo final; veja como testar logs com caplog.

Valide níveis por ambiente, ausência de duplicação, encoding e rotação. Gere um erro com logger.exception() dentro de except para confirmar o traceback. Verifique também que segredos sejam removidos antes do evento chegar ao handler.

A referência oficial de logging.config, consultada em 28 de julho de 2026, define o schema aceito por dictConfig e os erros de configuração.