koussay/dev/: flask-pii-logger-0.1.0 metadata and description
Structured JSON logger with PII redaction for Flask apps
| author_email | OneCloud Infrastructure <admin@cloudteam.tn> |
| classifiers |
|
| description_content_type | text/markdown |
| keywords | flask,logging,pii,redaction,json |
| license | MIT |
| metadata_version | 2.4 |
| project_urls |
|
| provides_extras |
|
| requires_dist |
|
| requires_python | >=3.10 |
Because this project isn't in the mirror_whitelist,
no releases from root/pypi are included.
| File | Tox results | History |
|---|---|---|
flask_pii_logger-0.1.0-py3-none-any.whl
|
|
|
flask_pii_logger-0.1.0.tar.gz
|
|
flask-pii-logger
Structured JSON logger with automatic PII redaction for Flask applications.
Logs are emitted as single-line JSON objects — ready to ship to Datadog, CloudWatch, Loki, or any log aggregator — with sensitive fields like passwords, tokens, IBANs, and card numbers scrubbed automatically before they ever hit disk.
Features
- Structured JSON output on every log line
- Automatic PII redaction — passwords, tokens, IBANs, card numbers, API keys
- Per-request context stamping via
put_context - Rotating file handler + stdout handler out of the box
- Works with any Flask app factory pattern
- Full exception logging with stack traces (also redacted)
Installation
pip install flask-pii-logger
Or from source:
git clone https://github.com/your-org/flask-pii-logger.git
cd flask-pii-logger
uv venv
uv pip install -e ".[dev]"
Quick Start
import logging
from flask import Flask
from flask_pii_logger import logger
def create_app():
app = Flask(__name__)
logger.init(
app,
level=logging.INFO,
log_file="/var/log/myapp/app.log", # optional — omit for stdout only
backup_count=15, # optional — rotated files to keep
)
return app
Logging
from flask_pii_logger import logger
logger.info("User signed in", event="auth.login", user_id=42)
logger.warning("Rate limit approaching", event="rate.warning", remaining=5)
logger.error("Payment declined", event="payment.declined", order_id="ord_123")
logger.debug("Request payload", event="debug.payload", body=request.json)
# Inside an except block — captures type, message, and full stack trace
try:
process_payment()
except Exception as exc:
logger.exception(exc, event="payment.failed", order_id="ord_123")
Per-Request Context
Use put_context inside before_request to stamp every log in that request with shared fields like request_id, user_id, or tenant_id:
import uuid
from flask import request
from flask_pii_logger import logger
@app.before_request
def attach_context():
logger.put_context("request_id", str(uuid.uuid4()))
logger.put_context("method", request.method)
logger.put_context("path", request.path)
Every subsequent log in that request will automatically include those fields:
{
"timestamp": "2026-05-06T10:00:00.000Z",
"level": "INFO",
"name": "myapp",
"message": "Payment done",
"event": "payment.success",
"order_id": "ord_123",
"request_id": "a1b2-c3d4",
"method": "POST",
"path": "/pay"
}
PII Redaction
Redaction is automatic — you never need to scrub data manually before logging.
Sensitive keys are redacted by name regardless of value:
| Key | Redacted |
|---|---|
password, password_hash |
yes |
token, access_token, refresh_token |
yes |
authorization, auth |
yes |
secret, client_secret |
yes |
api_key, x_api_key |
yes |
iban, account_number |
yes |
card_number, cvv |
yes |
Pattern-based redaction runs on all string values:
| Pattern | Example |
|---|---|
| IBAN | GB29NWBK60161331926819 → [REDACTED] |
| Card numbers | 4111 1111 1111 1111 → [REDACTED] |
| Bearer tokens | Authorization: Bearer eyJ... → [REDACTED] |
| Inline secrets | password=s3cr3t → [REDACTED] |
Redaction applies recursively to nested dicts, lists, and tuples:
logger.info("User updated", user={
"name": "Alice",
"password": "s3cr3t", # → [REDACTED]
"card_number": "4111..." # → [REDACTED]
})
Log Output Format
Every line is a single JSON object:
{
"timestamp": "2026-05-06T10:00:01.123Z",
"level": "ERROR",
"name": "myapp",
"message": "Unhandled exception",
"event": "payment.failed",
"error": {
"type": "TimeoutError",
"message": "Gateway timed out",
"stack": ["Traceback (most recent call last):", "..."]
},
"order_id": "ord_123",
"request_id": "a1b2-c3d4"
}
API Reference
logger.init(app, level, log_file, backup_count)
Initializes the logger. Call once in your app factory.
| Parameter | Type | Default | Description |
|---|---|---|---|
app |
Flask |
required | Your Flask application instance |
level |
int |
logging.INFO |
Minimum log level |
log_file |
str | None |
None |
Path to rotating log file. None logs to stdout only |
backup_count |
int |
15 |
Number of rotated log files to keep |
logger.info(msg, event, **kwargs)
logger.warning(msg, event, **kwargs)
logger.error(msg, event, **kwargs)
logger.debug(msg, event, **kwargs)
Log at the given level. All extra keyword arguments are included as fields in the JSON output.
| Parameter | Type | Description |
|---|---|---|
msg |
str |
Log message |
event |
str | None |
Machine-readable event name e.g. payment.failed |
**kwargs |
Any |
Any extra fields to include in the log |
logger.exception(exc, message, event, **kwargs)
Log an exception with full stack trace. Use inside except blocks.
| Parameter | Type | Default | Description |
|---|---|---|---|
exc |
Exception |
required | The caught exception |
message |
str |
"Unhandled exception" |
Human-readable message |
event |
str | None |
None |
Machine-readable event name |
logger.put_context(key, value)
Attach a field to the current request's log context. Must be called within a Flask request context (e.g. inside before_request).
Development
# Clone and set up
git clone https://github.com/your-org/flask-pii-logger.git
cd flask-pii-logger
uv venv
uv pip install -e ".[dev]"
# Run tests
uv run pytest tests/ -v