Skip to content
This repository was archived by the owner on Nov 7, 2022. It is now read-only.

Commit 5129823

Browse files
Add implementation of Jaeger receiver config
- Added factory and config loading for Jaeger receiver. - Added ErrDataTypeIsNotSupported to factory definitions. Testing done: automated tests
1 parent 231ed43 commit 5129823

File tree

6 files changed

+354
-3
lines changed

6 files changed

+354
-3
lines changed

internal/factories/factories.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ package factories
1616

1717
import (
1818
"context"
19+
"errors"
1920
"fmt"
2021

21-
"github.com/census-instrumentation/opencensus-service/consumer"
22-
"github.com/census-instrumentation/opencensus-service/receiver"
23-
2422
"github.com/spf13/viper"
2523

24+
"github.com/census-instrumentation/opencensus-service/consumer"
2625
"github.com/census-instrumentation/opencensus-service/internal/configmodels"
26+
"github.com/census-instrumentation/opencensus-service/receiver"
2727
)
2828

2929
///////////////////////////////////////////////////////////////////////////////
@@ -56,6 +56,11 @@ type ReceiverFactory interface {
5656
consumer consumer.MetricsConsumer) (receiver.MetricsReceiver, error)
5757
}
5858

59+
// ErrDataTypeIsNotSupported can be returned by CreateTraceReceiver or
60+
// CreateMetricsReceiver if the particular telemetry data type is not supported
61+
// by the receiver.
62+
var ErrDataTypeIsNotSupported = errors.New("telemetry type is not supported")
63+
5964
// CustomUnmarshaler is a function that un-marshals a viper data into a config struct
6065
// in a custom way.
6166
type CustomUnmarshaler func(v *viper.Viper, viperKey string, intoCfg interface{}) error

receiver/jaegerreceiver/config.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2019, OpenCensus 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 jaegerreceiver
16+
17+
import (
18+
"github.com/census-instrumentation/opencensus-service/internal/configmodels"
19+
)
20+
21+
// ConfigV2 defines configuration for Jaeger receiver.
22+
type ConfigV2 struct {
23+
Protocols map[string]*configmodels.ReceiverSettings `mapstructure:"protocols"`
24+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2019, OpenCensus 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 jaegerreceiver
16+
17+
import (
18+
"path"
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
"github.com/stretchr/testify/require"
23+
24+
"github.com/census-instrumentation/opencensus-service/internal/configmodels"
25+
"github.com/census-instrumentation/opencensus-service/internal/configv2"
26+
"github.com/census-instrumentation/opencensus-service/internal/factories"
27+
)
28+
29+
var _ = configv2.RegisterTestFactories()
30+
31+
func TestLoadConfig(t *testing.T) {
32+
factory := factories.GetReceiverFactory(typeStr)
33+
34+
config, err := configv2.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"))
35+
36+
require.NoError(t, err)
37+
require.NotNil(t, config)
38+
39+
assert.Equal(t, len(config.Receivers), 2)
40+
41+
r0 := config.Receivers["jaeger"]
42+
assert.Equal(t, r0, factory.CreateDefaultConfig())
43+
44+
r1 := config.Receivers["jaeger/customname"].(*ConfigV2)
45+
assert.Equal(t, r1,
46+
&ConfigV2{
47+
Protocols: map[string]*configmodels.ReceiverSettings{
48+
"thrift-http": {
49+
Enabled: false,
50+
Endpoint: "127.0.0.1:3456",
51+
},
52+
"thrift-tchannel": {
53+
Enabled: true,
54+
Endpoint: "0.0.0.0:123",
55+
},
56+
},
57+
})
58+
}

receiver/jaegerreceiver/factory.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2019, OpenCensus 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 jaegerreceiver
16+
17+
// This file implements factory for Jaeger receiver.
18+
19+
import (
20+
"context"
21+
"errors"
22+
"fmt"
23+
"net"
24+
"strconv"
25+
26+
"github.com/census-instrumentation/opencensus-service/consumer"
27+
"github.com/census-instrumentation/opencensus-service/internal/configmodels"
28+
"github.com/census-instrumentation/opencensus-service/internal/factories"
29+
"github.com/census-instrumentation/opencensus-service/receiver"
30+
)
31+
32+
var _ = factories.RegisterReceiverFactory(&receiverFactory{})
33+
34+
const (
35+
// The value of "type" key in configuration.
36+
typeStr = "jaeger"
37+
38+
// Protocol values.
39+
protoThriftHTTP = "thrift-http"
40+
protoThriftTChannel = "thrift-tchannel"
41+
42+
// Default endpoints to bind to.
43+
defaultHTTPBindEndpoint = "127.0.0.1:14268"
44+
defaultTChannelBindEndpoint = "127.0.0.1:14267"
45+
)
46+
47+
// receiverFactory is the factory for Jaeger receiver.
48+
type receiverFactory struct {
49+
}
50+
51+
// Type gets the type of the Receiver config created by this factory.
52+
func (f *receiverFactory) Type() string {
53+
return typeStr
54+
}
55+
56+
// CustomUnmarshaler returns nil because we don't need custom unmarshaling for this config.
57+
func (f *receiverFactory) CustomUnmarshaler() factories.CustomUnmarshaler {
58+
return nil
59+
}
60+
61+
// CreateDefaultConfig creates the default configuration for Jaeger receiver.
62+
func (f *receiverFactory) CreateDefaultConfig() configmodels.Receiver {
63+
return &ConfigV2{
64+
Protocols: map[string]*configmodels.ReceiverSettings{
65+
protoThriftTChannel: {
66+
Enabled: false,
67+
Endpoint: defaultTChannelBindEndpoint,
68+
},
69+
protoThriftHTTP: {
70+
Enabled: false,
71+
Endpoint: defaultHTTPBindEndpoint,
72+
},
73+
},
74+
}
75+
}
76+
77+
// CreateTraceReceiver creates a trace receiver based on provided config.
78+
func (f *receiverFactory) CreateTraceReceiver(
79+
ctx context.Context,
80+
cfg configmodels.Receiver,
81+
nextConsumer consumer.TraceConsumer,
82+
) (receiver.TraceReceiver, error) {
83+
84+
// Convert settings in the source config to Configuration struct
85+
// that Jaeger receiver understands.
86+
87+
rCfg := cfg.(*ConfigV2)
88+
89+
protoHTTP := rCfg.Protocols[protoThriftHTTP]
90+
protoTChannel := rCfg.Protocols[protoThriftTChannel]
91+
92+
config := Configuration{}
93+
94+
// Set ports
95+
if protoHTTP != nil {
96+
var err error
97+
config.CollectorHTTPPort, err = extractPortFromEndpoint(protoHTTP.Endpoint)
98+
if err != nil {
99+
return nil, err
100+
}
101+
}
102+
103+
if protoTChannel != nil {
104+
var err error
105+
config.CollectorThriftPort, err = extractPortFromEndpoint(protoTChannel.Endpoint)
106+
if err != nil {
107+
return nil, err
108+
}
109+
}
110+
111+
if (protoHTTP == nil && protoTChannel == nil) ||
112+
(config.CollectorHTTPPort == 0 && config.CollectorThriftPort == 0) {
113+
return nil, errors.New("either " + protoThriftHTTP + " or " + protoThriftTChannel +
114+
" protocol endpoint with non-zero port must be defined for " + typeStr + " receiver")
115+
}
116+
117+
// Jaeger receiver implementation currently does not allow specifying which interface
118+
// to bind to so we cannot use yet the address part of endpoint.
119+
120+
// Create the receiver.
121+
return New(ctx, &config, nextConsumer)
122+
}
123+
124+
// CreateMetricsReceiver creates a metrics receiver based on provided config.
125+
func (f *receiverFactory) CreateMetricsReceiver(
126+
cfg configmodels.Receiver,
127+
consumer consumer.MetricsConsumer,
128+
) (receiver.MetricsReceiver, error) {
129+
return nil, factories.ErrDataTypeIsNotSupported
130+
}
131+
132+
// extract the port number from string in "address:port" format. If the
133+
// port number cannot be extracted returns an error.
134+
func extractPortFromEndpoint(endpoint string) (int, error) {
135+
_, portStr, err := net.SplitHostPort(endpoint)
136+
if err != nil {
137+
return 0, fmt.Errorf("endpoint is not formatted correctly: %s", err.Error())
138+
}
139+
port, err := strconv.ParseInt(portStr, 10, 0)
140+
if err != nil {
141+
return 0, fmt.Errorf("endpoint port is not a number: %s", err.Error())
142+
}
143+
if port < 1 || port > 65535 {
144+
return 0, fmt.Errorf("port number must be between 1 and 65535")
145+
}
146+
return int(port), nil
147+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2019, OpenCensus 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 jaegerreceiver
16+
17+
import (
18+
"context"
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
23+
"github.com/census-instrumentation/opencensus-service/internal/factories"
24+
)
25+
26+
func TestCreateDefaultConfig(t *testing.T) {
27+
factory := factories.GetReceiverFactory(typeStr)
28+
cfg := factory.CreateDefaultConfig()
29+
assert.NotNil(t, cfg, "failed to create default config")
30+
}
31+
32+
func TestCreateReceiver(t *testing.T) {
33+
factory := factories.GetReceiverFactory(typeStr)
34+
cfg := factory.CreateDefaultConfig()
35+
36+
tReceiver, err := factory.CreateTraceReceiver(context.Background(), cfg, nil)
37+
assert.NoError(t, err, "receiver creation failed")
38+
assert.NotNil(t, tReceiver, "receiver creation failed")
39+
40+
mReceiver, err := factory.CreateMetricsReceiver(cfg, nil)
41+
assert.Equal(t, err, factories.ErrDataTypeIsNotSupported)
42+
assert.Nil(t, mReceiver)
43+
}
44+
45+
func TestCreateNoEndpoints(t *testing.T) {
46+
factory := factories.GetReceiverFactory(typeStr)
47+
cfg := factory.CreateDefaultConfig()
48+
rCfg := cfg.(*ConfigV2)
49+
50+
rCfg.Protocols[protoThriftHTTP].Endpoint = ""
51+
rCfg.Protocols[protoThriftTChannel].Endpoint = ""
52+
_, err := factory.CreateTraceReceiver(context.Background(), cfg, nil)
53+
assert.Error(t, err, "receiver creation with no endpoints must fail")
54+
}
55+
56+
func TestCreateInvalidTChannelEndpoint(t *testing.T) {
57+
factory := factories.GetReceiverFactory(typeStr)
58+
cfg := factory.CreateDefaultConfig()
59+
rCfg := cfg.(*ConfigV2)
60+
61+
rCfg.Protocols[protoThriftTChannel].Endpoint = ""
62+
_, err := factory.CreateTraceReceiver(context.Background(), cfg, nil)
63+
assert.Error(t, err, "receiver creation with invalid tchannel endpoint must fail")
64+
}
65+
66+
func TestCreateNoPort(t *testing.T) {
67+
factory := factories.GetReceiverFactory(typeStr)
68+
cfg := factory.CreateDefaultConfig()
69+
rCfg := cfg.(*ConfigV2)
70+
71+
rCfg.Protocols[protoThriftHTTP].Endpoint = "127.0.0.1:"
72+
_, err := factory.CreateTraceReceiver(context.Background(), cfg, nil)
73+
assert.Error(t, err, "receiver creation with no port number must fail")
74+
}
75+
76+
func TestCreateLargePort(t *testing.T) {
77+
factory := factories.GetReceiverFactory(typeStr)
78+
cfg := factory.CreateDefaultConfig()
79+
rCfg := cfg.(*ConfigV2)
80+
81+
rCfg.Protocols[protoThriftHTTP].Endpoint = "127.0.0.1:65536"
82+
_, err := factory.CreateTraceReceiver(context.Background(), cfg, nil)
83+
assert.Error(t, err, "receiver creation with too large port number must fail")
84+
}
85+
86+
func TestCreateNoProtocols(t *testing.T) {
87+
factory := factories.GetReceiverFactory(typeStr)
88+
cfg := factory.CreateDefaultConfig()
89+
rCfg := cfg.(*ConfigV2)
90+
91+
delete(rCfg.Protocols, protoThriftHTTP)
92+
delete(rCfg.Protocols, protoThriftTChannel)
93+
_, err := factory.CreateTraceReceiver(context.Background(), cfg, nil)
94+
assert.Error(t, err, "receiver creation with no protocols must fail")
95+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
receivers:
2+
jaeger:
3+
jaeger/customname:
4+
protocols:
5+
thrift-http:
6+
endpoint: "127.0.0.1:3456"
7+
thrift-tchannel:
8+
endpoint: "0.0.0.0:123"
9+
enabled: true
10+
11+
processors:
12+
exampleprocessor:
13+
14+
exporters:
15+
exampleexporter:
16+
17+
pipelines:
18+
traces:
19+
receivers: [jaeger]
20+
processors: [exampleprocessor]
21+
exporters: [exampleexporter]
22+

0 commit comments

Comments
 (0)