查询和查看日志

本页面提供了详细说明,介绍了如何使用 Grafana 界面查询日志并以直观方式呈现日志,以便深入了解服务事件和活动。

从 Google Distributed Cloud (GDC) 气隙设备中部署的工作负载和服务收集日志后,您就可以开始 分析这些日志了。如需分析日志,您可以在信息丰富的 Grafana 面板上以直观方式呈现和过滤日志,也可以使用 gRPC 调用以编程方式访问日志。

您可以通过以下方法访问日志:

  • Grafana 面板:通过 Grafana 实例的“日志”面板深入了解项目的活动记录。借助此面板,您可以查询和精确定位特定日志,从而根据您的需求提供精细的数据可观测性。Grafana 提供了一个用户友好的界面,用于过滤和分析工作负载数据,并创建自定义信息中心和面板以实现全面可视化。

准备工作

如需获得在 Grafana 界面上查询日志并以直观方式呈现日志所需的权限,请让组织 IAM 管理员或项目 IAM 管理员为您授予预定义的组织 Grafana Viewer 或项目 Grafana Viewer 角色之一。根据您需要的访问权限级别,您可以在组织或项目中获取 Grafana 角色。

或者,如需获得从 Log Query API 查询日志所需的权限,请让项目 IAM 管理员在项目命名空间中为您授予 Log Query API 查询者角色。

如需详细了解这些角色,请参阅 准备 IAM 权限

为日志构建查询

通过系统监控实例的界面查询日志时,您可以选择数据源以检索项目的运维日志,并获得查询的集成视图。如需过滤结果,请使用查询语言表达式按标签搜索日志。例如,您可以在查询中将 clusternamespace 标签分别设置为标识集群和项目命名空间的值。

系统监控实例端点

对于应用运维人员 (AO)

以下网址是项目监控实例的端点:

https://GDC_URL/PROJECT_NAMESPACE/grafana

替换以下内容:

  • GDC_URL:您在 GDC 中的组织的网址。
  • PROJECT_NAMESPACE:项目的命名空间。

对于平台管理员 (PA)

以下网址是项目监控实例的端点:

https://GDC_URL/platform-obs/grafana

GDC_URL 替换为您在 GDC 中的组织的网址。

查询和过滤日志

选择以下方法之一,构建查询并过滤项目工作负载中的日志:

本部分介绍如何使用 Grafana 中的“日志”面板访问日志。

确定 Grafana 端点

对于应用运维人员 (AO)

以下网址是项目监控实例的端点:

https://GDC_URL/PROJECT_NAMESPACE/grafana

替换以下内容:

  • GDC_URL:您在 GDC 中的组织的网址。
  • PROJECT_NAMESPACE:项目的命名空间。

对于平台管理员 (PA)

以下网址是项目监控实例的端点:

https://GDC_URL/platform-obs/grafana

GDC_URL 替换为您在 GDC 中的组织的网址。

在 Grafana 界面中查看日志

在 Grafana 界面中查询日志:

  1. 在 GDC 控制台中,选择您的项目。
  2. 在导航菜单中,选择 运维 > 日志记录
  3. 点击在 Grafana Loki 中查看全部

系统会打开一个新页面,其中包含 Grafana 端点 并显示界面。

  1. 在该界面上,点击导航菜单中的探索 探索 以打开探索 页面。
  2. 探索 栏的菜单中,根据您的宇宙类型选择一个数据源以检索日志:
  • 单区域宇宙:选择以下数据源之一,以显示宇宙的单个区域中的日志记录数据:

  • 运维日志:显示运维日志。

  • 审核日志:显示审核日志。

  • 运维日志 ZONE_NAME:显示特定区域的运维日志。

  • 审核日志 ZONE_NAME:显示特定区域的审核日志。

此外,如需在单个信息中心内以直观方式呈现跨区域数据,并将多个区域添加到查询中,请选择混合 作为数据源。

  1. 输入查询,以使用 LogQL(日志查询语言)表达式从“日志”面板中搜索日志。您可以通过以下任一方式执行此步骤:

    • 使用交互式查询构建器界面。然后,点击运行查询
    • 直接在文本字段中输入查询,然后按 Shift+Enter 运行查询。

    该页面会显示与您的查询匹配的日志。查询日志后,您可以导出这些日志。点击导出 ,以纯文本或 CSV 格式下载日志。您还可以为日志选择时间范围

    在“探索”页面上选择“审核日志”选项以获取审核日志。

    图 1. 用于从 Grafana 界面查询审核日志的菜单选项。

    在图 1 中,审核日志 选项会显示一个界面,您可以在其中构建来自 Grafana 的查询以检索审核日志。

    如需查看用于查询不同日志的标签和值的示例,请参阅示例查询和标签

    为日志选择时间范围

    如需查询特定时间范围内的日志,请按以下步骤操作:

    1. 点击 Grafana 中的 时间选择器 菜单。

    2. 在菜单中,执行以下操作之一:

      • 选择相对时间范围选项,例如过去 30 分钟。
      • 通过从日历中选择特定日期和时间并点击应用时间范围 ,设置自定义绝对时间范围。
    3. (可选)点击更改时间设置 ,以从时间范围控件中更改时区会计年度 设置。

    时间设置是按信息中心保存的。如需详细了解特定时间范围内的查询,请参阅 https://grafana.com/docs/loki/latest/reference/api/#query-loki-over-a-range-of-time

    发送查询

    使用 HTTP 或 gRPC 客户端向 Log Query API 端点发送查询。

    HTTP

    按照说明使用 HTTP 客户端直接访问 API。 您可以依赖 kubectl 来管理身份验证,也可以自行处理身份验证。

    使用 curlwget 等 HTTP 客户端或您创建和管理的 HTTP 客户端查询 Log Query API。以下示例使用 curl 工具查询 API,您可以对 wget 命令使用类似格式:

    1. 对 c网址 请求进行身份验证:

      1. 下载并安装 gdcloud CLI
      2. 设置 gdcloud core/organization_console_url 属性:

        gdcloud config set core/organization_console_url https://GDC_URL
        

        GDC_URL 替换为 GDC 中组织的网址。

      3. 使用配置的身份提供方登录

        gdcloud auth login
        
      4. 使用您的用户和密码进行身份验证并登录。

      5. 将指定帐号的身份令牌导出到环境变量:

        export TOKEN="$($HOME/gdcloud auth print-identity-token --audiences=https://LOG_QUERY_API_ENDPOINT)"
        

        LOG_QUERY_API_ENDPOINT 替换为您要从中查询日志的 Log Query API 端点以及要连接的网域。因此,audiences 标志的值可以是 https://operational-log-query-api.org-1.zone1.google.gdch.test

        登录成功后,您可以通过 gdcloud auth print-identity-token 命令在 c网址 请求中使用授权标头。如需了解详情,请参阅 gdcloud auth print-identity-token

    2. 如需列出项目的所有标签,请发送以下查询:

      curl -H "Authorization: Bearer ${TOKEN}" \
      https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels \
      -H "Content-Type: application/json" -v
      

      替换以下内容:

      • LOG_QUERY_API_ENDPOINT:您要从中查询日志的 Log Query API 端点
      • PROJECT_NAMESPACE:您的项目命名空间。
    3. 如需列出项目的特定标签值,请发送以下查询:

      curl -H "Authorization: Bearer ${TOKEN}" \
      https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels/labels/LABEL/values \
      -H "Content-Type: application/json" -v
      

      替换以下内容:

      • LOG_QUERY_API_ENDPOINT:您要从中查询日志的 Log Query API 端点
      • PROJECT_NAMESPACE:您的项目命名空间。
      • LABEL:您要查询其值的特定标签。
    4. 如需查询特定项目的日志,请构建 logs_filter 查询并将其包含在请求正文中:

      curl -X GET -H "Authorization: Bearer ${TOKEN}" \
      https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/logs \
      -H "Content-Type: application/json" -d \
      '{"logs_filter": {"labels_equal": {"LABEL": "LABEL_VALUE"}}}' -v
      

      替换以下内容:

      • LOG_QUERY_API_ENDPOINT:您要从中查询日志的 Log Query API 端点
      • PROJECT_NAMESPACE:您的项目命名空间。
      • LABEL:您要查询日志的特定标签。
      • LABEL_VALUE:您要查询日志的标签值。

      如需查看构建 logs_filter 查询的所有选项,请参阅 API 文档

    gRPC

    gRPC 受到各种编程语言的广泛支持,与 HTTP 客户端相比,它提供了一种更高效的通信方法。

    如需使用 gRPC 查询日志,您必须满足以下前提条件:

    • 根据 Google 提供的协议缓冲区创建自己的客户端库。
    • 在客户端中实现身份验证。
    • 实现重试。

    如需了解协议缓冲区,请参阅 API 文档

    以下示例展示了如何使用未经身份验证的 gRPC 客户端从 Go 程序查询日志。该示例假定您创建了一个 golang 软件包,其中包含用于导入代码依赖项的 Bazel build 文件:

    1. 将以下代码保存到名为 client.go 的 Go 程序中:

      package main
      import (
              "context"
              "crypto/tls"
              "flag"
              "fmt"
              "google.golang.org/grpc/credentials"
              "google.golang.org/grpc/metadata"
              pb "<import path to generated log query api protos>/pkg/apis/public/logging/v1/proto"
              "google.golang.org/grpc"
      )
      
      var serverAddr = flag.String("server", "localhost:8080", "server address")
      
      func main() {
              flag.Parse()
              tc := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
              conn, err := grpc.Dial(*serverAddr, grpc.WithTransportCredentials(tc))
      
              if err != nil {
                      panic(error.Error(fmt.Errorf("create client connection failed: %v", err)))
              }
              defer conn.Close()
      
              c := pb.NewLogsClient(conn)
              md := metadata.Pairs("clienttest", "test")
              ctx := metadata.NewOutgoingContext(context.Background(), md)
      
              err = listLabels(ctx, c, "project-foo")
              if err != nil {
                      panic(error.Error(err))
              }
      
              if err := listLabelValues(ctx, c, "project-foo", "resource-bar"); err != nil {
                      panic(error.Error(err))
              }
      
              if err := listLogs(ctx, c, "project-foo", &pb.ListLogsFilter{
                      LabelsEqual:    map[string]string{"resource-bar": "resource-bar-value"},
                      OrderAscending: true,
              }); err != nil {
                      panic(error.Error(err))
              }
      }
      
      // List all labels for a project.
      
      func listLabels(ctx context.Context, c pb.LogsClient, project string) error {
              lbr := &pb.ListLabelsRequest{
                      Parent:   project,
                      PageSize: 1000, // PageSize can be configured to limit the number of responses per page.
              }
              resp, err := c.ListLabels(ctx, lbr)
              if err != nil {
                      return fmt.Errorf("list labels: %v", err)
              }
              fmt.Printf("%v", resp)
              return nil
      }
      
      // List specific label values for a project.
      
      func listLabelValues(ctx context.Context, c pb.LogsClient, project string, label string) error {
              lbr := &pb.ListLabelValuesRequest{
                      Parent:   project,
                      Label:    label,
                      PageSize: 1000, // PageSize can be configured to limit the number of responses per page.
              }
              resp, err := c.ListLabelValues(ctx, lbr)
              if err != nil {
                      return fmt.Errorf("list label values: %v", err)
              }
              fmt.Printf("%v", resp)
              return nil
      }
      
      // List logs for a specific project.
      
      func listLogs(ctx context.Context, c pb.LogsClient, project string, lf *pb.ListLogsFilter) error {
              lbr := &pb.ListLogsRequest{
                      Parent:     project,
                      LogsFilter: lf,
                      PageSize:   5, // PageSize can be configured to limit the number of responses per page.
              }
              resp, err := c.ListLogs(ctx, lbr)
              if err != nil {
                      return fmt.Errorf("list logs: %v", err)
              }
              fmt.Printf("logs: %v", resp)
              return nil
      }
      
    2. 运行 Go 程序:

      go run PATH_TO_API/client.go -server=LOG_QUERY_API_ENDPOINT:443
      

      替换以下内容:

      • PATH_TO_API:API 文件的路径。
      • LOG_QUERY_API_ENDPOINT:您要从中查询日志的 Log Query API 端点

      如果未指定服务器标志,则默认请求会发送到 localhost

示例查询和标签

以下是一些可用于查询日志的默认标签:

  • cluster:集群的名称。
  • namespace:您的项目命名空间。
  • node:节点名称。
  • pod:Pod 名称。
  • container:容器名称。

以下代码示例展示了如何使用标签和值查询不同的日志:

  • 选择服务器日志:

    {cluster="admin", namespace="kube-system", resources="k8s_container", container="kube-apiserver"}
    
  • 选择集群审核日志:

    {cluster="admin", resources="k8s_audit"}