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

Commit 79342d9

Browse files
author
Paulo Janotti
authored
Implement receivers factory (#470)
Implement the receivers factory by adding a template type that can be used by receivers in general. Small changes were made to the factory interface to better cover the usage in the actual code.
1 parent e871853 commit 79342d9

File tree

4 files changed

+788
-9
lines changed

4 files changed

+788
-9
lines changed

receiver/factory.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
package receiver
1616

1717
import (
18-
"github.com/census-instrumentation/opencensus-service/consumer"
1918
"github.com/spf13/viper"
19+
"go.uber.org/zap"
20+
21+
"github.com/census-instrumentation/opencensus-service/consumer"
2022
)
2123

2224
// TraceReceiverFactory is an interface that builds a new TraceReceiver based on
@@ -25,11 +27,12 @@ type TraceReceiverFactory interface {
2527
// Type gets the type of the TraceReceiver created by this factory.
2628
Type() string
2729
// NewFromViper takes a viper.Viper config and creates a new TraceReceiver which uses next as the
28-
// next TraceConsumer in the pipeline.
29-
NewFromViper(cfg *viper.Viper, next consumer.TraceConsumer) (TraceReceiver, error)
30-
// DefaultConfig returns the default configuration for TraceReceivers
30+
// next TraceConsumer in the pipeline. The factory can use the logger and pass it to the receiver if
31+
// appropriate
32+
NewFromViper(v *viper.Viper, next consumer.TraceConsumer, logger *zap.Logger) (receiver TraceReceiver, err error)
33+
// DefaultConfig gets the default configuration for the TraceReceiver
3134
// created by this factory.
32-
DefaultConfig() *viper.Viper
35+
DefaultConfig() interface{}
3336
}
3437

3538
// MetricsReceiverFactory is an interface that builds a new MetricsReceiver based on
@@ -38,9 +41,10 @@ type MetricsReceiverFactory interface {
3841
// Type gets the type of the MetricsReceiver created by this factory.
3942
Type() string
4043
// NewFromViper takes a viper.Viper config and creates a new MetricsReceiver which uses next as the
41-
// next MetricsConsumer in the pipeline.
42-
NewFromViper(cfg *viper.Viper, next consumer.MetricsConsumer) (MetricsReceiver, error)
43-
// DefaultConfig returns the default configuration for MetricsReceivers
44+
// next MetricsConsumer in the pipeline. The factory can use the logger and pass it to the receiver if
45+
// appropriate.
46+
NewFromViper(v *viper.Viper, next consumer.MetricsConsumer, logger *zap.Logger) (receiver MetricsReceiver, err error)
47+
// DefaultConfig gets the default configuration for the MetricsReceiver
4448
// created by this factory.
45-
DefaultConfig() *viper.Viper
49+
DefaultConfig() interface{}
4650
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
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 factorytemplate allows easy construction of factories for receivers.
16+
// It requires the consumer to provide only functions to create the default
17+
// configuration and how to create the receiver from that configuration.
18+
package factorytemplate
19+
20+
import (
21+
"errors"
22+
"fmt"
23+
24+
"github.com/spf13/viper"
25+
"go.uber.org/zap"
26+
27+
"github.com/census-instrumentation/opencensus-service/consumer"
28+
"github.com/census-instrumentation/opencensus-service/receiver"
29+
)
30+
31+
var (
32+
// ErrEmptyReciverType is returned when an empty name is given.
33+
ErrEmptyReciverType = errors.New("empty receiver type")
34+
// ErrNilNewDefaultCfg is returned when a nil newDefaultCfg is given.
35+
ErrNilNewDefaultCfg = errors.New("nil newDefaultCfg")
36+
// ErrNilNewReceiver is returned when a nil newReceiver is given.
37+
ErrNilNewReceiver = errors.New("nil newReceiver")
38+
// ErrNilNext is returned when a nil next is given.
39+
ErrNilNext = errors.New("nil next")
40+
// ErrNilViper is returned when the required viper parameter was nil.
41+
ErrNilViper = errors.New("nil Viper instance")
42+
)
43+
44+
// factory implements the boiler-plate code used to create factories for receivers.
45+
// Instead of implementing the interface directly one can only provide the parameters
46+
// to contruct a new receiver factory.
47+
type factory struct {
48+
receiverType string
49+
newDefaultCfg func() interface{}
50+
}
51+
52+
type traceReceiverFactory struct {
53+
factory
54+
newReceiver func(interface{}, consumer.TraceConsumer) (receiver.TraceReceiver, error)
55+
}
56+
57+
var _ (receiver.TraceReceiverFactory) = (*traceReceiverFactory)(nil)
58+
59+
type metricsReceiverFactory struct {
60+
factory
61+
newReceiver func(interface{}, consumer.MetricsConsumer) (receiver.MetricsReceiver, error)
62+
}
63+
64+
var _ (receiver.MetricsReceiverFactory) = (*metricsReceiverFactory)(nil)
65+
66+
// NewTraceReceiverFactory creates a factory for the given receiver "type" that
67+
// will have as the default configuration the object returned by newDefaultCfg and
68+
// that can be created using newReceiver from the configuration type returned by
69+
// newDefaultCfg.
70+
//
71+
// The object returned by newDefaultCfg should have its fields properly decorated using
72+
// the mapstructure attribute.
73+
//
74+
// The first parameter passed to newReceiver is going to be from the same type returned by
75+
// newDefaultCfg. The receiver implementer is going to be able to cast it to the appropriate
76+
// type.
77+
func NewTraceReceiverFactory(
78+
receiverType string,
79+
newDefaulfCfg func() interface{},
80+
newReceiver func(interface{}, consumer.TraceConsumer) (receiver.TraceReceiver, error),
81+
) (receiver.TraceReceiverFactory, error) {
82+
if receiverType == "" {
83+
return nil, ErrEmptyReciverType
84+
}
85+
if newDefaulfCfg == nil {
86+
return nil, ErrNilNewDefaultCfg
87+
}
88+
if newReceiver == nil {
89+
return nil, ErrNilNewReceiver
90+
}
91+
92+
return &traceReceiverFactory{
93+
factory: factory{
94+
receiverType: receiverType,
95+
newDefaultCfg: newDefaulfCfg,
96+
},
97+
newReceiver: newReceiver,
98+
}, nil
99+
}
100+
101+
// NewMetricsReceiverFactory creates a factory for the given receiver "type" that
102+
// will have as the default configuration the object returned by newDefaultCfg and
103+
// that can be created using newReceiver from the configuration type returned by
104+
// newDefaultCfg.
105+
//
106+
// The object returned by newDefaultCfg should have its fields properly decorated using
107+
// the mapstructure attribute.
108+
//
109+
// The first parameter passed to newReceiver is going to be from the same type returned by
110+
// newDefaultCfg. The receiver implementer is going to be able to cast it to the appropriate
111+
// type.
112+
func NewMetricsReceiverFactory(
113+
receiverType string,
114+
newDefaulfCfg func() interface{},
115+
newReceiver func(interface{}, consumer.MetricsConsumer) (receiver.MetricsReceiver, error),
116+
) (receiver.MetricsReceiverFactory, error) {
117+
if receiverType == "" {
118+
return nil, ErrEmptyReciverType
119+
}
120+
if newDefaulfCfg == nil {
121+
return nil, ErrNilNewDefaultCfg
122+
}
123+
if newReceiver == nil {
124+
return nil, ErrNilNewReceiver
125+
}
126+
127+
return &metricsReceiverFactory{
128+
factory: factory{
129+
receiverType: receiverType,
130+
newDefaultCfg: newDefaulfCfg,
131+
},
132+
newReceiver: newReceiver,
133+
}, nil
134+
}
135+
136+
// Type gets the type of the receiver created by this factory.
137+
func (f *factory) Type() string {
138+
return f.receiverType
139+
}
140+
141+
// NewFromViper takes a viper.Viper configuration and creates a new TraceReceiver.
142+
func (trf *traceReceiverFactory) NewFromViper(v *viper.Viper, next consumer.TraceConsumer, logger *zap.Logger) (receiver.TraceReceiver, error) {
143+
if next == nil {
144+
return nil, ErrNilNext
145+
}
146+
cfg, err := trf.configFromViper(v)
147+
if err != nil {
148+
return nil, err
149+
}
150+
r, err := trf.newReceiver(cfg, next)
151+
if err != nil {
152+
return nil, err
153+
}
154+
155+
logger.Info("Trace receiver created", zap.String("type", trf.Type()), zap.String("config", fmt.Sprintf("%+v", cfg)))
156+
return r, nil
157+
}
158+
159+
// NewFromViper takes a viper.Viper configuration and creates a new TraceReceiver.
160+
func (mrf *metricsReceiverFactory) NewFromViper(v *viper.Viper, next consumer.MetricsConsumer, logger *zap.Logger) (receiver.MetricsReceiver, error) {
161+
if next == nil {
162+
return nil, ErrNilNext
163+
}
164+
cfg, err := mrf.configFromViper(v)
165+
if err != nil {
166+
return nil, err
167+
}
168+
r, err := mrf.newReceiver(cfg, next)
169+
if err != nil {
170+
return nil, err
171+
}
172+
173+
logger.Info("Metrics receiver created", zap.String("type", mrf.Type()), zap.String("config", fmt.Sprintf("%+v", cfg)))
174+
return r, nil
175+
}
176+
177+
// DefaultConfig gets the default configuration for the receiver
178+
// created by this factory.
179+
func (f *factory) DefaultConfig() interface{} {
180+
return f.newDefaultCfg()
181+
}
182+
183+
// configFromViper takes a viper.Viper, generates a default config and returns the
184+
// resulting configuration.
185+
func (f *factory) configFromViper(v *viper.Viper) (cfg interface{}, err error) {
186+
if v == nil {
187+
return nil, ErrNilViper
188+
}
189+
190+
cfg = f.newDefaultCfg()
191+
err = v.Unmarshal(cfg)
192+
if err != nil {
193+
return nil, err
194+
}
195+
196+
return cfg, err
197+
}

0 commit comments

Comments
 (0)