Skip to content

Commit

Permalink
config: NewSDK can return valid MeterProvider
Browse files Browse the repository at this point in the history
Follow up to open-telemetry#4741, does the same but for metric signal.

Fixes open-telemetry#4371

Signed-off-by: Alex Boten <aboten@lightstep.com>
  • Loading branch information
Alex Boten committed Jan 11, 2024
1 parent 17cfab9 commit abb6fec
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068, #3108)
- Add `SDK.Shutdown` method in `"go.opentelemetry.io/contrib/config"`. (#4583)
- `NewSDK` in `go.opentelemetry.io/contrib/config` now returns a configured SDK with a valid `TracerProvider`. (#4741)
- `NewSDK` in `go.opentelemetry.io/contrib/config` now returns a configured SDK with a valid `MeterProvider`. (#)

### Changed

Expand Down
6 changes: 5 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ func NewSDK(opts ...ConfigurationOption) (SDK, error) {
return SDK{}, err
}

mp, mpShutdown := initMeterProvider(o)
mp, mpShutdown, err := meterProvider(o, r)
if err != nil {
return SDK{}, err
}

tp, tpShutdown, err := tracerProvider(o, r)
if err != nil {
return SDK{}, err
Expand Down
60 changes: 56 additions & 4 deletions config/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,67 @@
package config // import "go.opentelemetry.io/contrib/config"

import (
"context"
"errors"

"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/noop"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
)

func initMeterProvider(cfg configOptions) (metric.MeterProvider, shutdownFunc) {
func meterProvider(cfg configOptions, res *resource.Resource) (metric.MeterProvider, shutdownFunc, error) {
if cfg.opentelemetryConfig.MeterProvider == nil {
return noop.NewMeterProvider(), noopShutdown
return noop.NewMeterProvider(), noopShutdown, nil
}
opts := []sdkmetric.Option{
sdkmetric.WithResource(res),
}

var errs []error
for _, reader := range cfg.opentelemetryConfig.MeterProvider.Readers {
r, err := metricReader(cfg.ctx, reader)
if err == nil {
opts = append(opts, sdkmetric.WithReader(r))
} else {
errs = append(errs, err)
}
}
if len(errs) > 0 {
return noop.NewMeterProvider(), noopShutdown, errors.Join(errs...)
}

mp := sdkmetric.NewMeterProvider(opts...)
return mp, mp.Shutdown, nil
}

func metricReader(ctx context.Context, r MetricReader) (sdkmetric.Reader, error) {
if r.Periodic != nil && r.Pull != nil {
return nil, errors.New("must not specify multiple metric reader type")
}

if r.Periodic != nil {
exp, err := metricExporter(ctx, r.Periodic.Exporter)
if err != nil {
return nil, err
}
return periodMetricReader(r.Periodic, exp)
}

if r.Pull != nil {

}
return nil, errors.New("no valid metric reader")
}

func periodMetricReader(pmr *PeriodicMetricReader, exp sdkmetric.Exporter) (sdkmetric.Reader, error) {
var opts []sdkmetric.PeriodicReaderOption
return sdkmetric.NewPeriodicReader(exp, opts...), nil
}

func metricExporter(ctx context.Context, exporter MetricExporter) (sdkmetric.Exporter, error) {
if exporter.Console != nil && exporter.OTLP != nil {
return nil, errors.New("must not specify multiple exporters")
}
mp := sdkmetric.NewMeterProvider()
return mp, mp.Shutdown
return nil, errors.New("no valid metric exporter")
}
53 changes: 50 additions & 3 deletions config/metric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
package config

import (
"context"
"errors"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/noop"
"go.opentelemetry.io/otel/sdk/resource"
)

func TestInitMeterProvider(t *testing.T) {
func TestMeterProvider(t *testing.T) {
tests := []struct {
name string
cfg configOptions
Expand All @@ -23,10 +27,53 @@ func TestInitMeterProvider(t *testing.T) {
name: "no-meter-provider-configured",
wantProvider: noop.NewMeterProvider(),
},
{
name: "error-in-config",
cfg: configOptions{
opentelemetryConfig: OpenTelemetryConfiguration{
MeterProvider: &MeterProvider{
Readers: []MetricReader{
{
Periodic: &PeriodicMetricReader{},
Pull: &PullMetricReader{},
},
},
},
},
},
wantProvider: noop.NewMeterProvider(),
wantErr: errors.Join(errors.New("must not specify multiple metric reader type")),
},
{
name: "multiple-errors-in-config",
cfg: configOptions{
opentelemetryConfig: OpenTelemetryConfiguration{
MeterProvider: &MeterProvider{
Readers: []MetricReader{
{
Periodic: &PeriodicMetricReader{},
Pull: &PullMetricReader{},
},
{
Periodic: &PeriodicMetricReader{
Exporter: MetricExporter{
Console: Console{},
OTLP: &OTLPMetric{},
},
},
},
},
},
},
},
wantProvider: noop.NewMeterProvider(),
wantErr: errors.Join(errors.New("must not specify multiple metric reader type"), errors.New("must not specify multiple exporters")),
},
}
for _, tt := range tests {
mp, err := initMeterProvider(tt.cfg)
mp, shutdown, err := meterProvider(tt.cfg, resource.Default())
require.Equal(t, tt.wantProvider, mp)
require.NoError(t, tt.wantErr, err)
assert.Equal(t, tt.wantErr, err)
require.NoError(t, shutdown(context.Background()))
}
}

0 comments on commit abb6fec

Please sign in to comment.