"""Logging Configuration."""
from __future__ import annotations
import logging
import sys
from typing import TYPE_CHECKING
import structlog
from litestar.logging.config import LoggingConfig
from byte_bot.server.lib import settings
from byte_bot.server.lib.log import controller
from byte_bot.server.lib.log.utils import EventFilter, msgspec_json_renderer
if TYPE_CHECKING:
    from collections.abc import Sequence
    from typing import Any
    from structlog import BoundLogger
    from structlog.types import Processor
__all__ = (
    "config",
    "configure",
    "controller",
    "default_processors",
    "get_logger",
    "stdlib_processors",
)
default_processors = [
    structlog.contextvars.merge_contextvars,
    controller.drop_health_logs,
    structlog.processors.add_log_level,
    structlog.processors.TimeStamper(fmt="iso", utc=True),
]
"""Default processors to apply to all loggers. See :mod:`structlog.processors` for more information."""
stdlib_processors = [
    structlog.processors.TimeStamper(fmt="iso", utc=True),
    structlog.stdlib.add_log_level,
    structlog.stdlib.ExtraAdder(),
    EventFilter(["color_message"]),
    structlog.stdlib.ProcessorFormatter.remove_processors_meta,
]
"""Processors to apply to the stdlib logger. See :mod:`structlog.stdlib` for more information."""
if sys.stderr.isatty() or "pytest" in sys.modules:
    LoggerFactory: Any = structlog.WriteLoggerFactory
    console_processor = structlog.dev.ConsoleRenderer(
        colors=True,
        exception_formatter=structlog.dev.plain_traceback,
    )
    default_processors.extend([console_processor])
    stdlib_processors.append(console_processor)
else:
    LoggerFactory = structlog.BytesLoggerFactory
    default_processors.extend([msgspec_json_renderer])
config = LoggingConfig(
    root={"level": logging.getLevelName(settings.log.LEVEL), "handlers": ["queue_listener"]},
    formatters={
        "standard": {"()": structlog.stdlib.ProcessorFormatter, "processors": stdlib_processors},
    },
    loggers={
        "uvicorn.access": {
            "propagate": False,
            "level": settings.log.UVICORN_ACCESS_LEVEL,
            "handlers": ["queue_listener"],
        },
        "uvicorn.error": {
            "propagate": False,
            "level": settings.log.UVICORN_ERROR_LEVEL,
            "handlers": ["queue_listener"],
        },
    },
)
"""Pre-configured log config for application deps.
While we use structlog for internal app logging, we still want to ensure
that logs emitted by any of our dependencies are handled in a non-
blocking manner.
"""
[docs]
def get_logger(*args: Any, **kwargs: Any) -> BoundLogger:
    """Return a configured logger for the given name.
    Args:
        *args: Positional arguments to pass to :func:`get_logger() <structlog.get_logger()>`
        **kwargs: Keyword arguments to pass to :func:`get_logger() <structlog.get_logger()>`
    Returns:
        Logger: A configured logger instance
    """
    config.configure()
    configure(default_processors)  # type: ignore[arg-type]
    return structlog.getLogger(*args, **kwargs)  # type: ignore[no-any-return]