使用 Python 查询 GCP Stackdriver 日志

Posted

技术标签:

【中文标题】使用 Python 查询 GCP Stackdriver 日志【英文标题】:Using Python to Query GCP Stackdriver logs 【发布时间】:2018-10-22 10:05:31 【问题描述】:

我正在使用 Python3 向 Stackdriver 查询 GCP 日志。不幸的是,包含重要数据的日志条目以“NoneType”而不是“dict”或“str”的形式返回给我。结果“entry.payload”是“None”类型,“entry.payload_pb”有我想要的数据,但它是乱码。

有没有办法让 Stackdriver 以干净的格式返回这些数据,或者有什么方法可以解析它? 如果没有,我是否应该通过一种比我正在做的更好的方式查询这些数据并产生干净的数据?

我的代码如下所示:

#!/usr/bin/python3

from google.cloud.logging import Client, ASCENDING, DESCENDING
from google.oauth2.service_account import Credentials

projectName = 'my_project'
myFilter = 'logName="projects/' + projectName + '/logs/compute.googleapis.com%2Factivity_log"'

client = Client(project = projectName)
entries = client.list_entries(order_by=DESCENDING, page_size = 500, filter_ = myFilter)
for entry in entries:
    if isinstance(entry.payload, dict):
        print(entry.payload)
    if isinstance(entry.payload, str):
        print(entry.payload)
    if isinstance(entry.payload, None):
        print(entry.payload_pb)

“entry.payload_pb”数据总是这样开始:

type_url: "type.googleapis.com/google.cloud.audit.AuditLog"
 value: "\032;\n9gcp-user@my-project.iam.gserviceaccount.com"I\n\r129.105.16.28\0228

【问题讨论】:

【参考方案1】:

看起来与解析 protobuf 以进行日志记录相关的 python 库中的某些内容已损坏。 我发现了两个老问题

    https://github.com/GoogleCloudPlatform/google-cloud-python/issues/3218 https://github.com/GoogleCloudPlatform/google-cloud-python/issues/2674

这似乎在不久前得到了解决 - 但我相信问题被重新引入。 我已针对此问题为 google 支持开票,他们正在调查。

作为解决方法 - 您可以使用两个选项:

    您可以创建导出(接收器)到 BigQuery - 因此在这种情况下您可以轻松查询日志 - 这种方法的问题是它不会导出您在创建导出之前收集的旧数据。

    您可以使用 gcloud 命令。特别是

    gcloud 日志读取

它非常强大(支持过滤器、时间戳)——但它的输出格式是 yaml。您可以安装和使用 PyYAML 库将日志转换为字典。

【讨论】:

【参考方案2】:

LogEntry.proto_payload 是一个Any message,它对其他一些原型缓冲区消息进行编码。 proto 消息的类型由type_url 指示,消息体被序列化到value 字段中。确定类型后,您可以使用类似的方式对其进行反序列化

from google.cloud.audit import AuditLog
...

audit_log = AuditLog()
audit_log.ParseFromString(entry.payload_pb.value)

AuditLog 消息可在https://github.com/googleapis/googleapis/blob/master/google/cloud/audit/audit_log.proto 和相应的Python definitions can be built using the protoc compiler 获得

请注意,AuditLog 消息的某些字段也可以包含其他 Any 消息。更多详情https://cloud.google.com/logging/docs/audit/api/

【讨论】:

感谢您的回复。我相信 protobuf 定义出现在这里:github.com/googleapis/googleapis/blob/master/google/cloud/audit/…。但是,我在任何地方都看不到相应的 audit_log.py。这是分布在我没看到的地方吗? 通常接口代码(适用于任何语言)是从 .proto 文件构建的。请参阅developers.google.com/protocol-buffers/docs/…(是的,这就是正确的 audit_log.proto)【参考方案3】:

如果有人遇到与我相同的问题,我的解决方法如下: 1)下载并安装protobuf。我在带有 brew (brew install protobuf) 2)下载并安装grpcio。我用pip install grpcio 3) 将“Google API”下载到已知目录。我用/tmp,这个命令git clone https://github.com/googleapis/googleapis 4) 将目录更改为您刚刚在第 3 步中下载的存储库的根目录 5) 使用protoc 构建python 存储库。这个命令对我有用 protoc -I=/tmp/googleapis/ --python_out=/tmp/ /tmp/googleapis/google/cloud/audit/audit_log.proto 6) 您的 audit_log_pb2.py 文件应该存在于 /tmp/audit_log_pb2.py 7) 将此文件放在正确的路径或与您的脚本相同的目录中。 8) 将此行添加到脚本中的导入:import audit_log_pb2 9)在我这样做之后,Protobuf 条目的entry.payload 部分始终填充有字典。

请注意:您应该使用以下命令protoc --version 验证您使用的protoc 的版本。您真的想使用 protoc 3.x,因为我们正在构建的文件来自规范的版本 3。我在 Linux 机器上安装的 Ubuntu 软件包是第 2 版,这有点令人沮丧。此外,虽然此文件是为 Python 2.x 构建的,但它似乎可以在 Python 3.x 中正常工作。

【讨论】:

警告:不幸的是,googleapis/google/cloud/audit/audit_log.proto 没有保持最新,所以像 this one that I initiated 这样的 API 的任何添加都没有添加到原型中,因此不会像我假设的那样可读。 【参考方案4】:

实际上我错过了,但您可以禁用 gRPC 并通过将环境变量 GOOGLE_CLOUD_DISABLE_GRPC 设置为非空字符串来使 API 返回 dict (JSON) 有效负载,例如GOOGLE_CLOUD_DISABLE_GRPC=true.

这将填充payload 而不是payload_pb - 比编译可能已过时的原型缓冲区更容易!

【讨论】:

【参考方案5】:

我关注了@rhinestone-cowguy 的回答,但认为示例用法会对找到此答案的人有所帮助。要使用已编译的(原型)代码:

from google.cloud import logging
import audit_log_pb2

client = logging.Client()
PROJECT_IDS = ["one-project", "another-project"]

for entry in client.list_entries(projects=PROJECT_IDS):  # API call(s)

    # The proto payload is an Any message.
    audit_log = audit_log_pb2.AuditLog()
    entry.payload.Unpack(audit_log)
    print(audit_log)

Python Generated Code 中记录了 Any 消息的使用。

【讨论】:

以上是关于使用 Python 查询 GCP Stackdriver 日志的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 查询 GCP Stackdriver 日志

带有presto的GCP dataproc - 有没有办法使用pyhive通过python远程运行查询?

如何快速查询 GCP 表

ValueError:必须使用 beam.io.gcp.bigquery.ReadFromBigQuery 指定 BigQuery 表或查询

比较 GCP 数据存储区查询性能

使用 python 标记日志到 gcp 日志查看器