zoukankan      html  css  js  c++  java
  • logstash 统计告警

     在实际的项目中需要对线上日志做实时分析跟统计,这一套方案可以用现有的ELK(ElasticSearch, Logstash, Kibana)方案既可以满足,关于这个方案的具体的步骤可以参考网上的解决方案。但如果只想统计某个错误码(http状态码,业务错误码)在指定时间内出现多少次然后就触发一个告警或者某个指令动作(邮件或者是调用已经写好的http接口,例如例如微信平台来通知告警信息等),这种需求可以用logstash进行实现,并且这种方案比较轻量级,很容易实现。这里以在linux平台为主。

    下载

    首先下载 最新的logstash 压缩包,https://download.elastic.co/logstash/logstash/logstash-2.3.2.zip ,下载后用unzip命令进行解压只指定的目录,解压后会生成一个目录logstash-2.3.2 这个目录,里面包含下面这些文件:

    基本配置

    开始可以通过一个小的介绍了解logstash是怎么回事,链接里面有一些基本的demo,有兴趣可以参考里面的写一下。链接如下:

    http://udn.yyuap.com/doc/logstash-best-practice-cn/get_start/hello_world.html

    运行命令如下:

    假设在与logstash 平级目录新建一个 配置文件,sample.conf ,这个配置文件就是定义 input filter output 这3块,其主要表示 input的来源是什么(文件或命令之类的),filter 代表对于输入的内容按照规则怎么来过滤,output 就是按照过滤的规则进行输出 。

    最简单的写法如下:

    # bin/logstash -e 'input{stdin{}}output{stdout{codec=>rubydebug}}'

    如果是在sample.conf 中写入则如下:

    input {
        stdin{}
    }
    filter {
        
    }
    output {
        stdout {}
    }
    # bin/logstash -f sample.conf

    特殊配置

    在实际的业务中可能往往要对日志做过滤,然后根据某些关键字段进行统计,通过统计结果来决定需要做什么。logstash 本身对于syslog,redis等日志在过滤的时候一般不需要自己写正则表达式去过滤,这些都是通用的,在filter中可以直接通过%{定义的常量}来获取日志内容,已经自动支持的过滤的日志包含下面这些:

    这个列表不全,对于已经支持的这些可以直接到github 上进行搜索(https://github.com/logstash/logstash/tree/v1.4.2/patterns),上面都有这些日志过滤的正则表达式,这些是属于通用配置。 

    往往在业务日志中,所打印的业务关键错误码以及格式并非与通用格式相匹配,那么此时就需要自己针对自己的业务日志格式,写出正则表达式来过滤自己想要的信息。

    这里就以日志中的errno 来为例,所实现的目的就是 当这个错误码在30s内出现3次就把这个错误输出出来或告警。

    在logstash中正则表达式叫做grok表达式,其规则跟perl与ruby的正则表达式一样。 也有在线的grok正则表达式校验工具:http://grokdebug.herokuapp.com/

    这里就以下面的日志格式为例:log.txt

    begin 10001 end
    begin 10001 end
    begin 10001 end
    

    在sample.conf 中,grok 是写在filter 中的,这里既可以直接写正则表达式,也可以引用外部文件的正则表达。

    方式1:

    grok {
        match => {
            "message" => "s+(?<code>d+?)s+"
        }
    }

    方式2就是预先在 patterns/ 目录下创建一个文件,这个文件里面含有正则表达式,例如创建文件的名称为 test ,内容如下:

    ERRORCODE s+(?<code>d+?)s+
    grok {
        patterns_dir => "../../patterns/test"
        match => ["message", "%{ERRORCODE:code:int}"]
    }:

    很显然这里我们习惯采用方式2,因为正则匹配相关的可以单独在一个文件,在sample.conf 就直接引用正则匹配中字段值,例如上面就直接用"ERRORCODE", message 中%后面花括号中的写法规则如下:

    %{PATTERN_NAME:capture_name:data_type}

    以上面完子为例,完整的 sample.conf 内容如下:

    input {
        # 以日志文件作为来源
    file {
        # 文件路径
        path => "../../log.txt"
    }
    }
    filter {
        # 正则解析
        grok {
        # 增加自定义的正则,这里我把自定义的正则文件,加在了这个目录下
        patterns_dir => "../../patterns/test"
        # 从message字段中解析出 code
        match => ["message", "%{ERRORCODE:code:int}"]
        # 删除原来的message字段
        remove_field => [ "message" ]
        # 增加WARN,作为标记
        add_tag => "warn"
        }
    
        # 计数
        metrics {
        # 计数器数据保存的字段名 code的值就是上面解析出来的
        meter => "events_%{code}"
        # 增加"metric",作为标记
        add_tag => "metric"
        # 3秒内的message数据才统计,避免延迟
        # ignore_older_than => 3
        # 每隔300秒统计一次
        flush_interval => "30"
        # 每301秒清空计数器
        clear_interval => "31"
        }
        # 如果event中标记为“metric”的
        if "metric" in [tags] {
        # 执行ruby代码
            ruby {
            # 如果count为10001的数量小于3条,就忽略此事件(即不发送任何消息)。
                code => "event.cancel if event['events_10001']['count'] < 3"
            }
        }
    }
    output {
    # 输出到console
        stdout {
            codec => rubydebug
        }
    }

    上面配置结束后,由于开启 debug 模式,所以当每次往 log.txt 写入 "begin 10001 end" 在控制台下都会有输出,输入内容下:

    {
             "@version" => "1",
             "@timestamp" => "2016-11-14T13:14:14.374Z",
              "path" => "../../log.txt",
              "host" => "xxxx",
              "code" => "10001",
              "tags" => [
              [0] "warn"
            ]
    }

    当在30s内输入的次数大于3次的时候,输出的内容如下:

    {
          "@version" => "1",
          "@timestamp" => "2016-11-14T13:14:20.148Z",
           "message" => "xxx",
           "events_" => {
            "WARN" => {
                   "count" => 3,
                 "rate_1m" => 2.1864058457089883,
                 "rate_5m" => 3.814999397602868,
                "rate_15m" => 4.1951645878441255
            }
         },
              "tags" => [
            [0] "metric"
        ]
    }

    通过上面的结构可以看出我们在输出的时候还可以写表达式,例如只有当30s内大于3次才输出信息的话可以在 output 中加一个判断,逻辑如下:

    output {
        # 如果event中标记为“metric”,表示只发送计数的消息。
        if "metric" in [tags] {
        # 执行一个简单的命令
            exec {
                command => "echo "hello: %{events_10001.count}""
            }
        }
    }

    到这里已经结束,关于logstash中的 统计相关的规则可以参考:http://udn.yyuap.com/doc/logstash-best-practice-cn/filter/metrics.html

    输出的形式也是多种的 可以对接ES,触发http接口,这里就以输出为例。

  • 相关阅读:
    职业规划——第1.0章、模拟面试的小记(一)
    菜鸟VUER学习记——零0章、打开新的大门
    职业规划——第0章、哇,原来需要的这么多
    经营自己,愈发强大——《软技能——代码之外的生存指南》读后感
    如何阅读一本书
    Java开发规范
    JVM堆和栈的区别
    2016年7月书单推荐
    web性能优化——代理(nginx)
    web性能优化——浏览器相关
  • 原文地址:https://www.cnblogs.com/stackflow/p/6071807.html
Copyright © 2011-2022 走看看