Elasticsearch:Dissect 和 Grok 处理器之间的区别

Posted 中国社区官方博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch:Dissect 和 Grok 处理器之间的区别相关的知识,希望对你有一定的参考价值。

针对很多情况我们可以直接使用 Dissect 处理器来对非结构化化的日志进行结构化。在我之前的文章 “Elasticsearch:深入理解 Dissect ingest processor” 有做笔记深入的讲解。在很多的情况下,我们也可以使用 Grok  处理器来进行结构化。那么这两者之间有什么区别呢?在实际的使用中,我们到底首先哪一个呢?

一般来说,我们需要首先 Dissect 处理器,这是因为它的速度比 Grok 要快很多。Grok 是基于正则匹配,执行速度比 Dissect 要蛮很多。当然 Grok 也有自己的独到之处。它可以同时使用多个 patterns 来对日志来进行匹配。这个是 Dissect 不具备的能力。

下面,我们使用一些简单的例子来进行展示。

展示

我们可以使用 Dissect 处理器来对如下的日志来进行格式化。我们知道 Dissect 处理器对空格非常敏感。如果匹配不对,就会解析失败。

POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "dissect": {
          "field": "message",
          "pattern": "%{@timestamp->} %{status}"
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "message": "2019-09-29 STATUS_OK"
      }
    },
    {
      "_source": {
        "message": "2019-09-29       STATUS_OK"
      }
    }
  ]
}

在上面,尽管两个 message 的格式有所不同,但是我们使用了 -> 来避免错误的解析。上面命令显示的结果为:

{
  "docs" : [
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "@timestamp" : "2019-09-29",
          "message" : "2019-09-29 STATUS_OK",
          "status" : "STATUS_OK"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T01:29:27.141784Z"
        }
      }
    },
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "@timestamp" : "2019-09-29",
          "message" : "2019-09-29       STATUS_OK",
          "status" : "STATUS_OK"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T01:29:27.14179Z"
        }
      }
    }
  ]
}

上面的解析,我们也可以使用 Grok 处理器来进行解析:

POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "grok": {
          "field": "message",
          "patterns": [
            "%{EVENTDATE:@timestamp} %{WORD:status}"
          ],
          "pattern_definitions": {
            "EVENTDATE": "%{YEAR}-%{MONTHNUM}-%{MONTHDAY}"
          }
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "message": "2019-09-29 STATUS_OK"
      }
    }
  ]
}

在上面,我们使用了定制的 pattern 来完成对 @timestamp 的解析。你可以进一步阅读 “Elastic:在 Grok 中运用 custom pattern 来定义 pattern”。上面运行的结果为:

{
  "docs" : [
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "@timestamp" : "2019-09-29",
          "message" : "2019-09-29 STATUS_OK",
          "status" : "STATUS_OK"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T01:31:22.028392Z"
        }
      }
    }
  ]
}

就像我之前所说的,尽管 Dissect 和 Grok 都可以满足要求,我们首选 Dissect,毕竟它的效率要高很多。正则匹配是一个比较慢的运算。

在 Grok 使用多个 patterns 进行匹配

在上面,我们展示了 Dissect 和 Grok。在许多的情况下,它们都可以派上用场,但是有一种情况是 Grok 独有的。Grok 它可以同时使用多个 patterns 来对日志的文件进行匹配。比如,我们有如下的两种日志:

{
    "message": "55.3.244.1 OK"
}

{
    "message": "55.3.244.1 0.043"
}

 显然上面的两种日志的格式是完全不同的。第一种的情况是 IP 加上一个 status,而对于第二种情况来说说,它是 IP 加上一个浮点数。在这种情况下,我们使用 Dissect 是完全无能为力了。

我们可以使用 Grok 来完美地匹配这两种情况:

POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "grok": {
          "field": "message",
          "patterns": [
            "%{IP:client} %{NUMBER:duration:float}",
            "%{IP:client} %{WORD:status}"
          ]
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "message": "55.3.244.1 OK"
      }
    },
    {
      "_source": {
        "message": "55.3.244.1 0.043"
      }
    }
  ]
}

在上面,我们在 Grok 的 pattern 里定义了如下的 patterns:

"patterns": [
    "%{IP:client} %{NUMBER:duration:float}",
    "%{IP:client} %{WORD:status}"
]

也就是说它可以同时匹配两个模式。其中的任何一个匹配,就可以完成文档的正确解析。运行上面的命令,我们可以看到如下的结果:

{
  "docs" : [
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "client" : "55.3.244.1",
          "message" : "55.3.244.1 OK",
          "status" : "OK"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T01:39:44.282416Z"
        }
      }
    },
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "duration" : 0.043,
          "client" : "55.3.244.1",
          "message" : "55.3.244.1 0.043"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T01:39:44.282424Z"
        }
      }
    }
  ]
}

从输出的结果中,我们可以清楚地看到结构化的输出。

我们甚至结合定制 pattern,让它生成更为复杂的匹配模式:

POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "grok": {
          "field": "message",
          "patterns": [
            "%{IP:client} %{VERSION:version} %{NUMBER:num}",
            "%{IP:client} %{NUMBER:duration:float} %{NUMBER:num}",
            "%{IP:client} %{WORD:status} %{NUMBER:num}"
          ],
          "pattern_definitions": {
            "VERSION": """\\d\\.\\d+\\.\\d"""
          }
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "message": "55.3.244.1 7.31.1 12"
      }
    },
    {
      "_source": {
        "message": "55.3.244.1 OK 14"
      }
    },
    {
      "_source": {
        "message": "55.3.244.1 0.043 15"
      }
    }
  ]
}

在上面,我们运用 custom pattterns 来定制一个 pattern。它被用来匹配 version。上面运行的结果是:

{
  "docs" : [
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "num" : "12",
          "client" : "55.3.244.1",
          "message" : "55.3.244.1 7.31.1 12",
          "version" : "7.31.1"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T02:21:22.447666Z"
        }
      }
    },
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "num" : "14",
          "client" : "55.3.244.1",
          "message" : "55.3.244.1 OK 14",
          "status" : "OK"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T02:21:22.447673Z"
        }
      }
    },
    {
      "doc" : {
        "_index" : "_index",
        "_type" : "_doc",
        "_id" : "_id",
        "_source" : {
          "duration" : 0.043,
          "num" : "15",
          "client" : "55.3.244.1",
          "message" : "55.3.244.1 0.043 15"
        },
        "_ingest" : {
          "timestamp" : "2021-07-20T02:21:22.447676Z"
        }
      }
    }
  ]
}

以上是关于Elasticsearch:Dissect 和 Grok 处理器之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

Logstash的filter插件-Dissect

elasticsearch

Elasticsearch分片大小和个数设计

elasticsearch 内存配置

ElasticSearch优化系列七:优化建议

windows运行Elasticsearch内存占用过大