30
loading...
This website collects cookies to deliver better user experience
# src/helpers/structlog
import structlog
from structlog.dev import set_exc_info, ConsoleRenderer
from structlog.processors import StackInfoRenderer, TimeStamper, add_log_level
def config_structlog():
structlog.configure_once(
processors=[
add_log_level,
StackInfoRenderer(),
set_exc_info,
TimeStamper(fmt="%Y-%m-%d %H:%M.%S", utc=False),
ConsoleRenderer(),
]
)
main.py
, we use this helper function like this:from src.helpers.structlog import config_structlog
import structlog
config_structlog
def hello_world(_request):
logger = structlog.get_logger()
logger.msg('hello world')
return "", 200
ENVIRONMENT
) that can be set to local
or production
.ENVIRONMENT
is set to production
, we will use a JSON renderer instead of the ConsoleRenderer. We also don't care about timestamps as GCP adds timestamps regardless.level
while GCP expects it to be uppercase and under severity
. Another default behaviour is that GCP will print our whole json-message in the summary line if we don't include a message
. We can solve that by creating our own processors (_GCP_severity_processor and _GCP_add_display_message).Edit from the future (2022-01-04): We learned that if you add a property called
import os
from typing import Any
import structlog
from structlog.dev import set_exc_info, ConsoleRenderer
from structlog.processors import StackInfoRenderer, TimeStamper, add_log_level
def config_structlog():
# Custom renderer when in development:
if os.getenv("PP_ENVIRONMENT") == "local":
structlog.configure_once(
processors=[
add_log_level,
StackInfoRenderer(),
set_exc_info,
TimeStamper(fmt="%Y-%m-%d %H:%M.%S", utc=False),
ConsoleRenderer(),
]
)
else:
structlog.configure_once(
processors=[
add_log_level,
StackInfoRenderer(),
set_exc_info,
_GCP_severity_processor,
_GCP_add_display_message,
structlog.processors.JSONRenderer(),
]
)
def _GCP_severity_processor(
logger: Any,
method_name: str,
event_dict: Any,
) -> Any:
"""
Add GCP severity to event_dict.
Level is not a perfect one to one mapping to GCP severity.
Here are the avaliable levels/method names:
- debug
- info
- warning
- warn (translates to warning as level)
- error
- err
- fatal
- exception
- critical
- msg
"""
event_dict["severity"] = event_dict["level"].upper()
del event_dict["level"]
return event_dict
def _GCP_add_display_message(
logger: Any,
method_name: str,
event_dict: Any,
) -> Any:
"""
Add display message to event_dict.
By default GCP logs will just show a string representation of the full blob.
To show the message only you can use this processor.
"""
event_dict["message"] = event_dict["event"]
del event_dict["event"]
return event_dict
rich
(run pip install rich
), you get beautiful, pretty printed exceptions. They look like this:log.exception()
because otherwise rich
will crash.src/helpers/structlog.py
and call it before using the logger.