github.com/amazechain/amc@v0.1.3/internal/metrics/prometheus/parseing.go (about)

     1  package prometheus
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"github.com/prometheus/client_golang/prometheus"
     9  )
    10  
    11  func parseMetric(s string) (string, prometheus.Labels, error) {
    12  	if len(s) == 0 {
    13  		return "", nil, fmt.Errorf("metric cannot be empty")
    14  	}
    15  	n := strings.IndexByte(s, '{')
    16  	if n < 0 {
    17  		if err := validateIdent(s); err != nil {
    18  			return "", nil, err
    19  		}
    20  
    21  		return s, nil, nil
    22  	}
    23  	ident := s[:n]
    24  	s = s[n+1:]
    25  	if err := validateIdent(ident); err != nil {
    26  		return "", nil, err
    27  	}
    28  	if len(s) == 0 || s[len(s)-1] != '}' {
    29  		return "", nil, fmt.Errorf("missing closing curly brace at the end of %q", ident)
    30  	}
    31  
    32  	tags, err := parseTags(s[:len(s)-1])
    33  
    34  	if err != nil {
    35  		return "", nil, err
    36  	}
    37  
    38  	return ident, tags, nil
    39  }
    40  
    41  func parseTags(s string) (prometheus.Labels, error) {
    42  	if len(s) == 0 {
    43  		return nil, nil
    44  	}
    45  
    46  	var labels prometheus.Labels
    47  
    48  	for {
    49  		n := strings.IndexByte(s, '=')
    50  		if n < 0 {
    51  			return nil, fmt.Errorf("missing `=` after %q", s)
    52  		}
    53  		ident := s[:n]
    54  		s = s[n+1:]
    55  		if err := validateIdent(ident); err != nil {
    56  			return nil, err
    57  		}
    58  		if len(s) == 0 || s[0] != '"' {
    59  			return nil, fmt.Errorf("missing starting `\"` for %q value; tail=%q", ident, s)
    60  		}
    61  		s = s[1:]
    62  
    63  		value := ""
    64  
    65  		for {
    66  			n = strings.IndexByte(s, '"')
    67  			if n < 0 {
    68  				return nil, fmt.Errorf("missing trailing `\"` for %q value; tail=%q", ident, s)
    69  			}
    70  			m := n
    71  			for m > 0 && s[m-1] == '\\' {
    72  				m--
    73  			}
    74  			if (n-m)%2 == 1 {
    75  				value = value + s[:n]
    76  				s = s[n+1:]
    77  				continue
    78  			}
    79  			value = value + s[:n]
    80  			if labels == nil {
    81  				labels = prometheus.Labels{}
    82  			}
    83  			labels[ident] = value
    84  			s = s[n+1:]
    85  			if len(s) == 0 {
    86  				return labels, nil
    87  			}
    88  			if !strings.HasPrefix(s, ",") {
    89  				return nil, fmt.Errorf("missing `,` after %q value; tail=%q", ident, s)
    90  			}
    91  			s = skipSpace(s[1:])
    92  			break
    93  		}
    94  	}
    95  }
    96  
    97  func skipSpace(s string) string {
    98  	for len(s) > 0 && s[0] == ' ' {
    99  		s = s[1:]
   100  	}
   101  	return s
   102  }
   103  
   104  func validateIdent(s string) error {
   105  	if !identRegexp.MatchString(s) {
   106  		return fmt.Errorf("invalid identifier %q", s)
   107  	}
   108  	return nil
   109  }
   110  
   111  var identRegexp = regexp.MustCompile("^[a-zA-Z_:.][a-zA-Z0-9_:.]*$")