Score:2

jsonPayload (structured logging) output from Python Google Cloud Function's logging needed to create Log-Based Metrics (LBM) in GCP

I need the jsonPayload in the logs of a Google Cloud Function instead of the textPayload. My aim is to use the keys of the dictionary as labels (see Log-based metrics labels) for Log-Based Metrics so that these can be addressed in Grafana.

I am using Python's logging module, but I can also switch to something else if needed.

I need as output in the logs:

jsonPayload: `{'key1':value1, 'key2':value2}`

But I get a textPayload output instead, the whole next line is a string:

"2022-02-08 15:43:32,460 [INFO]: {"key1": value1, "key2": value2}"

Real example from the logs, in the middle, you see the textPayload:

enter image description here

The picture as text:

{
insertId: "000000-1b431ffd-e42d-4f83-xyz"
labels: {1}
logName: "projects/MY_PROJECT/logs/cloudfunctions.googleapis.com%2Fcloud-functions"
receiveTimestamp: "2022-02-08T15:43:41.808217166Z"
resource: {2}
textPayload: "2022-02-08 15:43:32,460 [INFO]: {"json_metadata": {"countrows": 736203, "countcolumns": 6, "size": 48261360, "gcs_stamp": "2022-02-08 15:43:32.451000+00:00", "python_stamp": "2022-02-08 15:43:31.055538"}}"
timestamp: "2022-02-08T15:43:32.460Z"
trace: "projects/MY_PROJECT/traces/dd97759176248586a3d3xyz"
}

First tries

Reading from https://cloud.google.com/logging/docs/structured-logging:

In Cloud Logging, structured logs refer to log entries that use the jsonPayload field to add structure to their payloads. Structured logging applies to user-written logs.

I tried to get this "structured logging" following Writing structured logs by

logging.info(json.dumps(json_for_gcp_lbm))

but to no avail.

Further in the links: there is a built-in Logging agent from GCP that uses fluentd as to About the Logging agent seems to be available only for Google Kubernetes Engine or the App Engine, not in a Google Cloud Function:

If you're using Google Kubernetes Engine or the App Engine flexible environment, you can write structured logs as JSON objects serialized on a single line to stdout or stderr. The Logging agent then sends the structured logs to Cloud Logging as the jsonPayload of the LogEntry structure.

How can I get the jsonPayload in this output?

mdobrucki avatar
tr flag
Do I understand correctly - the output you provided is from using the [example](https://cloud.google.com/functions/docs/monitoring/logging#writing_structured_logs)? What python version are you using?
questionto42standswithUkraine avatar
@mdobrucki Yes, I have used `logging.info(json.dumps(json_for_gcp_lbm))` which is taken from the example of that link, but I only used the very last line of that example, hoping that this would already make it. I use a `Python 3.9` cloud function.
mdobrucki avatar
tr flag
If you are using python 3.9 the example provided in docs should do the trick, make sure to follow it correctly and structure your data accordingly. Have you considered using Logging client libraries with this [example](https://cloud.google.com/logging/docs/reference/libraries#write_structured_logs)?
questionto42standswithUkraine avatar
@mdobrucki No, I must have overseen that since I have searched directly for "structured json" instead. I will check it with the google library and use the example's logger.
mdobrucki avatar
tr flag
Let me know what you've established.
questionto42standswithUkraine avatar
@mdobrucki Yes, it worked. My fault since that guide in the link is quite clear. I had some issues with the datetime classes - I got `google.protobuf.json_format.ParseError: Value 2022-02-09 13:27:35.067000+00:00 has unexpected type <class 'datetime.datetime'>`. But solved it with `str()` around that datetime class for now, could also use `.strftime()` to make it a string. `default=str` as a parameter how you can use it in built-in Python module `logging` does not work. Anyway, you may answer if you like, I could then perhaps "edit in" my example how I got it to work.
Score:1
tr flag

You can set up structured logging following the example in the docs. Make sure your python version is 3.8 or above. Another way to achieve that is to use Logging client libraries.

Example from the OP for the second method:

Put into your requirements.txt:

google-cloud-logging==3.0.0

as the most recent version at the time of writing.

from google.cloud import logging as gclogger

(or name it as you like)

and call the json logging with:

json_for_gcp_lbm = {MY_JSON_HERE}

    from google.cloud import logging as gclogger

    ...

    logging_client = gclogger.Client()
    logger_name = "MY_LOG_NAME_OF_FREE_CHOICE" # Saved in the google cloud logs
    logger = logging_client.logger(logger_name)

    # I do not know how it would work with `import logging` as the 
    # built-in Python module, but I got it to work with adding
    # Following line does not work
    # logging.info(json.dumps(json_for_gcp_lbm, default=str))
    # Instead, we need 
    # https://cloud.google.com/logging/docs/samples/logging-write-log-entry#code-sample
    logger.log_struct(json_for_gcp_lbm)

Which leads to a jsonPayload output:

enter image description here

And you can then choose any label from the json in the "Create logs metric" (Log-Based Metrics / LBM) menu:

enter image description here

questionto42standswithUkraine avatar
I do not know how it would get the jsonPayload using `import logging` as the built-in Python module in the first link, though :). When using only the last line of the example, it gives only `textPayload` instead. Likely, I need the `request` part with that `global_log_fields = {}` to make it work. I think that `import google.cloud.logging` is more "pythonic" then, even if I have to install and import the google cloud logging for this.
questionto42standswithUkraine avatar
Small bonus, I had not asked this, saw this by chance: there is a passage further down on the same page of your first link about how I could also access the new `google.cloud.logging` made logs with its `jsonPayload` entries from inside the CF, see [Using the Logging API](https://cloud.google.com/functions/docs/monitoring/logging#using_the_logging_api).
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.