jacob
jacob

Reputation: 2896

How to bundle Cloud Logging entries by request?

I'm try to get Cloud Logging to bundle (i.e., group) log entries by request in Cloud Logs Explorer, similar to what node-js-logging-winston does on the Cloud Functions Node runtime: https://github.com/googleapis/nodejs-logging-winston#using-as-an-express-middleware It's also what App Engine does automatically.

There's general instructions in the following blog how to accomplish this using Python and Flask: https://medium.com/google-cloud/combining-correlated-log-lines-in-google-stackdriver-dd23284aeb29

Here's a screenshot of what it would look like in Logs Explorer.

enter image description here

Here's a script that is supposed to do this, but the entries are not grouping by request.


import argparse
import datetime
import time
import uuid

from google.cloud import logging


def _log_timestamp():
    return datetime.datetime.now(datetime.timezone.utc)


def _log_trace_id():
    return uuid.uuid4().hex


def _log_request_time(request_start_time):
    return "%.5fs" % (time.time() - request_start_time)


def run(project_id):
    request_start_time = time.time()
    trace_id = _log_trace_id()

    client = logging.Client(project=project_id)

    app_logger = client.logger('child')
    app_logger.log_struct(
        {"message": 'app log entry # 1'},
        severity='INFO',
        trace=f'projects/{project_id}/traces/{trace_id}',
        timestamp=_log_timestamp()
    )
    app_logger.log_struct(
        {"message": 'app log entry # 2'},
        severity='INFO',
        trace=f'projects/{project_id}/traces/{trace_id}',
        timestamp=_log_timestamp()
    )

    request_logger = client.logger('parent')
    request_logger.log_struct(
        {"message": 'TEXT'},
        severity='INFO',
        trace=f'projects/{project_id}/traces/{trace_id}',
        timestamp=_log_timestamp(),
        http_request=dict(
            request_method='GET',
            request_url='https://request.example.com/test-logging',
            status=200,
            user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)'
                       ' Chrome/92.0.4515.107 Safari/537.36',
            response_size=15773,
            latency=_log_request_time(request_start_time),
            remote_ip='127.0.0.1',
            referer='https://referer.example.com/',
        )
    )


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument('--project',
                        required=True,
                        help='Project ID')
    args = parser.parse_args()

    run(args.project)

And here is a screenshot of Logs Explorer showing the request was not bundled together:

enter image description here

Thanks.

Upvotes: 4

Views: 1394

Answers (1)

jacob
jacob

Reputation: 2896

I received an answer from Google Cloud Support. The code in my question is fine. In order to view the logs bundled by request, it's necessary in the Logs Explorer to filter for the parent logName. Then the app log entries are nested inside the request log entry. If the parent logName is not specifically filtered, then it shows all the log entries (request and app) in a flat list, as shown in the screenshot in my question.

Here is a screenshot of the properly nested log entries:

enter image description here

Upvotes: 6

Related Questions