Which is a better way of saving Cloud Logging for Python in Cloud Functions?
Tags: googlecloud, python
Published: 2022-02-12 11:09:04

There were multiple ways to save logs from Cloud Functions to Cloud Logging using Python, so I tried to organize the merits and demerits in a simple way.

# TL;DR

|ways|1.Standard Logger|2.Structured logging|3.Official logging handlers|4.Using Cloud Logging API directly|
|:--|:--|:--|:--|:--|
|no needs to extra libraries|✔|✔|-|-|
|allows log severity|-|✔|✔|✔|
|allows to add other fields|-|✔|-|✔|
|allows Python 3.7|✔|-|✔|✔|

## 1. using Standard Logging

This is the most simple way. You can use the standard logger, but it doesn’t support the severity.

The following code is an example using the standard logger in Cloud Functions.

```python
import logging

import flask

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

def main(request):
    print("PRINT message")
    logger.debug("DEBUG message")
    logger.info("INFO message")
    logger.warning("WARNING message")
    logger.error("ERROR message")
    logger.critical("CRITICAL message")
    logger.exception("EXCEPTION message")
    return flask.jsonify({'result': 'ok'})
```

The following was the actual screenshot from the Cloud Functions console.
You can see that all severity of entries are `default`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/65951a40zv78uio8wy0g.png)
 
## 2. using Structured logging

If you want to include log levels or other specific [fields](https://cloud.google.com/logging/docs/agent/logging/configuration#special-fields) in your log entries, you can write logs to `stdout` or `stderr` in the form of a single line of serialized JSON. The Structured logging support is available in Python 3.8 and later.

https://cloud.google.com/functions/docs/monitoring/logging#writing_structured_logs

The following code is an example using the Structured logging in Cloud Functions.

```python
import logging

import flask

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

def main(request):
    print("PRINT message")
    logger.debug("DEBUG message")
    logger.info("INFO message")
    logger.warning("WARNING message")
    logger.error("ERROR message")
    logger.critical("CRITICAL message")
    logger.exception("EXCEPTION message")
    return flask.jsonify({'result': 'ok'})
```

The following was the actual screenshot from the Cloud Functions console.
You can see that all severity has been correctly reflected.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0zfod8r111nyrjl3rsb.png)
 

When I tried on Python 3.7 runtime, the severity didn’t support below as described in Official Doc.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuzi6h5kgsktpqnikql0.png)
 

## 3. using Official logging handlers

Logging handlers with Python loggers are provided by the official library.

https://cloud.google.com/logging/docs/setup/python#configuring_the_logging_handler

The following code is an example using the logging handlers in Cloud Functions. (The library version of google-cloud-logging I used was 2.7.0. )

```python
import logging

import flask
import google.cloud.logging

client = google.cloud.logging.Client()
client.setup_logging()
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

def main(request):
    print("PRINT message")
    logger.debug("DEBUG message")
    logger.info("INFO message")
    logger.warning("WARNING message")
    logger.error("ERROR message")
    logger.critical("CRITICAL message")
    logger.exception("EXCEPTION message")
    return flask.jsonify({'result': 'ok'})
```


The following was the actual screenshot from the Cloud Functions console.
You can see that all severity has been correctly reflected.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1mkeqwr1brvvcsr18bz.png)
 


## 4. using Cloud Logging API directly

The official Doc also explains how to run the API directly using the Cloud Logging API client.

https://cloud.google.com/logging/docs/setup/python#use_the_cloud_client_library_directly

The following code is an example using the calling directory in Cloud Functions. (The library version of google-cloud-logging I used was 2.7.0. )

```python
import flask
from google.cloud import logging

logging_client = logging.Client()
log_name = "hello-logging-func4"
logger = logging_client.logger(log_name)

def main(request):
    print("PRINT message")
    logger.log_text("DEFAULT message", severity="DEFAULT")
    logger.log_text("DEBUG message", severity="DEBUG")
    logger.log_text("INFO message", severity="INFO")
    logger.log_text("NOTICE message", severity="NOTICE")
    logger.log_text("WARNING message", severity="WARNING")
    logger.log_text("ERROR message", severity="ERROR")
    logger.log_text("CRITICAL message", severity="CRITICAL")
    logger.log_text("ALERT message", severity="ALERT")
    logger.log_text("EMERGENCY message", severity="EMERGENCY")
    return flask.jsonify({'result': 'ok'})
```

The following was the actual screenshot from the Cloud Functions console, but you cannot see all of the log entries.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gvurz6ly7omhykgfibk.png)
 

You can see all of the log entries from the Cloud Logging console.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5e5be85bce9dk0p3v3fm.png)
 
# Conclusion

This post introduced ways of saving Cloud Logging for Python in Cloud Functions and organized the merits and demerits in a simple way.

If you don't need a log level, I recommend using Python Standard Logger(No.1).

If you need a log level, I recommend using official logging handlers(No.3) because you can setup easily. Or I recommend using Structured logging(No.2) because it is very flexible.