1// Copyright The OpenTelemetry 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
15package simple // import "go.opentelemetry.io/otel/sdk/metric/selector/simple"
16
17import (
18	"go.opentelemetry.io/otel/metric"
19	export "go.opentelemetry.io/otel/sdk/export/metric"
20	"go.opentelemetry.io/otel/sdk/metric/aggregator/array"
21	"go.opentelemetry.io/otel/sdk/metric/aggregator/ddsketch"
22	"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
23	"go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue"
24	"go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount"
25	"go.opentelemetry.io/otel/sdk/metric/aggregator/sum"
26)
27
28type (
29	selectorInexpensive struct{}
30	selectorExact       struct{}
31	selectorSketch      struct {
32		config *ddsketch.Config
33	}
34	selectorHistogram struct {
35		boundaries []float64
36	}
37)
38
39var (
40	_ export.AggregatorSelector = selectorInexpensive{}
41	_ export.AggregatorSelector = selectorSketch{}
42	_ export.AggregatorSelector = selectorExact{}
43	_ export.AggregatorSelector = selectorHistogram{}
44)
45
46// NewWithInexpensiveDistribution returns a simple aggregation selector
47// that uses counter, minmaxsumcount and minmaxsumcount aggregators
48// for the three kinds of metric.  This selector is faster and uses
49// less memory than the others because minmaxsumcount does not
50// aggregate quantile information.
51func NewWithInexpensiveDistribution() export.AggregatorSelector {
52	return selectorInexpensive{}
53}
54
55// NewWithSketchDistribution returns a simple aggregation selector that
56// uses counter, ddsketch, and ddsketch aggregators for the three
57// kinds of metric.  This selector uses more cpu and memory than the
58// NewWithInexpensiveDistribution because it uses one DDSketch per distinct
59// instrument and label set.
60func NewWithSketchDistribution(config *ddsketch.Config) export.AggregatorSelector {
61	return selectorSketch{
62		config: config,
63	}
64}
65
66// NewWithExactDistribution returns a simple aggregation selector that uses
67// counter, array, and array aggregators for the three kinds of metric.
68// This selector uses more memory than the NewWithSketchDistribution
69// because it aggregates an array of all values, therefore is able to
70// compute exact quantiles.
71func NewWithExactDistribution() export.AggregatorSelector {
72	return selectorExact{}
73}
74
75// NewWithHistogramDistribution returns a simple aggregation selector that uses counter,
76// histogram, and histogram aggregators for the three kinds of metric. This
77// selector uses more memory than the NewWithInexpensiveDistribution because it
78// uses a counter per bucket.
79func NewWithHistogramDistribution(boundaries []float64) export.AggregatorSelector {
80	return selectorHistogram{boundaries: boundaries}
81}
82
83func sumAggs(aggPtrs []*export.Aggregator) {
84	aggs := sum.New(len(aggPtrs))
85	for i := range aggPtrs {
86		*aggPtrs[i] = &aggs[i]
87	}
88}
89
90func lastValueAggs(aggPtrs []*export.Aggregator) {
91	aggs := lastvalue.New(len(aggPtrs))
92	for i := range aggPtrs {
93		*aggPtrs[i] = &aggs[i]
94	}
95}
96
97func (selectorInexpensive) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
98	switch descriptor.InstrumentKind() {
99	case metric.ValueObserverInstrumentKind:
100		lastValueAggs(aggPtrs)
101	case metric.ValueRecorderInstrumentKind:
102		aggs := minmaxsumcount.New(len(aggPtrs), descriptor)
103		for i := range aggPtrs {
104			*aggPtrs[i] = &aggs[i]
105		}
106	default:
107		sumAggs(aggPtrs)
108	}
109}
110
111func (s selectorSketch) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
112	switch descriptor.InstrumentKind() {
113	case metric.ValueObserverInstrumentKind:
114		lastValueAggs(aggPtrs)
115	case metric.ValueRecorderInstrumentKind:
116		aggs := ddsketch.New(len(aggPtrs), descriptor, s.config)
117		for i := range aggPtrs {
118			*aggPtrs[i] = &aggs[i]
119		}
120	default:
121		sumAggs(aggPtrs)
122	}
123}
124
125func (selectorExact) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
126	switch descriptor.InstrumentKind() {
127	case metric.ValueObserverInstrumentKind:
128		lastValueAggs(aggPtrs)
129	case metric.ValueRecorderInstrumentKind:
130		aggs := array.New(len(aggPtrs))
131		for i := range aggPtrs {
132			*aggPtrs[i] = &aggs[i]
133		}
134	default:
135		sumAggs(aggPtrs)
136	}
137}
138
139func (s selectorHistogram) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
140	switch descriptor.InstrumentKind() {
141	case metric.ValueObserverInstrumentKind:
142		lastValueAggs(aggPtrs)
143	case metric.ValueRecorderInstrumentKind:
144		aggs := histogram.New(len(aggPtrs), descriptor, s.boundaries)
145		for i := range aggPtrs {
146			*aggPtrs[i] = &aggs[i]
147		}
148	default:
149		sumAggs(aggPtrs)
150	}
151}
152