Datadog grok 自定义 java 堆栈解析和有序列表字段

Datadog grok custom java stack parsing and ordered list fields

我在 datadog 的 grok 管道中有以下日志示例:

2022-05-10 11:26:58 [SEVERE]: Log from eu.myapp
  dev added message - eu.myapp.Controller.<init>
java.lang.NullPointerException
    at eu.myapp.Controller.<init>(Controller.java:48)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)

和下面的简单解析规则

log %{_date}%{space}\[%{_status}\]\:%{space}%{data:logger}(\n%{space}%{data:msg}%{space}-%{space}%{data:in})?(\n%{space}%{data:error.msg})?(\n%{space}%{data:error.stack})?

并尝试通过重复 error.stack 使每一行都添加到数组

log %{_date}%{space}\[%{_status}\]\:%{space}%{data:logger}(\n%{space}%{data:msg}%{space}-%{space}%{data:in})?(\n%{space}%{data:error.msg})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})?(\n%{space}%{data:error.stack})

输出简单:

{  
  "level": "SEVERE",
  "timestamp": 1652182018000,
  "error": {
    "msg": "java.lang.NullPointerException",
    "stack": "at eu.myapp.Controller.<init>(Controller.java:48)\n        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)\n        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)\n        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)\n        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)"
  },
  "in": "eu.myapp.Controller.<init>",
  "msg": "dev added message",
  "logger": "Log from eu.myapp"
 }

输出更好:

{
  "level": "SEVERE",
  "timestamp": 1652182018000,
  "error": {
    "msg": "java.lang.NullPointerException",
    "stack": [
      "at java.lang.reflect.Constructor.newInstance(Constructor.java:423)",
      "at eu.myapp.Controller.<init>(Controller.java:48)",
      "at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)",
      "at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)",
      "at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)"
    ]
  },
  "in": "eu.myapp.Controller.<init>",
  "msg": "dev added message",
  "logger": "Log from eu.myapp"
}

如您所见,更好的输出更具可读性,但列表现在是无序的。有什么方法可以让 error.stack 订购吗?或者比我现在做的更好地分析这种情况的任何其他提示或技巧。

我必须注意,我无法控制日志文件的生成或格式。

整个堆栈跟踪应该在 error.msg 属性内。

所以你可以更新你的 grok 解析器到这个(你可以放回你的状态和日期助手规则)。

log %{date("yyyy-MM-dd HH:mm:ss"):timestamp}%{space}\[%{word:status}\]\:%{space}%{data:logger}(\n%{space}%{data:msg}%{space}-%{space}%{data:in})?(\n%{data:error.msg})?

我还建议将 msg 重命名为 message,将 error.msg 重命名为 error.stack。您可以看到它们在文档中被列为 reserved attribute。这将使堆栈跟踪变得漂亮UI,看起来更清晰。

还记得在您的管道中创建 message, status, and date 重新映射器,以便您的日志的默认值全部得到适当更新。