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 14package model 15 16import ( 17 "fmt" 18 "regexp" 19 "sort" 20 "strings" 21) 22 23var ( 24 // MetricNameRE is a regular expression matching valid metric 25 // names. Note that the IsValidMetricName function performs the same 26 // check but faster than a match with this regular expression. 27 MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`) 28) 29 30// A Metric is similar to a LabelSet, but the key difference is that a Metric is 31// a singleton and refers to one and only one stream of samples. 32type Metric LabelSet 33 34// Equal compares the metrics. 35func (m Metric) Equal(o Metric) bool { 36 return LabelSet(m).Equal(LabelSet(o)) 37} 38 39// Before compares the metrics' underlying label sets. 40func (m Metric) Before(o Metric) bool { 41 return LabelSet(m).Before(LabelSet(o)) 42} 43 44// Clone returns a copy of the Metric. 45func (m Metric) Clone() Metric { 46 clone := make(Metric, len(m)) 47 for k, v := range m { 48 clone[k] = v 49 } 50 return clone 51} 52 53func (m Metric) String() string { 54 metricName, hasName := m[MetricNameLabel] 55 numLabels := len(m) - 1 56 if !hasName { 57 numLabels = len(m) 58 } 59 labelStrings := make([]string, 0, numLabels) 60 for label, value := range m { 61 if label != MetricNameLabel { 62 labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value)) 63 } 64 } 65 66 switch numLabels { 67 case 0: 68 if hasName { 69 return string(metricName) 70 } 71 return "{}" 72 default: 73 sort.Strings(labelStrings) 74 return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", ")) 75 } 76} 77 78// Fingerprint returns a Metric's Fingerprint. 79func (m Metric) Fingerprint() Fingerprint { 80 return LabelSet(m).Fingerprint() 81} 82 83// FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing 84// algorithm, which is, however, more susceptible to hash collisions. 85func (m Metric) FastFingerprint() Fingerprint { 86 return LabelSet(m).FastFingerprint() 87} 88 89// IsValidMetricName returns true iff name matches the pattern of MetricNameRE. 90// This function, however, does not use MetricNameRE for the check but a much 91// faster hardcoded implementation. 92func IsValidMetricName(n LabelValue) bool { 93 if len(n) == 0 { 94 return false 95 } 96 for i, b := range n { 97 if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) { 98 return false 99 } 100 } 101 return true 102} 103