Handlers
Logger reference

Synchronous HTTP Handler

SyncHTTPHandler is a stdlib logging.Handler implementation that forwards log records to an HTTP endpoint using the requests library.

1. Behavior and Context

The handler is intended for sink entries with type: "http" in the config pipeline. It supports:

  • configurable HTTP method
  • optional headers
  • payload normalization from LogRecord
  • compatibility with both running and non-running event-loop contexts

2. Purpose

  • Transport Bridge: Connect stdlib logging to HTTP collectors.
  • Minimal Coupling: Works with plain logging and structlog output.
  • Resilience: Best-effort delivery without raising into application flow.

3. High-Level API & Examples

Example 1: Direct Handler Usage

python
import logging
from jazzmine.logging.handlers import SyncHTTPHandler

handler = SyncHTTPHandler(
    url="https://collector.internal/logs",
    method="POST",
    headers={"Authorization": "Bearer <token>"},
)

logger = logging.getLogger("http_logger")
logger.setLevel(logging.INFO)
logger.addHandler(handler)

logger.info('{"event":"startup","ok":true}')

Example 2: Through Package Config

python
from jazzmine.logging import BaseLogger

logger = BaseLogger({
    "name": "gateway",
    "level": "INFO",
    "json": True,
    "sinks": [
        {
            "type": "http",
            "url": "https://collector.internal/logs",
            "method": "POST",
            "headers": {"X-Api-Key": "<key>"},
        }
    ],
})
logger.resolve_config()
logger.info("payment accepted", order_id="o-17")

4. Detailed Class Functionality

__init__(url, method='POST', headers=None, timeout=2.0)

  • Validates requests dependency.
  • Stores endpoint, upper-cased method, headers, and timeout.

emit(record: logging.LogRecord) -> None

  • Builds payload:
  • if record.msg is dict or list, uses directly
  • else attempts json.loads(record.getMessage())
  • fallback payload is { "message": ..., "level": ... }
  • If an event loop is running, submits _post(payload) via asyncio.to_thread.
  • If no event loop, sends synchronously.
  • Any exception triggers handleError(record).

_post(payload) -> None

  • Sends JSON payload using requests.post or generic requests.request.
  • Swallows network exceptions.

5. Error Handling

  • LoggerDependencyError during initialization if requests is missing.
  • Delivery errors are swallowed in _post.
  • emit wraps failures with standard logging handleError semantics.

6. Remarks

  • This handler is best-effort; it does not provide retry, backoff, or DLQ semantics.
  • For high-volume async delivery, prefer the async worker-based path.