设置日志中错误的格式

本文档介绍了在使用 Cloud Logging 报告错误事件时如何设置日志条目的格式。

您可以通过执行 Cloud Logging API 方法 write 或 Error Reporting API 方法 report 向 Google Cloud 项目报告错误事件。使用 Cloud Logging API 报告错误事件时,请求正文会包含一个 LogEntry 对象(必须包含堆栈轨迹)或 ReportedErrorEvent 对象。

准备工作

  • 按照适用于您的语言和平台的设置说明进行操作。

  • 如果您需要基于 API 密钥的身份验证,则必须使用 Error Reporting API。如需使用 Error Reporting API 报告错误事件,请执行方法 report,并将该方法的请求正文的格式设置为 ReportedErrorEvent 对象。

    使用 Error Reporting API 时,系统会自动生成包含格式正确的错误消息的日志条目,并将其写入 Cloud Logging。这些日志条目会写入一个日志,其 logName 格式如下:

    projects/PROJECT_ID/clouderrorreporting.googleapis.com%2Freported_errors
    

    由于日志条目是通过调用 report 生成的,因此可能会产生 Cloud Logging 提取费用。如需控制提取哪些日志,请参阅排除过滤条件

    如果您使用 Error Reporting API 报告错误事件,则本文档的其余部分不适用。

LogEntry 格式要求

本部分介绍如何设置 LogEntry 格式,以便 Error Reporting 捕获日志条目中包含的错误事件。

记录堆栈轨迹

如需记录属于堆栈轨迹的错误事件,请将错误事件编写为以下某种类型:

  • 多行 textPayload
  • 包含 messagestack_traceexception 字段的 jsonPayload

    您可以指定其中多个字段。如果指定了其中多个字段,则评估顺序为:stack_traceexceptionmessage

    如果错误事件的格式为 ReportedErrorEvent 对象,请将其字段复制到 jsonPayload。如需了解详情并查看示例,请参阅记录格式为 ReportedErrorEvent 对象的错误

  • 一个 jsonPayload,不包含 messagestack_traceexception 字段,但包含堆栈轨迹。

    Error Reporting 会在 jsonPayload 中的所有字段内搜索堆栈轨迹。如果找到多个堆栈轨迹,则会选择一条堆栈轨迹。选择算法可确保选择的一致性。

记录短信

如需记录文本消息的错误事件,请对 jsonPayload 使用以下格式:

    "jsonPayload": {
      "@type": "type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent",
      "message": "Text message"
    },

如果您将 @type 字段设置为指定值,Error Reporting 始终会评估日志条目,就好像所有必填字段都存在一样。因此,Error Reporting 会捕获错误事件。

如果您将 @type 字段设置为其他值或未设置,则 Cloud Logging 会搜索标记为 serviceContext 的字段,以确定载荷是否为 ReportedErrorEvent 对象。

jsonPayloadmessagestack_traceexception 字段包含堆栈轨迹时,您无需设置 @type 字段。在这些情况下,Error Reporting 会自动捕获错误事件。

支持的受监控资源

LogEntry 对象的 resource 字段设置为以下受支持的受监控的资源类型之一:

  • app_script_function
  • aws_ec2_instance
  • cloud_function
  • cloud_run_jobs
  • cloud_run_revision
  • consumed_api
  • container
  • dataflow_step
  • gae_app
  • gce_instance
  • k8s_container
  • k8s_pod
  • ml_job1
  • workflows.googleapis.com/Workflow
  • global1

1 不支持 textPayload

示例

本部分介绍如何确保 Error Reporting 会在日志条目包含文本消息或堆栈轨迹时处理该日志条目。

记录文本消息的错误事件

以下示例展示了如何在要记录文本消息的错误事件时设置 LogEntry 对象的格式,并对 LogEntryjsonPayload 字段使用以下 JSON 结构:

{...
  {
    "jsonPayload": {
      "@type": "type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent",
      "message": "A simple text message"
    },
    "logName": "projects/test-project/logs/reported-error",
    "resource": {
      "labels": {
        "project_id": "test-project"
      },
      "type": "global"
    },
    "severity": "ERROR",
    "timestamp": "2019-06-27T13:43:26.375834551Z"
  }
}

如示例所示,您必须将 @type 字段设置为强制 Error Reporting 对日志条目分组的值:如需了解详情,请参阅记录文本消息

message 字段包含堆栈轨迹时,系统会自动分组日志条目,因此您无需指定 @type 字段。

记录格式为 ReportedErrorEvent 对象的错误

如果您的错误事件存储在 ReportedErrorEvent 对象中,请为 LogEntryjsonPayload 字段使用以下 JSON 结构:

{
  "eventTime": string,
  "serviceContext": {
    "service": string,     // Required.
    "version": string
  },
  "message": string,       // Required. This field contains the main error content to report.
  "@type": string          // Optional. For information about this field, see Log a text message.
  "context": {
    "httpRequest": {
      "method": string,
      "url": string,
      "userAgent": string,
      "referrer": string,
      "responseStatusCode": number,
      "remoteIp": string
    },
    "user": string,
    "reportLocation": {    // Required if no stack trace is provided.
      "filePath": string,
      "lineNumber": number,
      "functionName": string
    }
  }
}

确保在 message 字段中填充错误信息。如需了解如何将堆栈轨迹存储在 ReportedErrorEvent 对象的 message 字段中,请参阅 report 方法的参考页面。

以下示例说明了如何将 LogEntryjsonPayload 字段设置为 ReportedErrorEvent 对象格式。由于 message 字段包含堆栈轨迹,因此错误事件会按 Error Reporting 进行分组:

{...
   "jsonPayload": {
      "serviceContext": {
        "service": "frontend",
        "version": "bf6b5b09b9d3da92c7bf964ab1664fe751104517"
      },
      "message": "com.example.shop.Template$CartDiv retrieveCart: Error\njava.lang.IndexOutOfBoundsException: Index: 4, Size: 4\n\tat java.util.ArrayList.rangeCheck(ArrayList.java:635)\n\tat java.util.ArrayList.get(ArrayList.java:411)\n\tat com.example.shop.Cart.retrieve(Cart.java:76)\n\tat com.example.shop.Cart.generate(Cart.java:55)\n\tat com.example.shop.Template$CartDiv.retrieveCart(Template.java:113)\n\tat com.example.shop.Template.generate(Template.java:22)\n\tat com.example.shop.CartServlet.doGet(CartServlet.java:115)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:717)\n",
      "context":
        "httpRequest": {
          "method": "GET",
          "url": "http://example.com/shop/cart",
          "responseStatusCode": 500
        },
        "user": "9f32f587135aa6774e78ed30fbaabcce3ec5528f"
      }
   },
   "logName": "projects/test-project/logs/reported-error",
   "resource": {
      "labels": {
        "project_id": "test-project"
      },
      "type": "global"
   },
   "severity": "ERROR",
   "timestamp": "2019-06-27T13:43:26.375834551Z"
}

使用 textPayload 字段记录错误事件

如需记录错误事件,您可以使用 LogEntrytextPayload 字段来存储错误数据。例如,以下 Google Cloud CLI 命令会生成严重级别为 ERRORtextPayload 字段包含错误事件的日志条目:

gcloud logging write test-log --severity=ERROR --payload-type=text 'RuntimeException: Oops! Something bad happened.
at com.example.MyClass.method(MyClass.java:123)
at com.example.OtherClass.doStuff(Unknown Source)
at com.example.Sys.create(Native Method)'

上一个命令的结果是按 Error Reporting 分组的日志条目:

{...
    logName: "projects/PROJECT_ID/logs/test-log"
    severity: "ERROR"
    textPayload: "RuntimeException: Oops! Something bad happened.
                  at com.example.MyClass.method(MyClass.java:123)
                  at com.example.OtherClass.doStuff(Unknown Source)
                  at com.example.Sys.create(Native Method)"
    ...
}