...

Source file src/go.opencensus.io/metric/registry.go

Documentation: go.opencensus.io/metric

     1  // Copyright 2018, OpenCensus Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package metric
    16  
    17  import (
    18  	"sort"
    19  	"sync"
    20  	"time"
    21  
    22  	"go.opencensus.io/metric/metricdata"
    23  )
    24  
    25  // Registry creates and manages a set of gauges and cumulative.
    26  // External synchronization is required if you want to add gauges and cumulative to the same
    27  // registry from multiple goroutines.
    28  type Registry struct {
    29  	baseMetrics sync.Map
    30  }
    31  
    32  type metricOptions struct {
    33  	unit        metricdata.Unit
    34  	labelkeys   []metricdata.LabelKey
    35  	constLabels map[metricdata.LabelKey]metricdata.LabelValue
    36  	desc        string
    37  }
    38  
    39  // Options apply changes to metricOptions.
    40  type Options func(*metricOptions)
    41  
    42  // WithDescription applies provided description.
    43  func WithDescription(desc string) Options {
    44  	return func(mo *metricOptions) {
    45  		mo.desc = desc
    46  	}
    47  }
    48  
    49  // WithUnit applies provided unit.
    50  func WithUnit(unit metricdata.Unit) Options {
    51  	return func(mo *metricOptions) {
    52  		mo.unit = unit
    53  	}
    54  }
    55  
    56  // WithLabelKeys applies provided label.
    57  func WithLabelKeys(keys ...string) Options {
    58  	return func(mo *metricOptions) {
    59  		labelKeys := make([]metricdata.LabelKey, 0)
    60  		for _, key := range keys {
    61  			labelKeys = append(labelKeys, metricdata.LabelKey{Key: key})
    62  		}
    63  		mo.labelkeys = labelKeys
    64  	}
    65  }
    66  
    67  // WithLabelKeysAndDescription applies provided label.
    68  func WithLabelKeysAndDescription(labelKeys ...metricdata.LabelKey) Options {
    69  	return func(mo *metricOptions) {
    70  		mo.labelkeys = labelKeys
    71  	}
    72  }
    73  
    74  // WithConstLabel applies provided constant label.
    75  func WithConstLabel(constLabels map[metricdata.LabelKey]metricdata.LabelValue) Options {
    76  	return func(mo *metricOptions) {
    77  		mo.constLabels = constLabels
    78  	}
    79  }
    80  
    81  // NewRegistry initializes a new Registry.
    82  func NewRegistry() *Registry {
    83  	return &Registry{}
    84  }
    85  
    86  // AddFloat64Gauge creates and adds a new float64-valued gauge to this registry.
    87  func (r *Registry) AddFloat64Gauge(name string, mos ...Options) (*Float64Gauge, error) {
    88  	f := &Float64Gauge{
    89  		bm: baseMetric{
    90  			bmType: gaugeFloat64,
    91  		},
    92  	}
    93  	_, err := r.initBaseMetric(&f.bm, name, mos...)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  	return f, nil
    98  }
    99  
   100  // AddInt64Gauge creates and adds a new int64-valued gauge to this registry.
   101  func (r *Registry) AddInt64Gauge(name string, mos ...Options) (*Int64Gauge, error) {
   102  	i := &Int64Gauge{
   103  		bm: baseMetric{
   104  			bmType: gaugeInt64,
   105  		},
   106  	}
   107  	_, err := r.initBaseMetric(&i.bm, name, mos...)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	return i, nil
   112  }
   113  
   114  // AddInt64DerivedGauge creates and adds a new derived int64-valued gauge to this registry.
   115  // A derived gauge is convenient form of gauge where the object associated with the gauge
   116  // provides its value by implementing func() int64.
   117  func (r *Registry) AddInt64DerivedGauge(name string, mos ...Options) (*Int64DerivedGauge, error) {
   118  	i := &Int64DerivedGauge{
   119  		bm: baseMetric{
   120  			bmType: derivedGaugeInt64,
   121  		},
   122  	}
   123  	_, err := r.initBaseMetric(&i.bm, name, mos...)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	return i, nil
   128  }
   129  
   130  // AddFloat64DerivedGauge creates and adds a new derived float64-valued gauge to this registry.
   131  // A derived gauge is convenient form of gauge where the object associated with the gauge
   132  // provides its value by implementing func() float64.
   133  func (r *Registry) AddFloat64DerivedGauge(name string, mos ...Options) (*Float64DerivedGauge, error) {
   134  	f := &Float64DerivedGauge{
   135  		bm: baseMetric{
   136  			bmType: derivedGaugeFloat64,
   137  		},
   138  	}
   139  	_, err := r.initBaseMetric(&f.bm, name, mos...)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	return f, nil
   144  }
   145  
   146  func bmTypeToMetricType(bm *baseMetric) metricdata.Type {
   147  	switch bm.bmType {
   148  	case derivedGaugeFloat64:
   149  		return metricdata.TypeGaugeFloat64
   150  	case derivedGaugeInt64:
   151  		return metricdata.TypeGaugeInt64
   152  	case gaugeFloat64:
   153  		return metricdata.TypeGaugeFloat64
   154  	case gaugeInt64:
   155  		return metricdata.TypeGaugeInt64
   156  	case derivedCumulativeFloat64:
   157  		return metricdata.TypeCumulativeFloat64
   158  	case derivedCumulativeInt64:
   159  		return metricdata.TypeCumulativeInt64
   160  	case cumulativeFloat64:
   161  		return metricdata.TypeCumulativeFloat64
   162  	case cumulativeInt64:
   163  		return metricdata.TypeCumulativeInt64
   164  	default:
   165  		panic("unsupported metric type")
   166  	}
   167  }
   168  
   169  // AddFloat64Cumulative creates and adds a new float64-valued cumulative to this registry.
   170  func (r *Registry) AddFloat64Cumulative(name string, mos ...Options) (*Float64Cumulative, error) {
   171  	f := &Float64Cumulative{
   172  		bm: baseMetric{
   173  			bmType: cumulativeFloat64,
   174  		},
   175  	}
   176  	_, err := r.initBaseMetric(&f.bm, name, mos...)
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  	return f, nil
   181  }
   182  
   183  // AddInt64Cumulative creates and adds a new int64-valued cumulative to this registry.
   184  func (r *Registry) AddInt64Cumulative(name string, mos ...Options) (*Int64Cumulative, error) {
   185  	i := &Int64Cumulative{
   186  		bm: baseMetric{
   187  			bmType: cumulativeInt64,
   188  		},
   189  	}
   190  	_, err := r.initBaseMetric(&i.bm, name, mos...)
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  	return i, nil
   195  }
   196  
   197  // AddInt64DerivedCumulative creates and adds a new derived int64-valued cumulative to this registry.
   198  // A derived cumulative is convenient form of cumulative where the object associated with the cumulative
   199  // provides its value by implementing func() int64.
   200  func (r *Registry) AddInt64DerivedCumulative(name string, mos ...Options) (*Int64DerivedCumulative, error) {
   201  	i := &Int64DerivedCumulative{
   202  		bm: baseMetric{
   203  			bmType: derivedCumulativeInt64,
   204  		},
   205  	}
   206  	_, err := r.initBaseMetric(&i.bm, name, mos...)
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  	return i, nil
   211  }
   212  
   213  // AddFloat64DerivedCumulative creates and adds a new derived float64-valued gauge to this registry.
   214  // A derived cumulative is convenient form of cumulative where the object associated with the cumulative
   215  // provides its value by implementing func() float64.
   216  func (r *Registry) AddFloat64DerivedCumulative(name string, mos ...Options) (*Float64DerivedCumulative, error) {
   217  	f := &Float64DerivedCumulative{
   218  		bm: baseMetric{
   219  			bmType: derivedCumulativeFloat64,
   220  		},
   221  	}
   222  	_, err := r.initBaseMetric(&f.bm, name, mos...)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	return f, nil
   227  }
   228  
   229  func createMetricOption(mos ...Options) *metricOptions {
   230  	o := &metricOptions{}
   231  	for _, mo := range mos {
   232  		mo(o)
   233  	}
   234  	return o
   235  }
   236  
   237  func (r *Registry) initBaseMetric(bm *baseMetric, name string, mos ...Options) (*baseMetric, error) {
   238  	val, ok := r.baseMetrics.Load(name)
   239  	if ok {
   240  		existing := val.(*baseMetric)
   241  		if existing.bmType != bm.bmType {
   242  			return nil, errMetricExistsWithDiffType
   243  		}
   244  	}
   245  	bm.start = time.Now()
   246  	o := createMetricOption(mos...)
   247  
   248  	var constLabelKeys []metricdata.LabelKey
   249  	for k := range o.constLabels {
   250  		constLabelKeys = append(constLabelKeys, k)
   251  	}
   252  	sort.Slice(constLabelKeys, func(i, j int) bool {
   253  		return constLabelKeys[i].Key < constLabelKeys[j].Key
   254  	})
   255  
   256  	var constLabelValues []metricdata.LabelValue
   257  	for _, k := range constLabelKeys {
   258  		constLabelValues = append(constLabelValues, o.constLabels[k])
   259  	}
   260  
   261  	bm.keys = append(constLabelKeys, o.labelkeys...)
   262  	bm.constLabelValues = constLabelValues
   263  
   264  	bm.desc = metricdata.Descriptor{
   265  		Name:        name,
   266  		Description: o.desc,
   267  		Unit:        o.unit,
   268  		LabelKeys:   bm.keys,
   269  		Type:        bmTypeToMetricType(bm),
   270  	}
   271  	r.baseMetrics.Store(name, bm)
   272  	return bm, nil
   273  }
   274  
   275  // Read reads all gauges and cumulatives in this registry and returns their values as metrics.
   276  func (r *Registry) Read() []*metricdata.Metric {
   277  	ms := []*metricdata.Metric{}
   278  	r.baseMetrics.Range(func(k, v interface{}) bool {
   279  		bm := v.(*baseMetric)
   280  		ms = append(ms, bm.read())
   281  		return true
   282  	})
   283  	return ms
   284  }
   285  

View as plain text