Skip to content

Commit

Permalink
config: separate schema version support into separate directories (op…
Browse files Browse the repository at this point in the history
…en-telemetry#6412)

This makes the migration from one version to another explicit in any
downstream dependencies. This will make dealing with breaking changes
much easier in the Collector as it will allow us to have end users
toggle a feature gate to enable support for new schema versions.

Doing this today is not possible as we cannot import both a v0.2.0 and a
v0.3.0 compatible config package. With the change in this PR, this will
be possible.

v0.2.0 directory was a copy based on
355fbbd

---------

Signed-off-by: Alex Boten <[email protected]>
Co-authored-by: Damien Mathieu <[email protected]>
  • Loading branch information
codeboten and dmathieu authored Dec 10, 2024
1 parent cee0910 commit 3af31bd
Show file tree
Hide file tree
Showing 27 changed files with 4,421 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

- Change the span name to be `GET /path` so it complies with the OTel HTTP semantic conventions in `go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho`. (#6365)
- Record errors instead of setting the `gin.errors` attribute in `go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin`. (#6346)
- The `go.opentelemetry.io/contrib/config` now supports multiple schemas in subdirectories (ie. `go.opentelemetry.io/contrib/config/v0.3.0`) for easier migration. (#6412)

### Fixed

Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,12 @@ OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_VERSION=v0.3.0
genjsonschema-cleanup:
rm -Rf ${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR}

GENERATED_CONFIG=./config/generated_config.go
GENERATED_CONFIG=./config/${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_VERSION}/generated_config.go

# Generate structs for configuration from opentelemetry-configuration schema
genjsonschema: genjsonschema-cleanup $(GOJSONSCHEMA)
mkdir -p ${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR}
mkdir -p ./config/${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_VERSION}
curl -sSL https://api.github.com/repos/open-telemetry/opentelemetry-configuration/tarball/${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_VERSION} | tar xz --strip 1 -C ${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR}
$(GOJSONSCHEMA) \
--capitalization ID \
Expand Down
9 changes: 6 additions & 3 deletions config/doc.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

// Package config can be used to parse a configuration file
// that follows the JSON Schema defined by the OpenTelemetry
// Configuration schema.
// Package config can be used to parse a configuration file that follows
// the JSON Schema defined by the OpenTelemetry Configuration schema. Different
// versions of the schema are supported by the code in the directory that
// matches the version number of the schema. For example, the import
// go.opentelemetry.io/contrib/config/v0.3.0 includes code that supports the
// v0.3.0 release of the configuration schema.
package config // import "go.opentelemetry.io/contrib/config"
152 changes: 152 additions & 0 deletions config/v0.2.0/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package config // import "go.opentelemetry.io/contrib/config/v0.2.0"

import (
"context"
"errors"

"gopkg.in/yaml.v3"

"go.opentelemetry.io/otel/log"
nooplog "go.opentelemetry.io/otel/log/noop"
"go.opentelemetry.io/otel/metric"
noopmetric "go.opentelemetry.io/otel/metric/noop"
"go.opentelemetry.io/otel/trace"
nooptrace "go.opentelemetry.io/otel/trace/noop"
)

const (
protocolProtobufHTTP = "http/protobuf"
protocolProtobufGRPC = "grpc/protobuf"

compressionGzip = "gzip"
compressionNone = "none"
)

type configOptions struct {
ctx context.Context
opentelemetryConfig OpenTelemetryConfiguration
}

type shutdownFunc func(context.Context) error

func noopShutdown(context.Context) error {
return nil
}

// SDK is a struct that contains all the providers
// configured via the configuration model.
type SDK struct {
meterProvider metric.MeterProvider
tracerProvider trace.TracerProvider
loggerProvider log.LoggerProvider
shutdown shutdownFunc
}

// TracerProvider returns a configured trace.TracerProvider.
func (s *SDK) TracerProvider() trace.TracerProvider {
return s.tracerProvider
}

// MeterProvider returns a configured metric.MeterProvider.
func (s *SDK) MeterProvider() metric.MeterProvider {
return s.meterProvider
}

// LoggerProvider returns a configured log.LoggerProvider.
func (s *SDK) LoggerProvider() log.LoggerProvider {
return s.loggerProvider
}

// Shutdown calls shutdown on all configured providers.
func (s *SDK) Shutdown(ctx context.Context) error {
return s.shutdown(ctx)
}

var noopSDK = SDK{
loggerProvider: nooplog.LoggerProvider{},
meterProvider: noopmetric.MeterProvider{},
tracerProvider: nooptrace.TracerProvider{},
shutdown: func(ctx context.Context) error { return nil },
}

// NewSDK creates SDK providers based on the configuration model.
func NewSDK(opts ...ConfigurationOption) (SDK, error) {
o := configOptions{}
for _, opt := range opts {
o = opt.apply(o)
}
if o.opentelemetryConfig.Disabled != nil && *o.opentelemetryConfig.Disabled {
return noopSDK, nil
}

r, err := newResource(o.opentelemetryConfig.Resource)
if err != nil {
return noopSDK, err
}

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

tp, tpShutdown, err := tracerProvider(o, r)
if err != nil {
return noopSDK, err
}

lp, lpShutdown, err := loggerProvider(o, r)
if err != nil {
return noopSDK, err
}

return SDK{
meterProvider: mp,
tracerProvider: tp,
loggerProvider: lp,
shutdown: func(ctx context.Context) error {
return errors.Join(mpShutdown(ctx), tpShutdown(ctx), lpShutdown(ctx))
},
}, nil
}

// ConfigurationOption configures options for providers.
type ConfigurationOption interface {
apply(configOptions) configOptions
}

type configurationOptionFunc func(configOptions) configOptions

func (fn configurationOptionFunc) apply(cfg configOptions) configOptions {
return fn(cfg)
}

// WithContext sets the context.Context for the SDK.
func WithContext(ctx context.Context) ConfigurationOption {
return configurationOptionFunc(func(c configOptions) configOptions {
c.ctx = ctx
return c
})
}

// WithOpenTelemetryConfiguration sets the OpenTelemetryConfiguration used
// to produce the SDK.
func WithOpenTelemetryConfiguration(cfg OpenTelemetryConfiguration) ConfigurationOption {
return configurationOptionFunc(func(c configOptions) configOptions {
c.opentelemetryConfig = cfg
return c
})
}

// ParseYAML parses a YAML configuration file into an OpenTelemetryConfiguration.
func ParseYAML(file []byte) (*OpenTelemetryConfiguration, error) {
var cfg OpenTelemetryConfiguration
err := yaml.Unmarshal(file, &cfg)
if err != nil {
return nil, err
}

return &cfg, nil
}
Loading

0 comments on commit 3af31bd

Please sign in to comment.