Plain is headed towards 1.0! Subscribe for development updates →

Logging

Default logging settings and key-value logger.

In Python, logging can be a surprisingly complex topic.

So Plain aims for easy-to-use defaults that "just work".

app_logger

The default app_logger doesn't do much!

But it is paired with the default settings to actually show the logs like you would expect, without any additional configuration.

from plain.logs import app_logger


def example_function():
    app_logger.info("Hey!")

app_logger.kv

 1import logging
 2
 3request_logger = logging.getLogger("plain.request")
 4
 5
 6def log_response(
 7    message,
 8    *args,
 9    response=None,
10    request=None,
11    logger=request_logger,
12    level=None,
13    exception=None,
14):
15    """
16    Log errors based on Response status.
17
18    Log 5xx responses as errors and 4xx responses as warnings (unless a level
19    is given as a keyword argument). The Response status_code and the
20    request are passed to the logger's extra parameter.
21    """
22    # Check if the response has already been logged. Multiple requests to log
23    # the same response can be received in some cases, e.g., when the
24    # response is the result of an exception and is logged when the exception
25    # is caught, to record the exception.
26    if getattr(response, "_has_been_logged", False):
27        return
28
29    if level is None:
30        if response.status_code >= 500:
31            level = "error"
32        elif response.status_code >= 400:
33            level = "warning"
34        else:
35            level = "info"
36
37    getattr(logger, level)(
38        message,
39        *args,
40        extra={
41            "status_code": response.status_code,
42            "request": request,
43        },
44        exc_info=exception,
45    )
46    response._has_been_logged = True