Skip to content

Quick Start

Basic Usage (Zero-Config)

import logging
import hushlog

logging.basicConfig(level=logging.INFO)
hushlog.patch()

logger = logging.getLogger(__name__)

logger.info("User email: john@example.com")
# Output: User email: [EMAIL REDACTED]

logger.info("Card: 4111-1111-1111-1111")
# Output: Card: [CREDIT_CARD REDACTED]

logger.info("SSN: 123-45-6789")
# Output: SSN: [SSN REDACTED]

Note

Call logging.basicConfig() (or set up handlers) before hushlog.patch(). patch() wraps handlers that exist at call time.

Partial Masking

from hushlog import Config

hushlog.patch(Config(mask_style="partial"))

logger.info("User email: john@example.com")
# Output: User email: j***@e***.com

logger.info("Card: 4111111111111111")
# Output: Card: ****-****-****-1111

Custom Mask Character

hushlog.patch(Config(mask_style="partial", mask_character="#"))
# Output: j###@e###.com

Disable Specific Patterns

hushlog.patch(Config(disable_patterns=frozenset({"phone", "ipv4"})))

Add Custom Patterns

hushlog.patch(Config(
    custom_patterns={"internal_id": r"ID-[A-Z]{3}-[0-9]{6}"},
))
# Matches: ID-ABC-123456 → [INTERNAL_ID REDACTED]

Teardown

hushlog.unpatch()  # Restores original formatters

Both patch() and unpatch() are idempotent — safe to call multiple times.

JSON Logging

from hushlog import RedactingJsonFormatter

formatter = RedactingJsonFormatter.from_config()
handler.setFormatter(formatter)

structlog

import structlog
from hushlog import structlog_processor

structlog.configure(
    processors=[
        structlog.stdlib.add_log_level,
        structlog_processor(),
        structlog.dev.ConsoleRenderer(),
    ],
)

loguru

from loguru import logger
from hushlog import loguru_sink

logger.remove()
logger.add(loguru_sink(print), format="{message}")

Dict Redaction (Standalone)

import hushlog

data = {"user": {"email": "alice@corp.io", "age": 30}}
clean = hushlog.redact_dict(data)
# {"user": {"email": "[EMAIL REDACTED]", "age": 30}}