# How Logging Is Implemented in lfnovo/open-notebook: A Loguru Configuration Guide

> Discover how lfnovo/open-notebook implements centralized logging with Loguru. Learn about stdout sinks, environment variable configuration, and thread-safe message emission in this FastAPI application.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: how-to-guide
- Published: 2026-06-26

---

**The lfnovo/open-notebook repository implements centralized logging using the Loguru library, configuring a single stdout sink in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) that respects the `LOGURU_LEVEL` environment variable while individual modules import a global logger instance to emit structured, thread-safe messages across the async FastAPI application.**

Understanding how logging works in the open-notebook codebase is essential for debugging AI provisioning workflows and monitoring database operations. The project adopts a centralized configuration pattern that ensures consistent log formatting and level control across all components, from utility modules to API routers.

## Centralized Logger Configuration in api/main.py

The logging infrastructure is initialized once at application startup in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py). This centralization guarantees that every module shares the same handler configuration and output format.

The configuration follows a three-step pattern:

1. **Remove the default handler** to eliminate duplicate stderr output
2. **Add a custom stdout sink** with environment-driven level control
3. **Enable async-safe serialization** for the FastAPI runtime

```python
from loguru import logger
import os
import sys

# Remove default stderr sink

logger.remove()

# Configure centralized stdout logging

logger.add(
    sys.stdout,
    level=os.getenv("LOGURU_LEVEL", "INFO"),
    enqueue=True,      # Thread-safe for async operations

    backtrace=True,    # Detailed exception tracebacks

    diagnose=True,     # Rich error context

)

```

This setup ensures that logs are emitted in a JSON-compatible format suitable for aggregation systems like Loki or Fluentd, while the `enqueue=True` parameter guarantees thread-safe operation across concurrent coroutines.

## Module-Level Logging Pattern

Individual modules do not configure their own handlers. Instead, they import the global logger instance and emit messages at appropriate severity levels.

In [`open_notebook/utils/graph_utils.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/graph_utils.py), the logger is imported at module level:

```python
from loguru import logger

```

This same pattern appears across the codebase in [`open_notebook/ai/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/models.py), [`open_notebook/utils/token_utils.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/token_utils.py), and [`api/routers/sources.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/sources.py). Modules log events using standard severity methods:

```python
from loguru import logger

def process_source(source_id: str):
    logger.debug("Processing source {}", source_id)
    try:
        result = fetch_source_data(source_id)
        logger.info("Successfully retrieved source {}", source_id)
        return result
    except Exception as exc:
        logger.error("Failed to fetch source {}: {}", source_id, exc)
        raise

```

The AI provisioning layer in [`open_notebook/ai/provision.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/provision.py) uses this pattern to log model selection actions, while [`open_notebook/database/repository.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/database/repository.py) records database operations. Command handlers in [`commands/source_commands.py`](https://github.com/lfnovo/open-notebook/blob/main/commands/source_commands.py) similarly emit execution logs using the same imported instance.

## Structured Logging and Async Safety

The logging implementation supports the application's async-first architecture through specific Loguru configuration options.

**Thread-Safe Serialization**: The `enqueue=True` parameter ensures that log messages from concurrent coroutines are serialized correctly, preventing race conditions during high-throughput AI processing.

**Rich Diagnostic Context**: Enabling `backtrace=True` and `diagnose=True` captures detailed exception information and variable states, crucial for debugging complex LangGraph workflows and SurrealDB interactions.

**Machine-Readable Output**: By writing to stdout with structured formatting, the logs integrate seamlessly with containerized deployments. Docker and Kubernetes can capture stdout streams for centralized aggregation without additional file handlers.

## Environment-Driven Log Level Control

The logging verbosity is controlled entirely through the `LOGURU_LEVEL` environment variable, eliminating hard-coded configuration changes.

To enable debug output during development:

```bash
export LOGURU_LEVEL=DEBUG
python -m api.main

```

For production deployments requiring only warnings and errors:

```bash
export LOGURU_LEVEL=WARNING

```

This approach allows operators to adjust verbosity without modifying source code or redeploying the application. The default level is `INFO`, providing a balanced view of application health without excessive noise.

## Summary

- **Centralized Configuration**: All logging is configured in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) with a single stdout sink and environment-based level control via `LOGURU_LEVEL`.
- **Global Logger Import**: Modules import `from loguru import logger` and emit messages using standard severity levels without additional setup.
- **Async-Ready**: The `enqueue=True` setting ensures thread-safe logging across FastAPI endpoints and database operations.
- **Structured Output**: Logs write to stdout in a format compatible with container orchestration and log aggregation systems.
- **Zero Hard-Coding**: Log levels are controlled exclusively through environment variables, supporting seamless transitions between development and production environments.

## Frequently Asked Questions

### What logging library does open-notebook use?

The repository uses **Loguru** as its sole logging dependency. You can see the import in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) and across utility modules like [`open_notebook/utils/graph_utils.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/graph_utils.py) and [`open_notebook/ai/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/models.py). This replaces the standard library `logging` module with a more ergonomic API and better async support.

### How do I change the log level in open-notebook without modifying code?

Set the `LOGURU_LEVEL` environment variable before starting the application. Valid values include `DEBUG`, `INFO`, `WARNING`, `ERROR`, and `CRITICAL`. For example, run `export LOGURU_LEVEL=DEBUG` to see detailed debug messages, or set it to `WARNING` to suppress info-level logs in production environments.

### Where is the logger configured in the open-notebook codebase?

The primary configuration resides in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py), where the code calls `logger.remove()` to clear default handlers and `logger.add()` to establish a stdout sink with specific formatting and concurrency settings. This single initialization point ensures all modules share identical logging behavior.

### Is the logging implementation thread-safe for async operations?

Yes, the configuration explicitly sets `enqueue=True` when adding the stdout sink, which enables Loguru's thread-safe queue mechanism. This is essential for the application's async architecture, ensuring that concurrent API requests and database operations in modules like [`open_notebook/database/repository.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/database/repository.py) log messages without corruption or race conditions.