...

Source file src/k8s.io/component-base/metrics/summary.go

Documentation: k8s.io/component-base/metrics

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package metrics
    18  
    19  import (
    20  	"context"
    21  
    22  	"github.com/blang/semver/v4"
    23  	"github.com/prometheus/client_golang/prometheus"
    24  )
    25  
    26  const (
    27  	DefAgeBuckets = prometheus.DefAgeBuckets
    28  	DefBufCap     = prometheus.DefBufCap
    29  	DefMaxAge     = prometheus.DefMaxAge
    30  )
    31  
    32  // Summary is our internal representation for our wrapping struct around prometheus
    33  // summaries. Summary implements both kubeCollector and ObserverMetric
    34  //
    35  // DEPRECATED: as per the metrics overhaul KEP
    36  type Summary struct {
    37  	ObserverMetric
    38  	*SummaryOpts
    39  	lazyMetric
    40  	selfCollector
    41  }
    42  
    43  // NewSummary returns an object which is Summary-like. However, nothing
    44  // will be measured until the summary is registered somewhere.
    45  //
    46  // DEPRECATED: as per the metrics overhaul KEP
    47  func NewSummary(opts *SummaryOpts) *Summary {
    48  	opts.StabilityLevel.setDefaults()
    49  
    50  	s := &Summary{
    51  		SummaryOpts: opts,
    52  		lazyMetric:  lazyMetric{stabilityLevel: opts.StabilityLevel},
    53  	}
    54  	s.setPrometheusSummary(noopMetric{})
    55  	s.lazyInit(s, BuildFQName(opts.Namespace, opts.Subsystem, opts.Name))
    56  	return s
    57  }
    58  
    59  // setPrometheusSummary sets the underlying KubeGauge object, i.e. the thing that does the measurement.
    60  func (s *Summary) setPrometheusSummary(summary prometheus.Summary) {
    61  	s.ObserverMetric = summary
    62  	s.initSelfCollection(summary)
    63  }
    64  
    65  // DeprecatedVersion returns a pointer to the Version or nil
    66  func (s *Summary) DeprecatedVersion() *semver.Version {
    67  	return parseSemver(s.SummaryOpts.DeprecatedVersion)
    68  }
    69  
    70  // initializeMetric invokes the actual prometheus.Summary object instantiation
    71  // and stores a reference to it
    72  func (s *Summary) initializeMetric() {
    73  	s.SummaryOpts.annotateStabilityLevel()
    74  	// this actually creates the underlying prometheus gauge.
    75  	s.setPrometheusSummary(prometheus.NewSummary(s.SummaryOpts.toPromSummaryOpts()))
    76  }
    77  
    78  // initializeDeprecatedMetric invokes the actual prometheus.Summary object instantiation
    79  // but modifies the Help description prior to object instantiation.
    80  func (s *Summary) initializeDeprecatedMetric() {
    81  	s.SummaryOpts.markDeprecated()
    82  	s.initializeMetric()
    83  }
    84  
    85  // WithContext allows the normal Summary metric to pass in context. The context is no-op now.
    86  func (s *Summary) WithContext(ctx context.Context) ObserverMetric {
    87  	return s.ObserverMetric
    88  }
    89  
    90  // SummaryVec is the internal representation of our wrapping struct around prometheus
    91  // summaryVecs.
    92  //
    93  // DEPRECATED: as per the metrics overhaul KEP
    94  type SummaryVec struct {
    95  	*prometheus.SummaryVec
    96  	*SummaryOpts
    97  	lazyMetric
    98  	originalLabels []string
    99  }
   100  
   101  // NewSummaryVec returns an object which satisfies kubeCollector and wraps the
   102  // prometheus.SummaryVec object. However, the object returned will not measure
   103  // anything unless the collector is first registered, since the metric is lazily instantiated,
   104  // and only members extracted after
   105  // registration will actually measure anything.
   106  //
   107  // DEPRECATED: as per the metrics overhaul KEP
   108  func NewSummaryVec(opts *SummaryOpts, labels []string) *SummaryVec {
   109  	opts.StabilityLevel.setDefaults()
   110  
   111  	fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
   112  	allowListLock.RLock()
   113  	if allowList, ok := labelValueAllowLists[fqName]; ok {
   114  		opts.LabelValueAllowLists = allowList
   115  	}
   116  	allowListLock.RUnlock()
   117  
   118  	v := &SummaryVec{
   119  		SummaryOpts:    opts,
   120  		originalLabels: labels,
   121  		lazyMetric:     lazyMetric{stabilityLevel: opts.StabilityLevel},
   122  	}
   123  	v.lazyInit(v, fqName)
   124  	return v
   125  }
   126  
   127  // DeprecatedVersion returns a pointer to the Version or nil
   128  func (v *SummaryVec) DeprecatedVersion() *semver.Version {
   129  	return parseSemver(v.SummaryOpts.DeprecatedVersion)
   130  }
   131  
   132  func (v *SummaryVec) initializeMetric() {
   133  	v.SummaryOpts.annotateStabilityLevel()
   134  	v.SummaryVec = prometheus.NewSummaryVec(v.SummaryOpts.toPromSummaryOpts(), v.originalLabels)
   135  }
   136  
   137  func (v *SummaryVec) initializeDeprecatedMetric() {
   138  	v.SummaryOpts.markDeprecated()
   139  	v.initializeMetric()
   140  }
   141  
   142  // Default Prometheus Vec behavior is that member extraction results in creation of a new element
   143  // if one with the unique label values is not found in the underlying stored metricMap.
   144  // This means  that if this function is called but the underlying metric is not registered
   145  // (which means it will never be exposed externally nor consumed), the metric will exist in memory
   146  // for perpetuity (i.e. throughout application lifecycle).
   147  //
   148  // For reference: https://github.com/prometheus/client_golang/blob/v0.9.2/prometheus/histogram.go#L460-L470
   149  //
   150  // In contrast, the Vec behavior in this package is that member extraction before registration
   151  // returns a permanent noop object.
   152  
   153  // WithLabelValues returns the ObserverMetric for the given slice of label
   154  // values (same order as the VariableLabels in Desc). If that combination of
   155  // label values is accessed for the first time, a new ObserverMetric is created IFF the summaryVec
   156  // has been registered to a metrics registry.
   157  func (v *SummaryVec) WithLabelValues(lvs ...string) ObserverMetric {
   158  	if !v.IsCreated() {
   159  		return noop
   160  	}
   161  	if v.LabelValueAllowLists != nil {
   162  		v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
   163  	}
   164  	return v.SummaryVec.WithLabelValues(lvs...)
   165  }
   166  
   167  // With returns the ObserverMetric for the given Labels map (the label names
   168  // must match those of the VariableLabels in Desc). If that label map is
   169  // accessed for the first time, a new ObserverMetric is created IFF the summaryVec has
   170  // been registered to a metrics registry.
   171  func (v *SummaryVec) With(labels map[string]string) ObserverMetric {
   172  	if !v.IsCreated() {
   173  		return noop
   174  	}
   175  	if v.LabelValueAllowLists != nil {
   176  		v.LabelValueAllowLists.ConstrainLabelMap(labels)
   177  	}
   178  	return v.SummaryVec.With(labels)
   179  }
   180  
   181  // Delete deletes the metric where the variable labels are the same as those
   182  // passed in as labels. It returns true if a metric was deleted.
   183  //
   184  // It is not an error if the number and names of the Labels are inconsistent
   185  // with those of the VariableLabels in Desc. However, such inconsistent Labels
   186  // can never match an actual metric, so the method will always return false in
   187  // that case.
   188  func (v *SummaryVec) Delete(labels map[string]string) bool {
   189  	if !v.IsCreated() {
   190  		return false // since we haven't created the metric, we haven't deleted a metric with the passed in values
   191  	}
   192  	return v.SummaryVec.Delete(labels)
   193  }
   194  
   195  // Reset deletes all metrics in this vector.
   196  func (v *SummaryVec) Reset() {
   197  	if !v.IsCreated() {
   198  		return
   199  	}
   200  
   201  	v.SummaryVec.Reset()
   202  }
   203  
   204  // WithContext returns wrapped SummaryVec with context
   205  func (v *SummaryVec) WithContext(ctx context.Context) *SummaryVecWithContext {
   206  	return &SummaryVecWithContext{
   207  		ctx:        ctx,
   208  		SummaryVec: v,
   209  	}
   210  }
   211  
   212  // SummaryVecWithContext is the wrapper of SummaryVec with context.
   213  type SummaryVecWithContext struct {
   214  	*SummaryVec
   215  	ctx context.Context
   216  }
   217  
   218  // WithLabelValues is the wrapper of SummaryVec.WithLabelValues.
   219  func (vc *SummaryVecWithContext) WithLabelValues(lvs ...string) ObserverMetric {
   220  	return vc.SummaryVec.WithLabelValues(lvs...)
   221  }
   222  
   223  // With is the wrapper of SummaryVec.With.
   224  func (vc *SummaryVecWithContext) With(labels map[string]string) ObserverMetric {
   225  	return vc.SummaryVec.With(labels)
   226  }
   227  

View as plain text