Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

autoexport: Add support for metrics #4229

Merged
merged 28 commits into from Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
80d77f8
autoexport: Add support for metrics
punya Aug 22, 2023
78ef081
Format and fix typo
punya Aug 22, 2023
0b6c412
Add changelog entry
punya Aug 22, 2023
3ea1366
Factor registry into metrics/spans/shared
punya Aug 22, 2023
3ae284a
Start adding metrics-related tests
punya Aug 23, 2023
155c74e
Generalize tests to metrics
punya Aug 23, 2023
2999fd4
Fix deps
punya Oct 16, 2023
d498e8e
Tests
punya Oct 18, 2023
c33d73f
Add support for Prometheus exporter
punya Oct 19, 2023
8c40f0a
Rename signal -> fixture in tests
punya Oct 19, 2023
ffd185b
Rewrite + respond to PR feedback
punya Oct 19, 2023
0f350db
Reduce unnecessarily fancy generics in tests
punya Oct 19, 2023
6d04d4c
Remove unnecessary generics in tests
punya Oct 19, 2023
5cf5027
Remove unused deps
punya Oct 19, 2023
4f0e614
Cleanup
punya Oct 19, 2023
90eeff5
Cleanup and lint fixes
punya Oct 19, 2023
6c1e67c
Fix copypasta and improve names
punya Oct 19, 2023
1e68beb
Tests for unspecified protocol
punya Oct 19, 2023
9cacbfc
Merge remote-tracking branch 'origin/main' into autoexport-metrics
punya Oct 19, 2023
b8c8b35
Appease gofumpt
punya Oct 19, 2023
1af21f1
DRY panic logic
punya Oct 19, 2023
2b08d9f
Avoid unnecessary require block
punya Oct 19, 2023
37ac9d5
Fix documentation
punya Oct 20, 2023
8f6c1bb
Use SpanOption rather than deprecated alias
punya Oct 20, 2023
b1a5584
Remove Prometheus support - deferred to #4472
punya Oct 23, 2023
3ecc111
Merge branch 'main' into autoexport-metrics
punya Oct 23, 2023
a8b2ef7
Move CHANGELOG entry and add deprecation
punya Oct 23, 2023
503e4ff
Update CHANGELOG.md
pellared Oct 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -14,12 +14,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add `"go.opentelemetry.io/contrib/samplers/jaegerremote".WithSamplingStrategyFetcher` which sets custom fetcher implementation. (#4045)
- Add `"go.opentelemetry.io/contrib/config"` package that includes configuration models generated via go-jsonschema. (#4376)
- Add `NewSDK` function to `"go.opentelemetry.io/contrib/config"`. The initial implementation only returns noop providers. (#4414)
- Add metrics support to `go.opentelemetry.io/contrib/exporters/autoexport`. (#4229)

### Changed

- Dropped compatibility testing for [Go 1.19].
The project no longer guarantees support for this version of Go. (#4352)

### Deprecated

- In `go.opentelemetry.io/contrib/exporters/autoexport`, `Option` was renamed to `SpanOption`. The old name is deprecated but continues to be supported as an alias. (#4229)

### Fixed

- The `go.opentelemetry.io/contrib/samplers/jaegerremote` sampler does not panic when the default HTTP round-tripper (`http.DefaultTransport`) is not `*http.Transport`. (#4045)
Expand Down
136 changes: 0 additions & 136 deletions exporters/autoexport/exporter_test.go

This file was deleted.

5 changes: 4 additions & 1 deletion exporters/autoexport/go.mod
Expand Up @@ -4,11 +4,13 @@ go 1.20

require (
github.com/stretchr/testify v1.8.4
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0
go.opentelemetry.io/otel/sdk v1.19.0
go.opentelemetry.io/otel/sdk/metric v1.19.0
)

require (
Expand All @@ -20,6 +22,7 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
Expand Down
10 changes: 8 additions & 2 deletions exporters/autoexport/go.sum
Expand Up @@ -24,18 +24,24 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k=
go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
Expand Down
97 changes: 97 additions & 0 deletions exporters/autoexport/metrics.go
@@ -0,0 +1,97 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package autoexport // import "go.opentelemetry.io/contrib/exporters/autoexport"

import (
"context"
"os"

"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/sdk/metric"
)

// MetricOption applies an autoexport configuration option.
type MetricOption = option[metric.Reader]

// WithFallbackMetricReader sets the fallback exporter to use when no exporter
// is configured through the OTEL_METRICS_EXPORTER environment variable.
func WithFallbackMetricReader(exporter metric.Reader) MetricOption {
return withFallback[metric.Reader](exporter)

Check warning on line 32 in exporters/autoexport/metrics.go

View check run for this annotation

Codecov / codecov/patch

exporters/autoexport/metrics.go#L31-L32

Added lines #L31 - L32 were not covered by tests
}

// NewMetricReader returns a configured [go.opentelemetry.io/otel/sdk/metric.Reader]
// defined using the environment variables described below.
//
// OTEL_METRICS_EXPORTER defines the metrics exporter; supported values:
// - "none" - "no operation" exporter
// - "otlp" (default) - OTLP exporter; see [go.opentelemetry.io/otel/exporters/otlp/otlpmetric]
//
// OTEL_EXPORTER_OTLP_PROTOCOL defines OTLP exporter's transport protocol;
// supported values:
// - "grpc" - protobuf-encoded data using gRPC wire format over HTTP/2 connection;
// see: [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc]
// - "http/protobuf" (default) - protobuf-encoded data over HTTP connection;
// see: [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp]
//
// An error is returned if an environment value is set to an unhandled value.
//
// Use [RegisterMetricReader] to handle more values of OTEL_METRICS_EXPORTER.
//
// Use [WithFallbackMetricReader] option to change the returned exporter
// when OTEL_TRACES_EXPORTER is unset or empty.
//
// Use [IsNoneMetricReader] to check if the retured exporter is a "no operation" exporter.
func NewMetricReader(ctx context.Context, opts ...MetricOption) (metric.Reader, error) {
return metricsSignal.create(ctx, opts...)
}

// RegisterMetricReader sets the MetricReader factory to be used when the
// OTEL_METRICS_EXPORTERS environment variable contains the exporter name. This
// will panic if name has already been registered.
func RegisterMetricReader(name string, factory func(context.Context) (metric.Reader, error)) {
must(metricsSignal.registry.store(name, factory))
}

var metricsSignal = newSignal[metric.Reader]("OTEL_METRICS_EXPORTER")

func init() {
RegisterMetricReader("otlp", func(ctx context.Context) (metric.Reader, error) {
proto := os.Getenv(otelExporterOTLPProtoEnvKey)
if proto == "" {
proto = "http/protobuf"
}

switch proto {
case "grpc":
r, err := otlpmetricgrpc.New(ctx)
if err != nil {
return nil, err
}

Check warning on line 82 in exporters/autoexport/metrics.go

View check run for this annotation

Codecov / codecov/patch

exporters/autoexport/metrics.go#L81-L82

Added lines #L81 - L82 were not covered by tests
return metric.NewPeriodicReader(r), nil
case "http/protobuf":
r, err := otlpmetrichttp.New(ctx)
if err != nil {
return nil, err
}

Check warning on line 88 in exporters/autoexport/metrics.go

View check run for this annotation

Codecov / codecov/patch

exporters/autoexport/metrics.go#L87-L88

Added lines #L87 - L88 were not covered by tests
return metric.NewPeriodicReader(r), nil
default:
return nil, errInvalidOTLPProtocol
}
})
RegisterMetricReader("none", func(ctx context.Context) (metric.Reader, error) {
return newNoopMetricReader(), nil
})
}
65 changes: 65 additions & 0 deletions exporters/autoexport/metrics_test.go
@@ -0,0 +1,65 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package autoexport // import "go.opentelemetry.io/contrib/exporters/autoexport"

import (
"context"
"fmt"
"reflect"
"testing"

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

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

func TestMetricExporterNone(t *testing.T) {
t.Setenv("OTEL_METRICS_EXPORTER", "none")
got, err := NewMetricReader(context.Background())
assert.NoError(t, err)
assert.True(t, IsNoneMetricReader(got))
}

func TestMetricExporterOTLP(t *testing.T) {
t.Setenv("OTEL_METRICS_EXPORTER", "otlp")

for _, tc := range []struct {
protocol, exporterType string
}{
{"http/protobuf", "*otlpmetrichttp.Exporter"},
{"", "*otlpmetrichttp.Exporter"},
{"grpc", "*otlpmetricgrpc.Exporter"},
} {
t.Run(fmt.Sprintf("protocol=%q", tc.protocol), func(t *testing.T) {
t.Setenv("OTEL_EXPORTER_OTLP_PROTOCOL", tc.protocol)

got, err := NewMetricReader(context.Background())
assert.NoError(t, err)
assert.IsType(t, &metric.PeriodicReader{}, got)

// Implementation detail hack. This may break when bumping OTLP exporter modules as it uses unexported API.
exporterType := reflect.Indirect(reflect.ValueOf(got)).FieldByName("exporter").Elem().Type()
assert.Equal(t, tc.exporterType, exporterType.String())
})
}
}

func TestMetricExporterOTLPOverInvalidProtocol(t *testing.T) {
t.Setenv("OTEL_METRICS_EXPORTER", "otlp")
t.Setenv("OTEL_EXPORTER_OTLP_PROTOCOL", "invalid-protocol")

_, err := NewMetricReader(context.Background())
assert.Error(t, err)
}