写点什么

golang 脚本实时监控错误日志

作者:lixiaofeng
  • 2021 年 12 月 13 日
  • 本文字数:1523 字

    阅读完需:约 5 分钟

golang 脚本实时监控错误日志

对于日志的监控分析, ELK 依然已经成为业界标准了。其中 L 代表 Logstash, 用来采集日志。E 代表 Elasticsearch,用来存储检索分析。K 是 Kibana 用来显示。这一套日志分析监控系统非常强大。

若我们的需求非常简单,例如,要实时监控 MySQL,MongoDB 等的日志文件, 实时监控 error log。 若出现了 error log, 马上报警。

若是需求简单,没必要安装大块头的 ELK 情况下, 我们也可以自己写代码来实现对日志的实时监控。

基本思路如下:

  • 主进程定时采集新增日志,比如每秒采集一次,因为采集的是新增日志,所以即使很大(例如,几 GB 或者几十 GB)也不影响性能。当然,还要记录上次读取的位置。

  • 一个 go routinue 负责对新增日志的过滤,用来搜索过滤是否有 error 日志

  • 一个 go routinue 负责报警,发邮件发钉钉发微信等

主线程核心代码如下:

这里使用了两个循环。 内层循环, 每次新增的日志信息, 内层循环每次读取一行,使用通道传输给日志过滤的 go routinue。

外层循环,负责每秒钟读取一次新增的日志。seek, err := f.Seek(i, 0) 负责每次读取新增的日志,i 是上次读取到的日志偏移量。 finfo.Size() < i 判断是负责检测日志是否切割了。 因为每天切割一次日志,生成一个新的日志文件。若当前日志的总大小小于记录的偏移量, 则认为这是一个新日志。

for {        f, err := os.Open("D:\\project\\golang\\MyIncrLog\\1.log")        finfo, err := f.Stat()        //fmt.Println("file size:",finfo.Size()," offset:",i)        if err != nil {            fmt.Println(err)        }        if finfo.Size() < i {            i = 0        }        if err != nil {            fmt.Println(err)        }        seek, err := f.Seek(i, 0)        if err != nil {            fmt.Println(seek, err)        }        rd := bufio.NewReader(f)        for {            line, err := rd.ReadString('\n')            if err != nil || io.EOF == err {                if io.EOF != err {                    fmt.Println(err)                }                break            }            in <- line            n := len([]byte(line))            i = i + int64(n)            time.Sleep(time.Millisecond * 100)        }        time.Sleep(time.Second)        f.Close()    }
复制代码


下面的代码是过滤 error 日志的 go routiune。这个函数返回两个通道,主进程写数据到 in 通达以后,该 go routinue 马上启动去过滤该日志,并根据结果情况,确定是否输入到 out 通道中。

func Match() (chan<- string, <-chan string) {    in := make(chan string)    out := make(chan string)    go func() {        for {            select {            case s:=<-in:                if  strings.Contains(s, "[Error]") {                    out <- s                }            }        }    }()    return in, out}
复制代码


下面的代码是负责接收 out 通道里面的值, 然后调用 send 函数去处理。send 函数里面,我们可以根据我们的需要去报警, 发邮件发钉钉发微信等等都可以。

    go func(s send.Sender, out <-chan string) {        for {            err := s.Send(<-out)            if err != nil {                return            }        }    }(send.Faker{}, out)        func (f Faker) Send(msg string) error {    fmt.Print(msg)    // 发邮件,发微信,发钉钉    return nil}
复制代码


运行效果如下。只需要把日志地址和过滤关键词做成配置文件, 就可以对我们所需要的日志进行监控, 结果可以按照我们的需要发邮件发微信发钉钉等。


发布于: 3 小时前阅读数: 6
用户头像

lixiaofeng

关注

还未添加个人签名 2018.04.25 加入

还未添加个人简介

评论

发布
暂无评论
golang 脚本实时监控错误日志