Getting started
Installation
Very minimal usage
Output (without rich
library installed):
2023-03-29T14:48:37Z root [ INFO ] It works {foo=bar x=123}
2023-03-29T14:48:37Z root [ CRITICAL ] Houston, we have a problem!
Output (with rich
library installed):
Basic usage
from stlog import getLogger, setup
# Set the logging default configuration (human output on stderr)
setup()
# Get a logger
logger = getLogger(__name__)
logger.info("It works", foo="bar", x=123)
logger.critical("Houston, we have a problem!")
Output (without rich
library installed):
2023-03-29T14:48:37Z __main__ [ INFO ] It works {foo=bar x=123}
2023-03-29T14:48:37Z __main__ [ CRITICAL ] Houston, we have a problem!
Output (with rich
library installed):
Usage with context
from stlog import LogContext, getLogger, setup
# Set the logging default configuration (human output on stderr)
setup()
# ...
# Set the (kind of) global execution context
# (thread, worker, async friendly: one context by execution)
# (for example in a wsgi/asgi middleware)
# Note: ExecutionContext is a static class, so a kind of global singleton
LogContext.reset_context()
LogContext.add(request_id="4c2383f5")
LogContext.add(client_id=456, http_method="GET")
# ... in another file/class/...
# Get a logger
logger = getLogger(__name__)
logger.info("It works", foo="bar", x=123)
logger.critical("Houston, we have a problem!")
Output (without rich
library installed):
2023-03-29T14:48:37Z __main__ [ INFO ] It works {client_id=456 foo=bar http_method=GET request_id=4c2383f5 x=123}
2023-03-29T14:48:37Z __main__ [ CRITICAL ] Houston, we have a problem! {client_id=456 http_method=GET request_id=4c2383f5}
Output (with rich
library installed):
What about if you want to get a more parsing friendly output (for example in JSON on stdout
) while keeping the human output on stderr
(without any context)?
import sys
from stlog import LogContext, getLogger, setup
from stlog.output import StreamOutput
from stlog.formatter import HumanFormatter, JsonFormatter
setup(
outputs=[
StreamOutput(
stream=sys.stderr,
formatter=HumanFormatter(exclude_extras_keys_fnmatchs=["*"]),
),
StreamOutput(stream=sys.stdout, formatter=JsonFormatter(indent=4)),
]
)
# See previous example for details
LogContext.reset_context()
LogContext.add(request_id="4c2383f5")
LogContext.add(client_id=456, http_method="GET")
logger = getLogger(__name__)
logger.info("It works", foo="bar", x=123)
logger.critical("Houston, we have a problem!")
Human output (on stderr
):
2023-03-29T14:48:37Z __main__ [ INFO ] It works
2023-03-29T14:48:37Z __main__ [ CRITICAL ] Houston, we have a problem!
JSON ouput (on stdout
) for machines:
{
"client_id": 456,
"foo": "bar",
"http_method": "GET",
"level": "INFO",
"logger": "__main__",
"message": "It works",
"request_id": "4c2383f5",
"source": {
"funcName": "<module>",
"lineno": 21,
"module": "qs3",
"path": "/path/filename.py",
"process": 6789,
"processName": "MainProcess",
"thread": 12345,
"threadName": "MainThread"
},
"time": "2023-03-29T14:48:37Z",
"x": 123
}
{
"client_id": 456,
"http_method": "GET",
"level": "CRITICAL",
"logger": "__main__",
"message": "Houston, we have a problem!",
"request_id": "4c2383f5",
"source": {
"funcName": "<module>",
"lineno": 22,
"module": "qs3",
"path": "/path/filename.py",
"process": 6789,
"processName": "MainProcess",
"thread": 12345,
"threadName": "MainThread"
},
"time": "2023-03-29T14:48:37Z"
}