Skip to content

Commit 91728bc

Browse files
Make component interfaces uniform (#488)
This change fixes inconsistencies in component interfaces. Motivation: - Uniformness results in reduction of code that currently has to deal with differences. - Processor.Start is missing and is important for allowing processors to communicate with the Host. What's changed: - Introduced Component interface. - Unified Host interface. - Added a Start function to processors (via Component interface). - Start/Shutdown is now called for Processors from service start/shutdown. - Receivers, Exporters, Processors, Extensions now embed Component interface. - Replaced StartTraceReception/StartMetricsReception by single Start function for receivers. - Replaced StopTraceReception/StopMetricsReception by single Shutdown function for receivers. Note: before merging this we need to announce the change in Gitter since it breaks existing implementations in contrib (although the fix is easy). Resolves #477 Resolves #262
1 parent 256ec41 commit 91728bc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+499
-332
lines changed

component/component.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2019 OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package component
16+
17+
import "context"
18+
19+
// Component is either a receiver, exporter, processor or extension.
20+
type Component interface {
21+
// Start tells the component to start. Host parameter can be used for communicating
22+
// with the host after Start() has already returned. If error is returned by
23+
// Start() then the collector startup will be aborted.
24+
// If this is an exporter component it may prepare for exporting
25+
// by connecting to the endpoint.
26+
Start(host Host) error
27+
28+
// Shutdown is invoked during service shutdown.
29+
Shutdown() error
30+
}
31+
32+
// Host represents the entity that is hosting a Component. It is used to allow communication
33+
// between the Component and its host (normally the service.Application is the host).
34+
type Host interface {
35+
// ReportFatalError is used to report to the host that the extension
36+
// encountered a fatal error (i.e.: an error that the instance can't recover
37+
// from) after its start function had already returned.
38+
ReportFatalError(err error)
39+
40+
// Context returns a context provided by the host to be used on the component
41+
// operations.
42+
Context() context.Context
43+
}

component/component_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2019 OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package component

receiver/receivertest/mock_host.go renamed to component/mock_host.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,17 @@
1414

1515
// Package receivertest define types and functions used to help test packages
1616
// implementing the receiver package interfaces.
17-
package receivertest
17+
package component
1818

1919
import (
2020
"context"
21-
22-
"github.com/open-telemetry/opentelemetry-collector/receiver"
2321
)
2422

2523
// MockHost mocks a receiver.ReceiverHost for test purposes.
2624
type MockHost struct {
2725
}
2826

29-
var _ receiver.Host = (*MockHost)(nil)
27+
var _ Host = (*MockHost)(nil)
3028

3129
// Context returns a context provided by the host to be used on the receiver
3230
// operations.
@@ -43,6 +41,6 @@ func (mh *MockHost) ReportFatalError(err error) {
4341

4442
// NewMockHost returns a new instance of MockHost with proper defaults for most
4543
// tests.
46-
func NewMockHost() receiver.Host {
44+
func NewMockHost() Host {
4745
return &MockHost{}
4846
}

receiver/receivertest/mock_host_test.go renamed to component/mock_host_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
// Package receivertest define types and functions used to help test packages
1616
// implementing the receiver package interfaces.
17-
package receivertest
17+
package component
1818

1919
import (
2020
"errors"

config/example_factories.go

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"go.uber.org/zap"
2222

23+
"github.com/open-telemetry/opentelemetry-collector/component"
2324
"github.com/open-telemetry/opentelemetry-collector/config/configerror"
2425
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
2526
"github.com/open-telemetry/opentelemetry-collector/consumer"
@@ -82,7 +83,20 @@ func (f *ExampleReceiverFactory) CreateTraceReceiver(
8283
if cfg.(*ExampleReceiver).FailTraceCreation {
8384
return nil, configerror.ErrDataTypeIsNotSupported
8485
}
85-
return &ExampleReceiverProducer{TraceConsumer: nextConsumer}, nil
86+
87+
// There must be one receiver for both metrics and traces. We maintain a map of
88+
// receivers per config.
89+
90+
// Check to see if there is already a receiver for this config.
91+
receiver, ok := exampleReceivers[cfg]
92+
if !ok {
93+
receiver = &ExampleReceiverProducer{}
94+
// Remember the receiver in the map
95+
exampleReceivers[cfg] = receiver
96+
}
97+
receiver.TraceConsumer = nextConsumer
98+
99+
return receiver, nil
86100
}
87101

88102
// CreateMetricsReceiver creates a metrics receiver based on this config.
@@ -94,33 +108,44 @@ func (f *ExampleReceiverFactory) CreateMetricsReceiver(
94108
if cfg.(*ExampleReceiver).FailMetricsCreation {
95109
return nil, configerror.ErrDataTypeIsNotSupported
96110
}
97-
return &ExampleReceiverProducer{MetricsConsumer: nextConsumer}, nil
111+
112+
// There must be one receiver for both metrics and traces. We maintain a map of
113+
// receivers per config.
114+
115+
// Check to see if there is already a receiver for this config.
116+
receiver, ok := exampleReceivers[cfg]
117+
if !ok {
118+
receiver = &ExampleReceiverProducer{}
119+
// Remember the receiver in the map
120+
exampleReceivers[cfg] = receiver
121+
}
122+
receiver.MetricsConsumer = nextConsumer
123+
124+
return receiver, nil
98125
}
99126

100127
// ExampleReceiverProducer allows producing traces and metrics for testing purposes.
101128
type ExampleReceiverProducer struct {
102129
TraceConsumer consumer.TraceConsumer
103-
TraceStarted bool
104-
TraceStopped bool
130+
Started bool
131+
Stopped bool
105132
MetricsConsumer consumer.MetricsConsumer
106-
MetricsStarted bool
107-
MetricsStopped bool
108133
}
109134

110135
// TraceSource returns the name of the trace data source.
111136
func (erp *ExampleReceiverProducer) TraceSource() string {
112137
return ""
113138
}
114139

115-
// StartTraceReception tells the receiver to start its processing.
116-
func (erp *ExampleReceiverProducer) StartTraceReception(host receiver.Host) error {
117-
erp.TraceStarted = true
140+
// Start tells the receiver to start its processing.
141+
func (erp *ExampleReceiverProducer) Start(host component.Host) error {
142+
erp.Started = true
118143
return nil
119144
}
120145

121-
// StopTraceReception tells the receiver that should stop reception,
122-
func (erp *ExampleReceiverProducer) StopTraceReception() error {
123-
erp.TraceStopped = true
146+
// Shutdown tells the receiver that should stop reception,
147+
func (erp *ExampleReceiverProducer) Shutdown() error {
148+
erp.Stopped = true
124149
return nil
125150
}
126151

@@ -129,17 +154,11 @@ func (erp *ExampleReceiverProducer) MetricsSource() string {
129154
return ""
130155
}
131156

132-
// StartMetricsReception tells the receiver to start its processing.
133-
func (erp *ExampleReceiverProducer) StartMetricsReception(host receiver.Host) error {
134-
erp.MetricsStarted = true
135-
return nil
136-
}
137-
138-
// StopMetricsReception tells the receiver that should stop reception,
139-
func (erp *ExampleReceiverProducer) StopMetricsReception() error {
140-
erp.MetricsStopped = true
141-
return nil
142-
}
157+
// This is the map of already created example receivers for particular configurations.
158+
// We maintain this map because the Factory is asked trace and metric receivers separately
159+
// when it gets CreateTraceReceiver() and CreateMetricsReceiver() but they must not
160+
// create separate objects, they must use one Receiver object per configuration.
161+
var exampleReceivers = map[configmodels.Receiver]*ExampleReceiverProducer{}
143162

144163
// MultiProtoReceiver is for testing purposes. We are defining an example multi protocol
145164
// config and factory for "multireceiver" receiver type.
@@ -293,7 +312,7 @@ type ExampleExporterConsumer struct {
293312
// Start tells the exporter to start. The exporter may prepare for exporting
294313
// by connecting to the endpoint. Host parameter can be used for communicating
295314
// with the host after Start() has already returned.
296-
func (exp *ExampleExporterConsumer) Start(host exporter.Host) error {
315+
func (exp *ExampleExporterConsumer) Start(host component.Host) error {
297316
exp.ExporterStarted = true
298317
return nil
299318
}

config/example_factories_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2019 OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"context"
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
23+
"github.com/open-telemetry/opentelemetry-collector/component"
24+
"github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata"
25+
)
26+
27+
func TestExampleExporterConsumer(t *testing.T) {
28+
exp := &ExampleExporterConsumer{}
29+
host := component.NewMockHost()
30+
assert.Equal(t, false, exp.ExporterStarted)
31+
err := exp.Start(host)
32+
assert.NoError(t, err)
33+
assert.Equal(t, true, exp.ExporterStarted)
34+
35+
assert.Equal(t, 0, len(exp.Traces))
36+
err = exp.ConsumeTraceData(context.Background(), consumerdata.TraceData{})
37+
assert.NoError(t, err)
38+
assert.Equal(t, 1, len(exp.Traces))
39+
40+
assert.Equal(t, 0, len(exp.Metrics))
41+
err = exp.ConsumeMetricsData(context.Background(), consumerdata.MetricsData{})
42+
assert.NoError(t, err)
43+
assert.Equal(t, 1, len(exp.Metrics))
44+
45+
assert.Equal(t, false, exp.ExporterShutdown)
46+
err = exp.Shutdown()
47+
assert.NoError(t, err)
48+
assert.Equal(t, true, exp.ExporterShutdown)
49+
}
50+
51+
func TestExampleReceiverProducer(t *testing.T) {
52+
rcv := &ExampleReceiverProducer{}
53+
host := component.NewMockHost()
54+
assert.Equal(t, false, rcv.Started)
55+
err := rcv.Start(host)
56+
assert.NoError(t, err)
57+
assert.Equal(t, true, rcv.Started)
58+
59+
err = rcv.Shutdown()
60+
assert.NoError(t, err)
61+
assert.Equal(t, true, rcv.Started)
62+
}

exporter/exporter.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,13 @@
1616
package exporter
1717

1818
import (
19+
"github.com/open-telemetry/opentelemetry-collector/component"
1920
"github.com/open-telemetry/opentelemetry-collector/consumer"
2021
)
2122

22-
// Host represents the entity where the exporter is being hosted. It is used to
23-
// allow communication between the exporter and its host.
24-
type Host interface {
25-
// ReportFatalError is used to report to the host that the exporter encountered
26-
// a fatal error (i.e.: an error that the instance can't recover from) after
27-
// its start function has already returned.
28-
ReportFatalError(err error)
29-
}
30-
3123
// Exporter defines functions that trace and metric exporters must implement.
3224
type Exporter interface {
33-
// Start tells the exporter to start. The exporter may prepare for exporting
34-
// by connecting to the endpoint. Host parameter can be used for communicating
35-
// with the host after Start() has already returned. If error is returned by
36-
// Start() then the collector startup will be aborted.
37-
Start(host Host) error
38-
39-
// Shutdown is invoked during service shutdown.
40-
Shutdown() error
25+
component.Component
4126
}
4227

4328
// TraceExporter composes TraceConsumer with some additional exporter-specific functions.

exporter/exporterhelper/metricshelper.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"go.opencensus.io/trace"
2121

22+
"github.com/open-telemetry/opentelemetry-collector/component"
2223
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
2324
"github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata"
2425
"github.com/open-telemetry/opentelemetry-collector/exporter"
@@ -37,7 +38,7 @@ type metricsExporter struct {
3738

3839
var _ (exporter.MetricsExporter) = (*metricsExporter)(nil)
3940

40-
func (me *metricsExporter) Start(host exporter.Host) error {
41+
func (me *metricsExporter) Start(host component.Host) error {
4142
return nil
4243
}
4344

exporter/exporterhelper/tracehelper.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"go.opencensus.io/trace"
2121

22+
"github.com/open-telemetry/opentelemetry-collector/component"
2223
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
2324
"github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata"
2425
"github.com/open-telemetry/opentelemetry-collector/exporter"
@@ -37,7 +38,7 @@ type traceExporter struct {
3738

3839
var _ (exporter.TraceExporter) = (*traceExporter)(nil)
3940

40-
func (te *traceExporter) Start(host exporter.Host) error {
41+
func (te *traceExporter) Start(host component.Host) error {
4142
return nil
4243
}
4344

exporter/exportertest/nop_exporter.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package exportertest
1717
import (
1818
"context"
1919

20+
"github.com/open-telemetry/opentelemetry-collector/component"
2021
"github.com/open-telemetry/opentelemetry-collector/consumer/consumerdata"
2122
"github.com/open-telemetry/opentelemetry-collector/exporter"
2223
)
@@ -32,7 +33,7 @@ type nopExporter struct {
3233
var _ exporter.TraceExporter = (*nopExporter)(nil)
3334
var _ exporter.MetricsExporter = (*nopExporter)(nil)
3435

35-
func (ne *nopExporter) Start(host exporter.Host) error {
36+
func (ne *nopExporter) Start(host component.Host) error {
3637
return nil
3738
}
3839

0 commit comments

Comments
 (0)