Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,11 @@ Inside the library, use standard named loggers:

```python
# mylib/service.py
import logging

from rich.panel import Panel

from logurich import ctx
from logurich import ctx, get_logger

logger = logging.getLogger(__name__)
logger = get_logger(__name__)


def run_job(job_id: str) -> None:
Expand Down Expand Up @@ -118,7 +116,7 @@ run_job("job-42")

Guidelines for libraries:

- Use `logging.getLogger(__name__)` inside library modules.
- Use `get_logger(__name__)` from logurich inside library modules.
- Do not call `init_logger()` or `shutdown_logger()` from library code.
- Emit normal stdlib log calls such as `logger.info("Value %s", value)`.
- Use `extra={"context": ...}` and `extra={"renderables": ...}` only as optional metadata; they render nicely when the consuming application uses Logurich, and `logger.ctx(...)` / `logger.rich(...)` are also available when Logurich has been imported/configured by the application.
Expand All @@ -129,15 +127,14 @@ Guidelines for libraries:
When `enqueue=True`, Logurich is process-safe only if worker processes send records through the shared logging queue created by the parent process.

```python
import logging
import multiprocessing as mp

from logurich import configure_child_logging, get_log_queue, init_logger
from logurich import configure_child_logging, get_log_queue, get_logger, init_logger


def worker(log_queue: mp.Queue, worker_id: int) -> None:
configure_child_logging(log_queue)
logging.getLogger(f"worker.{worker_id}").info("worker=%s ready", worker_id)
get_logger(f"worker.{worker_id}").info("worker=%s ready", worker_id)


def main() -> None:
Expand Down Expand Up @@ -167,15 +164,15 @@ Install the optional Click extra to automatically expose logger configuration fl

```python
import click
import logging

from logurich import get_logger
from logurich.opt_click import click_logger_params


@click.command()
@click_logger_params
def cli():
logger = logging.getLogger(__name__)
logger = get_logger(__name__)
logger.info("Click integration ready!")
```

Expand All @@ -200,12 +197,10 @@ This is useful when tests or interactive sessions need to reset logging between
The `user_input` module provides Rich-enhanced prompts with type coercion, hidden input, and optional timeouts. It does **not** depend on Click.

```python
import logging

from logurich import init_logger, user_input, user_input_with_timeout
from logurich import get_logger, init_logger, user_input, user_input_with_timeout

init_logger("INFO", enqueue=False)
logger = logging.getLogger(__name__)
logger = get_logger(__name__)

# Basic string input
name = user_input("Enter your name", type=str)
Expand Down
12 changes: 6 additions & 6 deletions examples/async_context.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import asyncio
import logging
import multiprocessing as mp
import time

from logurich import (
configure_child_logging,
ctx,
get_log_queue,
get_logger,
global_context_configure,
init_logger,
)

request_log = logging.getLogger("example.request")
db_log = logging.getLogger("example.db")
task_log = logging.getLogger("example.task")
thread_log = logging.getLogger("example.thread")
process_log = logging.getLogger("example.process")
request_log = get_logger("example.request")
db_log = get_logger("example.db")
task_log = get_logger("example.task")
thread_log = get_logger("example.thread")
process_log = get_logger("example.process")


async def fetch_user_profile() -> None:
Expand Down
6 changes: 2 additions & 4 deletions examples/base.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import logging

from rich.panel import Panel
from rich.table import Table

from logurich import ctx, init_logger
from logurich import ctx, get_logger, init_logger


def create_rich_table() -> Table:
Expand All @@ -17,7 +15,7 @@ def create_rich_table() -> Table:

if __name__ == "__main__":
init_logger("INFO", enqueue=False)
logger = logging.getLogger(__name__)
logger = get_logger(__name__)

logger.info("This is a basic log message")
logger.info("Hello %s", "world")
Expand Down
5 changes: 2 additions & 3 deletions examples/click_cli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import logging

import click

from logurich import get_logger
from logurich.opt_click import click_logger_params


Expand All @@ -11,7 +10,7 @@
@click.option("--count", default=1, type=int, help="Number of greetings to emit.")
def main(name: str, count: int) -> None:
"""Demonstrate automatic logger wiring inside a Click command."""
logger = logging.getLogger(__name__)
logger = get_logger(__name__)

for _ in range(count):
logger.info("Hello %s", name)
Expand Down
6 changes: 3 additions & 3 deletions examples/mp_adv_data_processing.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
import multiprocessing as mp
import os
import random
Expand All @@ -13,6 +12,7 @@
configure_child_logging,
ctx,
get_log_queue,
get_logger,
global_context_configure,
global_context_set,
init_logger,
Expand All @@ -35,7 +35,7 @@ def init_worker(log_queue):


def process_item(item):
logger = logging.getLogger("processor.worker")
logger = get_logger("processor.worker")
global_context_set(item=ctx(str(item["id"]), label="item", style="cyan"))

try:
Expand Down Expand Up @@ -92,7 +92,7 @@ def worker_entry(item):
def main():
init_logger("INFO", log_verbose=2, enqueue=True)
log_queue = get_log_queue()
logger = logging.getLogger("processor.main")
logger = get_logger("processor.main")

with global_context_configure(
group=ctx("DataProcessor", style="green", show_key=True)
Expand Down
12 changes: 6 additions & 6 deletions examples/mp_example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
import multiprocessing as mp
import random
import time
Expand All @@ -10,14 +9,15 @@
configure_child_logging,
ctx,
get_log_queue,
get_logger,
global_context_configure,
init_logger,
)


def worker_function(log_queue, worker_id):
configure_child_logging(log_queue)
logger = logging.getLogger(f"workers.{worker_id}")
logger = get_logger(f"workers.{worker_id}")

with global_context_configure(worker=ctx(f"Worker-{worker_id}", show_key=True)):
logger.info("Worker %s starting", worker_id)
Expand Down Expand Up @@ -65,7 +65,7 @@ def main() -> None:
init_logger("INFO", log_verbose=2, enqueue=True)
log_queue = get_log_queue()

logging.getLogger("main").info("Multiprocessing example starting")
get_logger("main").info("Multiprocessing example starting")

with global_context_configure(
process=ctx("Main-Process", style="magenta", show_key=True)
Expand All @@ -75,7 +75,7 @@ def main() -> None:
for i in range(3)
]

logging.getLogger("main").info(
get_logger("main").info(
"Starting worker processes",
extra={
"renderables": (
Expand All @@ -95,14 +95,14 @@ def main() -> None:
for index, process in enumerate(processes, start=1):
table.add_row(f"Worker {index}", str(process.pid), "Running")

logging.getLogger("main").info(
get_logger("main").info(
"Workers started",
extra={"renderables": (table,)},
)

for index, process in enumerate(processes, start=1):
process.join()
logging.getLogger("main").info(
get_logger("main").info(
"Worker %s (PID: %s) has completed",
index,
process.pid,
Expand Down
5 changes: 2 additions & 3 deletions examples/serialize.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import logging
import os

from rich.panel import Panel
from rich.table import Table

from logurich import ctx, global_context_configure, init_logger
from logurich import ctx, get_logger, global_context_configure, init_logger


def build_table() -> Table:
Expand All @@ -27,7 +26,7 @@ def build_table() -> Table:
rotation=None,
retention=None,
)
logger = logging.getLogger(__name__)
logger = get_logger(__name__)

logger.info(
"Basic serialized message",
Expand Down
8 changes: 3 additions & 5 deletions examples/user_input_example.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import logging

from logurich import init_logger, user_input, user_input_with_timeout
from logurich import get_logger, init_logger, user_input, user_input_with_timeout

if __name__ == "__main__":
init_logger("INFO", enqueue=False)
logger = logging.getLogger(__name__)
logger = get_logger(__name__)

# Basic string input
name = user_input("Enter your name", type=str)
Expand All @@ -19,7 +17,7 @@
logger.info("Secret length: %d", len(secret))

# Custom logger
custom = logging.getLogger("custom")
custom = get_logger("custom")
colour = user_input("Favourite colour", type=str, custom_logger=custom)
logger.info("Colour: %s", colour)

Expand Down
Loading