Simplest way to perform logging from Google Cloud Run

An easy way to integrate Google Cloud Platform logging into your Python code is to create a subclass from logging.StreamHandler. This way logging levels will also match those of Google Cloud Logging, enabling you to filter based on severity. This solution also works within Cloud Run containers.

Also you can just add this handler to any existing logger configuration, without needing to change current logging code.

import json
import logging
import os
import sys
from logging import StreamHandler

from flask import request


class GoogleCloudHandler(StreamHandler):
    def __init__(self):
        StreamHandler.__init__(self)

    def emit(self, record):
        msg = self.format(record)
        # Get project_id from Cloud Run environment
        project = os.environ.get('GOOGLE_CLOUD_PROJECT')

        # Build structured log messages as an object.
        global_log_fields = {}
        trace_header = request.headers.get('X-Cloud-Trace-Context')

        if trace_header and project:
            trace = trace_header.split('/')
            global_log_fields['logging.googleapis.com/trace'] = (
                f"projects/{project}/traces/{trace[0]}")

        # Complete a structured log entry.
        entry = dict(severity=record.levelname, message=msg)
        print(json.dumps(entry))
        sys.stdout.flush()

A way to configure and use the handler could be:

def get_logger():
    logger = logging.getLogger(__name__)

    if not logger.handlers:
        gcp_handler = GoogleCloudHandler()
        gcp_handler.setLevel(logging.DEBUG)

        gcp_formatter = logging.Formatter(
            '%(levelname)s %(asctime)s [%(filename)s:%(funcName)s:%(lineno)d] %(message)s')
        gcp_handler.setFormatter(gcp_formatter)
        logger.addHandler(gcp_handler)
    return logger

#For Python/Java

Using "google-cloud-logging" module is the easiest way to push container logs to Stackdriver logs. COnfigure google-cloud-logging to work with python's default logging module

import logging as log
import google.cloud.logging as logging

def doSomething(param):
    logging_client = logging.Client()
    logging_client.setup_logging()
log.info(f"Some log here: {param}") 

now you should see this log in Stackdriver logging under Cloud Run Revision.


I am running into the exact same issue. I did find that flushing stdout causes the logging to appear when it otherwise would not. Looks like a bug in Cloud Run to me.

print(json.dumps(entry))
import sys
sys.stdout.flush()

Output with flushing