loguru icon indicating copy to clipboard operation
loguru copied to clipboard

A suggestion on obtaining a logger

Open jsonvot opened this issue 3 months ago • 4 comments

In daily use, when multiple handlers have been added, if you need to specify a particular handler for logging, you often have to use filter functions and bind methods to filter out the desired handler for logging. This approach is somewhat indirect. It is hoped that, similar to the logging library which has a basicConfig interface, there could also be a way to directly create a logger via a method like getLogger(sink='{time:YYYYMMDD}.log'), allowing logs to be printed to that log file. This is roughly the idea. Do you think this would be more convenient?

jsonvot avatar Sep 21 '25 15:09 jsonvot

Hi.

Loguru is built around the concept of a single global logger (essentially a lightweight facade), with log management delegated to the handlers. Introducing support for multiple distinct loggers would represent a fundamental shift away from this design choice, which I don't think is very desirable.

However, I have planned a new method, namely logger.new(), which should enable creating loggers with their own independent handlers. Perhaps this will be useful in your situation. Can you please help me understand a concrete use case: why would you need to specify a particular logging for handler?

Delgan avatar Sep 22 '25 07:09 Delgan

+1 on me. @Delgan I can explain my situation and needs.

I'm working on evaluating ML model for now. source codes outside of evaluation itself's implementation(e.g. model inference code, preprocessing code, etc ) already using loguru and they are calling logger.something. And also inside evaluation script it is using loguru to log things both to stderr and file. (plus, format I want to use for inside evaluation and outside evaluation is different)

But to implement evaluation's logging, for now, I need to modify global logger instead, which modifies expected behavior of logger called outside evaluation script.

So I thought I need a method to obtain new logger instance, not global one, but found no way present for now.

MilkClouds avatar Nov 07 '25 07:11 MilkClouds

Hi. As a backend developer, my backend applications are typically structured into several modules—such as API modules, script modules, and scheduled task modules. I aim to unify the configuration of log handlers in a single configuration file. Instead of using a single shared logger for all components, I prefer to categorize log handlers into dedicated types (e.g., api_logger, script_logger, and task_logger). This practice enables me to quickly locate and retrieve the specific log information I need for troubleshooting or auditing.

jsonvot avatar Nov 07 '25 11:11 jsonvot

Hi. There's an alternative approach to achieve this without needing logger.new(). First, let's look at how logging works: handlers are stored in a dictionary. When retrieving a logger, you can directly get the logger named handler_name using logging.getLogger(handler_name).

logging.config.dictConfig({
    ......
    "handlers": {
        "api_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "filename": "logs/api.log",
            "maxBytes": 1024*1024*10,  # 10MB rotation
            "backupCount": 5,
            "formatter": "json"
        },
        "script_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "filename": "logs/script.log",
            "maxBytes": 1024*1024*10,
            "backupCount": 5,
            "formatter": "json"
        },
        "task_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "filename": "logs/task.log",
            "maxBytes": 1024*1024*10,
            "backupCount": 5,
            "formatter": "json"
        }
    },
    "loggers": {
        "api_logger": {
            "level": "INFO",
            "handlers": ["api_file"],
            "propagate": False  # 不向上传播,避免重复输出
        },
        "script_logger": {
            "level": "INFO",
            "handlers": ["script_file"],
            "propagate": False
        },
        "task_logger": {
            "level": "INFO",
            "handlers": ["task_file"],
            "propagate": False
        }
    }
})

# Get logger
api_logger = logging.getLogger("api_logger")
script_logger = logging.getLogger("script_logger")
task_logger = logging.getLogger("task_logger")

api_logger.info("api_logger test")
script_logger.warning("script_logger test")
task_logger.error("task_logger test")

However, with Loguru, when multiple handlers exist, you need to use the logger.bind() method to iterate through handlers and retrieve a specific logger:

logger.configure(
    handlers=[
        dict(sink=sys.stderr, format="[{time}] {message}"),
        dict(sink="file.log", enqueue=True, serialize=True),
    ],
    ......
)
logger.bind(......).info(...)

I'm wondering if we could implement it like this: for example, allowing the handlers parameter in logger.configure() to support a dictionary format:

logger.configure(
    handlers={
        "console": dict(sink=sys.stderr, format="[{time}] {message}"),
        "api_logger": dict(sink="api_logger.log", enqueue=True, serialize=True),
        "script_logger": dict(sink="script_logger.log", enqueue=True, serialize=True),
    },
    ......
)
api_logger = logging.getLogger("api_logger")
script_logger = logging.getLogger("script_logger")

api_logger.info('api_logger  test')
script_logger .info('script_logger test')

Then, add a method similar to logger.getLogger(handler_name) as a simple way to retrieve a specific logger. The existing logger.bind() method can be retained as an advanced way to filter loggers. Of course, this is just an idea of mine for reference.

jsonvot avatar Nov 12 '25 03:11 jsonvot