Metadata-Version: 2.4
Name: raven-logger
Version: 1.0.6
Summary: Application logging SDK for raven-log contract compliance — structured, validated JSON logs
Author-email: Giggso <m.abbasi@giggso.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/giggso/raven-logger
Project-URL: Issues, https://github.com/giggso/raven-logger/issues
Keywords: logging,observability,structured-logging,raven,tracing
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Logging
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: kafka
Requires-Dist: confluent-kafka>=2.0.0; extra == "kafka"
Dynamic: license-file

# raven-logger

Application logging SDK for **raven-log contract compliance** — emit validated, structured JSON records from any Python service.

## Install

```bash
# Core (stdout emitter only)
pip install raven-logger

# With Kafka emitter support
pip install "raven-logger[kafka]"
```

## Quick start

```python
from raven_logger import raven_log, new_trace_id, new_span_id

trace = new_trace_id()

raven_log(
    level="INFO",
    criticality="P3",
    message="User signed in",
    service="auth-service",
    env="prod",
    principal="user:42",
    project="my-app",
    trace_id=trace,
)
```

Output (one JSON line to stdout):

```json
{
  "schema_version": "1",
  "timestamp": "2026-06-22T12:00:00.000000+00:00",
  "level": "INFO",
  "criticality": "P3",
  "service": "auth-service",
  "env": "prod",
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "span_id": "a1b2c3d4",
  "principal": "user:42",
  "error_code": "",
  "message": "User signed in",
  "context": {},
  "sample_payload": "",
  "project": "my-app"
}
```

## Kafka emitter

`KafkaEmitter` is a production-ready emitter that sends records directly to a Kafka topic. Pass it as `_emit` to `raven_log`.

### Local / Docker broker (no authentication)

```python
from raven_logger import raven_log, KafkaEmitter

emitter = KafkaEmitter(
    bootstrap_servers="localhost:9092",
    topic="raven-logs",
    cluster_name="local-dev",   # optional label, not sent to broker
)

raven_log(
    level="INFO",
    criticality="P3",
    message="User signed in",
    service="auth-service",
    env="dev",
    principal="user:42",
    project="my-app",
    _emit=emitter,
)
```

### Authenticated cluster (SASL_SSL)

```python
emitter = KafkaEmitter(
    bootstrap_servers="broker.example.com:9092",
    topic="raven-logs",
    sasl_username="my-user",
    sasl_password="my-secret",
)
```

When `sasl_username` and `sasl_password` are provided the security protocol defaults to `SASL_SSL`. Omit both for `PLAINTEXT` (local/Docker). Providing only one raises `ValueError` at construction time.

### `KafkaEmitter` parameters

| Parameter | Required | Default | Description |
|---|---|---|---|
| `bootstrap_servers` | ✓ | — | Broker address(es), e.g. `"localhost:9092"` |
| `topic` | ✓ | — | Target Kafka topic |
| `cluster_name` | — | `""` | Human label stored on the instance; not sent to broker |
| `sasl_username` | — | `None` | SASL username; must be paired with `sasl_password` |
| `sasl_password` | — | `None` | SASL password; must be paired with `sasl_username` |
| `security_protocol` | — | auto | Overrides the auto-detected protocol (`PLAINTEXT` / `SASL_SSL`) |
| `sasl_mechanism` | — | `"PLAIN"` | SASL mechanism |

`KafkaEmitter` requires `confluent-kafka`. Install it with `pip install "raven-logger[kafka]"`.

## API

### `raven_log(...) -> dict`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `level` | `"ERROR"` \| `"WARN"` \| `"INFO"` \| `"DEBUG"` | ✓ | Log level |
| `criticality` | `"P1"` \| `"P2"` \| `"P3"` \| `"P4"` | ✓ | Business criticality |
| `message` | `str` | ✓ | Human-readable description |
| `service` | `str` | ✓ | Emitting service name |
| `env` | `"prod"` \| `"staging"` \| `"dev"` | ✓ | Deployment environment |
| `principal` | `str` | ✓ | Acting identity (e.g. `"user:42"`) |
| `project` | `str` | ✓ | Project/team identifier |
| `error_code` | `str` | Required for `ERROR`/`WARN` | Machine-readable error code |
| `trace_id` | `str` | — | Distributed trace ID (auto-generated if omitted) |
| `span_id` | `str` | — | Span ID (auto-generated if omitted) |
| `context` | `dict` | — | Arbitrary structured context |
| `sample_payload` | `str` | — | Redacted payload snippet |
| `_emit` | `callable` | — | Custom emitter; defaults to stdout JSON writer |

Returns the emitted record as a `dict`.

### `new_trace_id() -> str`

Generates a UUID v4 trace ID for use at service boundaries.

### `new_span_id() -> str`

Generates an 8-character span ID for operations within a trace.

## License

MIT © Giggso
