| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- import logging
- from logging.config import dictConfig
- import os
- import re
- from logging.handlers import RotatingFileHandler, HTTPHandler
- class StripAnsiFormatter(logging.Formatter):
- """Formatter that strips ANSI escape sequences from formatted log text."""
- ANSI_RE = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]")
- def format(self, record):
- text = super().format(record)
- return self.ANSI_RE.sub("", text)
- def setup_logging(app):
- """Configure logging: console, optional file and external HTTP handler.
- Controlled by env vars:
- - LOG_FILE: path to write rotating logs
- - LOG_MAX_BYTES: max bytes per file (default 10MB)
- - LOG_BACKUP_COUNT: number of backups (default 5)
- - EXTERNAL_LOG_URL: if set, an HTTPHandler will POST logs to this URL
- """
- level = logging.DEBUG if app.config.get("DEBUG") else logging.INFO
- handlers = {
- "console": {
- "class": "logging.StreamHandler",
- "formatter": "default",
- "level": level,
- }
- }
- root_handlers = ["console"]
- log_file = os.getenv("LOG_FILE")
- if log_file:
- # ensure parent dirs exist
- dirname = os.path.dirname(log_file)
- if dirname:
- os.makedirs(dirname, exist_ok=True)
- handlers["file"] = {
- "class": "logging.handlers.RotatingFileHandler",
- "formatter": "file",
- "level": level,
- "filename": log_file,
- "maxBytes": int(os.getenv("LOG_MAX_BYTES", 10 * 1024 * 1024)),
- "backupCount": int(os.getenv("LOG_BACKUP_COUNT", 5)),
- }
- root_handlers.append("file")
- external = os.getenv("EXTERNAL_LOG_URL")
- if external:
- handlers["external"] = {
- "class": "logging.handlers.HTTPHandler",
- "formatter": "default",
- "level": level,
- "host": external,
- "url": "/",
- "method": "POST",
- }
- root_handlers.append("external")
- config = {
- "version": 1,
- "disable_existing_loggers": False,
- "formatters": {
- "default": {
- "format": "%(asctime)s %(levelname)s %(name)s: %(message)s",
- },
- "file": {
- "()": "app.utils.logger.StripAnsiFormatter",
- "format": "%(asctime)s %(levelname)s %(name)s: %(message)s",
- },
- },
- "handlers": handlers,
- "root": {
- "handlers": root_handlers,
- "level": level,
- },
- }
- dictConfig(config)
|