github.com/go-graphite/carbonapi@v0.17.0/expr/helper/metric/extract.go (about)

     1  package metric
     2  
     3  import (
     4  	"unicode"
     5  	"unicode/utf8"
     6  
     7  	"github.com/go-graphite/carbonapi/pkg/parser"
     8  )
     9  
    10  // ExtractMetric extracts metric out of function list
    11  func ExtractMetric(s string) string {
    12  	// search for a metric name in 's'
    13  	// metric name is defined to be a Series of name characters terminated by a ',' or ')'
    14  	// work sample: bla(bla{bl,a}b[la,b]la) => bla{bl,a}b[la
    15  
    16  	var (
    17  		start, braces, i, w int
    18  		r                   rune
    19  	)
    20  
    21  FOR:
    22  	for braces, i, w = 0, 0, 0; i < len(s); i += w {
    23  
    24  		w = 1
    25  		if parser.IsNameChar(s[i]) {
    26  			continue
    27  		}
    28  
    29  		switch s[i] {
    30  		// If metric name have tags, we want to skip them
    31  		case ';':
    32  			break FOR
    33  		case '{':
    34  			braces++
    35  		case '}':
    36  			if braces == 0 {
    37  				break FOR
    38  			}
    39  			braces--
    40  		case ',':
    41  			if braces == 0 {
    42  				break FOR
    43  			}
    44  		case ')':
    45  			break FOR
    46  		case '=':
    47  			// allow metric name to end with any amount of `=` without treating it as a named arg or tag
    48  			if i == len(s)-1 || s[i+1] == '=' || s[i+1] == ',' || s[i+1] == ')' {
    49  				continue
    50  			}
    51  			fallthrough
    52  		default:
    53  			r, w = utf8.DecodeRuneInString(s[i:])
    54  			if unicode.In(r, parser.RangeTables...) {
    55  				continue
    56  			}
    57  			start = i + 1
    58  		}
    59  	}
    60  
    61  	return s[start:i]
    62  }