# Sluglogger

[![PyPI version](https://badge.fury.io/py/sluglogger.svg)](https://pypi.org/project/sluglogger/)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Discord.py style coloured console logging for Python applications.

## Installation

```bash
pip install sluglogger
```

## Quick Start

```python
import logging
import sluglogger

sluglogger.setup_logging(level=logging.DEBUG)

log = logging.getLogger("myapp")
log.debug("Debug message")
log.info("Info message")
log.warning("Warning message")
log.error("Error message")
log.critical("Critical message")
```

Output:

```
2026-03-11 12:30:45 DEBUG    myapp Debug message
2026-03-11 12:30:45 INFO     myapp Info message
2026-03-11 12:30:45 WARNING  myapp Warning message
2026-03-11 12:30:45 ERROR    myapp Error message
2026-03-11 12:30:45 CRITICAL myapp Critical message
```

Colours in a supported terminal:

- Timestamp in dark gray
- DEBUG in gray
- INFO in blue
- WARNING in yellow
- ERROR in red
- CRITICAL in bold red
- Logger name in magenta

## Usage

### Basic Setup

```python
import sluglogger

sluglogger.setup_logging()
```

This sets up logging with coloured output if the terminal supports it, otherwise falls back to a plain text format.

### Named Loggers

```python
import logging
import sluglogger

sluglogger.setup_logging(level=logging.DEBUG)

gateway = logging.getLogger("myapp.gateway")
gateway.info("Connecting to gateway...")

http = logging.getLogger("myapp.http")
http.debug("GET /api/v10/users/@me")
http.warning("Rate limited")

client = logging.getLogger("myapp.client")
client.info("Logged in as Bot#1234")
```

### Library-Only Logging

To only configure logging for your library and not the root logger:

```python
sluglogger.setup_logging(root=False)
```

### Custom Handler

```python
import logging
import sluglogger

handler = logging.FileHandler("app.log")
sluglogger.setup_logging(handler=handler, level=logging.DEBUG)
```

### Custom Formatter

```python
import logging
import sluglogger

formatter = logging.Formatter('[{asctime}] [{levelname:<8}] {name}: {message}', style='{')
sluglogger.setup_logging(formatter=formatter)
```

### Error with Traceback

```python
import logging
import sluglogger

sluglogger.setup_logging()
log = logging.getLogger("myapp")

try:
    result = 1 / 0
except ZeroDivisionError:
    log.error("Something went wrong", exc_info=True)
```

Tracebacks are always displayed in red in colour-supporting terminals.

### Advanced Setup

For more control, use Python's logging module directly:

```python
import logging
import logging.handlers

logger = logging.getLogger("myapp")
logger.setLevel(logging.DEBUG)
logging.getLogger("myapp.http").setLevel(logging.INFO)

handler = logging.handlers.RotatingFileHandler(
    filename="app.log",
    encoding="utf-8",
    maxBytes=32 * 1024 * 1024,
    backupCount=5,
)

dt_fmt = "%Y-%m-%d %H:%M:%S"
formatter = logging.Formatter("[{asctime}] [{levelname:<8}] {name}: {message}", dt_fmt, style="{")
handler.setFormatter(formatter)
logger.addHandler(handler)
```

## API

### setup_logging

```python
sluglogger.setup_logging(
    *,
    handler=...,
    formatter=...,
    level=...,
    root=True,
)
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| handler | `logging.Handler` | `StreamHandler` | The log handler to use |
| formatter | `logging.Formatter` | `_ColourFormatter` | The formatter to use |
| level | `int` | `logging.INFO` | The log level |
| root | `bool` | `True` | Whether to configure the root logger |

### stream_supports_colour

```python
sluglogger.stream_supports_colour(stream)
```

Returns `True` if the given stream supports coloured output. Checks for TTY, PyCharm, VS Code, Docker, ANSICON, and Windows Terminal.

### _ColourFormatter

A `logging.Formatter` subclass that adds ANSI colour codes to log output. Used automatically by `setup_logging` when the output stream supports colour.

## License

MIT License - see [LICENSE](LICENSE) for details.
