labelset.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. "encoding/json"
  16. "fmt"
  17. "sort"
  18. "strings"
  19. )
  20. // A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet
  21. // may be fully-qualified down to the point where it may resolve to a single
  22. // Metric in the data store or not. All operations that occur within the realm
  23. // of a LabelSet can emit a vector of Metric entities to which the LabelSet may
  24. // match.
  25. type LabelSet map[LabelName]LabelValue
  26. func (ls LabelSet) Equal(o LabelSet) bool {
  27. if len(ls) != len(o) {
  28. return false
  29. }
  30. for ln, lv := range ls {
  31. olv, ok := o[ln]
  32. if !ok {
  33. return false
  34. }
  35. if olv != lv {
  36. return false
  37. }
  38. }
  39. return true
  40. }
  41. // Before compares the metrics, using the following criteria:
  42. //
  43. // If m has fewer labels than o, it is before o. If it has more, it is not.
  44. //
  45. // If the number of labels is the same, the superset of all label names is
  46. // sorted alphanumerically. The first differing label pair found in that order
  47. // determines the outcome: If the label does not exist at all in m, then m is
  48. // before o, and vice versa. Otherwise the label value is compared
  49. // alphanumerically.
  50. //
  51. // If m and o are equal, the method returns false.
  52. func (ls LabelSet) Before(o LabelSet) bool {
  53. if len(ls) < len(o) {
  54. return true
  55. }
  56. if len(ls) > len(o) {
  57. return false
  58. }
  59. lns := make(LabelNames, 0, len(ls)+len(o))
  60. for ln := range ls {
  61. lns = append(lns, ln)
  62. }
  63. for ln := range o {
  64. lns = append(lns, ln)
  65. }
  66. // It's probably not worth it to de-dup lns.
  67. sort.Sort(lns)
  68. for _, ln := range lns {
  69. mlv, ok := ls[ln]
  70. if !ok {
  71. return true
  72. }
  73. olv, ok := o[ln]
  74. if !ok {
  75. return false
  76. }
  77. if mlv < olv {
  78. return true
  79. }
  80. if mlv > olv {
  81. return false
  82. }
  83. }
  84. return false
  85. }
  86. func (ls LabelSet) Clone() LabelSet {
  87. lsn := make(LabelSet, len(ls))
  88. for ln, lv := range ls {
  89. lsn[ln] = lv
  90. }
  91. return lsn
  92. }
  93. // Merge is a helper function to non-destructively merge two label sets.
  94. func (l LabelSet) Merge(other LabelSet) LabelSet {
  95. result := make(LabelSet, len(l))
  96. for k, v := range l {
  97. result[k] = v
  98. }
  99. for k, v := range other {
  100. result[k] = v
  101. }
  102. return result
  103. }
  104. func (l LabelSet) String() string {
  105. lstrs := make([]string, 0, len(l))
  106. for l, v := range l {
  107. lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v))
  108. }
  109. sort.Strings(lstrs)
  110. return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
  111. }
  112. // Fingerprint returns the LabelSet's fingerprint.
  113. func (ls LabelSet) Fingerprint() Fingerprint {
  114. return labelSetToFingerprint(ls)
  115. }
  116. // FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing
  117. // algorithm, which is, however, more susceptible to hash collisions.
  118. func (ls LabelSet) FastFingerprint() Fingerprint {
  119. return labelSetToFastFingerprint(ls)
  120. }
  121. // UnmarshalJSON implements the json.Unmarshaler interface.
  122. func (l *LabelSet) UnmarshalJSON(b []byte) error {
  123. var m map[LabelName]LabelValue
  124. if err := json.Unmarshal(b, &m); err != nil {
  125. return err
  126. }
  127. // encoding/json only unmarshals maps of the form map[string]T. It treats
  128. // LabelName as a string and does not call its UnmarshalJSON method.
  129. // Thus, we have to replicate the behavior here.
  130. for ln := range m {
  131. if !LabelNameRE.MatchString(string(ln)) {
  132. return fmt.Errorf("%q is not a valid label name", ln)
  133. }
  134. }
  135. *l = LabelSet(m)
  136. return nil
  137. }