Skip to main content

A tiny, dependency-free logging framework with PII scrubbing, JSON output, and colored CLI logs

Project description

oak

Screenshot 2026-08-01 at 4 23 37 PM

PyPi: https://pypi.org/project/oak-logging/1.0.0/ Try it out! https://kavya-24.github.io/oak-logging/

A tiny, dependency-free logging framework for Python, built on top of the standard library's logging. It gives you:

  • Levelsdebug, info, warning, error, exception
  • Structured errors — a dedicated formatter prints exception type, message and traceback in a readable block
  • PII scrubbing — redacts emails, phone numbers, SSNs, credit cards, IPs, and sensitive field names (passwords, tokens, API keys, ...) from messages and extra fields
  • JSON output — structured, machine-friendly lines for shipping to log aggregators
  • Colored CLI logs — automatic ANSI colors on TTYs
  • Simple initialization — one init() call to configure everything

Zero dependencies. Python 3.9+.

Install

pip install oak-logging   # import stays `import oak`

Or from source:

pip install -e .

Quick start

import oak

log = oak.init("DEBUG")

log.debug("entering parse loop")
log.info("user signed up", extra={"user_id": 42})
log.warning("disk at 90%", extra={"usage_pct": 90.1})
log.error("payment failed")

Output (colors shown when writing to a terminal):

2026-08-01 15:30:00 DEBUG app: entering parse loop
2026-08-01 15:30:00 INFO  app: user signed up
2026-08-01 15:30:00 WARNING app: disk at 90%
2026-08-01 15:30:00 ERROR app: payment failed

Initialization options

log = oak.init(
    level="DEBUG",          # str or int; default "INFO"
    output="console",       # "console", "json", or a file path
    format="%(asctime)s %(levelname)s %(name)s: %(message)s",
    error_format=True,      # structured block for ERROR+ logs
    pii_scrubbing=True,     # redact PII from messages and extra fields
    color=None,             # None=auto (TTY), True=force, False=off
    name="app",             # underlying stdlib logger name
)

You can also configure the root logger imperatively with oak.configure(...), and grab additional loggers with oak.get_logger("worker") — they share the same configuration.

PII scrubbing

PII is redacted from the log message itself and from any extra values:

  1. Pattern-based — known PII shapes are redacted anywhere in the message:

    log.info("contact jane@example.com or 555-123-4567")
    # contact [REDACTED] or [REDACTED]
    
  2. Key-basedextra fields whose names look sensitive are redacted (including nested dicts and lists):

    log.info("signup", extra={
        "email": "jane@example.com",   # redacted
        "password": "hunter2",         # redacted
        "user_id": 7,                  # kept
    })
    

    extra is not printed by default — it behaves exactly like stdlib logging: reference a key in your format string to see it, and the scrubbed value is what gets logged:

    log = oak.init(format="%(asctime)s %(levelname)s %(email)s")
    # 2026-08-01 15:30:00 INFO [REDACTED]
    

Covered patterns: email, phone numbers, SSNs, credit card numbers, IPv4 and MAC addresses. Sensitive key names include email, password, token, api_key, ssn, credit_card, and more. Disable scrubbing with pii_scrubbing=False if you ever need to (not recommended).

Scrubbing helpers are public too: oak.scrub_message, oak.scrub_extra, oak.scrub_value, and oak.REDACTED.

Structured errors

With the default error_format=True, ERROR/exception logs get a readable, structured error block:

try:
    json.loads(bad_payload)
except ValueError:
    log.exception("could not parse payload")
2026-08-01 15:30:00 ERROR app: could not parse payload
  ERROR TYPE: JSONDecodeError
  ERROR MSG : Expecting value: line 1 column 1 (char 0)
  TRACEBACK:
  Traceback (most recent call last):
    ...

JSON output

log = oak.init("INFO", json=True)
log.info("order placed")
log.error("payment failed for jane@example.com")
{"ts": "2026-08-01T15:30:00", "level": "INFO", "logger": "app", "message": "order placed"}
{"ts": "2026-08-01T15:30:00", "level": "ERROR", "logger": "app", "message": "payment failed for [REDACTED]"}

File output

log = oak.init(level="INFO", output="app.log")

Demo

oak-demo

Development

python -m venv .venv
.venv/bin/pip install -e . pytest
.venv/bin/python -m pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oak_logging-1.0.0.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oak_logging-1.0.0-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file oak_logging-1.0.0.tar.gz.

File metadata

  • Download URL: oak_logging-1.0.0.tar.gz
  • Upload date:
  • Size: 11.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.5

File hashes

Hashes for oak_logging-1.0.0.tar.gz
Algorithm Hash digest
SHA256 2c59f8f8433ce5aa1a209004410942af4c31c3011c47fea6d29c9f641f687eb3
MD5 c6ffd1886b50d0bc211ddfa64d32c0c0
BLAKE2b-256 acebc4a134a83de7c95fcbe14f31f0c4a499d774cde6aeb9f77fa61c9f248c7b

See more details on using hashes here.

File details

Details for the file oak_logging-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: oak_logging-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.5

File hashes

Hashes for oak_logging-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bcd3e6beb1f1f2959e861ff044a6c78b5524b380f66bdcb1c5997753b38d5086
MD5 799e526c318de477b87d8237800c8ebb
BLAKE2b-256 07c90bfcaf2a73522fd952a8115735ba4ffea9da8b0a2c3e3654ebef57cc43eb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page