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

Commit 36103bb

Browse files
author
Steven Karis
authored
Move agent main.go to use viper instead of yaml.v2 (#471)
* Move agent to use viper instead of yaml.v2
1 parent 7fdef34 commit 36103bb

File tree

8 files changed

+161
-105
lines changed

8 files changed

+161
-105
lines changed

cmd/ocagent/main.go

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package main
1919
import (
2020
"context"
2121
"fmt"
22-
"io/ioutil"
2322
"log"
2423
"net"
2524
"net/http"
@@ -80,19 +79,22 @@ func main() {
8079
}
8180

8281
func runOCAgent() {
83-
yamlBlob, err := ioutil.ReadFile(configYAMLFile)
82+
viperCfg.SetConfigFile(configYAMLFile)
83+
err := viperCfg.ReadInConfig()
8484
if err != nil {
8585
log.Fatalf("Cannot read the YAML file %v error: %v", configYAMLFile, err)
8686
}
87-
agentConfig, err := config.ParseOCAgentConfig(yamlBlob)
87+
88+
var agentConfig config.Config
89+
err = viperCfg.Unmarshal(&agentConfig)
8890
if err != nil {
89-
log.Fatalf("Failed to parse own configuration %v error: %v", configYAMLFile, err)
91+
log.Fatalf("Error unmarshalling yaml config file %v: %v", configYAMLFile, err)
9092
}
9193

9294
// Ensure that we check and catch any logical errors with the
9395
// configuration e.g. if an receiver shares the same address
9496
// as an exporter which would cause a self DOS and waste resources.
95-
if err := agentConfig.CheckLogicalConflicts(yamlBlob); err != nil {
97+
if err := agentConfig.CheckLogicalConflicts(); err != nil {
9698
log.Fatalf("Configuration logical error: %v", err)
9799
}
98100

@@ -110,12 +112,6 @@ func runOCAgent() {
110112
log.Fatalf("Failed to start net/http/pprof: %v", err)
111113
}
112114

113-
// TODO(skaris): move the rest of the configs to use viper
114-
err = viperutils.LoadYAMLBytes(viperCfg, []byte(yamlBlob))
115-
if err != nil {
116-
log.Fatalf("Config: failed to create viper from YAML: %v", err)
117-
}
118-
119115
traceExporters, metricsExporters, closeFns, err := config.ExportersFromViperConfig(logger, viperCfg)
120116
if err != nil {
121117
log.Fatalf("Config: failed to create exporters from YAML: %v", err)
@@ -125,7 +121,7 @@ func runOCAgent() {
125121
commonMetricsSink := processor.NewMultiMetricsDataProcessor(metricsExporters)
126122

127123
// Add other receivers here as they are implemented
128-
ocReceiverDoneFn, err := runOCReceiver(logger, agentConfig, commonSpanSink, commonMetricsSink)
124+
ocReceiverDoneFn, err := runOCReceiver(logger, &agentConfig, commonSpanSink, commonMetricsSink)
129125
if err != nil {
130126
log.Fatal(err)
131127
}
@@ -138,6 +134,7 @@ func runOCAgent() {
138134
closeFns = append(closeFns, zCloseFn)
139135
}
140136

137+
// TODO: Generalize the startup of these receivers when unifying them w/ collector
141138
// If the Zipkin receiver is enabled, then run it
142139
if agentConfig.ZipkinReceiverEnabled() {
143140
zipkinReceiverAddr := agentConfig.ZipkinReceiverAddress()
@@ -167,7 +164,7 @@ func runOCAgent() {
167164

168165
// If the Prometheus receiver is enabled, then run it.
169166
if agentConfig.PrometheusReceiverEnabled() {
170-
promDoneFn, err := runPrometheusReceiver(agentConfig.PrometheusConfiguration(), commonMetricsSink)
167+
promDoneFn, err := runPrometheusReceiver(viperCfg, commonMetricsSink)
171168
if err != nil {
172169
log.Fatal(err)
173170
}
@@ -228,10 +225,10 @@ func runOCReceiver(logger *zap.Logger, acfg *config.Config, tdp processor.TraceD
228225
opencensusreceiver.WithCorsOrigins(corsOrigins))
229226

230227
if err != nil {
231-
return nil, fmt.Errorf("Failed to create the OpenCensus receiver on address %q: error %v", addr, err)
228+
return nil, fmt.Errorf("failed to create the OpenCensus receiver on address %q: error %v", addr, err)
232229
}
233230
if err := view.Register(observability.AllViews...); err != nil {
234-
return nil, fmt.Errorf("Failed to register internal.AllViews: %v", err)
231+
return nil, fmt.Errorf("failed to register internal.AllViews: %v", err)
235232
}
236233

237234
// Temporarily disabling the grpc metrics since they do not provide good data at this moment,
@@ -245,19 +242,19 @@ func runOCReceiver(logger *zap.Logger, acfg *config.Config, tdp processor.TraceD
245242
switch {
246243
case acfg.CanRunOpenCensusTraceReceiver() && acfg.CanRunOpenCensusMetricsReceiver():
247244
if err := ocr.Start(ctx, tdp, mdp); err != nil {
248-
return nil, fmt.Errorf("Failed to start Trace and Metrics Receivers: %v", err)
245+
return nil, fmt.Errorf("failed to start Trace and Metrics Receivers: %v", err)
249246
}
250247
log.Printf("Running OpenCensus Trace and Metrics receivers as a gRPC service at %q", addr)
251248

252249
case acfg.CanRunOpenCensusTraceReceiver():
253250
if err := ocr.StartTraceReception(ctx, tdp); err != nil {
254-
return nil, fmt.Errorf("Failed to start TraceReceiver: %v", err)
251+
return nil, fmt.Errorf("failed to start TraceReceiver: %v", err)
255252
}
256253
log.Printf("Running OpenCensus Trace receiver as a gRPC service at %q", addr)
257254

258255
case acfg.CanRunOpenCensusMetricsReceiver():
259256
if err := ocr.StartMetricsReception(ctx, mdp); err != nil {
260-
return nil, fmt.Errorf("Failed to start MetricsReceiver: %v", err)
257+
return nil, fmt.Errorf("failed to start MetricsReceiver: %v", err)
261258
}
262259
log.Printf("Running OpenCensus Metrics receiver as a gRPC service at %q", addr)
263260
}
@@ -283,10 +280,10 @@ func runJaegerReceiver(collectorThriftPort, collectorHTTPPort int, next processo
283280
// and not use their defaults of 5778, 6831, 6832
284281
})
285282
if err != nil {
286-
return nil, fmt.Errorf("Failed to create new Jaeger receiver: %v", err)
283+
return nil, fmt.Errorf("failed to create new Jaeger receiver: %v", err)
287284
}
288285
if err := jtr.StartTraceReception(context.Background(), next); err != nil {
289-
return nil, fmt.Errorf("Failed to start Jaeger receiver: %v", err)
286+
return nil, fmt.Errorf("failed to start Jaeger receiver: %v", err)
290287
}
291288
doneFn = func() error {
292289
return jtr.StopTraceReception(context.Background())
@@ -298,11 +295,11 @@ func runJaegerReceiver(collectorThriftPort, collectorHTTPPort int, next processo
298295
func runZipkinReceiver(addr string, next processor.TraceDataProcessor) (doneFn func() error, err error) {
299296
zi, err := zipkinreceiver.New(addr)
300297
if err != nil {
301-
return nil, fmt.Errorf("Failed to create the Zipkin receiver: %v", err)
298+
return nil, fmt.Errorf("failed to create the Zipkin receiver: %v", err)
302299
}
303300

304301
if err := zi.StartTraceReception(context.Background(), next); err != nil {
305-
return nil, fmt.Errorf("Cannot start Zipkin receiver with address %q: %v", addr, err)
302+
return nil, fmt.Errorf("cannot start Zipkin receiver with address %q: %v", addr, err)
306303
}
307304
doneFn = func() error {
308305
return zi.StopTraceReception(context.Background())
@@ -314,11 +311,11 @@ func runZipkinReceiver(addr string, next processor.TraceDataProcessor) (doneFn f
314311
func runZipkinScribeReceiver(config *config.ScribeReceiverConfig, next processor.TraceDataProcessor) (doneFn func() error, err error) {
315312
zs, err := scribe.NewReceiver(config.Address, config.Port, config.Category)
316313
if err != nil {
317-
return nil, fmt.Errorf("Failed to create the Zipkin Scribe receiver: %v", err)
314+
return nil, fmt.Errorf("failed to create the Zipkin Scribe receiver: %v", err)
318315
}
319316

320317
if err := zs.StartTraceReception(context.Background(), next); err != nil {
321-
return nil, fmt.Errorf("Cannot start Zipkin Scribe receiver with %v: %v", config, err)
318+
return nil, fmt.Errorf("cannot start Zipkin Scribe receiver with %v: %v", config, err)
322319
}
323320
doneFn = func() error {
324321
return zs.StopTraceReception(context.Background())
@@ -327,8 +324,8 @@ func runZipkinScribeReceiver(config *config.ScribeReceiverConfig, next processor
327324
return doneFn, nil
328325
}
329326

330-
func runPrometheusReceiver(promConfig *prometheusreceiver.Configuration, next processor.MetricsDataProcessor) (doneFn func() error, err error) {
331-
pmr, err := prometheusreceiver.New(promConfig)
327+
func runPrometheusReceiver(v *viper.Viper, next processor.MetricsDataProcessor) (doneFn func() error, err error) {
328+
pmr, err := prometheusreceiver.New(v.Sub("receivers.prometheus"))
332329
if err != nil {
333330
return nil, err
334331
}

internal/config/config.go

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"go.uber.org/zap"
2626
"google.golang.org/grpc"
2727
"google.golang.org/grpc/credentials"
28-
yaml "gopkg.in/yaml.v2"
2928

3029
"github.com/census-instrumentation/opencensus-service/exporter/awsexporter"
3130
"github.com/census-instrumentation/opencensus-service/exporter/datadogexporter"
@@ -87,9 +86,9 @@ var defaultScribeConfiguration = &ScribeReceiverConfig{
8786
// * ZPages
8887
// * Exporters
8988
type Config struct {
90-
Receivers *Receivers `yaml:"receivers"`
91-
ZPages *ZPagesConfig `yaml:"zpages"`
92-
Exporters *Exporters `yaml:"exporters"`
89+
Receivers *Receivers `mapstructure:"receivers"`
90+
ZPages *ZPagesConfig `mapstructure:"zpages"`
91+
Exporters *Exporters `mapstructure:"exporters"`
9392
}
9493

9594
// Receivers denotes configurations for the various telemetry ingesters, such as:
@@ -98,10 +97,10 @@ type Config struct {
9897
// * Prometheus (metrics)
9998
// * Zipkin (traces)
10099
type Receivers struct {
101-
OpenCensus *ReceiverConfig `yaml:"opencensus"`
102-
Zipkin *ReceiverConfig `yaml:"zipkin"`
103-
Jaeger *ReceiverConfig `yaml:"jaeger"`
104-
Scribe *ScribeReceiverConfig `yaml:"zipkin-scribe"`
100+
OpenCensus *ReceiverConfig `mapstructure:"opencensus"`
101+
Zipkin *ReceiverConfig `mapstructure:"zipkin"`
102+
Jaeger *ReceiverConfig `mapstructure:"jaeger"`
103+
Scribe *ScribeReceiverConfig `mapstructure:"zipkin-scribe"`
105104

106105
// Prometheus contains the Prometheus configurations.
107106
// Such as:
@@ -111,7 +110,7 @@ type Receivers struct {
111110
//
112111
// static_configs:
113112
// - targets: ['localhost:9988']
114-
Prometheus *prometheusreceiver.Configuration `yaml:"prometheus"`
113+
Prometheus *prometheusreceiver.Configuration `mapstructure:"prometheus"`
115114
}
116115

117116
// ReceiverConfig is the per-receiver configuration that identifies attributes
@@ -120,23 +119,23 @@ type Receivers struct {
120119
// * Various ports
121120
type ReceiverConfig struct {
122121
// The address to which the OpenCensus receiver will be bound and run on.
123-
Address string `yaml:"address"`
124-
CollectorHTTPPort int `yaml:"collector_http_port"`
125-
CollectorThriftPort int `yaml:"collector_thrift_port"`
122+
Address string `mapstructure:"address"`
123+
CollectorHTTPPort int `mapstructure:"collector_http_port"`
124+
CollectorThriftPort int `mapstructure:"collector_thrift_port"`
126125

127126
// The allowed CORS origins for HTTP/JSON requests the grpc-gateway adapter
128127
// for the OpenCensus receiver. See github.com/rs/cors
129128
// An empty list means that CORS is not enabled at all. A wildcard (*) can be
130129
// used to match any origin or one or more characters of an origin.
131-
CorsAllowedOrigins []string `yaml:"cors_allowed_origins"`
130+
CorsAllowedOrigins []string `mapstructure:"cors_allowed_origins"`
132131

133132
// DisableTracing disables trace receiving and is only applicable to trace receivers.
134-
DisableTracing bool `yaml:"disable_tracing"`
133+
DisableTracing bool `mapstructure:"disable_tracing"`
135134
// DisableMetrics disables metrics receiving and is only applicable to metrics receivers.
136-
DisableMetrics bool `yaml:"disable_metrics"`
135+
DisableMetrics bool `mapstructure:"disable_metrics"`
137136

138137
// TLSCredentials is a (cert_file, key_file) configuration.
139-
TLSCredentials *TLSCredentials `yaml:"tls_credentials"`
138+
TLSCredentials *TLSCredentials `mapstructure:"tls_credentials"`
140139
}
141140

142141
// ScribeReceiverConfig carries the settings for the Zipkin Scribe receiver.
@@ -147,23 +146,23 @@ type ScribeReceiverConfig struct {
147146
// a listener for at most one of the host's IP addresses.
148147
//
149148
// The default value bind to all available interfaces on the local computer.
150-
Address string `yaml:"address" mapstructure:"address"`
151-
Port uint16 `yaml:"port" mapstructure:"port"`
149+
Address string `mapstructure:"address" mapstructure:"address"`
150+
Port uint16 `mapstructure:"port" mapstructure:"port"`
152151
// Category is the string that will be used to identify the scribe log messages
153152
// that contain Zipkin spans.
154-
Category string `yaml:"category" mapstructure:"category"`
153+
Category string `mapstructure:"category" mapstructure:"category"`
155154
}
156155

157156
// Exporters denotes the configurations for the various backends
158157
// that this service exports observability signals to.
159158
type Exporters struct {
160-
Zipkin *zipkinexporter.ZipkinConfig `yaml:"zipkin"`
159+
Zipkin *zipkinexporter.ZipkinConfig `mapstructure:"zipkin"`
161160
}
162161

163162
// ZPagesConfig denotes the configuration that zPages will be run with.
164163
type ZPagesConfig struct {
165-
Disabled bool `yaml:"disabled"`
166-
Port int `yaml:"port"`
164+
Disabled bool `mapstructure:"disabled"`
165+
Port int `mapstructure:"port"`
167166
}
168167

169168
// OpenCensusReceiverAddress is a helper to safely retrieve the address
@@ -375,32 +374,17 @@ func (c *Config) OpenCensusReceiverTLSCredentialsServerOption() (opt opencensusr
375374
return tlsCreds.ToOpenCensusReceiverServerOption()
376375
}
377376

378-
// ParseOCAgentConfig unmarshals byte content in the YAML file format
379-
// to retrieve the configuration that will be used to run the OpenCensus agent.
380-
func ParseOCAgentConfig(yamlBlob []byte) (*Config, error) {
381-
var cfg Config
382-
if err := yaml.Unmarshal(yamlBlob, &cfg); err != nil {
383-
return nil, err
384-
}
385-
return &cfg, nil
386-
}
387-
388377
// CheckLogicalConflicts serves to catch logical errors such as
389378
// if the Zipkin receiver port conflicts with that of the exporter,
390379
// lest we'll have a self DOS because spans will be exported "out" from
391380
// the exporter, yet be received from the receiver, then sent back out
392381
// and back in a never ending loop.
393-
func (c *Config) CheckLogicalConflicts(blob []byte) error {
394-
var cfg Config
395-
if err := yaml.Unmarshal(blob, &cfg); err != nil {
396-
return err
397-
}
398-
399-
if cfg.Exporters == nil || cfg.Exporters.Zipkin == nil || !c.ZipkinReceiverEnabled() {
382+
func (c *Config) CheckLogicalConflicts() error {
383+
if c.Exporters == nil || c.Exporters.Zipkin == nil || !c.ZipkinReceiverEnabled() {
400384
return nil
401385
}
402386

403-
zc := cfg.Exporters.Zipkin
387+
zc := c.Exporters.Zipkin
404388

405389
zExporterAddr := zc.EndpointURL()
406390
zExporterURL, err := url.Parse(zExporterAddr)
@@ -485,7 +469,7 @@ func ExportersFromViperConfig(logger *zap.Logger, v *viper.Viper) ([]processor.T
485469
for _, cfg := range parseFns {
486470
tes, mes, tesDoneFns, err := cfg.fn(exportersViper)
487471
if err != nil {
488-
err = fmt.Errorf("Failed to create config for %q: %v", cfg.name, err)
472+
err = fmt.Errorf("failed to create config for %q: %v", cfg.name, err)
489473
return nil, nil, nil, err
490474
}
491475

internal/config/config_test.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ package config_test
1717
import (
1818
"testing"
1919

20-
yaml "gopkg.in/yaml.v2"
20+
"github.com/spf13/viper"
2121

2222
"github.com/census-instrumentation/opencensus-service/exporter/zipkinexporter"
2323
"github.com/census-instrumentation/opencensus-service/internal/config"
24+
"github.com/census-instrumentation/opencensus-service/internal/config/viperutils"
2425
)
2526

2627
// Issue #233: Zipkin receiver and exporter loopback detection
@@ -39,11 +40,17 @@ exporters:
3940
endpoint: "http://localhost:9411/api/v2/spans"
4041
`)
4142

42-
cfg, err := config.ParseOCAgentConfig(regressionYAML)
43+
v := viper.New()
44+
err := viperutils.LoadYAMLBytes(v, regressionYAML)
4345
if err != nil {
4446
t.Fatalf("Unexpected YAML parse error: %v", err)
4547
}
46-
if err := cfg.CheckLogicalConflicts(regressionYAML); err != nil {
48+
var cfg config.Config
49+
err = v.Unmarshal(&cfg)
50+
if err != nil {
51+
t.Fatalf("Unexpected error unmarshaling viper: %s", err)
52+
}
53+
if err := cfg.CheckLogicalConflicts(); err != nil {
4754
t.Fatalf("Unexpected error: %v", err)
4855
}
4956

@@ -53,10 +60,10 @@ exporters:
5360

5461
var ecfg struct {
5562
Exporters *struct {
56-
Zipkin *zipkinexporter.ZipkinConfig `yaml:"zipkin"`
57-
} `yaml:"exporters"`
63+
Zipkin *zipkinexporter.ZipkinConfig `mapstructure:"zipkin"`
64+
} `mapstructure:"exporters"`
5865
}
59-
_ = yaml.Unmarshal(regressionYAML, &ecfg)
66+
_ = v.Unmarshal(&ecfg)
6067
if g, w := ecfg.Exporters.Zipkin.EndpointURL(), "http://localhost:9411/api/v2/spans"; g != w {
6168
t.Errorf("Exporters.Zipkin.EndpointURL mismatch\nGot: %s\nWant:%s", g, w)
6269
}
@@ -84,10 +91,15 @@ receivers:
8491
zipkin:
8592
address: "localhost:9410"`)
8693

87-
cfg, err := config.ParseOCAgentConfig(regressionYAML)
94+
v := viper.New()
95+
err := viperutils.LoadYAMLBytes(v, regressionYAML)
8896
if err != nil {
8997
t.Fatalf("Unexpected YAML parse error: %v", err)
9098
}
99+
err = v.Unmarshal(cfg)
100+
if err != nil {
101+
t.Fatalf("Unexpected error unmarshaling viper: %s", err)
102+
}
91103

92104
if cfg.CanRunOpenCensusTraceReceiver() {
93105
t.Fatal("yaml.CanRunOpenCensusTraceReceiver: Unexpected True for a nil Receiver.OpenCensus")

internal/config/tls_credentials.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ package config
1818
// that are used for starting a server.
1919
type TLSCredentials struct {
2020
// CertFile is the file path containing the TLS certificate.
21-
CertFile string `yaml:"cert_file"`
21+
CertFile string `mapstructure:"cert_file"`
2222

2323
// KeyFile is the file path containing the TLS key.
24-
KeyFile string `yaml:"key_file"`
24+
KeyFile string `mapstructure:"key_file"`
2525
}
2626

2727
// nonEmpty returns true if the TLSCredentials are non-nil and

0 commit comments

Comments
 (0)