> ## Documentation Index
> Fetch the complete documentation index at: https://docs.myspellchecker.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging Guide

> Configure centralized logging with debug mode, JSON output for log aggregators, and per-module log levels.

All mySpellChecker modules log under the `myspellchecker` namespace. Call `configure_logging()` once at application startup to control log level, output format (human-readable or JSON), and destination.

## Overview

The logging system provides:

* Centralized configuration for all myspellchecker modules
* Consistent logger naming under the `myspellchecker` namespace
* Support for development (verbose) and production (JSON) modes
* Thread-safe logger caching
* Easy integration via `get_logger()`

## Basic Configuration

Configure logging once at the start of your application:

```python theme={null}
from myspellchecker.utils.logging_utils import configure_logging

# Simple setup (outputs to stderr)
configure_logging(level="INFO")
```

## Configuration Options

`configure_logging` supports several parameters:

| Parameter       | Type    | Default | Description                                           |
| --------------- | ------- | ------- | ----------------------------------------------------- |
| `level`         | str/int | INFO    | Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)     |
| `json_output`   | bool    | False   | Output as JSON for log aggregators                    |
| `debug_mode`    | bool    | False   | Verbose format with timestamps and line numbers       |
| `format_string` | str     | None    | Custom format string (overrides other format options) |
| `stream`        | TextIO  | stderr  | Output stream                                         |

### Format Strings

The logging system uses different formats based on configuration:

```python theme={null}
# Default format
"%(levelname)s: %(name)s: %(message)s"

# Debug format (debug_mode=True)
"%(asctime)s - %(levelname)s - %(name)s:%(lineno)d - %(message)s"

# JSON format (json_output=True)
'{"time": "%(asctime)s", "level": "%(levelname)s", "logger": "%(name)s", "message": "%(message)s"}'

# Simple format (custom)
"%(message)s"
```

### Examples

**Development Mode:**

```python theme={null}
configure_logging(level="DEBUG", debug_mode=True)
# Output: 2023-10-27 10:00:00 - DEBUG - myspellchecker.core.spellchecker:45 - Loaded 5000 words
```

**Production Mode:**

```python theme={null}
configure_logging(level="INFO", json_output=True)
# Output: {"time": "...", "level": "INFO", "logger": "myspellchecker.core", "message": "Ready"}
```

**Simple Build Output:**

```python theme={null}
configure_logging(level="INFO", format_string="%(message)s")
# Output: Building dictionary...
```

## Using Loggers in Your Code

If you are extending mySpellChecker or writing custom components, use the logging utility:

```python theme={null}
from myspellchecker.utils.logging_utils import get_logger

logger = get_logger(__name__)

def my_custom_function():
    logger.debug("Starting processing")
    try:
        # ...
        logger.info("Success")
    except Exception as e:
        logger.error(f"Failed: {e}")
```

### Logger Naming

`get_logger()` ensures consistent naming under the `myspellchecker` namespace:

```python theme={null}
# In src/myspellchecker/algorithms/symspell.py
logger = get_logger(__name__)
# Returns logger named "myspellchecker.algorithms.symspell"

# With short name
logger = get_logger("custom")
# Returns logger named "myspellchecker.custom"
```

### Logger Caching

Loggers are cached for efficiency (LRU cache with 256 entries):

```python theme={null}
# These return the same logger instance
logger1 = get_logger(__name__)
logger2 = get_logger(__name__)
assert logger1 is logger2  # True
```

## Setting Log Levels

Use Python's standard logging to set levels per module:

```python theme={null}
import logging

# Set package-wide level
logging.getLogger("myspellchecker").setLevel(logging.DEBUG)

# Silence a noisy module
logging.getLogger("myspellchecker.algorithms.symspell").setLevel(logging.WARNING)

# Enable debug for specific module
logging.getLogger("myspellchecker.core.validators").setLevel(logging.DEBUG)
```

## Advanced Configuration

Get the root logger for custom handlers and filters:

```python theme={null}
import logging

# Get root myspellchecker logger
root_logger = logging.getLogger("myspellchecker")

# Add custom handler
file_handler = logging.FileHandler("spellchecker.log")
root_logger.addHandler(file_handler)

# Add filter
class SensitiveFilter(logging.Filter):
    def filter(self, record):
        # Filter out sensitive info
        return "password" not in record.getMessage()

root_logger.addFilter(SensitiveFilter())
```

## Integration with Standard Logging

The logging utilities are compatible with Python's standard logging:

```python theme={null}
import logging

# Standard pattern still works
logger = logging.getLogger("myspellchecker.mymodule")
logger.info("This works too")

# Configure via standard logging
logging.getLogger("myspellchecker").setLevel(logging.DEBUG)
```

## CLI Logging

The CLI automatically configures logging:

```bash theme={null}
# Normal output
myspellchecker check input.txt

# Verbose output
myspellchecker check input.txt --verbose

# Debug output (same as verbose)
myspellchecker check input.txt -v
```

## Best Practices

1. **Configure once**: Call `configure_logging()` once at application startup
2. **Use get\_logger**: Always use `get_logger(__name__)` for consistent naming
3. **Log levels**: Use appropriate levels (DEBUG for development, INFO+ for production)
4. **Structured logging**: Use JSON output in production for log aggregators
5. **Don't log sensitive data**: Be careful with user input in log messages

## Troubleshooting

### Duplicate Logs

If you see duplicate logs, ensure:

1. `configure_logging()` is called only once
2. You're not adding handlers manually without removing existing ones

```python theme={null}
# Reset handlers
import logging
logger = logging.getLogger("myspellchecker")
logger.handlers.clear()
configure_logging(level="INFO")
```

### No Output

If logs aren't appearing:

1. Check the log level
2. Verify `configure_logging()` was called
3. Check the output stream

```python theme={null}
import sys
configure_logging(level="DEBUG", stream=sys.stdout)
```

## See Also

* [Configuration Guide](/guides/configuration) - General configuration
* [Performance Tuning](/guides/performance-tuning) - Optimization guide
