使用 Cloud Logging 的第二方触发器

Cloud Audit Logs 中会记录许多 Google Cloud Platform 事件。您可以过滤这些日志,并使用接收器将其转发到 Pub/Sub 主题。然后,这些 Pub/Sub 主题可以发送通知来触发 Cloud Functions 函数。这样,您就可以基于任何生成审核日志的 Google Cloud Platform 服务创建自定义事件。

配置

如需运行以下示例,您将需要一个 Pub/Sub 主题和一个 Cloud Logging 接收器。该示例使用它们将 Cloud Audit Logs 转发到 Cloud Functions 函数。

事件结构

与所有由 Pub/Sub 触发的函数一样,由 Cloud 日志条目触发的函数也会接收 PubsubMessage 对象,该对象的 data 参数是一个采用 base64 编码的字符串。对于 Cloud 日志事件,将该值解码后,系统会以 JSON 字符串形式返回相关日志条目。

示例代码

您可以使用由 Pub/Sub 触发的函数(如下所示)来检测导出的 Cloud 日志并做出响应:

Node.js

exports.processLogEntry = data => {
  const dataBuffer = Buffer.from(data.data, 'base64');

  const logEntry = JSON.parse(dataBuffer.toString('ascii')).protoPayload;
  console.log(`Method: ${logEntry.methodName}`);
  console.log(`Resource: ${logEntry.resourceName}`);
  console.log(`Initiator: ${logEntry.authenticationInfo.principalEmail}`);
};

Python

import base64
import json

def process_log_entry(data, context):
    data_buffer = base64.b64decode(data["data"])
    log_entry = json.loads(data_buffer)["protoPayload"]

    print(f"Method: {log_entry['methodName']}")
    print(f"Resource: {log_entry['resourceName']}")
    print(f"Initiator: {log_entry['authenticationInfo']['principalEmail']}")

Go


// Package log contains examples for handling Cloud Functions logs.
package log

import (
	"context"
	"log"
)

// PubSubMessage is the payload of a Pub/Sub event.
// See the documentation for more details:
// https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage
type PubSubMessage struct {
	Data []byte `json:"data"`
}

// ProcessLogEntry processes a Pub/Sub message from Cloud Logging.
func ProcessLogEntry(ctx context.Context, m PubSubMessage) error {
	log.Printf("Log entry data: %s", string(m.Data))
	return nil
}

Java


import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import functions.eventpojos.PubsubMessage;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.logging.Logger;

public class StackdriverLogging implements BackgroundFunction<PubsubMessage> {
  private static final Logger logger = Logger.getLogger(StackdriverLogging.class.getName());

  @Override
  public void accept(PubsubMessage message, Context context) {
    String name = "World";

    if (!message.getData().isEmpty()) {
      name = new String(Base64.getDecoder().decode(
          message.getData().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
    }
    String res = String.format("Hello, %s", name);
    logger.info(res);
  }
}

部署函数

要部署函数,请使用以下命令:

Node.js

gcloud functions deploy processLogEntry \
--runtime nodejs20 \
--trigger-topic YOUR_PUBSUB_TOPIC

使用 --runtime 标志可以指定支持的 Node.js 版本的运行时 ID 来运行您的函数。

Python

gcloud functions deploy process_log_entry \
--runtime python312 \
--trigger-topic YOUR_PUBSUB_TOPIC

使用 --runtime 标志可以指定支持的 Python 版本的运行时 ID 来运行您的函数。

Go

gcloud functions deploy ProcessLogEntry \
--runtime go121 \
--trigger-topic YOUR_PUBSUB_TOPIC

使用 --runtime 标志可以指定支持的 Go 版本的运行时 ID 来运行您的函数。

Java

gcloud functions deploy java-log-function \
--entry-point StackdriverLogging \
--runtime java17 \
--memory 512MB \
--trigger-topic YOUR_PUBSUB_TOPIC

使用 --runtime 标志可以指定支持的 Java 版本的运行时 ID 来运行您的函数。

触发函数

当与您的某个过滤条件匹配的 Cloud 日志条目创建后,您应该会看到与您的函数对应的日志条目:

Method: METHOD
Resource: projects/YOUR_GCLOUD_PROJECT/...
Initiator: YOUR_EMAIL_ADDRESS