Как десериализовать журналы приложений App Engine из StackDriver Logging API?

В рамках перехода на Python 3 мне нужно перейти с logservice в API ведения журналов StackDriver. У меня установлен google-cloud-logging, и я могу успешно получать журналы приложений GAE. например:

>>> from google.cloud.logging_v2 import LoggingServiceV2Client
>>> entries = LoggingServiceV2Client().list_log_entries(('projects/projectname',),
         filter_='resource.type="gae_app" AND protoPayload.@type="type.googleapis.com/google.appengine.logging.v1.RequestLog"')
>>> print(next(iter(entries)))
proto_payload {
  type_url: "type.googleapis.com/google.appengine.logging.v1.RequestLog"
  value: "\n\ts~brid-gy\022\0018\032R5d..."
}

Это дает мне LogEntry с текстовыми журналами приложений в поле proto_payload.value. Как мне десериализовать это поле? Я нашел много связанных упоминаний в документах, но ничего не указывает мне на класс, сгенерированный google.appengine.logging.v1.RequestLog protobuf, где бы я ни мог использовать, если это вообще правильная идея. Кто-нибудь сделал это?


person Dustin Ingram    schedule 07.11.2019    source источник


Ответы (3)


Ву! Наконец-то это заработало. Мне пришлось вручную сгенерировать и использовать привязки Python для буфера протокола google.appengine.logging.v1.RequestLog. Вот как.

Во-первых, я клонировал эти два репозитория в голове:

Затем я сгенерировал request_log_pb2.py из request_log.proto, запустив:

protoc -I googleapis/ -I protobuf/src/ --python_out . googleapis/google/appengine/logging/v1/request_log.proto

Наконец, я установил googleapis-common-protos и protobuf. Затем я смог десериализовать proto_payload с помощью:

from google.cloud.logging_v2 import LoggingServiceV2Client
client = LoggingServiceV2Client(...)
log = next(iter(client.list_log_entries(('projects/brid-gy',),
   filter_='logName="projects/brid-gy/logs/appengine.googleapis.com%2Frequest_log"')))

import request_log_pb2
pb = request_log_pb2.RequestLog.FromString(log.proto_payload.value)
print(pb)
person ryan    schedule 19.12.2019
comment
Для пользователей, которые не понимают, где request_log_pb2.py заканчивается после выполнения команды protoc, создается целая структура dir: google/appengine/logging/v1/request_log_pb2.py . - person hamx0r; 10.03.2021

Вы можете использовать LogEntry.to_api_repr() для получения JSON-версии файла LogEntry.

>>> from google.cloud.logging import Client
>>> entries = Client().list_entries(filter_="severity:DEBUG")        
>>> entry = next(iter(entries))
>>> entry.to_api_repr()
{'logName': 'projects/PROJECT_NAME/logs/cloudfunctions.googleapis.com%2Fcloud-functions'
, 'resource': {'type': 'cloud_function', 'labels': {'region': 'us-central1', 'function_name': 'tes
t', 'project_id': 'PROJECT_NAME'}}, 'labels': {'execution_id': '1zqolde6afmx'}, 'insertI
d': '000000-f629ab40-aeca-4802-a678-d513e605608e', 'severity': 'DEBUG', 'timestamp': '2019-10-24T2
1:55:14.135056Z', 'trace': 'projects/PROJECT_NAME/traces/9c5201c3061d91c2b624abb950838b4
0', 'textPayload': 'Function execution started'}
person Dustin Ingram    schedule 07.11.2019
comment
Спасибо за ответ! это не работает для меня, хотя. to_api_repr() дает мне: TypeError: Can not find message descriptor by type_url: type.googleapis.com/google.appengine.logging.v1.RequestLog. Похоже, что сопровождающие библиотеки Google Cloud Python сами боролись с этим в течение многих лет: github.com/googleapis/google-cloud-python/issues/2572 , github.com/googleapis/google-cloud-python/issues/2674 - person ryan; 07.11.2019

Вы действительно хотите использовать API v2?

Если нет, используйте from google.cloud import logging и установите os.environ['GOOGLE_CLOUD_DISABLE_GRPC'] = 'true' или аналогичную настройку env.

Это эффективно вернет JSON в payload вместо payload_pb

person Yannick Einsweiler    schedule 19.12.2019