promql字符串解析

举报
涩涩 发表于 2019/12/27 17:40:27 2019/12/27
【摘要】 lexer 用来将promql字符串解析成itemvolume_manager_total_volumes{instance="lfgphicprd07591",job="kubernetes-nodes",kubernetes_io_arch="amd64"}[5m]// item represents a token or text string returned from the sc...

lexer 用来将promql字符串解析成item

volume_manager_total_volumes{instance="lfgphicprd07591",job="kubernetes-nodes",kubernetes_io_arch="amd64"}[5m]

// item represents a token or text string returned from the scanner.
type item struct {
	typ ItemType // The type of this item.
	pos Pos      // The starting position, in bytes, of this item in the input string.
	val string   // The value of this item.
}

StateFunc

// stateFn represents the state of the scanner as a function that returns the next state.
type stateFn func(*lexer) stateFn

lexStatements 识别所有表达式中可分类的部分,并将一般可解析的转化为item
lexInsideBraces 识别{}中可能出现的字符解析:eof space 字母或者下划线 ," ' =~ != !~ ` 
lexValueSequence  
lexLineComment 识别注释行
lexNumberOrDuration 识别数组或者区间 
lexString 识别引号中的文本包括单双引号
lexRawString 识别原始的文本
lexKeywordOrIdentifier 识别字母数字标记符号(labelname)或关键字
lexDuration识别时间区间 smhdwy  
lexSpace识别空白字符 
lexIdentifier 识别字母数字标记符号
lexNumber 识别数字
lexEscape 识别转义字符

操作pos

next

// next returns the next rune in the input.
func (l *lexer) next() rune {
	if int(l.pos) >= len(l.input) {
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
	l.width = Pos(w)
	l.pos += l.width
	return r
}

peek

// peek returns but does not consume the next rune in the input.
func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}

backup

// backup steps back one rune. Can only be called once per call of next.
func (l *lexer) backup() {
	l.pos -= l.width
}

读取item

emit

loop

// run runs the state machine for the lexer.
func (l *lexer) run() {
	for l.state = lexStatements; l.state != nil; {
		l.state = l.state(l)
	}
	close(l.items)
}

utf8.DecodeRuneInString() 返回一个r和长度,r对应字符本身,长度对应r采用UTF8编码后的编码字节数目

parse

ParseMetric、ParseMetricSelector 处理基本逻辑一致:

  1. 初始化新的解析器

  2. 使用func (p *parser) labelMatchers(operators ...ItemType) []*labels.Matcher获取过滤器中所有match

  3. ParseMetric 直接获取labelMatchers中name、value返回labels.Labels

  4. ParseMetricSelector 获取所有p.labelMatchers(ItemEQL, ItemNEQ, ItemEQLRegex, ItemNEQRegex)过滤并根据传入的name 字符串创建一个 __name__="name"的Matcher

    func newParser(input string) *parser {
    	p := &parser{
    		lex: lex(input),
    	}
    	return p
    }
  • ParseMetric 

    newParser(input string)  -->  metric()
    判断第一个item类型为左大括号:p.labelSet() 判断最后一个是不是 ItemComma ItemRightBrace 作为终止标志 
    获取label name、value以及 matchType(过滤类型)
  • ParseMetricSelector

    newParser(input string)  -->  parseExpr() --> VectorSelector(name)
  • ParseExpr

    newParser(input string)  -->  parseExpr() --> typecheck(expr)


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。