ES 数据预处理 Ingest Node/Pipeline

需求

收集所有服务的请求日志,存储以供后续使用。

初步想法是用Nginx将所有服务的请求输出到日志,再由收集器将日志 收集起来->解析->存储。

使用ES家族的 filebeat 收集NG日志,可是收集到的日志不太好解析,而且还增加个时间字段,转换某些字段等操作,后来想法是再写个服务(或Logstash)吧 Filebeat调这个服务,由这个服务做处理解析。但是又感觉太重了,偶然发现 ES 原生 已经支持数据处理(filter)了。
于是花了半天研究了下,下面把坑、和使用方法都记一下。

具体参考了优秀的这篇文章:

关于 Ingest Node/Pipeline 的详解。赞!
https://www.felayman.com/articles/2017/11/24/1511527532643.html
还有官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/handling-failure-in-pipelines.html

先看下效果吧:
【源】NG log
61.50.98.62 - [08/Jan/2019:13:11:09 +0800] "GET /images/index/img05_11.jpg HTTP/1.1" 200 312473 "http://vipcode.cn/" - 0.210 0.052 100.118.58.9:80 200 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3494.0 Safari/537.36

【结果】处理后存入后的效果:

要做的事情:

  1. 增加 gmt_create 记录数据时间。
  2. 将以空格分隔的NG日志 解析为 图中的K->V

解决过程:

  1. create index ... 略过。
  2. 创建pipeline(processor)增加gmt_create
  3. 创建pipeline(processor)解析 ng log
    2、3步最终是要合一起的,一个processor即增加了时间也解析了格式;可我初次试验的时候是分开调试的。

创建processor:

其中用到了 set 和 grok (在上面的连接中有介绍)
_ingest/pipeline/nglogproc

这里坑有两个,

  1. {{_ingest.timestamp}} 存到ES里的时间是UTC0的时间,晚于国内8小时。
  2. grok 的调试比较烦人,虽说写比较容易,比对数据是最耗时的。

解决方案:

  1. 因为 _ingest.timestamp 是ES生成的,没有找到通过哪个配置能修改,想了一晚上最后想编译源码解决去了。还好,不用管,Kibana会正常显示、检索。
  2. Grok语法和内置的表达式网上有很多,熟悉一下然后 根据这个调试器http://grokdebug.herokuapp.com,一点点来吧。

最后,post ES 处理保存数据:

没有出错就是文章开始的效果图了,_ingest.timestamp 不会出错,会出问题的多半出在grok和源数据不匹配的问题里,错误里会有部分提示。

One more thing, 贴出我的 grok
Log1:
112.17.88.223 - [08/Jan/2019:10:49:08 +0800] "GET /open_008/08_img6.png HTTP/1.1" 200 1445 "https://www.vipcd.com/_zh/open_008.min.css" - 0.005 0.004 59.110.185.113:80 200 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Log2:
39.104.152.143 - [08/Jan/2019:17:34:18 +0800] "GET / HTTP/1.1" 200 9262 "-" - 0.032 0.031 172.17.231.247:8080 200 Go-http-client/1.1
Log3:
39.82.11.241 - [22/Jan/2019:16:53:04 +0800] "GET /v1?uuid=vipcode2165376223244&uid=154814718762578s5dfaco&project=act&logType=pv&logVersion=1.0&refer=&ua=Mozilla%2F5.0%20(iPad%3B%20U%3B%20CPU%20OS%205_0%20like%20Mac%20OS%20X%3B%20en-us)%20AppleWebKit%2F534.46%20(KHTML%2C%20like%20Gecko)%20Version%2F5.1%20Mobile%2F9A334%20Safari%2F7534.48.3&subType=guangdiantong%7C%7ChasCode&screensize=w800||h1280&url=http%3A%2F%2Fact.vipcode.com%2Fmps%2Fproduce%2F1545381467902%2Fpc%2Findex.html%3FstClId%3D7%26sLClId%3D0%26plId%3D0%26unId%3D0%26kwd%3D%26lGPId%3D150%26acId%3D0%26pSId%3D28%26acPFlag%3D0%26sFFlag%3D0%26remark%3D113Lllq122105%26qz_gdt%3Df7mumxf7aaaoaehyrkya HTTP/1.1" 200 1 "http://act.vipcode.com/mps/produce/1545381467902/pc/index.html?stClId=7&sLClId=0&plId=0&unId=0&kwd=&lGPId=150&acId=0&pSId=28&acPFlag=0&sFFlag=0&remark=113Lllq122105&qz_gdt=f7mumxf7aaaoaehyrkya" - 0.000 - - - Mozilla/5.0 (iPad; U; CPU OS 5_0 like Mac OS X; en-us) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
Grok:
%{IP:client} %{USER:user} \[%{HTTPDATE:http_date}\] \"%{WORD:method} %{NOTSPACE:http_uri} HTTP/%{NUMBER:http_ver}\" %{NUMBER:http_st_ng} %{NUMBER:bytes} \"(?https?://[^ ]+|-)\" (?[0-9]+(\.[0-9]+){3}(?:, [0-9]+(\.[0-9]+){3})*|-) %{NUMBER:rsp_time1} (?:%{NUMBER:rsp_time2}|-) (?[0-9]+(\.[0-9]+){3}(:[0-9]+)?|-) (?:%{NUMBER:http_st_server}|-) (?.*$)

nglogproc Pipleline:

{
    "description": "nginx log processor",
    "processors": [
      {
        "grok": {
          "field": "message",
          "patterns": [
            "%{IP:client} %{USER:user} \\[%{HTTPDATE:http_date}\\] \"%{WORD:method} %{NOTSPACE:http_uri} HTTP/%{NUMBER:http_ver}\" %{NUMBER:http_st_ng} %{NUMBER:bytes} \"(?[^\"]+|-)\" (?[0-9]+(\\.[0-9]+){3}(?:, [0-9]+(\\.[0-9]+){3})*|-) %{NUMBER:rsp_tn} (?[0-9.]+(, [0-9.]+)*|-) (?[0-9]+(\\.[0-9]+){3}(:[0-9]+)?(, ([0-9]+(\\.[0-9]+){3}(:[0-9]+)?))*|-) (?[0-9]+(, [0-9]+)*|-) (?.*$)"
          ],
          "on_failure": [
            {
              "set": {
                "field": "g_err0",
                "value": "{{_ingest.on_failure_message }}"
              }
            }
          ]
        }
      },
      {
        "set": {
          "field": "gmt_create",
          "value": "{{_ingest.timestamp}}"
        }
      },
      {
        "grok": {
          "field": "http_uri",
          "patterns": [
            "/v\\d+\\?uuid=(?[^&]*+)&uid=(?[^&]*+)&project=(?[^&]*+)&logType=(?[^&]*+)&logVersion=(?[^&]*+)&refer=(?[^&]*+)&ua=(?[^&]*+)&subType=(?[^&]*+)&screensize=(?[^&]*+)&url=(?.*+$)"
          ],
          "on_failure": [
            {
              "set": {
                "field": "g_err1",
                "value": "{{_ingest.on_failure_message }}"
              }
            }
          ]
        }
      },
      {
        "urldecode": {
          "field": "ua",
          "on_failure": [
            {
              "set": {
                "field": "g_err2",
                "value": "{{_ingest.on_failure_message }}"
              }
            }
          ]
        }
      },
      {
        "urldecode": {
          "field": "url",
          "on_failure": [
            {
              "set": {
                "field": "g_err2",
                "value": "{{_ingest.on_failure_message }}"
              }
            }
          ]
        }
      },
      {
        "urldecode": {
          "field": "screensize",
          "on_failure": [
            {
              "set": {
                "field": "g_err2",
                "value": "{{_ingest.on_failure_message }}"
              }
            }
          ]
        }
      },
      {
        "urldecode": {
          "field": "subType",
          "on_failure": [
            {
              "set": {
                "field": "g_err2",
                "value": "{{_ingest.on_failure_message }}"
              }
            }
          ]
        }
      }
    ]
  }

这种方式的好处是非常简便,缺点是容错率非常低对格式有着严格的要求。

不过庆幸的是其提供了“当错误发生时你要做的事情 —— on_failure ”

Filebeat 使用 Pipeline
http://www.axiaoxin.com/article/236/
在FB配置文件中增加配置即可。

你可能感兴趣的:(ES 数据预处理 Ingest Node/Pipeline)