本节重点介绍 :
- 新建项目 log2metrics
- 编写配置文件yaml
- main 解析配置,校验正则,设置log
- 根据配置文件设置metrics
新建项目 log2metrics
go mod init
go mod init log2metrics
编写配置文件yaml
http_addr: 0.0.0.0:8087
log_level: INFOlog_strategy:- metric_name: log_containerd_totalmetric_help: /var/log/messages 中的 containerd日志 totalfile_path: /var/log/messagespattern: ".*containerd.*"func: cnttags:level: ".*level=(.*?) .*"- metric_name: ngx_acc_codemetric_help: nginx code avgfile_path: /var/log/nginx/access.logpattern: '.*\[code=(.*?)\].*'func: avg
log_strategy 字段解析
- metric_name :指定暴露的metrics名称 如 ngx_access_cnt
- metric_help : 暴露指标的metrics帮助信息,支持中文
- file_path : 指定日志路径
- pattern:提供日志匹配正则 ,如过滤包含 containerd的日志
- func :计算方法
- cnt 对符合规则的日志进行计数 ,就是日志的总数counter
- max 对符合规则的日志抓取出的数字算最大值 ,如code=404 和code=500 max结果就是 500
- min 对符合规则的日志抓取出的数字算最小值
- sum 对符合规则的日志抓取出的数字算和
- avg 对符合规则的日志抓取出的数字算平均值
- tags:标签的正则,
- key=正则
- key最后用来设置metrics的标签
- value正则匹配的结果是标签的值
代码中解析配置文件
日志采集策略文件
package strategyimport "regexp"type Strategy struct {ID int64 `json:"id" yaml:"-"`MetricName string `json:"metric_name" yaml:"metric_name" ` MetricHelp string `json:"metric_help" yaml:"metric_help" ` FilePath string `json:"file_path" yaml:"file_path"` Pattern string `json:"pattern" yaml:"pattern"` Tags map[string]string `json:"tags" yaml:"tags"` Func string `json:"func" yaml:"func" ` Creator string `json:"creator"`PatternReg *regexp.Regexp `json:"-"` TagRegs map[string]*regexp.Regexp `json:"-"`
}
解析配置的方法
package configimport ("fmt""github.com/toolkits/pkg/logger""io/ioutil""log2metrics/strategy""regexp""gopkg.in/yaml.v2"
)type Config struct {LogStrategies []*strategy.Strategy `yaml:"log_strategy"`LogLevel string `yaml:"log_level"`HttpAddr string `yaml:"http_addr"`
}func Load(s string) (*Config, error) {cfg := &Config{}err := yaml.Unmarshal([]byte(s), cfg)if err != nil {return nil, err}cfg.LogStrategies = updateRegs(cfg)return cfg, nil
}
func updateRegs(cfg *Config) []*strategy.Strategy {res := []*strategy.Strategy{}for _, st := range cfg.LogStrategies {st := stif len(st.Pattern) != 0 {reg, err := regexp.Compile(st.Pattern)if err != nil {logger.Errorf("compile pattern regexp failed:[sid:%d][pat:%s][err:%v]", st.ID, st.Pattern, err)continue}st.PatternReg = reg}st.TagRegs = map[string]*regexp.Regexp{}for tagk, tagv := range st.Tags {reg, err := regexp.Compile(tagv)if err != nil {logger.Errorf("compile tag failed:[sid:%d][pat:%s][err:%v]", st.ID, tagv, err)continue}st.TagRegs[tagk] = reg}res = append(res, st)}return res
}func LoadFile(filename string) (*Config, error) {content, err := ioutil.ReadFile(filename)if err != nil {return nil, err}cfg, err := Load(string(content))if err != nil {fmt.Printf("[parsing YAML file errr...][error:%v]", err)return nil, err}return cfg, nil
}
updateRegs校验用户配置的正则
- 使用regexp.Compile解析 st.Pattern
- 如果报错了说明用户配置的正则不对,那么就忽略这个配置
- 对于标签的正则st.TagRegs的处理方式是
main 解析配置,设置log
解析命令行
package mainimport ("context""github.com/oklog/run""github.com/prometheus/client_golang/prometheus""github.com/prometheus/common/promlog"promlogflag "github.com/prometheus/common/promlog/flag""github.com/prometheus/common/version""github.com/toolkits/pkg/logger""gopkg.in/alecthomas/kingpin.v2""log2metrics/common""log2metrics/config""log2metrics/consumer""log2metrics/counter""log2metrics/logjob""log2metrics/metrics""os""os/signal""path/filepath""syscall"
)func main() {var (app = kingpin.New(filepath.Base(os.Args[0]), "The log2metrics")configFile = app.Flag("config.file", "log2metrics configuration file path.").Default("log2metrics.yml").String())promlogConfig := promlog.Config{}app.Version(version.Print("log2metrics"))app.HelpFlag.Short('h')promlogflag.AddFlags(app, &promlogConfig)kingpin.MustParse(app.Parse(os.Args[1:]))
解析配置文件和设置log
sConfig, err := config.LoadFile(*configFile)if err != nil {logger.Infof("config.LoadFile Error,Exiting ...error:%v", err)return}logger.SetSeverity(sConfig.LogLevel)
根据配置文件设置metrics
package metricsimport ("github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp""log2metrics/strategy""net/http"
)func CreateMetrics(ss []*strategy.Strategy) map[string]*prometheus.GaugeVec {mmap := make(map[string]*prometheus.GaugeVec)for _, s := range ss {labels := []string{}for k := range s.Tags {labels = append(labels, k)}m := prometheus.NewGaugeVec(prometheus.GaugeOpts{Name: s.MetricName,Help: s.MetricHelp,}, labels)mmap[s.MetricName] = m}return mmap}
解读
- 遍历配置文件解析完之后的策略数组
- 初始化一个gauge类型的metrics
- 名字为用户配置的 MetricName
- Help为用户配置的 MetricHelp
- labels为用户配置的 tags的key
- 以metrics 的name为key,value是这个metrics 创建一个map
main.go中创建这个metrics的map
metricsMap := metrics.CreateMetrics(sConfig.LogStrategies)for _, m := range metricsMap {prometheus.MustRegister(m)}
本节重点总结 :
- 新建项目 log2metrics
- 编写配置文件yaml
- main 解析配置,设置log
- 根据配置文件设置metrics