Skip to content

Commit

Permalink
add config parsing module
Browse files Browse the repository at this point in the history
This module parses configuration as defined per the opentelemetry-configuration schema.

Signed-off-by: Alex Boten <aboten@lightstep.com>
  • Loading branch information
Alex Boten committed Sep 27, 2023
1 parent e901cf0 commit 5c2b253
Show file tree
Hide file tree
Showing 27 changed files with 1,616 additions and 3 deletions.
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
}

0 comments on commit 5c2b253

Please sign in to comment.