Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest way to perform logging from Google Cloud Run

I followed this guide https://firebase.google.com/docs/hosting/cloud-run to setup cloud run docker. Then I tried to follow this guide https://cloud.google.com/run/docs/logging to perform a simple log. Trying to write a structured log to stdout This is my code:

    trace_header = request.headers.get('X-Cloud-Trace-Context')

    if trace_header:
        trace = trace_header.split('/')
        global_log_fields['logging.googleapis.com/trace'] = "projects/sp-64d90/traces/" + trace[0]

    # Complete a structured log entry.
    entry = dict(severity='NOTICE',
                 message='This is the default display field.',
                 # Log viewer accesses 'component' as jsonPayload.component'.
                 component='arbitrary-property',
                 **global_log_fields)

    print(json.dumps(entry))

I cannot see this log in the Cloud Logs Viewer. I do see the http Get logs each time I call the docker. Am I missing anything? I am new to this and wondered what is the simples way to be able to log information and view it assuming the docker I created was exactly with the steps from the guide (https://firebase.google.com/docs/hosting/cloud-run)

Thanks

like image 724
Zorik Avatar asked Mar 24 '20 09:03

Zorik


3 Answers

#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.

like image 74
Onkar Avatar answered Oct 05 '22 10:10

Onkar


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

like image 34
offlinemark Avatar answered Oct 05 '22 10:10

offlinemark


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
like image 36
DfreakD Avatar answered Oct 05 '22 10:10

DfreakD