美文网首页日志处理
ELK实践(二)--多行日志处理

ELK实践(二)--多行日志处理

作者: 上岸的魚 | 来源:发表于2020-04-06 17:58 被阅读0次

    前言:

    上文https://www.jianshu.com/p/8b68ac58b191通过logstash grok进行数据处理,提取出日志类型及message,并可以生成到不同的索引文件;
    随后的使用中发现针对错误日志,由于日志信息换行导致message会分散到多条日志中,如下图所示:

    日志内容(部分)如下
    [2020-04-06 15:55:14.521] |http-nio-8020-exec-10|ERROR| com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Exception during pool initialization.
    com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
    
    The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
        at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
        at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836)
        at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)
    
    
    kibana错误日志显示

    1.多行处理

    目前针对多行合并处理通常采用的logstash的multiline插件完成。
    笔者采用如下方式处理时,发现无法启动logstash,提示multiline不被beats支持,进入docker查看 codec的multiline插件是安装过的。

    input {
       beats {
           port => 5044
              codec => multiline  {
                 pattern => "^\[\d*-\d*"
                 negate => true
                 what => "previous"
               }
            }
      }
    

    查阅官方资料的确有显示该功能不被支持,如果要合并则需要我们从源头配置Filebeat去处理,只能姑且理解为ES期望这种多行文本合并的操作最好在源头解决掉。
    https://www.elastic.co/guide/en/beats/filebeat/6.8/multiline-examples.html

    不支持multiline
    解决方案
    采集日志我们采用了log-pilot,其内部使用了filebeat,我们修改其filebeat模式后重新部署log-pilot。
    **master节点**
     [root@k8s-master es]# kubectl get pods -n kube-system | grep log-pilot
    log-pilot-9pt27                         1/1     Running   0          3d17h
    log-pilot-qq9w5                         1/1     Running   1          3d17h
    log-pilot-vc7qs                         1/1     Running   0          3d17h
    kubectl cp kube-system/log-pilot-9pt27:/pilot/filebeat.tpl  filebeat.tpl #复制容器中filebeat.tpl文件到master节点
    

    如上文提及,我们的日志格式如下:

    ***********.Net日志**************
    [2020-04-05 12:59:04.7338]|netCore07.LogHelper|INFO|请求Healthy:04/05/2020 12:59:04 
    [2020-04-05 12:59:16.3861]|netCore07.LogHelper|INFO|请求DefaultIndex:04/05/2020 12:59:16 
    [2020-04-05 12:59:17.5992]|netCore07.LogHelper|INFO|请求DefaultIndex:04/05/2020 12:59:17 
    [2020-04-05 12:59:18.1920]|netCore07.LogHelper|INFO|请求DefaultIndex:04/05/2020 12:59:18 
    [2020-04-05 12:59:21.6663]|netCore07.LogHelper|INFO|请求Healthy:04/05/2020 12:59:21 
    ***********Java日志**************
    [2020-04-05 13:16:58.351] |http-nio-8020-exec-1|INFO| o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
    [2020-04-05 13:16:58.351] |http-nio-8020-exec-1|INFO| org.springframework.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
    [2020-04-05 13:16:58.375] |http-nio-8020-exec-1|INFO| org.springframework.web.servlet.DispatcherServlet - Completed initialization in 22 ms
    [2020-04-05 13:16:58.434] |http-nio-8020-exec-1|INFO| com.xxx.controller.StudentController - File-springboot-say:xx
    

    针对日志我们编写一个正则匹配每条日志的开头格式
    ^.{0,3}\[[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}\]|^[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}

    vim filebeat.tpl  #修改该文件
    {{range .configList}}
    {{range .configList}}
    {{range .configList}}
    {{range .configList}}
      scan_frequency: 10s
      fields_under_root: true
      {{if .Stdout}}
      docker-json: true
      {{end}}
      {{if eq .Format "json"}}
      json.keys_under_root: true
      {{end}}
      fields:
          {{range $key, $value := .Tags}}
          {{ $key }}: {{ $value }}
          {{end}}
          {{range $key, $value := $.container}}
          {{ $key }}: {{ $value }}
          {{end}}
      tail_files: false
      close_inactive: 2h
      close_eof: false
      close_removed: true
      clean_removed: true
      close_renamed: false
    #以下4行是我们手动添加的
      multiline.pattern: '^.{0,3}\[[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}\]|^[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}'
      multiline.negate: true
      multiline.match: after
      multiline.max_lines: 1000
      multiline.timeout: 20s
    {{end}}
    

    参数说明:
    multiline.negate: 多行匹配模式是否取反,默认false
    multiline.match: 定义多行内容被添加到模式匹配行之后还是之前,默认无,可以被设置为after或者before
    multiline.max_lines: 单一聚合最大的行数,超过会被丢弃
    multiline.timeout:多行匹配超时时间,超过超时时间后的当前多行匹配事件将停止并发送,然后开始一个新的多行匹配事件,默认5秒,这个很有用,以往我们用logstash的multiline时就会遇到最后一条日志无法采集,需要新日志插入才能采集的情况。

    文件编写完毕后我们重新制作一个定制版log-pilot镜像:

    vim Dockerfile
    FROM registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.6-filebeat
    COPY filebeat.tpl /pilot/filebeat.tpl
    ####wq保存dockerFile
    ####然后执行docker build制作镜像
    [root@k8s-master log-pilot]# docker build -t 192.168.0.230:8083/es/log-pilot .
    Sending build context to Docker daemon  3.584kB
    Step 1/2 : FROM registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.7-filebeat
     ---> 10a688e1229a
    Step 2/2 : COPY filebeat.tpl /pilot/filebeat.tpl
     ---> 433f59cc094e
    Successfully built 433f59cc094e
    Successfully tagged 192.168.0.230:8083/es/log-pilot:latest
    ####上传镜像到仓库
    [root@k8s-master log-pilot]# docker push 192.168.0.230:8083/es/log-pilot
    The push refers to repository [192.168.0.230:8083/es/log-pilot]
    5d508534be62: Pushed 
    385d5e9ef470: Pushed 
    60121972171a: Pushed 
    f48d07bb0c66: Pushed 
    93d544c0cc28: Pushed 
    b204552c6406: Pushed 
    721384ec99e5: Pushed 
    latest: digest: sha256:e8cba23fec45b221df0fc6e7b640c0475085dce4e39e14c0eb77cfd6571115c4 size: 1788
    

    重新部署log-pilot
    kubectl delete -f log-pilot.yaml 删除当前的log-pilot
    接下来修改log-pilot.yaml中镜像地址为我们刚才制作的镜像完整名称
    kubectl apply -f log-pilot.yaml 再重新部署log-pilot

    2.验证

    重新访问下报错的URL路径,系统记录下报错日志,然后我们到kibana中查看
    从容器日志文件中查看,出现2条错误日志,内容很长,文中就不再粘贴。
    kibana中查看,和预期一样,记录了两条完整的日志


    kibana多行日志整合

    说明:列表中是摘要,点击列表行可以查看单个文档,查看完整日志信息。

    总结

    这种从源头解决多行的问题并不是笔者所期望的,配置方式的灵活度并不如logstash的脚本模式,您也可能尝试通过logstash的filter中使用multiline模式达到同样的效果,示例:

    filter {
       multiline {
                pattern => "^.{0,3}\[[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}\]|^[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}"
                negate => true
                what => "previous"
            }
        grok {   
            match => {"message" => ".{0,3}%{TIMESTAMP_ISO8601:logTime}.{0,10}\|.*\|%{LOGLEVEL:logLevel}\|%{GREEDYDATA:message}"}
            #用上面提取的message覆盖原message字段
            overwrite => ["message"]
           }
    }
    

    相关文章

      网友评论

        本文标题:ELK实践(二)--多行日志处理

        本文链接:https://www.haomeiwen.com/subject/alavphtx.html