metric.go 2.5 KB

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