Skip to content

Parsers

Sun Jianbo edited this page Mar 11, 2018 · 10 revisions

Parser 是在数据被logkit读取后,用户可以根据需要定制化的解析日志格式,抽取数据中的字段,转化为结构化数据的方式。

目前logkit已经内置一部分数据解析方式,他们分别为:

  1. csv(按行通过分隔符解析): csv parser
  2. json(通过json反序列化解析): json parser
  3. grok(通过配置grok pattern解析): grok parser
  4. qiniulog(七牛开源的golang日志库日志格式解析): Qiniu Log Parser
  5. kafkarest(Kafkarest日志解析): KafkaRestLog Parser
  6. raw(直接按行读取返回): Raw Parser
  7. syslog(系统的syslog日志格式): syslog parser
  8. mysqllog(mysql慢请求日志解析): mysqllog parser

Parser 典型配置如下

    "parser":{
        "name":"req_csv",
        "type":"csv",
        "labels":"machine nb110,team pandora"
    },
  1. name parser的name,用来标识
  2. type parser的类型
  3. labels 对于所有的Parser,我们均提供了标签功能,用于记录一些额外的信息,添加到结构化的数据字段中,如常见的日志所在机器、业务所述团队等信息,labels的写法则是标签名称和数值以空格隔开<标签名> <标签内容>,多个标签提供逗号分隔。

根据不同的Parser,还需要填写其他特定Parser相关的配置文件,详情请参阅各Parser的配置页面。

如何添加更多的Parser(自定义Parser)?

若上述内置的解析器依旧无法满足您的需求,Logkit也支持用户根据需要自己实现解析逻辑,只需要实现如下两个接口。

type LogParser interface {
    Name() string
    // parse lines into structured datas
    Parse(lines []string) (datas []sender.Data, err error)
}

Parser的接口非常简单,一共就2个方法。

首先 Name() 函数表示Parser的名称,用于标识;其次就是批量解析数据的Parse方法,传入的是一个字符串数组,数组的每一个元素就是reader中readline函数获取的每一行,为了性能更高传入数组进行批量解析,返回的数据就是按照sender中定义的Data类型,实际上对应的就是Go语言的 map[string]interface{}类型。

所以Parser要做2件事情。

  1. 确定最终要解析出的schema,即字段(field或者key)和类型(type)。像json这种数据天生就含有schema,无需用户定义,其他类型的解析器可能需要用户在配置文件中写明schema是怎么样的。
  2. 定义规则将传入的字符串按照schema解析。Parser之间的主要区别实际上就是规则的不同,如csv parser就是按照指定的分隔符分隔;json parser就是按照json格式解析 等等。根据你Parser对应要解析的字符串内容实现你的解析规则即可。

实现完成Parser后,注意在 NewParserRegistry()中注册对应的new方法噢,如下所示。

func NewParserRegistry() *ParserRegistry {
	ps := &ParserRegistry{
		parserTypeMap: map[string]func(conf.MapConf) (LogParser, error){},
	}
	ps.RegisterParser(TypeCSV, NewCsvParser)
	ps.RegisterParser(TypeRaw, NewRawlogParser)
	ps.RegisterParser(TypeKafkaRest, NewKafaRestlogParser)
	ps.RegisterParser(TypeEmpty, NewEmptyParser)
	ps.RegisterParser(TypeGrok, NewGrokParser)
	ps.RegisterParser(TypeJson, NewJsonParser)
	ps.RegisterParser(TypeNginx, NewNginxParser)
  
       //ps.RegisterParser(TypeMyNewParser, NewMyNewParser)

	return ps
}

一个示例的自定义Parser

package samples

import (
	"strings"

	"github.com/qiniu/logkit/conf"
	"github.com/qiniu/logkit/parser"
	"github.com/qiniu/logkit/sender"
)

// 一个自定义parser的示例,将日志放到data中的log字段中
type CustomParser struct {
	// parser 的名字
	name string
	// 每行截断最大字符数
	maxLen int
}

func NewMyParser(c conf.MapConf) (parser.LogParser, error) {
	// 获取parser配置中的name项,默认myparser
	name, _ := c.GetStringOr("name", "myparsername")
	// 获取parser配置中的max_len选项,默认1000
	maxLen, _ := c.GetIntOr("max_len", 1000)
	p := &CustomParser{
		name:   name,
		maxLen: maxLen,
	}
	return p, nil
}

func (p *CustomParser) Name() string {
	return p.name
}

func (p *CustomParser) Parse(lines []string) (datas []sender.Data, err error) {
	for _, l := range lines {
		d := sender.Data{}
		line := strings.TrimSpace(l)
		if len(line) > p.maxLen {
			line = line[:p.maxLen]
		}
		d["log"] = line
		datas = append(datas, d)
	}
	return datas, nil
}
Clone this wiki locally