乐趣区

关于golang:Go进阶45Golang简洁的日志收集系统替代ELKB

1. 背景

不废话,
Golang 日志查看疼点

  1. linux 查看日志, 个别开发者对 linux 命令不是很相熟, 搜寻日志更加难上加难
  2. JAVA 生态 ELKB 日志收集搭建简单,
  3. 须要的是一个疾速查看搜寻, 客户端来搜寻日志

1.1 后期筹备

咱们能够应用 logrus hook 疾速的输入日志到 Elastic Search 在应用 Chrome Elastic Search GUI 插件疾速的定位你想用的日志.

  1. 收集日志: https://github.com/sirupsen/l…
  2. 日志保留: docker elastic-search 数据库 : docker run -d --name es.dev -p 9201:9200 -p 9301:9300 -e "discovery.type=single-node" elastic/elasticsearch:6.7.1
  3. ES 客户端: chrome 插件 Chrome Plugin ElasticSearch Head

2. 装置 ES 数据库

你能够去网上搜搜寻 es 数据库装置, 在本教程中咱们就来装置一个 docker es 单节点 (解决 golang 日志性能足够)

  • 拉取镜像 docker pull elasticsearch:6.7.0
  • 装置 docker docker run -d --name mojocn.es -p 9201:9200 -p 9301:9300 -e "discovery.type=single-node" elastic/elasticsearch:6.7.1

这样就您就启动了一个 名字为 mojocn.es 端口 9201 的单节点数据库.

3. 编写实现 logrus HOOK interface (外围代码)

main.go 残缺代码: https://github.com/mojocn/eslogrushook

package main

import (
    "context"
    "fmt"
    "github.com/olivere/elastic"
    "github.com/sirupsen/logrus"
    "log"
    "os"
    "strings"
    "time"
)

//cfg 配置文件
type cfg struct {
    LogLvl     string   // 日志级别
    EsAddrs    []string //ES addr
    EsUser     string   //ES user
    EsPassword string   //ES password
}

//setupLogrus 初始化 logrus 同时把 logrus 的 logger var 援用到这个 common.Logger
func setupLogrus(cc cfg) error {//logFileName := fmt.Sprintf("%s_%s.log", os.Args[1], time.Now().Format("06_01_02T15_04_05"))
    //
    //f, err := os.Create(logFileName)
    //if err != nil {
    //    return err
    //}

    logLvl, err := logrus.ParseLevel(cc.LogLvl)
    if err != nil {return err}
    logrus.SetLevel(logLvl)
    //logrus.SetReportCaller(true)
    //logrus.SetFormatter(&logrus.JSONFormatter{})
    // 应用 console 默认输入

    //logrus.SetOutput(f)

    logrus.SetReportCaller(true)
    // 开启 logrus ES hook
    esh := newEsHook(cc)
    logrus.AddHook(esh)
    fmt.Printf(">= error 级别, 查看日志 %#v  中的 logrus* 索引 \n", cc.EsAddrs)

    return nil
}
func main() {
    cc := cfg{
        LogLvl:     "error",
        EsAddrs:    []string{"http://es.felix.mojotv.cn:9202/"},
        EsUser:     "",
        EsPassword: "",
    }
    err := setupLogrus(cc)
    if err != nil {log.Fatal(err)
    }
    logrus.WithField("URI", "mojotv.cn").Error("I love my son Felix")
    // 期待日志发送到 ES
    time.Sleep(time.Second * 10)
}

//esHook 自定义的 ES hook
type esHook struct {
    cmd    string // 记录启动的命令
    client *elastic.Client
}

//newEsHook 初始化
func newEsHook(cc cfg) *esHook {
    es, err := elastic.NewClient(elastic.SetURL(cc.EsAddrs...),
        elastic.SetBasicAuth(cc.EsUser, cc.EsPassword),
        elastic.SetSniff(false),
        elastic.SetHealthcheckInterval(15*time.Second),
        elastic.SetErrorLog(log.New(os.Stderr, "ES:", log.LstdFlags)),
        //elastic.SetInfoLog(log.New(os.Stdout, "ES:", log.LstdFlags)),
    )

    if err != nil {log.Fatal("failed to create Elastic V6 Client:", err)
    }
    return &esHook{client: es, cmd: strings.Join(os.Args, " ")}
}

//Fire logrus hook interface 办法
func (hook *esHook) Fire(entry *logrus.Entry) error {doc := newEsLog(entry)
    doc["cmd"] = hook.cmd
    go hook.sendEs(doc)
    return nil
}

//Levels logrus hook interface 办法
func (hook *esHook) Levels() []logrus.Level {return []logrus.Level{
        logrus.PanicLevel,
        logrus.FatalLevel,
        logrus.ErrorLevel,
    }
}

//sendEs 异步发送日志到 es
func (hook *esHook) sendEs(doc appLogDocModel) {defer func() {if r := recover(); r != nil {fmt.Println("send entry to es failed:", r)
        }
    }()
    _, err := hook.client.Index().Index(doc.indexName()).Type("_doc").BodyJson(doc).Do(context.Background())
    if err != nil {log.Println(err)
    }

}

//appLogDocModel es model
type appLogDocModel map[string]interface{}

func newEsLog(e *logrus.Entry) appLogDocModel {ins := map[string]interface{}{}
    for kk, vv := range e.Data {ins[kk] = vv
    }
    ins["time"] = time.Now().Local()
    ins["lvl"] = e.Level
    ins["message"] = e.Message
    ins["caller"] = fmt.Sprintf("%s:%d  %#v", e.Caller.File, e.Caller.Line, e.Caller.Func)
    return ins
}

// indexName es index name 工夫宰割
func (m *appLogDocModel) indexName() string {return "mojocn-cn-" + time.Now().Local().Format("2006-01-02")
}

go run main.go 日志输入

>= error 级别, 查看日志 []string{"http://i.love.mojotv.cn:9202/"}  中的 logrus* 索引
time="2020-07-17T17:26:03+08:00" level=error msg=lld func=main.main file="D:/GolandProjects/logrusEsHook/main.go:59" URI=mojotv.cn

4. Chrome 插件 ElasticSearch Head 日志查看

  1. 配置 ES 连贯地址
  2. 查看 / 搜寻 logrus 日志

退出移动版