Skip to content

Commit

Permalink
Add autoexport to automatically configure trace exporters (#2753)
Browse files Browse the repository at this point in the history
* add autoexport

* fix linting, add registry tests

* update env var to OTEL_TRACES_EXPORTERS

Co-authored-by: Tyler Yahn <codingalias@gmail.com>

* update to go 1.18

Co-authored-by: Tyler Yahn <codingalias@gmail.com>

* add changelog entry

* add autoexport

* fix linting, add registry tests

* update env var to OTEL_TRACES_EXPORTERS

Co-authored-by: Tyler Yahn <codingalias@gmail.com>

* update to go 1.18

Co-authored-by: Tyler Yahn <codingalias@gmail.com>

* add changelog entry

* fix changelog

* fix typo :(

* refactor to only return single trace exporter

* replace single case switch with if

* break up imports

* Update exporters/autoexport/exporter.go

Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>

* move and rename errDupReg to var block

* Apply suggestions from code review

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>

* fix const usage after rename

* update registry to reuse default otlp exporter

* update autoexport to use options design and register otlp exporters

* move otlp exporter registration to init

* add autoexport to dependabot and version.yml

* fix linter and update descriptions

* fix typo

* update go.mod

* fix changelog

* use go 1.19 in go.mod

* update registry to use span exporter factory instead

* fix formatting in registry

* update go.mod dependencies

* update tests

* add autoexport to codeowners

* update exporter func to get exporter from env

* fix typo in test name

* reverrt test names to PascalCase instead of snake_case

* Apply suggestions from code review

Co-authored-by: Jamie Danielson <jamieedanielson@gmail.com>

* Update CHANGELOG.md

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>

* update config option pattern to match repo

* update NewTraceExporter to return errors

* update registry factory funcs to take context

* return factory return params direclty during load

* add traceSpanExporterFactory type

* pass in context when making exporter from env

* add README

* add doc.go

* go mod tidy

* fix formatting

* Update exporters/autoexport/doc.go

Co-authored-by: Robert Pająk <pellared@hotmail.com>

* move docs from readme to docs.go

* fix typo

* Apply suggestions from code review

Co-authored-by: Robert Pająk <pellared@hotmail.com>

* remove traceSpanExporterFactoryFunc

* renamed NewTraceExporter to NewSpanExporter

---------

Co-authored-by: Tyler Yahn <codingalias@gmail.com>
Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
Co-authored-by: Jamie Danielson <jamieedanielson@gmail.com>
Co-authored-by: Robert Pająk <pellared@hotmail.com>
  • Loading branch information
6 people committed May 25, 2023
1 parent e9956ff commit 3e827e3
Show file tree
Hide file tree
Showing 12 changed files with 984 additions and 5 deletions.
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Expand Up @@ -190,6 +190,15 @@ updates:
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /exporters/autoexport
labels:
- dependencies
- go
- Skip Changelog
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /instrgen
labels:
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Added

- Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068, #3108)
- The `go.opentelemetry.io/contrib/exporters/autoexport` package to provide configuration of trace exporters with useful defaults and envar support. (#2753)

## [1.17.0/0.42.0/0.11.0] - 2023-05-23

Expand Down Expand Up @@ -68,7 +69,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Fixed

- AWS SDK rename attributes `aws.operation`, `aws.service` to `rpc.method`,`rpc.service` in `go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws`. (#3582, #3617)
- AWS SDK rename attributes `aws.operation`, `aws.service` to `rpc.method`,`rpc.service` in `go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws`. (#3582, #3617)
- AWS SDK span name to be of the format `Service.Operation` in `go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws`. (#3582, #3521)
- Prevent sampler configuration reset from erroneously sampling first span in `go.opentelemetry.io/contrib/samplers/jaegerremote`. (#3603, #3604)

Expand Down
10 changes: 6 additions & 4 deletions CODEOWNERS
Validating CODEOWNERS rules …
Expand Up @@ -16,7 +16,7 @@
# instrumentation/net/http/otelhttp/ @open-telemetry/collector-go-approvers @madvikinggod @mralias
# Path separator and minimum of 1 space between component path and owners is
# important for validation steps
#
#

* @open-telemetry/go-approvers

Expand All @@ -25,19 +25,21 @@ CODEOWNERS @MrAlias @Aneurysm9 @MadVikingGod
detectors/aws/ @open-telemetry/go-approvers @Aneurysm9
detectors/gcp/ @open-telemetry/go-approvers @dashpole

exporters/autoexport @open-telemetry/go-approvers @MikeGoldsmith

instrumentation/github.com/astaxie/beego/otelbeego/ @open-telemetry/go-approvers
instrumentation/github.com/aws/aws-lambda-go/otellambda/ @open-telemetry/go-approvers @Aneurysm9
instrumentation/github.com/aws/aws-sdk-go-v2/otelaws/ @open-telemetry/go-approvers @Aneurysm9
instrumentation/github.com/bradfitz/gomemcache/memcache/otelmemcache/ @open-telemetry/go-approvers
instrumentation/github.com/emicklei/go-restful/otelrestful/ @open-telemetry/go-approvers
instrumentation/github.com/gin-gonic/gin/otelgin/ @open-telemetry/go-approvers @hanyuancheung
instrumentation/github.com/gin-gonic/gin/otelgin/ @open-telemetry/go-approvers @hanyuancheung
instrumentation/github.com/go-kit/kit/otelkit/ @open-telemetry/go-approvers
instrumentation/github.com/gocql/gocql/otelgocql/ @open-telemetry/go-approvers
instrumentation/github.com/gorilla/mux/otelmux/ @open-telemetry/go-approvers
instrumentation/github.com/labstack/echo/otelecho/ @open-telemetry/go-approvers
instrumentation/github.com/Shopify/sarama/otelsarama/ @open-telemetry/go-approvers @pellared @hanyuancheung
instrumentation/github.com/Shopify/sarama/otelsarama/ @open-telemetry/go-approvers @pellared @hanyuancheung
instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo/ @open-telemetry/go-approvers
instrumentation/google.golang.org/grpc/otelgrpc/ @open-telemetry/go-approvers @dashpole @hanyuancheung
instrumentation/google.golang.org/grpc/otelgrpc/ @open-telemetry/go-approvers @dashpole @hanyuancheung
instrumentation/gopkg.in/macaron.v1/otelmacaron/ @open-telemetry/go-approvers

instrumentation/host/ @open-telemetry/go-approvers @MadVikingGod
Expand Down
22 changes: 22 additions & 0 deletions exporters/autoexport/README.md
@@ -0,0 +1,22 @@
# Automatic Exporter configuration

[![Go Reference][goref-image]][goref-url]
[![Apache License][license-image]][license-url]

This module provides easy access to configuring a trace exporter that can be used when configuring an OpenTelemetry Go SDK trace export pipeline.

## Useful links

- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
- For more about OpenTelemetry Go: <https://github.com/open-telemetry/opentelemetry-go>
- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]

## License

Apache 2.0 - See [LICENSE][license-url] for more information.

[license-url]: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[goref-image]: https://pkg.go.dev/badge/go.opentelemetry.io/contrib/exporters/autoexport.svg
[goref-url]: https://pkg.go.dev/go.opentelemetry.io/contrib/exporters/autoexport
[discussions-url]: https://github.com/open-telemetry/opentelemetry-go/discussions
33 changes: 33 additions & 0 deletions exporters/autoexport/doc.go
@@ -0,0 +1,33 @@
// 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.

// This module provides easy access to configuring a trace exporter
// that can be used when configuring an OpenTelemetry Go SDK trace export
// pipeline.
//
// [NewSpanExporter] looks for the `OTEL_TRACES_EXPORTER` environment
// variable and if set, attempts to load the exporter from it's registry of
// exporters. The registry is always loaded with an OTLP exporter with the key
// `otlp` and additional exporters can be registered using
// [RegisterSpanExporter].
// Exporter registration uses a factory method pattern to not unneccarily build
// exporters and use resources until they are requested.
//
// If the environment variable is not set, the fallback exporter is returned.
// The fallback exporter defaults to an
// [OTLP exporter](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp/otlptrace)
// and can be overridden using the [RegisterSpanExporter](https://pkg.go.dev/go.opentelemetry.io/contrib/exporters/autoexport#WithFallbackSpanExporter)
// option.

package autoexport // import "go.opentelemetry.io/contrib/exporters/autoexport"
98 changes: 98 additions & 0 deletions exporters/autoexport/exporter.go
@@ -0,0 +1,98 @@
// 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/sdk/trace"
)

const (
otelTracesExportersEnvKey = "OTEL_TRACES_EXPORTER"
)

type config struct {
fallbackExporter trace.SpanExporter
}

func newConfig(ctx context.Context, opts ...Option) (config, error) {
cfg := config{}
for _, opt := range opts {
cfg = opt.apply(cfg)
}

// if no fallback exporter is configured, use otlp exporter
if cfg.fallbackExporter == nil {
exp, err := spanExporter(context.Background(), "otlp")
if err != nil {
return cfg, err
}
cfg.fallbackExporter = exp
}
return cfg, nil
}

// Option applies an autoexport configuration option.
type Option interface {
apply(config) config
}

type optionFunc func(config) config

func (fn optionFunc) apply(cfg config) config {
return fn(cfg)
}

// WithFallbackSpanExporter sets the fallback exporter to use when no exporter
// is configured through the OTEL_TRACES_EXPORTER environment variable.
func WithFallbackSpanExporter(exporter trace.SpanExporter) Option {
return optionFunc(func(cfg config) config {
cfg.fallbackExporter = exporter
return cfg
})
}

// NewSpanExporter returns a configured SpanExporter defined using the environment
// variable OTEL_TRACES_EXPORTER, the configured fallback exporter via options or
// a default OTLP exporter (in this order).
func NewSpanExporter(ctx context.Context, opts ...Option) (trace.SpanExporter, error) {
// prefer exporter configured via environment variables over exporter
// passed in via exporter parameter
envExporter, err := makeExporterFromEnv(ctx)
if err != nil {
return nil, err
}
if envExporter != nil {
return envExporter, nil
}
config, err := newConfig(ctx, opts...)
if err != nil {
return nil, err
}
return config.fallbackExporter, nil
}

// makeExporterFromEnv returns a configured SpanExporter defined by the OTEL_TRACES_EXPORTER
// environment variable.
// nil is returned if no exporter is defined for the environment variable.
func makeExporterFromEnv(ctx context.Context) (trace.SpanExporter, error) {
expType, defined := os.LookupEnv(otelTracesExportersEnvKey)
if !defined {
return nil, nil
}
return spanExporter(ctx, expType)
}
64 changes: 64 additions & 0 deletions exporters/autoexport/exporter_test.go
@@ -0,0 +1,64 @@
// 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 (
"context"
"testing"

"github.com/stretchr/testify/assert"

"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/sdk/trace"
)

func TestOTLPExporterReturnedWhenNoEnvOrFallbackExporterConfigured(t *testing.T) {
exporter, err := NewSpanExporter(context.Background())
assert.Nil(t, err)
assert.NotNil(t, exporter)
assert.IsType(t, &otlptrace.Exporter{}, exporter)
}

func TestFallbackExporterReturnedWhenNoEnvExporterConfigured(t *testing.T) {
testExporter := &testExporter{}
exporter, err := NewSpanExporter(
context.Background(),
WithFallbackSpanExporter(testExporter),
)
assert.Nil(t, err)
assert.Equal(t, testExporter, exporter)
}

func TestEnvExporterIsPreferredOverFallbackExporter(t *testing.T) {
t.Setenv("OTEL_TRACES_EXPORTER", "otlp")

testExporter := &testExporter{}
exporter, err := NewSpanExporter(
context.Background(),
WithFallbackSpanExporter(testExporter),
)
assert.Nil(t, err)
assert.IsType(t, &otlptrace.Exporter{}, exporter)
}

type testExporter struct{}

func (e *testExporter) ExportSpans(ctx context.Context, ss []trace.ReadOnlySpan) error {
return nil
}

func (e *testExporter) Shutdown(ctx context.Context) error {
return nil
}
33 changes: 33 additions & 0 deletions exporters/autoexport/go.mod
@@ -0,0 +1,33 @@
module go.opentelemetry.io/contrib/exporters/autoexport

go 1.19

require (
github.com/stretchr/testify v1.7.1
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.10.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0
go.opentelemetry.io/otel/sdk v1.10.0
)

require (
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/otel v1.10.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 // indirect
go.opentelemetry.io/otel/trace v1.10.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
golang.org/x/text v0.3.5 // indirect
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
google.golang.org/grpc v1.46.2 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)

0 comments on commit 3e827e3

Please sign in to comment.