github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/prometheus/common/model/metric.go (about)

     1  // Copyright 2013 The Prometheus Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package model
    15  
    16  import (
    17  	"fmt"
    18  	"regexp"
    19  	"sort"
    20  	"strings"
    21  )
    22  
    23  var (
    24  	separator = []byte{0}
    25  	// MetricNameRE is a regular expression matching valid metric
    26  	// names. Note that the IsValidMetricName function performs the same
    27  	// check but faster than a match with this regular expression.
    28  	MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`)
    29  )
    30  
    31  // A Metric is similar to a LabelSet, but the key difference is that a Metric is
    32  // a singleton and refers to one and only one stream of samples.
    33  type Metric LabelSet
    34  
    35  // Equal compares the metrics.
    36  func (m Metric) Equal(o Metric) bool {
    37  	return LabelSet(m).Equal(LabelSet(o))
    38  }
    39  
    40  // Before compares the metrics' underlying label sets.
    41  func (m Metric) Before(o Metric) bool {
    42  	return LabelSet(m).Before(LabelSet(o))
    43  }
    44  
    45  // Clone returns a copy of the Metric.
    46  func (m Metric) Clone() Metric {
    47  	clone := make(Metric, len(m))
    48  	for k, v := range m {
    49  		clone[k] = v
    50  	}
    51  	return clone
    52  }
    53  
    54  func (m Metric) String() string {
    55  	metricName, hasName := m[MetricNameLabel]
    56  	numLabels := len(m) - 1
    57  	if !hasName {
    58  		numLabels = len(m)
    59  	}
    60  	labelStrings := make([]string, 0, numLabels)
    61  	for label, value := range m {
    62  		if label != MetricNameLabel {
    63  			labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
    64  		}
    65  	}
    66  
    67  	switch numLabels {
    68  	case 0:
    69  		if hasName {
    70  			return string(metricName)
    71  		}
    72  		return "{}"
    73  	default:
    74  		sort.Strings(labelStrings)
    75  		return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", "))
    76  	}
    77  }
    78  
    79  // Fingerprint returns a Metric's Fingerprint.
    80  func (m Metric) Fingerprint() Fingerprint {
    81  	return LabelSet(m).Fingerprint()
    82  }
    83  
    84  // FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing
    85  // algorithm, which is, however, more susceptible to hash collisions.
    86  func (m Metric) FastFingerprint() Fingerprint {
    87  	return LabelSet(m).FastFingerprint()
    88  }
    89  
    90  // IsValidMetricName returns true iff name matches the pattern of MetricNameRE.
    91  // This function, however, does not use MetricNameRE for the check but a much
    92  // faster hardcoded implementation.
    93  func IsValidMetricName(n LabelValue) bool {
    94  	if len(n) == 0 {
    95  		return false
    96  	}
    97  	for i, b := range n {
    98  		if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) {
    99  			return false
   100  		}
   101  	}
   102  	return true
   103  }