使用基于日志的指标

本页面介绍发出日志以创建可用性和延迟时间 SLI 的基础知识。它还提供了有关如何使用基于日志的指标定义 SLO 的实现示例。

使用日志条目中的数据元素创建服务等级指标是一种利用现有日志载荷的方法。否则,您可以向现有服务添加日志记录,这可能比创建指标插桩更容易。

日志和指标

日志会收集名为日志条目的记录,用于描述计算机系统中发生的特定事件。日志用代码、运行代码的平台服务(例如 Dataflow)以及平台所依赖的基础架构(例如 Compute Engine 实例)编写。

由于现代系统中的日志从写入磁盘的文本文件中剥离(有时仍是文本文件),因此日志条目类似于日志文件中的一行,并且可以被视为日志记录的基本单元。

日志条目至少包含两个内容:

  • 时间戳,用于指示事件发生的时间或将事件提取到日志记录系统中的时间。
  • 文本载荷,以非结构化文本数据或结构化数据形式,通常采用 JSON 格式。

日志还可以包含关联的元数据,特别是在将它们提取到 Cloud Logging 中时。此类元数据可能包括写入日志的资源、日志名称和每个条目的严重程度。

日志

日志有两个主要用途:

  • 事件日志介绍的是系统内部发生的特定事件。您可以使用事件日志来输出消息,以确保用户工作正常(“任务成功”),或者在出现问题时提供信息(“从服务器收到异常”)。
  • 事务日志描述了系统或组件处理的每个事务的详细信息。例如,负载均衡器会记录其收到的每个请求(无论请求是否成功),并记录其他信息,如请求的网址、HTTP 响应代码以及可能像使用了哪个后端来服务该请求的信息。

指标

与日志不同,指标通常不会描述具体事件。指标更常用于表示系统在一段时间内的状态或运行状况。指标由一系列测量系统的相关数据点组成:每个数据点都包含一个时间戳和一个数值。

指标还可以具有与之关联的元数据;数据点序列(称为时间序列)可能包含指标名称、说明,还常常包含用于指定哪些资源正在写入数据的标签等信息。如需了解 Monitoring 指标模型,请参阅指标、时间序列和资源

基于日志的指标

基于日志的指标是基于日志条目,通过从日志条目中提取信息并将其转换为时间序列数据创建的。Cloud Logging 提供了通过日志条目创建以下两种指标的机制:

  • 计数器指标,用于计算与特定过滤条件匹配的日志条目数。例如,您可以使用计数器指标来确定日志中记录的请求或错误数。

  • 分布指标,使用正则表达式来解析每个日志条目中的载荷,以将数值以分布形式进行提取。

如需详细了解 Cloud Logging 中基于日志的指标,请参阅使用基于日志的指标

将基于日志的指标用作 SLI

通过基于日志的指标,您可以采用在 Monitoring 中构建 SLI 所用的形式从日志中提取数据:

  • 您可以使用基于日志的计数器指标来表示基于请求的可用性 SLI。

  • 您可以使用基于日志的分布指标来表示基于请求的延迟时间 SLI。

示例日志条目

Stack Doctor 应用是进行服务插桩以发出日志消息的示例,日志消息包含有关服务的所有请求、错误和延迟时间的信息。stack-doctor GitHub 代码库中提供了该服务的代码。

服务会在 projects/stack-doctor/logs/bunyan_log 日志中生成 Cloud Logging 日志条目。每种事件类型的日志条目都包含不同的 message 值。不同类型的事件的日志条目如下所示:

  • 针对每个请求:

    {
      "insertId": "..........iTRVT5MOK2VOsVe31bzrTD",
      "jsonPayload": {
        "pid": 81846,
        "time": "Mon Aug 31 2020 20:30:49 GMT-0700 (Pacific Daylight Time)",
        "hostname": "<hostname>",
        "level": 30,
        "message": "request made",
        "v": 0,
        "name": "sli-log"
      },
        "resource": {
        "type": "global",
        "labels": {
          "project_id": "stack-doctor"
        }
      },
      "timestamp": "2020-09-01T03:30:49.263999938Z",
      "severity": "INFO",
      "logName": "projects/stack-doctor/logs/bunyan_log",
      "receiveTimestamp": "2020-09-01T03:30:50.003471183Z"
    }
    
  • 针对成功的请求:

    {
      "insertId": "..........qTRVT5MOK2VOsVe31bzrTD",
      "jsonPayload": {
        "name": "sli-log",
        "v": 0,
        "pid": 81846,
        "level": 30,
        "hostname": "<hostname>",
        "time": "Mon Aug 31 2020 20:30:49 GMT-0700 (Pacific Daylight Time)",
        "message": "success!"
      },
      "resource": {
        "type": "global",
        "labels": {
          "project_id": "stack-doctor"
        }
      },
      "timestamp": "2020-09-01T03:30:49.874000072Z",
      "severity": "INFO",
      "logName": "projects/stack-doctor/logs/bunyan_log",
      "receiveTimestamp": "2020-09-01T03:30:50.201547371Z"
    }
    
  • 针对已完成的请求:

    {
      "insertId": "..........mTRVT5MOK2VOsVe31bzrTD",
      "jsonPayload": {
        "time": "Mon Aug 31 2020 20:30:49 GMT-0700 (Pacific Daylight Time)",
        "level": 30,
        "name": "sli-log",
        "message": "slept for 606 ms",
        "hostname": "<hostname>",
        "pid": 81846,
        "v": 0
      },
      "resource": {
        "type": "global",
        "labels": {
          "project_id": "stack-doctor"
        }
      },
      "timestamp": "2020-09-01T03:30:49.874000072Z",
      "severity": "INFO",
      "logName": "projects/stack-doctor/logs/bunyan_log",
      "receiveTimestamp": "2020-09-01T03:30:50.201547371Z"
    }
    
  • 针对错误:

    {
      "insertId": "..........DTRVT5MOK2VOsVe31bzrTD",
      "jsonPayload": {
        "hostname": "<hostname>",
        "level": 50,
        "pid": 81846,
        "message": "failure!",
        "name": "sli-log",
        "time": "Mon Aug 31 2020 20:30:44 GMT-0700 (Pacific Daylight Time)",
        "v": 0
      },
      "resource": {
        "type": "global",
        "labels": {
          "project_id": "stack-doctor"
        }
      },
      "timestamp": "2020-09-01T03:30:44.414999961Z",
      "severity": "ERROR",
      "logName": "projects/stack-doctor/logs/bunyan_log",
      "receiveTimestamp": "2020-09-01T03:30:46.182157077Z"
    }
    

根据这些条目,您可以创建基于日志的指标,以统计所有请求数、统计错误数并跟踪请求延迟时间。然后,您可以使用基于日志的指标来创建可用性和延迟时间 SLI。

为 SLI 创建基于日志的指标。

您必须先创建基于日志的指标,然后才能根据基于日志的指标创建 SLI。

  • 对于针对请求和错误计数的可用性 SLI,可以使用基于日志的计数器指标。
  • 对于延迟时间 SLI,可以使用基于日志的分布指标。

创建基于日志的指标后,您可以在 Metrics Explorer 中搜索这些指标,从而在 Monitoring 中找到这些指标。在 Monitoring 中,基于日志的指标的前缀为 logging.googleapis.com/user

可用性 SLI 的指标

您可以通过使用 TimeSeriesRatio 结构设置“正常”或“错误”请求数与请求总数的比率,在 Cloud Monitoring API 中表示基于请求的可用性 SLI。此比率用于 RequestBasedSli 结构的 goodTotalRatio 字段。

您必须创建可用于构造此比率的基于日志的计数器指标。您必须至少创建以下指标中的两个:

  1. 统计事件总数的指标;此指标用于比率的 totalServiceFilter

    对于“stack-doctor”示例,您可以创建一个基于日志的指标,用于统计在其中显示“发出的请求”消息字符串的日志条目数。

  2. 统计“错误”事件数的指标,此指标用于比率的 badServiceFilter

    对于“stack-doctor”示例,您可以创建一个基于日志的指标,用于统计在其中显示“失败!”消息字符串的日志条目数。

  3. 统计“正常”事件数的指标,此指标用于比率的 goodServiceFilter

    对于“stack-doctor”示例,您可以创建一个基于日志的指标,用于统计在其中显示“成功!”消息字符串的日志条目数。

针对该示例所述的 SLI 基于名为 log_based_total_requests 的请求总数的指标和名为 log_based_errors 的错误数的指标。

您可以使用 Google Cloud 控制台、Cloud Logging API 或 Google Cloud CLI 创建基于日志的指标。如需使用 Google Cloud 控制台创建基于日志的计数器指标,可以使用以下过程:

  1. 在 Google Cloud 控制台中,转到基于日志的指标页面:

    前往基于日志的指标

    如果您使用搜索栏查找此页面,请选择子标题为 Logging 的结果。

    “基于日志的指标”页面显示了用户定义的指标表和系统定义的指标表。

  2. 点击位于用户定义的指标表上方的创建指标

  3. 指标类型窗格中,选择计数器

  4. 详细信息窗格中,为新指标指定名称。对于“stack-doctor”示例,输入 log_based_total_requestslog_based_errors

    您可以忽略此示例的其他字段。

  5. 过滤条件选择面板中,创建一个查询,以仅检索要在指标中计数的日志条目。

    对于“stack-doctor”示例,针对 log_based_total_requests 的查询可能包含以下内容:

    resource.type="global"
    logName="projects/stack-doctor/logs/bunyan_log"
    jsonPayload.message="request made"
    

    针对 logs_based_errors 的查询会更改消息字符串:

    resource.type="global"
    logName="projects/stack-doctor/logs/bunyan_log"
    jsonPayload.message="failure!"
    
  6. 点击预览日志以检查您的过滤条件,并在必要时进行调整。

  7. 忽略此示例的标签窗格。

  8. 点击创建指标以完成该过程。

如需详细了解如何创建基于日志的计数器指标,请参阅创建计数器指标

延迟时间 SLI 的指标

您可以使用 DistributionCut 结构在 Cloud Monitoring API 中表示基于请求的延迟时间 SLI,该 SLI 用于 RequestBasedSli 结构的 distributionCut 字段。您必须创建基于日志的分布指标才能创建延迟时间 SLI。此示例会创建一个名为 log_based_latency. 的基于日志的分布指标

您可以使用 Google Cloud 控制台、Cloud Logging API 或 Google Cloud CLI 创建基于日志的指标。如需使用 Google Cloud 控制台创建基于日志的分布指标,请按照以下步骤操作:

  1. 在 Google Cloud 控制台中,转到基于日志的指标页面:

    前往基于日志的指标

    如果您使用搜索栏查找此页面,请选择子标题为 Logging 的结果。

    “基于日志的指标”页面显示了用户定义的指标表和系统定义的指标表。

  2. 点击位于用户定义的指标表上方的创建指标

  3. 指标类型窗格中,选择分布

  4. 详细信息窗格中,为新指标指定名称。对于“stack-doctor”示例,输入 log_based_latency

    您可以忽略此示例的其他字段。

  5. 过滤条件选择面板中,创建一个查询,以仅检索要在指标中计数的日志条目。

    对于“stack-doctor”示例,针对 log_based_latency 的查询可能包含以下内容:

    resource.type="global"
    logName="projects/stack-doctor/logs/bunyan_log"
    jsonPayload.message="slept for"
    

    为过滤条件查询指定以下字段:

    • 字段名称json.message
    • 正则表达式\s(\d*)\s

      已完成请求的消息字符串的格式为“已休眠 nn 毫秒”。正则表达式从字符串中提取延迟时间值 nn

  6. 忽略此示例的标签窗格。

  7. 点击创建指标以完成该过程。

如需详细了解如何创建基于日志的分布指标,请参阅创建分布指标

可用性 SLI

在 Cloud Monitoring 中,您可以通过使用 TimeSeriesRatio 结构来表示基于请求的可用性 SLI。以下示例展示了一个在比率中使用 log_based_total_requestslog_based_errors 指标的 SLO。此 SLO 预计在一个滚动的 24 小时周期内,正常请求数与请求总数的比率至少为 98%。

{
 "serviceLevelIndicator": {
   "requestBased": {
     "goodTotalRatio": {
       "totalServiceFilter":
         "metric.type=\"logging.googleapis.com/user/log_based_total_requests\"
          resource.type=\"global\"",
       "badServiceFilter":
         "metric.type=\"logging.googleapis.com/user/log_based_errors\"
          resource.type=\"global\""
     }
   }
 },
 "goal": 0.98,
 "rollingPeriod": "86400s",
 "displayName": "Log-Based Availability"
}

延迟时间 SLI

在 Cloud Monitoring 中,您可以通过使用 DistributionCut 结构来表示基于请求的延迟时间 SLI。以下示例展示了一个 SLO,该 SLO 使用 log_based_latency 指标,并预计在一个滚动的 24 小时周期内 98% 的请求在 500 毫秒内完成:

{
  "serviceLevelIndicator": {
    "requestBased": {
      "distributionCut": {
        "distributionFilter":
          "metric.type=\"logging.googleapis.com/user/log_based_latency\"
          resource.type=\"global\"",
        "range": {
          "min": 0,
          "max": 500
        }
      }
    }
  },
  "goal": 0.98,
  "rollingPeriod": "86400s",
  "displayName": "98% requests under 500 ms"
}

其他资源