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