[feature] auto group/indent messages
Auto grouping/indenting log messages based on the end/start character of the message line. This is done by checking the last part of the message, in the example below it's .... When a message ends on ... level is increased. If the message starts with ... it's decreased.
This way is easier to see which operations are part of the same 'group'. You can also add colors for example.
Code:
log.info("level 1 op...")
log.info("level 2 op...")
log.info("level 3 op...")
log.info("level 3 msg 1")
log.info("level 3 msg 2")
log.info("...done, level 3")
log.info("...done, level 2")
log.info("...done, level 1")
Output:
2025-08-09 07:53:37 [INFO ] level 1 op... [suffix]
2025-08-09 07:53:37 [INFO ] | level 2 op [suffix]
2025-08-09 07:53:37 [INFO ] | | level 3 op... [suffix]
2025-08-09 07:53:37 [INFO ] | | | level 3 msg 1 [suffix]
2025-08-09 07:53:37 [INFO ] | | | level 3 msg 2 [suffix]
2025-08-09 07:53:37 [INFO ] | | ...done, level 3 [suffix]
2025-08-09 07:53:37 [INFO ] | ...done, level 2 [suffix]
2025-08-09 07:53:37 [INFO ] ...done, level 1 [suffix]
What do you think?
Hi.
For starters, let's note two similar tickets for reference:
- https://github.com/Delgan/loguru/issues/424
- https://github.com/Delgan/loguru/issues/989
- https://github.com/Delgan/loguru/issues/1167
Your suggestion goes even further by proposing to generate indentation automatically based on the content of the message. In my opinion, it's a little too "magical", and I don't think the content of the message should implicitly influence the structure and behavior of the logs.
Regarding the idea of indented logs, this is something I understand the appeal of, but I don't want to integrate it directly into Loguru (as discussed in the above tickets). I think this feature is best handled by a dedicated library such as eliottree.
That being said, Loguru is flexible enough that you should be able to craft your own indentation system using a custom formatter. Here is an example:
from loguru import logger
from contextvars import ContextVar
from datetime import datetime
import sys
_indent_level: ContextVar[int] = ContextVar("_indent_level", default=0)
def indenting_formatter(record):
level = _indent_level.get()
message = record["message"]
if message.endswith("..."):
_indent_level.set(level + 1)
elif message.startswith("..."):
_indent_level.set(level - 1)
level -= 1
indent_prefix = "| " * level
record["extra"]["indent_prefix"] = indent_prefix
return "{time} [{level.name:<8}] {extra[indent_prefix]}{message}\n{exception}"
logger.remove()
logger.add(sys.stderr, format=indenting_formatter)
logger.info("level 1 op...")
logger.info("level 2 op...")
logger.info("level 3 op...")
logger.info("level 3 msg 1")
logger.info("level 3 msg 2")
logger.info("...done, level 3")
logger.info("...done, level 2")
logger.info("...done, level 1")