labels.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // Copyright 2017 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 labels
  14. import (
  15. "bytes"
  16. "encoding/json"
  17. "sort"
  18. "strconv"
  19. "strings"
  20. "github.com/cespare/xxhash"
  21. )
  22. const sep = '\xff'
  23. // Well-known label names used by Prometheus components.
  24. const (
  25. MetricName = "__name__"
  26. AlertName = "alertname"
  27. BucketLabel = "le"
  28. InstanceName = "instance"
  29. )
  30. // Label is a key/value pair of strings.
  31. type Label struct {
  32. Name, Value string
  33. }
  34. // Labels is a sorted set of labels. Order has to be guaranteed upon
  35. // instantiation.
  36. type Labels []Label
  37. func (ls Labels) Len() int { return len(ls) }
  38. func (ls Labels) Swap(i, j int) { ls[i], ls[j] = ls[j], ls[i] }
  39. func (ls Labels) Less(i, j int) bool { return ls[i].Name < ls[j].Name }
  40. func (ls Labels) String() string {
  41. var b bytes.Buffer
  42. b.WriteByte('{')
  43. for i, l := range ls {
  44. if i > 0 {
  45. b.WriteByte(',')
  46. b.WriteByte(' ')
  47. }
  48. b.WriteString(l.Name)
  49. b.WriteByte('=')
  50. b.WriteString(strconv.Quote(l.Value))
  51. }
  52. b.WriteByte('}')
  53. return b.String()
  54. }
  55. // MarshalJSON implements json.Marshaler.
  56. func (ls Labels) MarshalJSON() ([]byte, error) {
  57. return json.Marshal(ls.Map())
  58. }
  59. // UnmarshalJSON implements json.Unmarshaler.
  60. func (ls *Labels) UnmarshalJSON(b []byte) error {
  61. var m map[string]string
  62. if err := json.Unmarshal(b, &m); err != nil {
  63. return err
  64. }
  65. *ls = FromMap(m)
  66. return nil
  67. }
  68. // MarshalYAML implements yaml.Marshaler.
  69. func (ls Labels) MarshalYAML() (interface{}, error) {
  70. return ls.Map(), nil
  71. }
  72. // UnmarshalYAML implements yaml.Unmarshaler.
  73. func (ls *Labels) UnmarshalYAML(unmarshal func(interface{}) error) error {
  74. var m map[string]string
  75. if err := unmarshal(&m); err != nil {
  76. return err
  77. }
  78. *ls = FromMap(m)
  79. return nil
  80. }
  81. // MatchLabels returns a subset of Labels that matches/does not match with the provided label names based on the 'on' boolean.
  82. // If on is set to true, it returns the subset of labels that match with the provided label names and its inverse when 'on' is set to false.
  83. func (ls Labels) MatchLabels(on bool, names ...string) Labels {
  84. matchedLabels := Labels{}
  85. nameSet := map[string]struct{}{}
  86. for _, n := range names {
  87. nameSet[n] = struct{}{}
  88. }
  89. for _, v := range ls {
  90. if _, ok := nameSet[v.Name]; on == ok {
  91. matchedLabels = append(matchedLabels, v)
  92. }
  93. }
  94. return matchedLabels
  95. }
  96. // Hash returns a hash value for the label set.
  97. func (ls Labels) Hash() uint64 {
  98. b := make([]byte, 0, 1024)
  99. for _, v := range ls {
  100. b = append(b, v.Name...)
  101. b = append(b, sep)
  102. b = append(b, v.Value...)
  103. b = append(b, sep)
  104. }
  105. return xxhash.Sum64(b)
  106. }
  107. // HashForLabels returns a hash value for the labels matching the provided names.
  108. // 'names' have to be sorted in ascending order.
  109. func (ls Labels) HashForLabels(b []byte, names ...string) (uint64, []byte) {
  110. b = b[:0]
  111. i, j := 0, 0
  112. for i < len(ls) && j < len(names) {
  113. if names[j] < ls[i].Name {
  114. j++
  115. } else if ls[i].Name < names[j] {
  116. i++
  117. } else {
  118. b = append(b, ls[i].Name...)
  119. b = append(b, sep)
  120. b = append(b, ls[i].Value...)
  121. b = append(b, sep)
  122. i++
  123. j++
  124. }
  125. }
  126. return xxhash.Sum64(b), b
  127. }
  128. // HashWithoutLabels returns a hash value for all labels except those matching
  129. // the provided names.
  130. // 'names' have to be sorted in ascending order.
  131. func (ls Labels) HashWithoutLabels(b []byte, names ...string) (uint64, []byte) {
  132. b = b[:0]
  133. j := 0
  134. for i := range ls {
  135. for j < len(names) && names[j] < ls[i].Name {
  136. j++
  137. }
  138. if ls[i].Name == MetricName || (j < len(names) && ls[i].Name == names[j]) {
  139. continue
  140. }
  141. b = append(b, ls[i].Name...)
  142. b = append(b, sep)
  143. b = append(b, ls[i].Value...)
  144. b = append(b, sep)
  145. }
  146. return xxhash.Sum64(b), b
  147. }
  148. // Copy returns a copy of the labels.
  149. func (ls Labels) Copy() Labels {
  150. res := make(Labels, len(ls))
  151. copy(res, ls)
  152. return res
  153. }
  154. // Get returns the value for the label with the given name.
  155. // Returns an empty string if the label doesn't exist.
  156. func (ls Labels) Get(name string) string {
  157. for _, l := range ls {
  158. if l.Name == name {
  159. return l.Value
  160. }
  161. }
  162. return ""
  163. }
  164. // Has returns true if the label with the given name is present.
  165. func (ls Labels) Has(name string) bool {
  166. for _, l := range ls {
  167. if l.Name == name {
  168. return true
  169. }
  170. }
  171. return false
  172. }
  173. // Equal returns whether the two label sets are equal.
  174. func Equal(ls, o Labels) bool {
  175. if len(ls) != len(o) {
  176. return false
  177. }
  178. for i, l := range ls {
  179. if l.Name != o[i].Name || l.Value != o[i].Value {
  180. return false
  181. }
  182. }
  183. return true
  184. }
  185. // Map returns a string map of the labels.
  186. func (ls Labels) Map() map[string]string {
  187. m := make(map[string]string, len(ls))
  188. for _, l := range ls {
  189. m[l.Name] = l.Value
  190. }
  191. return m
  192. }
  193. // New returns a sorted Labels from the given labels.
  194. // The caller has to guarantee that all label names are unique.
  195. func New(ls ...Label) Labels {
  196. set := make(Labels, 0, len(ls))
  197. for _, l := range ls {
  198. set = append(set, l)
  199. }
  200. sort.Sort(set)
  201. return set
  202. }
  203. // FromMap returns new sorted Labels from the given map.
  204. func FromMap(m map[string]string) Labels {
  205. l := make([]Label, 0, len(m))
  206. for k, v := range m {
  207. l = append(l, Label{Name: k, Value: v})
  208. }
  209. return New(l...)
  210. }
  211. // FromStrings creates new labels from pairs of strings.
  212. func FromStrings(ss ...string) Labels {
  213. if len(ss)%2 != 0 {
  214. panic("invalid number of strings")
  215. }
  216. var res Labels
  217. for i := 0; i < len(ss); i += 2 {
  218. res = append(res, Label{Name: ss[i], Value: ss[i+1]})
  219. }
  220. sort.Sort(res)
  221. return res
  222. }
  223. // Compare compares the two label sets.
  224. // The result will be 0 if a==b, <0 if a < b, and >0 if a > b.
  225. func Compare(a, b Labels) int {
  226. l := len(a)
  227. if len(b) < l {
  228. l = len(b)
  229. }
  230. for i := 0; i < l; i++ {
  231. if d := strings.Compare(a[i].Name, b[i].Name); d != 0 {
  232. return d
  233. }
  234. if d := strings.Compare(a[i].Value, b[i].Value); d != 0 {
  235. return d
  236. }
  237. }
  238. // If all labels so far were in common, the set with fewer labels comes first.
  239. return len(a) - len(b)
  240. }
  241. // Builder allows modifying Labels.
  242. type Builder struct {
  243. base Labels
  244. del []string
  245. add []Label
  246. }
  247. // NewBuilder returns a new LabelsBuilder.
  248. func NewBuilder(base Labels) *Builder {
  249. b := &Builder{
  250. del: make([]string, 0, 5),
  251. add: make([]Label, 0, 5),
  252. }
  253. b.Reset(base)
  254. return b
  255. }
  256. // Reset clears all current state for the builder.
  257. func (b *Builder) Reset(base Labels) {
  258. b.base = base
  259. b.del = b.del[:0]
  260. b.add = b.add[:0]
  261. for _, l := range b.base {
  262. if l.Value == "" {
  263. b.del = append(b.del, l.Name)
  264. }
  265. }
  266. }
  267. // Del deletes the label of the given name.
  268. func (b *Builder) Del(ns ...string) *Builder {
  269. for _, n := range ns {
  270. for i, a := range b.add {
  271. if a.Name == n {
  272. b.add = append(b.add[:i], b.add[i+1:]...)
  273. }
  274. }
  275. b.del = append(b.del, n)
  276. }
  277. return b
  278. }
  279. // Set the name/value pair as a label.
  280. func (b *Builder) Set(n, v string) *Builder {
  281. if v == "" {
  282. // Empty labels are the same as missing labels.
  283. return b.Del(n)
  284. }
  285. for i, a := range b.add {
  286. if a.Name == n {
  287. b.add[i].Value = v
  288. return b
  289. }
  290. }
  291. b.add = append(b.add, Label{Name: n, Value: v})
  292. return b
  293. }
  294. // Labels returns the labels from the builder. If no modifications
  295. // were made, the original labels are returned.
  296. func (b *Builder) Labels() Labels {
  297. if len(b.del) == 0 && len(b.add) == 0 {
  298. return b.base
  299. }
  300. // In the general case, labels are removed, modified or moved
  301. // rather than added.
  302. res := make(Labels, 0, len(b.base))
  303. Outer:
  304. for _, l := range b.base {
  305. for _, n := range b.del {
  306. if l.Name == n {
  307. continue Outer
  308. }
  309. }
  310. for _, la := range b.add {
  311. if l.Name == la.Name {
  312. continue Outer
  313. }
  314. }
  315. res = append(res, l)
  316. }
  317. res = append(res, b.add...)
  318. sort.Sort(res)
  319. return res
  320. }