本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
4.2KB

  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. // Validate checks whether all names and values in the label set
  27. // are valid.
  28. func (ls LabelSet) Validate() error {
  29. for ln, lv := range ls {
  30. if !ln.IsValid() {
  31. return fmt.Errorf("invalid name %q", ln)
  32. }
  33. if !lv.IsValid() {
  34. return fmt.Errorf("invalid value %q", lv)
  35. }
  36. }
  37. return nil
  38. }
  39. // Equal returns true iff both label sets have exactly the same key/value pairs.
  40. func (ls LabelSet) Equal(o LabelSet) bool {
  41. if len(ls) != len(o) {
  42. return false
  43. }
  44. for ln, lv := range ls {
  45. olv, ok := o[ln]
  46. if !ok {
  47. return false
  48. }
  49. if olv != lv {
  50. return false
  51. }
  52. }
  53. return true
  54. }
  55. // Before compares the metrics, using the following criteria:
  56. //
  57. // If m has fewer labels than o, it is before o. If it has more, it is not.
  58. //
  59. // If the number of labels is the same, the superset of all label names is
  60. // sorted alphanumerically. The first differing label pair found in that order
  61. // determines the outcome: If the label does not exist at all in m, then m is
  62. // before o, and vice versa. Otherwise the label value is compared
  63. // alphanumerically.
  64. //
  65. // If m and o are equal, the method returns false.
  66. func (ls LabelSet) Before(o LabelSet) bool {
  67. if len(ls) < len(o) {
  68. return true
  69. }
  70. if len(ls) > len(o) {
  71. return false
  72. }
  73. lns := make(LabelNames, 0, len(ls)+len(o))
  74. for ln := range ls {
  75. lns = append(lns, ln)
  76. }
  77. for ln := range o {
  78. lns = append(lns, ln)
  79. }
  80. // It's probably not worth it to de-dup lns.
  81. sort.Sort(lns)
  82. for _, ln := range lns {
  83. mlv, ok := ls[ln]
  84. if !ok {
  85. return true
  86. }
  87. olv, ok := o[ln]
  88. if !ok {
  89. return false
  90. }
  91. if mlv < olv {
  92. return true
  93. }
  94. if mlv > olv {
  95. return false
  96. }
  97. }
  98. return false
  99. }
  100. // Clone returns a copy of the label set.
  101. func (ls LabelSet) Clone() LabelSet {
  102. lsn := make(LabelSet, len(ls))
  103. for ln, lv := range ls {
  104. lsn[ln] = lv
  105. }
  106. return lsn
  107. }
  108. // Merge is a helper function to non-destructively merge two label sets.
  109. func (l LabelSet) Merge(other LabelSet) LabelSet {
  110. result := make(LabelSet, len(l))
  111. for k, v := range l {
  112. result[k] = v
  113. }
  114. for k, v := range other {
  115. result[k] = v
  116. }
  117. return result
  118. }
  119. func (l LabelSet) String() string {
  120. lstrs := make([]string, 0, len(l))
  121. for l, v := range l {
  122. lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v))
  123. }
  124. sort.Strings(lstrs)
  125. return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
  126. }
  127. // Fingerprint returns the LabelSet's fingerprint.
  128. func (ls LabelSet) Fingerprint() Fingerprint {
  129. return labelSetToFingerprint(ls)
  130. }
  131. // FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing
  132. // algorithm, which is, however, more susceptible to hash collisions.
  133. func (ls LabelSet) FastFingerprint() Fingerprint {
  134. return labelSetToFastFingerprint(ls)
  135. }
  136. // UnmarshalJSON implements the json.Unmarshaler interface.
  137. func (l *LabelSet) UnmarshalJSON(b []byte) error {
  138. var m map[LabelName]LabelValue
  139. if err := json.Unmarshal(b, &m); err != nil {
  140. return err
  141. }
  142. // encoding/json only unmarshals maps of the form map[string]T. It treats
  143. // LabelName as a string and does not call its UnmarshalJSON method.
  144. // Thus, we have to replicate the behavior here.
  145. for ln := range m {
  146. if !ln.IsValid() {
  147. return fmt.Errorf("%q is not a valid label name", ln)
  148. }
  149. }
  150. *l = LabelSet(m)
  151. return nil
  152. }
上海开阖软件有限公司 沪ICP备12045867号-1