...

Source file src/github.com/prometheus/common/model/labelset.go

Documentation: github.com/prometheus/common/model

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

View as plain text