Skip to content

Commit

Permalink
Replace registration system with an explicit dependency one (#159)
Browse files Browse the repository at this point in the history
Implements proposal: #138
  • Loading branch information
owais authored and Paulo Janotti committed Jul 17, 2019
1 parent 8721e3b commit 8905c13
Show file tree
Hide file tree
Showing 60 changed files with 712 additions and 466 deletions.
15 changes: 12 additions & 3 deletions cmd/otelsvc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,21 @@ package main
import (
"log"

_ "github.com/open-telemetry/opentelemetry-service/receiver/vmmetricsreceiver"
"github.com/open-telemetry/opentelemetry-service/defaults"
"github.com/open-telemetry/opentelemetry-service/service"
)

func main() {
if err := service.App.StartUnified(); err != nil {
log.Fatalf("Failed to run the service: %v", err)
handleErr := func(err error) {
if err != nil {
log.Fatalf("Failed to run the service: %v", err)
}
}

receivers, processors, exporters, err := defaults.Components()
handleErr(err)

svc := service.New(receivers, processors, exporters)
err = svc.StartUnified()
handleErr(err)
}
25 changes: 15 additions & 10 deletions config/configv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,25 +84,30 @@ const (
const typeAndNameSeparator = "/"

// Load loads a Config from Viper.
func Load(v *viper.Viper) (*configmodels.Config, error) {
func Load(
v *viper.Viper,
receiverFactories map[string]receiver.Factory,
processorFactories map[string]processor.Factory,
exporterFactories map[string]exporter.Factory,
) (*configmodels.Config, error) {

var config configmodels.Config

// Load the config.

receivers, err := loadReceivers(v)
receivers, err := loadReceivers(v, receiverFactories)
if err != nil {
return nil, err
}
config.Receivers = receivers

exporters, err := loadExporters(v)
exporters, err := loadExporters(v, exporterFactories)
if err != nil {
return nil, err
}
config.Exporters = exporters

processors, err := loadProcessors(v)
processors, err := loadProcessors(v, processorFactories)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -161,7 +166,7 @@ func decodeTypeAndName(key string) (typeStr, fullName string, err error) {
return
}

func loadReceivers(v *viper.Viper) (configmodels.Receivers, error) {
func loadReceivers(v *viper.Viper, factories map[string]receiver.Factory) (configmodels.Receivers, error) {
// Get the list of all "receivers" sub vipers from config source.
subViper := v.Sub(receiversKeyName)

Expand All @@ -183,7 +188,7 @@ func loadReceivers(v *viper.Viper) (configmodels.Receivers, error) {
}

// Find receiver factory based on "type" that we read from config source
factory := receiver.GetFactory(typeStr)
factory := factories[typeStr]
if factory == nil {
return nil, &configError{
code: errUnknownReceiverType,
Expand Down Expand Up @@ -227,7 +232,7 @@ func loadReceivers(v *viper.Viper) (configmodels.Receivers, error) {
return receivers, nil
}

func loadExporters(v *viper.Viper) (configmodels.Exporters, error) {
func loadExporters(v *viper.Viper, factories map[string]exporter.Factory) (configmodels.Exporters, error) {
// Get the list of all "exporters" sub vipers from config source.
subViper := v.Sub(exportersKeyName)

Expand All @@ -249,7 +254,7 @@ func loadExporters(v *viper.Viper) (configmodels.Exporters, error) {
}

// Find exporter factory based on "type" that we read from config source
factory := exporter.GetFactory(typeStr)
factory := factories[typeStr]
if factory == nil {
return nil, &configError{
code: errUnknownExporterType,
Expand Down Expand Up @@ -284,7 +289,7 @@ func loadExporters(v *viper.Viper) (configmodels.Exporters, error) {
return exporters, nil
}

func loadProcessors(v *viper.Viper) (configmodels.Processors, error) {
func loadProcessors(v *viper.Viper, factories map[string]processor.Factory) (configmodels.Processors, error) {
// Get the list of all "processors" sub vipers from config source.
subViper := v.Sub(processorsKeyName)

Expand All @@ -306,7 +311,7 @@ func loadProcessors(v *viper.Viper) (configmodels.Processors, error) {
}

// Find processor factory based on "type" that we read from config source.
factory := processor.GetFactory(typeStr)
factory := factories[typeStr]
if factory == nil {
return nil, &configError{
code: errUnknownProcessorType,
Expand Down
21 changes: 16 additions & 5 deletions config/configv2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ import (
"github.com/open-telemetry/opentelemetry-service/config/configmodels"
)

var _ = RegisterTestFactories()

func TestDecodeConfig(t *testing.T) {
receivers, processors, exporters, err := ExampleComponents()
assert.Nil(t, err)

// Load the config
config, err := LoadConfigFile(t, path.Join(".", "testdata", "valid-config.yaml"))
config, err := LoadConfigFile(
t, path.Join(".", "testdata", "valid-config.yaml"), receivers, processors, exporters,
)
if err != nil {
t.Fatalf("unable to load config, %v", err)
}
Expand Down Expand Up @@ -108,9 +110,13 @@ func TestDecodeConfig(t *testing.T) {
}

func TestDecodeConfig_MultiProto(t *testing.T) {
receivers, processors, exporters, err := ExampleComponents()
assert.Nil(t, err)

// Load the config
config, err := LoadConfigFile(t, path.Join(".", "testdata", "multiproto-config.yaml"))
config, err := LoadConfigFile(
t, path.Join(".", "testdata", "multiproto-config.yaml"), receivers, processors, exporters,
)
if err != nil {
t.Fatalf("unable to load config, %v", err)
}
Expand Down Expand Up @@ -194,8 +200,13 @@ func TestDecodeConfig_Invalid(t *testing.T) {
{name: "duplicate-pipeline", expected: errDuplicatePipelineName},
}

receivers, processors, exporters, err := ExampleComponents()
assert.Nil(t, err)

for _, test := range testCases {
_, err := LoadConfigFile(t, path.Join(".", "testdata", test.name+".yaml"))
_, err := LoadConfigFile(
t, path.Join(".", "testdata", test.name+".yaml"), receivers, processors, exporters,
)
if err == nil {
t.Errorf("expected error but succedded on invalid config case: %s", test.name)
} else if test.expected != 0 {
Expand Down
29 changes: 22 additions & 7 deletions config/example_factories.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,26 @@ func (f *ExampleProcessorFactory) CreateMetricsProcessor(
return nil, configerror.ErrDataTypeIsNotSupported
}

// RegisterTestFactories registers example factories. This is only used by tests.
func RegisterTestFactories() error {
_ = receiver.RegisterFactory(&ExampleReceiverFactory{})
_ = receiver.RegisterFactory(&MultiProtoReceiverFactory{})
_ = exporter.RegisterFactory(&ExampleExporterFactory{})
_ = processor.RegisterFactory(&ExampleProcessorFactory{})
return nil
// ExampleComponents registers example factories. This is only used by tests.
func ExampleComponents() (
receivers map[string]receiver.Factory,
processors map[string]processor.Factory,
exporters map[string]exporter.Factory,
err error,
) {
receivers, err = receiver.Build(
&ExampleReceiverFactory{},
&MultiProtoReceiverFactory{},
)
if err != nil {
return
}

exporters, err = exporter.Build(&ExampleExporterFactory{})
if err != nil {
return
}

processors, err = processor.Build(&ExampleProcessorFactory{})
return
}
16 changes: 13 additions & 3 deletions config/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@ import (
"os"
"testing"

"github.com/open-telemetry/opentelemetry-service/config/configmodels"
"github.com/spf13/viper"

"github.com/open-telemetry/opentelemetry-service/config/configmodels"
"github.com/open-telemetry/opentelemetry-service/exporter"
"github.com/open-telemetry/opentelemetry-service/processor"
"github.com/open-telemetry/opentelemetry-service/receiver"
)

// LoadConfigFile loads a config from file.
func LoadConfigFile(t *testing.T, fileName string) (*configmodels.Config, error) {
func LoadConfigFile(
t *testing.T,
fileName string,
receivers map[string]receiver.Factory,
processors map[string]processor.Factory,
exporters map[string]exporter.Factory,
) (*configmodels.Config, error) {
// Open the file for reading.
file, err := os.Open(fileName)
if err != nil {
Expand All @@ -41,5 +51,5 @@ func LoadConfigFile(t *testing.T, fileName string) (*configmodels.Config, error)
}

// Load the config from viper
return Load(v)
return Load(v, receivers, processors, exporters)
}
74 changes: 74 additions & 0 deletions defaults/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2019, 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 defaults composes the default set of components used by the otel service
package defaults

import (
"github.com/open-telemetry/opentelemetry-service/exporter"
"github.com/open-telemetry/opentelemetry-service/exporter/loggingexporter"
"github.com/open-telemetry/opentelemetry-service/exporter/opencensusexporter"
"github.com/open-telemetry/opentelemetry-service/exporter/prometheusexporter"
"github.com/open-telemetry/opentelemetry-service/internal"
"github.com/open-telemetry/opentelemetry-service/internal/collector/processor/nodebatcher"
"github.com/open-telemetry/opentelemetry-service/internal/collector/processor/queued"
"github.com/open-telemetry/opentelemetry-service/processor"
"github.com/open-telemetry/opentelemetry-service/processor/addattributesprocessor"
"github.com/open-telemetry/opentelemetry-service/receiver"
"github.com/open-telemetry/opentelemetry-service/receiver/jaegerreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/opencensusreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/prometheusreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/vmmetricsreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/zipkinreceiver"
)

// Components returns the default set of components used by the
// opentelemetry service
func Components() (
map[string]receiver.Factory,
map[string]processor.Factory,
map[string]exporter.Factory,
error,
) {
errs := []error{}
receivers, err := receiver.Build(
&jaegerreceiver.Factory{},
&zipkinreceiver.Factory{},
&prometheusreceiver.Factory{},
&opencensusreceiver.Factory{},
&vmmetricsreceiver.Factory{},
)
if err != nil {
errs = append(errs, err)
}

exporters, err := exporter.Build(
&opencensusexporter.Factory{},
&prometheusexporter.Factory{},
&loggingexporter.Factory{},
)
if err != nil {
errs = append(errs, err)
}

processors, err := processor.Build(
&addattributesprocessor.Factory{},
&queued.Factory{},
&nodebatcher.Factory{},
)
if err != nil {
errs = append(errs, err)
}
return receivers, processors, exporters, internal.CombineErrors(errs)
}
66 changes: 66 additions & 0 deletions defaults/defaults_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2019, 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.

// Program otelsvc is the Open Telemetry Service that collects stats
// and traces and exports to a configured backend.
package defaults

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"

"github.com/open-telemetry/opentelemetry-service/exporter"
"github.com/open-telemetry/opentelemetry-service/exporter/loggingexporter"
"github.com/open-telemetry/opentelemetry-service/exporter/opencensusexporter"
"github.com/open-telemetry/opentelemetry-service/exporter/prometheusexporter"
"github.com/open-telemetry/opentelemetry-service/internal/collector/processor/nodebatcher"
"github.com/open-telemetry/opentelemetry-service/internal/collector/processor/queued"
"github.com/open-telemetry/opentelemetry-service/processor"
"github.com/open-telemetry/opentelemetry-service/processor/addattributesprocessor"
"github.com/open-telemetry/opentelemetry-service/receiver"
"github.com/open-telemetry/opentelemetry-service/receiver/jaegerreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/opencensusreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/prometheusreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/vmmetricsreceiver"
"github.com/open-telemetry/opentelemetry-service/receiver/zipkinreceiver"
)

func TestDefaultComponents(t *testing.T) {
expectedReceivers := map[string]receiver.Factory{
"jaeger": &jaegerreceiver.Factory{},
"zipkin": &zipkinreceiver.Factory{},
"prometheus": &prometheusreceiver.Factory{},
"opencensus": &opencensusreceiver.Factory{},
"vmmetrics": &vmmetricsreceiver.Factory{},
}
expectedProcessors := map[string]processor.Factory{
"attributes": &addattributesprocessor.Factory{},
"queued-retry": &queued.Factory{},
"batch": &nodebatcher.Factory{},
}
expectedExporters := map[string]exporter.Factory{
"opencensus": &opencensusexporter.Factory{},
"prometheus": &prometheusexporter.Factory{},
"logging": &loggingexporter.Factory{},
}

receivers, processors, exporters, err := Components()
fmt.Println(err)
assert.Nil(t, err)
assert.Equal(t, expectedReceivers, receivers)
assert.Equal(t, expectedProcessors, processors)
assert.Equal(t, expectedExporters, exporters)
}
Loading

0 comments on commit 8905c13

Please sign in to comment.