# logger_loguru


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

Provides pre-configured logging setup using Loguru with
notebook-friendly defaults and hierarchical indentation support for
tracking nested operations.

**Key features:**  
[`config_logger()`](https://civvic.github.io/pote/logger_loguru.html#config_logger)
— One-line setup returning configured logger + tree logger  
[`tree_logger`](https://civvic.github.io/pote/logger_loguru.html#tree_logger)
— Hierarchical logging with automatic indentation (`llogger.push`,
`llogger.pop`)  
[`LogFormatter`](https://civvic.github.io/pote/logger_loguru.html#logformatter)
— Customizable format with indentation support  
[`LogLevelFilter`](https://civvic.github.io/pote/logger_loguru.html#loglevelfilter)
— Dynamic level filtering with temporary override

**When to use:** Need readable, structured logging in notebooks or
scripts with hierarchical context tracking (e.g., nested async
operations, recursive algorithms).

**Typical usage:**

``` python
from loguru import logger
from pote.logger_loguru import config_logger

logger, llogger = config_logger(logger)
llogger.info("root")
with llogger.inc_indent():
    llogger.info("nested")
```

<!-- # Prologue -->

# loguru basics

Quick exploration of loguru’s core features and rationale for this
module’s configuration choices.

Default handler:  
- logs are emitted to `sys.stderr` by default  
- messages can be logged with different severity levels  
- messages are formatted using curly braces (it uses str.format() under
the hood)

``` python
logger.debug("Hello, world! {}", 'aaaa')
```

In notebooks, traces are not good:

``` python
@logger.catch
def f(x): 100 / x  # type: ignore

def g():
    f(10)
    f(0)

g()
```

      ERROR | An error has been caught in function 'g', process 'MainProcess' (43630), thread 'MainThread' (8320000192):

[filter traceback in Jupyter when using
@logger.catch](https://github.com/Delgan/loguru/issues/437)

In notebooks contexts, configure your handler with backtrace option
disabled:

``` python
logger.remove()
logger.add(sys.stderr, backtrace=False)
```

    7

``` python
g()
```

    2025-11-13 14:40:05.849 | ERROR    | __main__:g:6 - An error has been caught in function 'g', process 'MainProcess' (43630), thread 'MainThread' (8320000192):
    Traceback (most recent call last):

      File "/var/folders/np/k2wj6f4s3rj0m9n0yt8pkk680000gn/T/ipykernel_43630/4019600944.py", line 6, in g
        f(0)
        └ <function f>

      File "/var/folders/np/k2wj6f4s3rj0m9n0yt8pkk680000gn/T/ipykernel_43630/4019600944.py", line 2, in f
        def f(x): 100 / x  # type: ignore
            │ │         └ 0
            │ └ 0
            └ <function f>

    ZeroDivisionError: division by zero

Add some colors and formatting to the output:

``` python
logger.remove()
i = logger.add(sys.stderr, colorize=True, format="[<fg #66a3ff>{time:YYYY-MM-DD HH:mm:ss}</fg #66a3ff>] [<fg #00ff00>{level}</fg #00ff00>] {message}")
logger.info("test {}", i)
logger.debug("Hello, world!")
```

    [2025-11-13 14:40:05] [INFO] test 8
    [2025-11-13 14:40:05] [DEBUG] Hello, world!

# formatter

Custom formatter that adds indentation tracking for hierarchical log
output.

------------------------------------------------------------------------

<a
href="https://github.com/civvic/pote/blob/main/pote/logger_loguru.py#L26"
target="_blank" style="float:right; font-size:smaller">source</a>

### LogFormatter

``` python

def LogFormatter(
    
)->None:

```

*Formats log records with indentation for tree-structured output*

``` python
fmt = LogFormatter()
test_eq(fmt.indent, '')
test_eq(LogFormatter._ind_level, 0)

record = {"extra": {}, "name": "test", "function": "fn", "line": 10}
fmt.format(record)
test_eq(record["extra"]["indent"], '')
record
```

    {'extra': {'indent': ''}, 'name': 'test', 'function': 'fn', 'line': 10}

``` python
LogFormatter._ind_level = 2
fmt2 = LogFormatter()
test_eq(fmt2.indent, '    ')  # 2 levels * 2 spaces
```

``` python
LogFormatter._ind_level = 0  # reset for other tests
```

------------------------------------------------------------------------

<a
href="https://github.com/civvic/pote/blob/main/pote/logger_loguru.py#L48"
target="_blank" style="float:right; font-size:smaller">source</a>

### LogLevelFilter

``` python

def LogLevelFilter(
    level:int | str
):

```

*Filter log records by minimum level with context manager for temporary
override*

``` python
# ⎸
# LEFT VERTICAL BOX LINE
# Unicode: U+23B8, UTF-8: E2 8E B8

# ⏐
# VERTICAL LINE EXTENSION
# Unicode: U+23D0, UTF-8: E2 8F 90

# │
# BOX DRAWINGS LIGHT VERTICAL
# Unicode: U+2502, UTF-8: E2 94 82
```

# loggers

Wrapper that manages indentation levels for hierarchical log output.

------------------------------------------------------------------------

<a
href="https://github.com/civvic/pote/blob/main/pote/logger_loguru.py#L89"
target="_blank" style="float:right; font-size:smaller">source</a>

### tree_logger

``` python

def tree_logger(
    logger:Any, fmt:LogFormatter
):

```

*Logger wrapper managing hierarchical indentation for tree-structured
output*

# setup

> Configuration functions for quick logger setup in library modules

------------------------------------------------------------------------

<a
href="https://github.com/civvic/pote/blob/main/pote/logger_loguru.py#L154"
target="_blank" style="float:right; font-size:smaller">source</a>

### setup_logger

``` python

def setup_logger(
    logger, name:str='__main__'
)->Logger:

```

*Apply standard config (format, level filter, backtrace) to logger*

<s>Note logging is disabled after
[`setup_logger`](https://civvic.github.io/pote/logger_loguru.html#setup_logger)
if called from a module distinct to ‘**main**’.</s>

``` python
logger = setup_logger(logger)
logger.info('test')
```

       INFO | test

------------------------------------------------------------------------

<a
href="https://github.com/civvic/pote/blob/main/pote/logger_loguru.py#L160"
target="_blank" style="float:right; font-size:smaller">source</a>

### config_logger

``` python

def config_logger(
    logger:Logger, # Logger instance from each module
)->tuple[Logger, tree_logger]:

```

*Configure logger with colors and return (logger, tree_logger) tuple*

**Module usage pattern:**

Each module imports and configures its own logger:

``` python
from loguru import logger
from pote.logger_loguru import config_logger

logger, llogger = config_logger(logger)

# Standard logging
logger.info("Processing started")

# Hierarchical logging  
llogger.info("Main operation")
with llogger.inc_indent():
    llogger.info("Sub-operation")
```

This gives each module independent logger configuration while
maintaining consistent formatting.

``` python
logger, llogger = config_logger(logger)
logger.info('configured')
```

       INFO | configured

``` python
test_eq(llogger.level, 0)
test_eq(llogger.indent, '')
llogger.info('root level')
```

       INFO | root level

``` python
_ = llogger.push
llogger.info("pushed once")
test_eq(llogger.level, 1)
test_eq(llogger.indent, '│ ')
```

       INFO | │ pushed once

``` python
_ = llogger.push
llogger.info("pushed twice")
test_eq(llogger.level, 2)
test_eq(llogger.indent, '│ │ ')
```

       INFO | │ │ pushed twice

``` python
_ = llogger.pop
test_eq(llogger.level, 1)
```

``` python
_ = llogger.reset()
test_eq(llogger.level, 0)
```

``` python
llogger.info('root')
with llogger.inc_indent():
    test_eq(llogger.level, 1)
    llogger.info('child')
    with llogger.inc_indent():
        test_eq(llogger.level, 2)
        llogger.info('grandchild')
    test_eq(llogger.level, 1)
    llogger.info('child')
test_eq(llogger.level, 0)
llogger.info('root')
```

       INFO | root
       INFO | │ child
       INFO | │ │ grandchild
       INFO | │ child
       INFO | root

``` python
class _Test:
    a = 'a'
    b = 'b'
    
    @llogger.bracket_logging("<n>{}</> <y>{}</>", 'test', b'b')
    async def test_bracket_logging_b(self):
        llogger.info("inside test_bracket_logging_b")
        test_eq(llogger.level, 2)  # nested 2 levels deep
        
    @llogger.bracket_logging("<n>{}</> <y>{}</>", 'test', b'a')
    async def test_bracket_logging_a(self):
        llogger.info("inside test_bracket_logging_a")
        test_eq(llogger.level, 1)  # nested 1 level
        await self.test_bracket_logging_b()  # type: ignore
        test_eq(llogger.level, 1)  # back to 1 after inner returns

_t = _Test()
llogger.reset()
test_eq(llogger.level, 0)
await _t.test_bracket_logging_a()  # type: ignore
test_eq(llogger.level, 0)  # back to root
```

       INFO | test a: >>>> test_bracket_logging_a...
       INFO | │ inside test_bracket_logging_a
       INFO | │ test b: >>>> test_bracket_logging_b...
       INFO | │ │ inside test_bracket_logging_b

bracket_logging decorator with nested calls

## <!-- # Colophon -->
