Opinionated Python logging config for local dev and Cloud Run/Functions
Project description
toolslog
Opinionated Python logging configuration. One import configures everything.
- Locally: human-readable plain text to stdout
- Cloud Run / Cloud Functions: structured JSON with
severityfield (auto-detected) - Zero dependencies — stdlib only
Install
pip install toolslog
Quick start
from toolslog import get_logger
logger = get_logger(__file__)
logger.debug("verbose detail") # hidden by default (level=INFO)
logger.info("normal flow")
logger.warning("potential issue")
logger.error("something failed")
logger.critical("system-level failure")
Output (local):
2026-02-26 15:03:17 | INFO | main | run:5 | normal flow
2026-02-26 15:03:17 | WARNING | main | run:6 | potential issue
2026-02-26 15:03:17 | ERROR | main | run:7 | something failed
2026-02-26 15:03:17 | CRITICAL | main | run:8 | system-level failure
Output (Cloud Run — auto-detected):
{"severity": "INFO", "message": "normal flow", "logger": "main", ...}
Log level control
Default level is INFO. Override via LOG_LEVEL environment variable.
# everything DEBUG (all modules):
LOG_LEVEL=DEBUG python main.py
# check / set / unset in current shell session:
echo $LOG_LEVEL
export LOG_LEVEL=DEBUG
unset LOG_LEVEL
Per-module overrides (in your script):
import logging
# only this script to DEBUG (imported modules stay at INFO):
logger.setLevel(logging.DEBUG)
# only a specific library to DEBUG:
logging.getLogger("toolsbq").setLevel(logging.DEBUG)
# silence a noisy library:
logging.getLogger("toolsbq").setLevel(logging.WARNING)
# suppress urllib3 connection/retry warnings:
logging.getLogger("urllib3").setLevel(logging.WARNING)
# suppress google-auth / google-api / discovery noise:
logging.getLogger("google").setLevel(logging.WARNING)
logging.getLogger("googleapiclient.discovery_cache").setLevel(logging.ERROR)
Searching logs
# errors and tracebacks:
grep -E "(\| ERROR \||\| CRITICAL \||Traceback|Error:|Exception:)" app.log
# warnings and above:
grep -E "\| (WARNING|ERROR|CRITICAL) \|" app.log
# specific module:
grep "| toolsbq |" app.log
# specific function (line number varies, so use a pattern):
grep "| fetch_data:" app.log
For libraries (toolsbq, toolssecret, etc.)
Libraries should not import toolslog. Just use the stdlib:
import logging
logger = logging.getLogger(__name__)
The calling application (which imports toolslog) configures the root logger. Libraries automatically inherit that configuration.
How it works
On import, toolslog:
- Detects environment (GCP vs local) via env vars (
K_SERVICE,FUNCTION_TARGET, etc.) - Clears any existing root logger handlers (e.g. from
functions_framework) - Adds a single handler with the appropriate formatter
- Sets the root level from
LOG_LEVELenv var (default:INFO)
This runs once — Python caches the import, so multiple from toolslog import get_logger
calls across modules are safe.
Note
This package is opinionated — it takes over the root logger. Use it in your own entry-point scripts, not in libraries you publish for others.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file toolslog-0.1.3.tar.gz.
File metadata
- Download URL: toolslog-0.1.3.tar.gz
- Upload date:
- Size: 6.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2c725e1986ae68f06e1b69a6a1676bc7d3349f7dfa8080380bca027354df56d
|
|
| MD5 |
f7469d7c69e3d53ff832b3b3302828a3
|
|
| BLAKE2b-256 |
c9ead0f3bb440a94dbeb6d1cfae7a1aa2a0f352c6c6eef81cfcd18d2bca1db94
|
File details
Details for the file toolslog-0.1.3-py3-none-any.whl.
File metadata
- Download URL: toolslog-0.1.3-py3-none-any.whl
- Upload date:
- Size: 5.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d1f9e4391969a43ae29c88fc869990f73591543fb34be53e2b2da445718581b
|
|
| MD5 |
18de2c898c99b0d5156c0ed3088c7ba8
|
|
| BLAKE2b-256 |
45a1bc1be8e623d0cf6670fd51c859340811825134265c799792644564757191
|