Skip to content

Commit

Permalink
Move everything from exporterhelper to component. (#4899) (#4891)
Browse files Browse the repository at this point in the history
Updates #4681

Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
  • Loading branch information
bogdandrutu authored Feb 23, 2022
1 parent 83c6ed1 commit c9c2531
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 280 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
- Deprecated `exporterhelper.WithMetrics` in favour of `component.WithMetricsExporter`
- Deprecated `exporterhelper.WithLogs` in favour of `component.WithLogsExporter`
- Deprecated `exporterhelper.NewFactory` in favour of `component.NewExporterFactory`
- Move helpers from receiverhelper to component (#4891)
- Deprecated `receiverhelper.CreateDefaultConfig` in favour of `component.ReceiverDefaultConfigFunc`
- Deprecated `receiverhelper.WithTraces` in favour of `component.WithTracesReceiver`
- Deprecated `receiverhelper.WithMetrics` in favour of `component.WithMetricsReceiver`
- Deprecated `receiverhelper.WithLogs` in favour of `component.WithLogsReceiver`
- Deprecated `receiverhelper.NewFactory` in favour of `component.NewReceiverFactory`

### 💡 Enhancements 💡

Expand Down
55 changes: 14 additions & 41 deletions component/componenttest/nop_receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/internal/internalinterface"
)

// NewNopReceiverCreateSettings returns a new nop settings for Create*Receiver functions.
Expand All @@ -35,57 +34,31 @@ type nopReceiverConfig struct {
config.ReceiverSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct
}

// nopReceiverFactory is factory for nopReceiver.
type nopReceiverFactory struct {
internalinterface.BaseInternal
}

var nopReceiverFactoryInstance = &nopReceiverFactory{}
var nopReceiverFactory = component.NewReceiverFactory(
"nop",
func() config.Receiver {
return &nopReceiverConfig{
ReceiverSettings: config.NewReceiverSettings(config.NewComponentID("nop")),
}
},
component.WithTracesReceiver(createTracesReceiver),
component.WithMetricsReceiver(createMetricsReceiver),
component.WithLogsReceiver(createLogsReceiver))

// NewNopReceiverFactory returns a component.ReceiverFactory that constructs nop receivers.
func NewNopReceiverFactory() component.ReceiverFactory {
return nopReceiverFactoryInstance
}

// Type gets the type of the Receiver config created by this factory.
func (f *nopReceiverFactory) Type() config.Type {
return config.NewComponentID("nop").Type()
}

// CreateDefaultConfig creates the default configuration for the Receiver.
func (f *nopReceiverFactory) CreateDefaultConfig() config.Receiver {
return &nopReceiverConfig{
ReceiverSettings: config.NewReceiverSettings(config.NewComponentID("nop")),
}
return nopReceiverFactory
}

// CreateTracesReceiver implements component.ReceiverFactory interface.
func (f *nopReceiverFactory) CreateTracesReceiver(
_ context.Context,
_ component.ReceiverCreateSettings,
_ config.Receiver,
_ consumer.Traces,
) (component.TracesReceiver, error) {
func createTracesReceiver(context.Context, component.ReceiverCreateSettings, config.Receiver, consumer.Traces) (component.TracesReceiver, error) {
return nopReceiverInstance, nil
}

// CreateMetricsReceiver implements component.ReceiverFactory interface.
func (f *nopReceiverFactory) CreateMetricsReceiver(
_ context.Context,
_ component.ReceiverCreateSettings,
_ config.Receiver,
_ consumer.Metrics,
) (component.MetricsReceiver, error) {
func createMetricsReceiver(context.Context, component.ReceiverCreateSettings, config.Receiver, consumer.Metrics) (component.MetricsReceiver, error) {
return nopReceiverInstance, nil
}

// CreateLogsReceiver implements component.ReceiverFactory interface.
func (f *nopReceiverFactory) CreateLogsReceiver(
_ context.Context,
_ component.ReceiverCreateSettings,
_ config.Receiver,
_ consumer.Logs,
) (component.LogsReceiver, error) {
func createLogsReceiver(context.Context, component.ReceiverCreateSettings, config.Receiver, consumer.Logs) (component.LogsReceiver, error) {
return nopReceiverInstance, nil
}

Expand Down
38 changes: 38 additions & 0 deletions component/factories_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,44 @@ func TestMakeExtensionFactoryMap(t *testing.T) {
}
}

func TestMakeReceiverFactoryMap(t *testing.T) {
type testCase struct {
name string
in []ReceiverFactory
out map[config.Type]ReceiverFactory
}

p1 := NewReceiverFactory("p1", nil)
p2 := NewReceiverFactory("p2", nil)
testCases := []testCase{
{
name: "different names",
in: []ReceiverFactory{p1, p2},
out: map[config.Type]ReceiverFactory{
p1.Type(): p1,
p2.Type(): p2,
},
},
{
name: "same name",
in: []ReceiverFactory{p1, p2, NewReceiverFactory("p1", nil)},
},
}

for i := range testCases {
tt := testCases[i]
t.Run(tt.name, func(t *testing.T) {
out, err := MakeReceiverFactoryMap(tt.in...)
if tt.out == nil {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.out, out)
})
}
}

func TestMakeProcessorFactoryMap(t *testing.T) {
type testCase struct {
name string
Expand Down
112 changes: 109 additions & 3 deletions component/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ package component // import "go.opentelemetry.io/collector/component"
import (
"context"

"go.opentelemetry.io/collector/component/componenterror"
"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/internal/internalinterface"
)

// Receiver allows the collector to receive metrics, traces and logs.
Expand Down Expand Up @@ -97,11 +99,10 @@ type ReceiverCreateSettings struct {
BuildInfo BuildInfo
}

// ReceiverFactory can create TracesReceiver, MetricsReceiver and
// and LogsReceiver. This is the new preferred factory type to create receivers.
// ReceiverFactory is factory interface for receivers.
//
// This interface cannot be directly implemented. Implementations must
// use the receiverhelper.NewFactory to implement it.
// use the NewReceiverFactory to implement it.
type ReceiverFactory interface {
Factory

Expand Down Expand Up @@ -132,3 +133,108 @@ type ReceiverFactory interface {
CreateLogsReceiver(ctx context.Context, set ReceiverCreateSettings,
cfg config.Receiver, nextConsumer consumer.Logs) (LogsReceiver, error)
}

// ReceiverFactoryOption apply changes to ReceiverOptions.
type ReceiverFactoryOption func(o *receiverFactory)

// ReceiverCreateDefaultConfigFunc is the equivalent of ReceiverFactory.CreateDefaultConfig().
type ReceiverCreateDefaultConfigFunc func() config.Receiver

// CreateDefaultConfig implements ReceiverFactory.CreateDefaultConfig().
func (f ReceiverCreateDefaultConfigFunc) CreateDefaultConfig() config.Receiver {
return f()
}

// CreateTracesReceiverFunc is the equivalent of ReceiverFactory.CreateTracesReceiver().
type CreateTracesReceiverFunc func(context.Context, ReceiverCreateSettings, config.Receiver, consumer.Traces) (TracesReceiver, error)

// CreateTracesReceiver implements ReceiverFactory.CreateTracesReceiver().
func (f CreateTracesReceiverFunc) CreateTracesReceiver(
ctx context.Context,
set ReceiverCreateSettings,
cfg config.Receiver,
nextConsumer consumer.Traces) (TracesReceiver, error) {
if f == nil {
return nil, componenterror.ErrDataTypeIsNotSupported
}
return f(ctx, set, cfg, nextConsumer)
}

// CreateMetricsReceiverFunc is the equivalent of ReceiverFactory.CreateMetricsReceiver().
type CreateMetricsReceiverFunc func(context.Context, ReceiverCreateSettings, config.Receiver, consumer.Metrics) (MetricsReceiver, error)

// CreateMetricsReceiver implements ReceiverFactory.CreateMetricsReceiver().
func (f CreateMetricsReceiverFunc) CreateMetricsReceiver(
ctx context.Context,
set ReceiverCreateSettings,
cfg config.Receiver,
nextConsumer consumer.Metrics,
) (MetricsReceiver, error) {
if f == nil {
return nil, componenterror.ErrDataTypeIsNotSupported
}
return f(ctx, set, cfg, nextConsumer)
}

// CreateLogsReceiverFunc is the equivalent of ReceiverFactory.CreateLogsReceiver().
type CreateLogsReceiverFunc func(context.Context, ReceiverCreateSettings, config.Receiver, consumer.Logs) (LogsReceiver, error)

// CreateLogsReceiver implements ReceiverFactory.CreateLogsReceiver().
func (f CreateLogsReceiverFunc) CreateLogsReceiver(
ctx context.Context,
set ReceiverCreateSettings,
cfg config.Receiver,
nextConsumer consumer.Logs,
) (LogsReceiver, error) {
if f == nil {
return nil, componenterror.ErrDataTypeIsNotSupported
}
return f(ctx, set, cfg, nextConsumer)
}

type receiverFactory struct {
internalinterface.BaseInternal
cfgType config.Type
ReceiverCreateDefaultConfigFunc
CreateTracesReceiverFunc
CreateMetricsReceiverFunc
CreateLogsReceiverFunc
}

// WithTracesReceiver overrides the default "error not supported" implementation for CreateTracesReceiver.
func WithTracesReceiver(createTracesReceiver CreateTracesReceiverFunc) ReceiverFactoryOption {
return func(o *receiverFactory) {
o.CreateTracesReceiverFunc = createTracesReceiver
}
}

// WithMetricsReceiver overrides the default "error not supported" implementation for CreateMetricsReceiver.
func WithMetricsReceiver(createMetricsReceiver CreateMetricsReceiverFunc) ReceiverFactoryOption {
return func(o *receiverFactory) {
o.CreateMetricsReceiverFunc = createMetricsReceiver
}
}

// WithLogsReceiver overrides the default "error not supported" implementation for CreateLogsReceiver.
func WithLogsReceiver(createLogsReceiver CreateLogsReceiverFunc) ReceiverFactoryOption {
return func(o *receiverFactory) {
o.CreateLogsReceiverFunc = createLogsReceiver
}
}

// NewReceiverFactory returns a ReceiverFactory.
func NewReceiverFactory(cfgType config.Type, createDefaultConfig ReceiverCreateDefaultConfigFunc, options ...ReceiverFactoryOption) ReceiverFactory {
f := &receiverFactory{
cfgType: cfgType,
ReceiverCreateDefaultConfigFunc: createDefaultConfig,
}
for _, opt := range options {
opt(f)
}
return f
}

// Type returns the type of the Receiver created by this ReceiverFactory.
func (f *receiverFactory) Type() config.Type {
return f.cfgType
}
82 changes: 44 additions & 38 deletions component/receiver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,55 +15,61 @@
package component

import (
"context"
"testing"

"github.com/stretchr/testify/assert"

"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/consumer"
)

type TestReceiverFactory struct {
ReceiverFactory
name config.Type
func TestNewReceiverFactory(t *testing.T) {
const typeStr = "test"
defaultCfg := config.NewReceiverSettings(config.NewComponentID(typeStr))
factory := NewReceiverFactory(
typeStr,
func() config.Receiver { return &defaultCfg })
assert.EqualValues(t, typeStr, factory.Type())
assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig())
_, err := factory.CreateTracesReceiver(context.Background(), ReceiverCreateSettings{}, &defaultCfg, nil)
assert.Error(t, err)
_, err = factory.CreateMetricsReceiver(context.Background(), ReceiverCreateSettings{}, &defaultCfg, nil)
assert.Error(t, err)
_, err = factory.CreateLogsReceiver(context.Background(), ReceiverCreateSettings{}, &defaultCfg, nil)
assert.Error(t, err)
}

// Type gets the type of the Receiver config created by this factory.
func (f *TestReceiverFactory) Type() config.Type {
return f.name
func TestNewReceiverFactory_WithOptions(t *testing.T) {
const typeStr = "test"
defaultCfg := config.NewReceiverSettings(config.NewComponentID(typeStr))
factory := NewReceiverFactory(
typeStr,
func() config.Receiver { return &defaultCfg },
WithTracesReceiver(createTracesReceiver),
WithMetricsReceiver(createMetricsReceiver),
WithLogsReceiver(createLogsReceiver))
assert.EqualValues(t, typeStr, factory.Type())
assert.EqualValues(t, &defaultCfg, factory.CreateDefaultConfig())

_, err := factory.CreateTracesReceiver(context.Background(), ReceiverCreateSettings{}, &defaultCfg, nil)
assert.NoError(t, err)

_, err = factory.CreateMetricsReceiver(context.Background(), ReceiverCreateSettings{}, &defaultCfg, nil)
assert.NoError(t, err)

_, err = factory.CreateLogsReceiver(context.Background(), ReceiverCreateSettings{}, &defaultCfg, nil)
assert.NoError(t, err)
}

func TestBuildReceivers(t *testing.T) {
type testCase struct {
in []ReceiverFactory
out map[config.Type]ReceiverFactory
}
func createTracesReceiver(context.Context, ReceiverCreateSettings, config.Receiver, consumer.Traces) (TracesReceiver, error) {
return nil, nil
}

testCases := []testCase{
{
in: []ReceiverFactory{
&TestReceiverFactory{name: "e1"},
&TestReceiverFactory{name: "e2"},
},
out: map[config.Type]ReceiverFactory{
"e1": &TestReceiverFactory{name: "e1"},
"e2": &TestReceiverFactory{name: "e2"},
},
},
{
in: []ReceiverFactory{
&TestReceiverFactory{name: "e1"},
&TestReceiverFactory{name: "e1"},
},
},
}
func createMetricsReceiver(context.Context, ReceiverCreateSettings, config.Receiver, consumer.Metrics) (MetricsReceiver, error) {
return nil, nil
}

for _, c := range testCases {
out, err := MakeReceiverFactoryMap(c.in...)
if c.out == nil {
assert.Error(t, err)
continue
}
assert.NoError(t, err)
assert.Equal(t, c.out, out)
}
func createLogsReceiver(context.Context, ReceiverCreateSettings, config.Receiver, consumer.Logs) (LogsReceiver, error) {
return nil, nil
}
Loading

0 comments on commit c9c2531

Please sign in to comment.