Skip to content

Commit

Permalink
add WithProducer to the prometheus exporter (#4473)
Browse files Browse the repository at this point in the history
  • Loading branch information
dashpole committed Aug 31, 2023
1 parent 2d2507d commit 02616a2
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 38 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Added

- Add `WithProducer` option in `go.opentelemetry.op/otel/exporters/prometheus` to restore the ability to register producers on the prometheus exporter's manual reader. (#4473)

### Deprecated

- The `NewMetricExporter` in `go.opentelemetry.io/otel/bridge/opencensus` was deprecated in `v0.35.0` (#3541).
Expand Down
21 changes: 11 additions & 10 deletions exporters/prometheus/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type config struct {
disableTargetInfo bool
withoutUnits bool
withoutCounterSuffixes bool
aggregation metric.AggregationSelector
readerOpts []metric.ManualReaderOption
disableScopeInfo bool
namespace string
}
Expand All @@ -47,14 +47,6 @@ 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
Expand All @@ -81,7 +73,16 @@ func WithRegisterer(reg prometheus.Registerer) Option {
// used.
func WithAggregationSelector(agg metric.AggregationSelector) Option {
return optionFunc(func(cfg config) config {
cfg.aggregation = agg
cfg.readerOpts = append(cfg.readerOpts, metric.WithAggregationSelector(agg))
return cfg
})
}

// WithProducer configure the metric Producer the exporter will use as a source
// of external metric data.
func WithProducer(producer metric.Producer) Option {
return optionFunc(func(cfg config) config {
cfg.readerOpts = append(cfg.readerOpts, metric.WithProducer(producer))
return cfg
})
}
Expand Down
53 changes: 26 additions & 27 deletions exporters/prometheus/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@
package prometheus // import "go.opentelemetry.io/otel/exporters/prometheus"

import (
"context"
"testing"

"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/assert"

"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
)

func TestNewConfig(t *testing.T) {
registry := prometheus.NewRegistry()

aggregationSelector := func(metric.InstrumentKind) metric.Aggregation { return nil }
producer := &noopProducer{}

testCases := []struct {
name string
Expand Down Expand Up @@ -56,17 +59,33 @@ func TestNewConfig(t *testing.T) {
},
wantConfig: config{
registerer: prometheus.DefaultRegisterer,
readerOpts: []metric.ManualReaderOption{metric.WithAggregationSelector(aggregationSelector)},
},
},
{
name: "WithProducer",
options: []Option{
WithProducer(producer),
},
wantConfig: config{
registerer: prometheus.DefaultRegisterer,
readerOpts: []metric.ManualReaderOption{metric.WithProducer(producer)},
},
},
{
name: "With Multiple Options",
options: []Option{
WithRegisterer(registry),
WithAggregationSelector(aggregationSelector),
WithProducer(producer),
},

wantConfig: config{
registerer: registry,
readerOpts: []metric.ManualReaderOption{
metric.WithAggregationSelector(aggregationSelector),
metric.WithProducer(producer),
},
},
},
{
Expand Down Expand Up @@ -132,38 +151,18 @@ func TestNewConfig(t *testing.T) {
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
cfg := newConfig(tt.options...)
// tested by TestConfigManualReaderOptions
cfg.aggregation = nil
// only check the length of readerOpts, since they are not compareable
assert.Equal(t, len(tt.wantConfig.readerOpts), len(cfg.readerOpts))
cfg.readerOpts = nil
tt.wantConfig.readerOpts = nil

assert.Equal(t, tt.wantConfig, cfg)
})
}
}

func TestConfigManualReaderOptions(t *testing.T) {
aggregationSelector := func(metric.InstrumentKind) metric.Aggregation { return nil }

testCases := []struct {
name string
config config
wantOptionCount int
}{
{
name: "Default",
config: config{},
wantOptionCount: 0,
},
type noopProducer struct{}

{
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)
})
}
func (*noopProducer) Produce(ctx context.Context) ([]metricdata.ScopeMetrics, error) {
return nil, nil
}
2 changes: 1 addition & 1 deletion exporters/prometheus/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,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(cfg.manualReaderOptions()...)
reader := metric.NewManualReader(cfg.readerOpts...)

collector := &collector{
reader: reader,
Expand Down

0 comments on commit 02616a2

Please sign in to comment.