Skip to content

logger

Logging factory to create instance-specific loggers for mounted subapps

create_logger(tag=None, config=None)

Create a logger instance for a specific app. The purpose of this function is to have different loggers for different subapps (if needed).

Parameters:

Name Type Description Default
tag str | None

String added to the each logging line idenfiting this logger

None
config ServerConfig | None

ServerConfig instance, will create the default one if not provided

None

Returns:

Type Description
Logger

Configured logger instance

Source code in optimade/server/logger.py
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def create_logger(
    tag: str | None = None, config: ServerConfig | None = None
) -> logging.Logger:
    """
    Create a logger instance for a specific app. The purpose of this function
    is to have different loggers for different subapps (if needed).

    Args:
        tag: String added to the each logging line idenfiting this logger
        config: ServerConfig instance, will create the default one if not provided

    Returns:
        Configured logger instance
    """
    config = config or ServerConfig()

    logger_name = "optimade" + (f".{tag}" if tag else "")
    logger = logging.getLogger(logger_name)
    logger.setLevel(logging.DEBUG)

    if logger.handlers:
        return logger

    # Console handler only on parent (.tag will propagate to parent anyway)
    if tag is None:
        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG if config.debug else config.log_level.value.upper())
        try:
            from uvicorn.logging import DefaultFormatter

            ch.setFormatter(DefaultFormatter("%(levelprefix)s [%(name)s] %(message)s"))
        except ImportError:
            pass
        logger.addHandler(ch)

    logs_dir = config.log_dir
    if logs_dir is None:
        logs_dir = Path(os.getenv("OPTIMADE_LOG_DIR", "/var/log/optimade/")).resolve()
    try:
        logs_dir.mkdir(exist_ok=True, parents=True)
        log_filename = f"optimade_{tag}.log" if tag else "optimade.log"
        fh = logging.handlers.RotatingFileHandler(
            logs_dir / log_filename, maxBytes=1_000_000, backupCount=5
        )
        fh.setLevel(logging.DEBUG)
        fh.setFormatter(
            logging.Formatter(
                "[%(levelname)-8s %(asctime)s %(filename)s:%(lineno)d][%(name)s] %(message)s",
                "%d-%m-%Y %H:%M:%S",
            )
        )
        logger.addHandler(fh)
    except OSError:
        logger.warning(
            "Log files are not saved (%s). Set OPTIMADE_LOG_DIR or fix permissions for %s.",
            tag,
            logs_dir,
        )

    return logger

get_logger()

Get logger for current context.

Source code in optimade/server/logger.py
21
22
23
24
25
26
27
def get_logger() -> logging.Logger:
    """
    Get logger for current context.
    """
    tag = _current_log_tag.get()
    logger_name = "optimade" + (f".{tag}" if tag else "")
    return logging.getLogger(logger_name)

set_logging_context(tag)

Set the current API tag for context-based logging

Source code in optimade/server/logger.py
16
17
18
def set_logging_context(tag: str | None):
    """Set the current API tag for context-based logging"""
    _current_log_tag.set(tag)