diff --git a/CHANGELOG.md b/CHANGELOG.md index e81ccaf4f46..34be9d346ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added - Prometheus exporter will register with a prometheus registerer on creation, there are options to control this. (#3239) +- Added the `WithAggregationSelector` option to the `go.opentelemetry.io/otel/exporters/prometheus` package to change the `AggregationSelector` used. (#3341) ### Changed diff --git a/exporters/prometheus/confg_test.go b/exporters/prometheus/confg_test.go index 91893d40f3a..52bccff2587 100644 --- a/exporters/prometheus/confg_test.go +++ b/exporters/prometheus/confg_test.go @@ -19,22 +19,28 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/aggregation" + "go.opentelemetry.io/otel/sdk/metric/view" ) func TestNewConfig(t *testing.T) { registry := prometheus.NewRegistry() + aggregationSelector := func(view.InstrumentKind) aggregation.Aggregation { return nil } + testCases := []struct { - name string - options []Option - wantRegisterer prometheus.Registerer + name string + options []Option + wantRegisterer prometheus.Registerer + wantAggregation metric.AggregationSelector }{ { name: "Default", options: nil, wantRegisterer: prometheus.DefaultRegisterer, }, - { name: "WithRegisterer", options: []Option{ @@ -42,6 +48,23 @@ func TestNewConfig(t *testing.T) { }, wantRegisterer: registry, }, + { + name: "WithAggregationSelector", + options: []Option{ + WithAggregationSelector(aggregationSelector), + }, + wantRegisterer: prometheus.DefaultRegisterer, + wantAggregation: aggregationSelector, + }, + { + name: "With Multiple Options", + options: []Option{ + WithRegisterer(registry), + WithAggregationSelector(aggregationSelector), + }, + wantRegisterer: registry, + wantAggregation: aggregationSelector, + }, { name: "nil options do nothing", options: []Option{ @@ -58,3 +81,31 @@ func TestNewConfig(t *testing.T) { }) } } + +func TestConfigManualReaderOptions(t *testing.T) { + aggregationSelector := func(view.InstrumentKind) aggregation.Aggregation { return nil } + + testCases := []struct { + name string + config config + wantOptionCount int + }{ + { + name: "Default", + config: config{}, + wantOptionCount: 0, + }, + + { + name: "WithAggregationSelector", + config: config{aggregation: aggregationSelector}, + wantOptionCount: 1, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + opts := tt.config.manualReaderOptions() + assert.Len(t, opts, tt.wantOptionCount) + }) + } +} diff --git a/exporters/prometheus/config.go b/exporters/prometheus/config.go index 6ee84732556..e70dade501d 100644 --- a/exporters/prometheus/config.go +++ b/exporters/prometheus/config.go @@ -16,11 +16,14 @@ package prometheus // import "go.opentelemetry.io/otel/exporters/prometheus" import ( "github.com/prometheus/client_golang/prometheus" + + "go.opentelemetry.io/otel/sdk/metric" ) // config contains options for the exporter. type config struct { - registerer prometheus.Registerer + registerer prometheus.Registerer + aggregation metric.AggregationSelector } // newConfig creates a validated config configured with options. @@ -37,6 +40,14 @@ func newConfig(opts ...Option) config { return cfg } +func (cfg config) manualReaderOptions() []metric.ManualReaderOption { + opts := []metric.ManualReaderOption{} + if cfg.aggregation != nil { + opts = append(opts, metric.WithAggregationSelector(cfg.aggregation)) + } + return opts +} + // Option sets exporter option values. type Option interface { apply(config) config @@ -57,3 +68,13 @@ func WithRegisterer(reg prometheus.Registerer) Option { return cfg }) } + +// WithAggregationSelector configure the Aggregation Selector the exporter will +// use. If no AggregationSelector is provided the DefaultAggregationSelector is +// used. +func WithAggregationSelector(agg metric.AggregationSelector) Option { + return optionFunc(func(cfg config) config { + cfg.aggregation = agg + return cfg + }) +} diff --git a/exporters/prometheus/exporter.go b/exporters/prometheus/exporter.go index e14fa3638c6..01c555970cc 100644 --- a/exporters/prometheus/exporter.go +++ b/exporters/prometheus/exporter.go @@ -50,7 +50,7 @@ func New(opts ...Option) (*Exporter, error) { // this assumes that the default temporality selector will always return cumulative. // we only support cumulative temporality, so building our own reader enforces this. // TODO (#3244): Enable some way to configure the reader, but not change temporality. - reader := metric.NewManualReader() + reader := metric.NewManualReader(cfg.manualReaderOptions()...) collector := &collector{ reader: reader,