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

add config parsing module #4228

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ updates:
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /config
labels:
- dependencies
- go
- Skip Changelog
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /detectors/aws/ec2
labels:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Set the description for the `rpc.server.duration` metric in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#4302)
- Add `NewServerHandler` and `NewClientHandler` that return a `grpc.StatsHandler` used for gRPC instrumentation in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#3002)
- Add new Prometheus bridge module in `go.opentelemetry.io/contrib/bridges/prometheus`. (#4227)
- Add module to parse configuration as per opentelemetry-config schema. (#4228)

### Changed

Expand Down
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ $(GOTMPL): PACKAGE=go.opentelemetry.io/build-tools/gotmpl
GORELEASE = $(TOOLS)/gorelease
$(GORELEASE): PACKAGE=golang.org/x/exp/cmd/gorelease

GOJSONSCHEMA = $(TOOLS)/go-jsonschema
$(GOJSONSCHEMA): PACKAGE=github.com/atombender/go-jsonschema/cmd/gojsonschema

tools: $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(MULTIMOD) $(DBOTCONF) $(CROSSLINK) $(GOTMPL) $(GORELEASE)

# Generate
Expand Down Expand Up @@ -283,3 +286,31 @@ COMMIT ?= "HEAD"
add-tags: | $(MULTIMOD)
@[ "${MODSET}" ] || ( echo ">> env var MODSET is not set"; exit 1 )
$(MULTIMOD) verify && $(MULTIMOD) tag -m ${MODSET} -c ${COMMIT}

# The source directory for opentelemetry-configuration schema.
OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR=tmp/opentelememetry-configuration

# The SHA matching the current version of the opentelemetry-configuration schema to use
OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_VERSION=main

# Cleanup temporary directory
genjsonschema-cleanup:
rm -Rf ${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR}

GENERATED_CONFIG=./config/generated_config.go

# Generate structs for configuration from opentelemetry-configuration schema
genjsonschema: genjsonschema-cleanup $(GOJSONSCHEMA)
mkdir -p ${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR}
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) \
--package config \
--tags mapstructure \
--output ${GENERATED_CONFIG} \
--schema-package=https://opentelemetry.io/otelconfig/opentelemetry_configuration.json=github.com/open-telemetry/opentelemetry-collector/schema \
${OPENTELEMETRY_CONFIGURATION_JSONSCHEMA_SRC_DIR}/schema/opentelemetry_configuration.json
@echo Modify jsonschema generated files.
sed -f ./config/jsonschema_patch.sed ${GENERATED_CONFIG} > ${GENERATED_CONFIG}.tmp
mv ${GENERATED_CONFIG}.tmp ${GENERATED_CONFIG}
$(MAKE) lint
$(MAKE) genjsonschema-cleanup
188 changes: 188 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

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

import (
"fmt"
"net/url"
"strings"
)

const (
// Supported protocols for OTLP exporter.
protocolProtobufHTTP = "http/protobuf"
protocolProtobufGRPC = "grpc/protobuf"
)

var (
errInvalidExporterConfiguration = fmt.Errorf("invalid exporter configuration")
errUnsupportedSpanProcessorType = fmt.Errorf("unsupported span processor type")
errUnsupportedMetricReaderType = fmt.Errorf("unsupported metric reader type")
)

// Validate checks for a valid batch processor for the SpanProcessor.
func (sp *SpanProcessor) Validate() error {
if sp.Batch != nil {
return sp.Batch.Exporter.Validate()
}
return errUnsupportedSpanProcessorType
}

// Validate checks for valid exporters to be configured for the SpanExporter.
func (se *SpanExporter) Validate() error {
if se.Console == nil && se.Otlp == nil {
return errInvalidExporterConfiguration
}
return nil
}

// Validate checks the configuration for Prometheus exporter.
func (p *Prometheus) Validate() error {
if p.Host == nil {
return fmt.Errorf("host must be specified")
}
if p.Port == nil {
return fmt.Errorf("port must be specified")
}
return nil
}

// Validate checks the configuration for OtlpMetric exporter.
func (om *OtlpMetric) Validate() error {
switch om.Protocol {
case protocolProtobufHTTP:
case protocolProtobufGRPC:
default:
return fmt.Errorf("unsupported protocol %s", om.Protocol)
}

if len(om.Endpoint) > 0 {
_, err := url.ParseRequestURI(normalizeEndpoint(om.Endpoint))
if err != nil {
return err
}
}
if om.Compression != nil {
switch *om.Compression {
case "gzip":
case "none":
default:
return fmt.Errorf("unsupported compression %q", *om.Compression)
}
}
return nil
}

// Validate checks for either a valid pull or periodic exporter for the MetricReader.
func (mr *MetricReader) Validate() error {
if mr.Pull != nil {
return mr.Pull.Validate()
}

Check warning on line 81 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L80-L81

Added lines #L80 - L81 were not covered by tests
if mr.Periodic != nil {
return mr.Periodic.Validate()
}

return errUnsupportedMetricReaderType
}

// Validate checks for valid exporters to be configured for the PullMetricReader.
func (pmr *PullMetricReader) Validate() error {
if pmr.Exporter.Prometheus == nil {
return errInvalidExporterConfiguration
}
return pmr.Exporter.Validate()
}

// Validate calls the configured exporter's Validate method.
func (me *MetricExporter) Validate() error {
if me.Otlp != nil {
return me.Otlp.Validate()
}
if me.Console != nil {
return nil
}
if me.Prometheus != nil {
return me.Prometheus.Validate()
}
return errInvalidExporterConfiguration

Check warning on line 108 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L108

Added line #L108 was not covered by tests
}

// Validate checks for valid exporters to be configured for the PeriodicMetricReader.
func (pmr *PeriodicMetricReader) Validate() error {
if pmr.Exporter.Otlp == nil && pmr.Exporter.Console == nil {
return errInvalidExporterConfiguration
}
return pmr.Exporter.Validate()
}

// Validate checks for a valid Selector or Stream to be configured for the View.
func (v *View) Validate() error {
if v.Selector == nil || v.Stream == nil {
return fmt.Errorf("invalid view configuration")
}
return nil

Check warning on line 124 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L120-L124

Added lines #L120 - L124 were not covered by tests
}

func (s *ViewSelector) instrumentNameStr() string {
if s.InstrumentName == nil {
return ""
}

Check warning on line 130 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L129-L130

Added lines #L129 - L130 were not covered by tests
return *s.InstrumentName
}

func (s *ViewSelector) meterNameStr() string {
if s.MeterName == nil {
return ""
}

Check warning on line 137 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L136-L137

Added lines #L136 - L137 were not covered by tests
return *s.MeterName
}

func (s *ViewSelector) meterVersionStr() string {
if s.MeterVersion == nil {
return ""
}

Check warning on line 144 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L143-L144

Added lines #L143 - L144 were not covered by tests
return *s.MeterVersion
}

func (s *ViewSelector) meterSchemaURLStr() string {
if s.MeterSchemaUrl == nil {
return ""
}

Check warning on line 151 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L150-L151

Added lines #L150 - L151 were not covered by tests
return *s.MeterSchemaUrl
}

func (s *ViewSelector) unitStr() string {
if s.Unit == nil {
return ""
}
return *s.Unit

Check warning on line 159 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L159

Added line #L159 was not covered by tests
}

func (s *ViewStream) nameStr() string {
if s.Name == nil {
return ""
}

Check warning on line 165 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L164-L165

Added lines #L164 - L165 were not covered by tests
return *s.Name
}

func (s *ViewStream) descriptionStr() string {
if s.Description == nil {
return ""
}

Check warning on line 172 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L171-L172

Added lines #L171 - L172 were not covered by tests
return *s.Description
}

func (e *ViewStreamAggregationExplicitBucketHistogram) recordMinMaxBool() bool {
if e.RecordMinMax == nil {
return false
}
return *e.RecordMinMax

Check warning on line 180 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L180

Added line #L180 was not covered by tests
}

func normalizeEndpoint(endpoint string) string {
if !strings.HasPrefix(endpoint, "https://") && !strings.HasPrefix(endpoint, "http://") {
return fmt.Sprintf("http://%s", endpoint)
}
return endpoint
}