Creating GCP-compatible structured log messages in Python

The Google Cloud Platform supports structured logging. All it takes is writing JSON objects to stdout
or stderr
. With structlog
, it’s straightforward to set up a processor chain that produces compatible log messages.
There are two special fields that are essential for filtering and searching logs:
The
severity
field takes one of nine different values fromDEBUG
toEMERGENCY
.The
message
field is shown in the log entry line in the GCP Logs Explorer.
Thus, we first map the ten structlog
methods to the nine LogSeverity values:
from structlog import EventDict
STRUCTLOG_TO_GCP = {
"critical": "CRITICAL",
"debug": "DEBUG",
"err": "ERROR",
"error": "ERROR",
"failure": "ALERT",
"fatal": "EMERGENCY",
"info": "INFO",
"log": "DEFAULT",
"msg": "DEFAULT",
"warning": "WARNING",
# Unused GCP severity: "NOTICE"
}
def add_gcp_severity(
_, method_name: str, event_dict: EventDict
) -> EventDict:
event_dict["severity"] = STRUCTLOG_TO_GCP.get(method_name,
"DEFAULT")
return event_dict
Then, we use two built-in structlog
processors to rename the event
field to message
and output everything as JSON:
import structlog
structlog.configure(
processors=[
add_gcp_severity,
structlog.processors.EventRenamer("message"),
structlog.processors.JSONRenderer(),
]
)
This produces messages in the right format:
log = structlog.get_logger()
log.info("Hello World!", key="value")
# {"key": "value", "severity": "INFO", "message": "Hello World!"}
Subscribe to my newsletter
Read articles from Kilian Kluge directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Kilian Kluge
Kilian Kluge
My journey into software and infrastructure engineering started in a physics research lab, where I discovered the merits of loose coupling and adherence to standards the hard way. I like automated testing, concise documentation, and hunting complex bugs.