pfroggy 0.1.1
A super configurable logging library for Python
License: MIT
Requires Python: >=3.9
Keywords: logging, logger, structured-logging, json-logging

# pfroggy 🐸

**Current version: 0.1.1**

A super configurable logging library for Python.

## Features

- **Multiple handlers**: Console, file, rotating file, JSON, HTTP/webhook
- **Flexible formatters**: Plain text, JSON, colored console output
- **Powerful filtering**: By level, regex, custom callables
- **Structured logging**: Key-value pairs alongside messages
- **Context & correlation IDs**: Request tracing support
- **Async-safe**: Context variables for async code
- **Configuration**: Programmatic, dict, YAML, or TOML

## Installation

```bash
pip install pfroggy

# With optional dependencies
pip install pfroggy[color]  # Colorama for Windows color support
pip install pfroggy[yaml]   # YAML config file support
pip install pfroggy[http]   # HTTP handler support
pip install pfroggy[all]    # All optional dependencies
```

## Quick Start

**Intent:** Get logging working with minimal code—just configure a level and start logging.

```python
import pfroggy

# Simple setup
logger = pfroggy.configure(level="INFO")
logger.info("Hello, world!")

# Get a named logger
log = pfroggy.get_logger("myapp.module")
log.info("Processing request", user_id=123, action="login")
```

The `configure()` helper sets up a root logger with sensible defaults (console output, colors). Named loggers form a hierarchy (`myapp.module` is a child of `myapp`), allowing granular control over log levels and handlers.

## Structured Logging

**Intent:** Attach arbitrary key-value data to log messages for better searchability and analysis.

```python
from pfroggy import Logger, ConsoleHandler, JsonFormatter

logger = Logger.get_logger("api")
handler = ConsoleHandler()
handler.formatter = JsonFormatter()
logger.add_handler(handler)

logger.info("Request received", method="GET", path="/users", duration_ms=45)
# {"timestamp": "2024-01-15T10:30:00", "level": "INFO", "logger": "api", "message": "Request received", "extra": {"method": "GET", "path": "/users", "duration_ms": 45}}
```

Any `**kwargs` passed to log methods become structured `extra` fields. Combined with `JsonFormatter`, this produces machine-parseable logs ideal for log aggregation systems like ELK or Datadog.

## Context & Correlation IDs

**Intent:** Automatically include request-scoped metadata (like user or request ID) in all logs within a scope, without passing it explicitly.

```python
from pfroggy import get_logger
from pfroggy.core.context import LogContext

logger = get_logger("api")

with LogContext(correlation_id="req-123", user="alice"):
    logger.info("Processing")  # Includes correlation_id and user in output
    do_work()
    logger.info("Done")
```

`LogContext` uses Python's `contextvars`, making it async-safe. All logs within the context block automatically include the correlation ID and any context fields—perfect for tracing requests across services.

## Bound Loggers

**Intent:** Create a logger that always includes certain fields, reducing repetition when logging from a specific component.

```python
logger = get_logger("worker")
job_logger = logger.bind(job_id="job-456", queue="high")

job_logger.info("Starting")  # Always includes job_id and queue
job_logger.info("Completed")
```

Bound loggers are lightweight wrappers that merge preset fields with each log call. Useful for background jobs, request handlers, or any code where certain context is constant.

## Configuration from Dict

**Intent:** Configure logging declaratively from application config (e.g., loaded from environment or config files) without writing setup code.

```python
from pfroggy import configure_from_dict

configure_from_dict({
    "level": "INFO",
    "handlers": [
        {
            "type": "console",
            "colorize": True,
            "formatter": {"type": "text", "format": "{timestamp} [{level}] {message}"}
        },
        {
            "type": "rotating_file",
            "filename": "app.log",
            "max_bytes": 10485760,
            "backup_count": 5,
            "formatter": {"type": "json"}
        }
    ]
})
```

This enables environment-specific logging (verbose in dev, JSON to files in prod) by swapping config dicts. Supports all handler types and formatter options.

## Configuration from File

**Intent:** Load logging configuration from external YAML/TOML files, keeping code clean and config separate.

```python
from pfroggy.config import configure_from_file

# From YAML (requires pfroggy[yaml])
configure_from_file("logging.yaml")

# From TOML
configure_from_file("logging.toml")
```

The file format mirrors the dict structure. YAML requires the `[yaml]` extra; TOML uses `tomllib` (Python 3.11+) or falls back to `tomli`.

## Custom Filters

**Intent:** Control which log records reach a handler beyond just level filtering—exclude noise, include only important events, etc.

```python
from pfroggy import Logger, ConsoleHandler
from pfroggy.filters.regex import RegexFilter
from pfroggy.filters.callable import CallableFilter

logger = Logger.get_logger()
handler = ConsoleHandler()

# Exclude health check logs
handler.add_filter(RegexFilter(r"health.?check", exclude=True))

# Custom filter
handler.add_filter(CallableFilter(lambda r: r.extra.get("important", False)))

logger.add_handler(handler)
```

Filters can be attached to loggers or individual handlers. `RegexFilter` matches message content; `CallableFilter` accepts any predicate function for full flexibility.

## Colored Console Output

**Intent:** Make logs easier to scan visually by color-coding severity levels.

```python
from pfroggy import Logger, Level, ConsoleHandler, TextFormatter, Color

logger = Logger.get_logger("app")
logger.level = Level.TRACE

# Default colors: TRACE=gray, DEBUG=cyan, INFO=green, WARNING=yellow, ERROR=red, CRITICAL=bold magenta
handler = ConsoleHandler(level=Level.TRACE, colorize=True)
handler.formatter = TextFormatter(fmt="[{level}] {message}")
logger.add_handler(handler)

logger.trace("Detailed trace info")
logger.debug("Debug information")
logger.info("Application started")
logger.warning("Disk space low")
logger.error("Connection failed")
logger.critical("System shutting down")
```

**Example output:**

![Output](/res/default_colors.png)

### Preset Color Schemes

```python
# Available: "default", "minimal", "bold", "pastel"
handler = ConsoleHandler(colors="bold")
```

### Custom Colors

```python
from pfroggy import Color, Level

handler = ConsoleHandler(colors={
    Level.INFO: Color.BLUE,
    Level.WARNING: Color.BOLD + Color.YELLOW,
    Level.ERROR: Color.BOLD + Color.BG_RED + Color.WHITE,
})

# Or modify at runtime
handler.set_color(Level.INFO, Color.MAGENTA + Color.UNDERLINE)
handler.set_colors("pastel")  # Switch entire scheme
```

### Available Color Constants

| Category | Constants |
|----------|-----------|
| Standard | `BLACK`, `RED`, `GREEN`, `YELLOW`, `BLUE`, `MAGENTA`, `CYAN`, `WHITE` |
| Bright | `BRIGHT_BLACK`, `BRIGHT_RED`, `BRIGHT_GREEN`, `BRIGHT_YELLOW`, `BRIGHT_BLUE`, `BRIGHT_MAGENTA`, `BRIGHT_CYAN`, `BRIGHT_WHITE` |
| Styles | `BOLD`, `DIM`, `ITALIC`, `UNDERLINE` |
| Backgrounds | `BG_RED`, `BG_GREEN`, `BG_YELLOW`, `BG_BLUE`, `BG_MAGENTA`, `BG_CYAN`, `BG_WHITE` |

Combine constants with `+`: `Color.BOLD + Color.BG_RED + Color.WHITE`

## Handlers

| Handler | Description |
|---------|-------------|
| `ConsoleHandler` | Writes to stdout/stderr with optional colors |
| `FileHandler` | Writes to a file |
| `RotatingFileHandler` | Rotates files by size |
| `JsonFileHandler` | Writes JSON-formatted logs |
| `HttpHandler` | Sends logs to HTTP endpoint (requires `pfroggy[http]`) |

## License

MIT