File size: 2,388 Bytes
e854df7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""
Logging configuration: console (colored) + rotating file handler.
"""
import logging
import sys
from pathlib import Path
from logging.handlers import RotatingFileHandler

_LOG_FORMAT = "%(asctime)s | %(levelname)-8s | %(name)-30s | %(message)s"
_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"


def setup_logger(
    name: str = "sen2sr",
    level: int = logging.INFO,
    log_file: str | None = "sen2sr.log",
    max_bytes: int = 10 * 1024 * 1024,  # 10 MB
    backup_count: int = 3,
) -> logging.Logger:
    """
    Create (or retrieve) a logger with a stream handler and optional file handler.

    Parameters
    ----------
    name        : Logger name (hierarchical, e.g. "sen2sr.pipeline").
    level       : Logging level (default INFO).
    log_file    : Path to log file; None disables file logging.
    max_bytes   : Max file size before rotation.
    backup_count: Number of rotated files to keep.

    Returns
    -------
    Configured logging.Logger instance.
    """
    logger = logging.getLogger(name)
    if logger.handlers:
        # Already configured β€” avoid duplicate handlers on repeated calls
        return logger

    logger.setLevel(level)
    formatter = logging.Formatter(_LOG_FORMAT, datefmt=_DATE_FORMAT)

    # ── Console handler ────────────────────────────────────────────────────────
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(formatter)
    console_handler.setLevel(level)
    logger.addHandler(console_handler)

    # ── Rotating file handler ─────────────────────────────────────────────────
    if log_file:
        log_path = Path(log_file)
        log_path.parent.mkdir(parents=True, exist_ok=True)
        file_handler = RotatingFileHandler(
            log_path,
            maxBytes=max_bytes,
            backupCount=backup_count,
            encoding="utf-8",
        )
        file_handler.setFormatter(formatter)
        file_handler.setLevel(level)
        logger.addHandler(file_handler)

    return logger


def get_logger(name: str) -> logging.Logger:
    """Convenience: return a child logger under the 'sen2sr' hierarchy."""
    return logging.getLogger(f"s2sr_pipe.{name}")