diff --git a/cmd/ocagent/main.go b/cmd/ocagent/main.go index ec111946..c979a682 100644 --- a/cmd/ocagent/main.go +++ b/cmd/ocagent/main.go @@ -35,6 +35,7 @@ import ( "github.com/census-instrumentation/opencensus-service/exporter" "github.com/census-instrumentation/opencensus-service/internal" "github.com/census-instrumentation/opencensus-service/internal/config" + "github.com/census-instrumentation/opencensus-service/internal/config/viperutils" "github.com/census-instrumentation/opencensus-service/receiver" "github.com/census-instrumentation/opencensus-service/receiver/jaeger" "github.com/census-instrumentation/opencensus-service/receiver/opencensus" @@ -87,7 +88,12 @@ func runOCAgent() { log.Fatalf("Could not instantiate logger: %v", err) } - traceExporters, metricsExporters, closeFns, err := config.ExportersFromYAMLConfig(logger, yamlBlob) + // TODO(skaris): move the rest of the configs to use viper + v, err := viperutils.ViperFromYAMLBytes([]byte(yamlBlob)) + if err != nil { + log.Fatalf("Config: failed to create viper from YAML: %v", err) + } + traceExporters, metricsExporters, closeFns, err := config.ExportersFromViperConfig(logger, v) if err != nil { log.Fatalf("Config: failed to create exporters from YAML: %v", err) } diff --git a/cmd/occollector/app/builder/builder_test.go b/cmd/occollector/app/builder/builder_test.go index 80cf2c9c..71fe6ed3 100644 --- a/cmd/occollector/app/builder/builder_test.go +++ b/cmd/occollector/app/builder/builder_test.go @@ -98,6 +98,7 @@ func TestMultiAndQueuedSpanProcessorConfig(t *testing.T) { DiscoveryMinPeers: 7, DiscoveryConnCheckTimeout: time.Second * 7, } + fst.RawConfig = v.Sub(queuedExportersConfigKey).Sub("proc-tchannel") snd := NewDefaultQueuedSpanProcessorCfg() snd.Name = "proc-http" snd.RetryOnFailure = false @@ -108,6 +109,7 @@ func TestMultiAndQueuedSpanProcessorConfig(t *testing.T) { Headers: map[string]string{"x-header-key": "00000000-0000-0000-0000-000000000001"}, Timeout: time.Second * 5, } + snd.RawConfig = v.Sub(queuedExportersConfigKey).Sub("proc-http") wCfg := &MultiSpanProcessorCfg{ Processors: []*QueuedSpanProcessorCfg{fst, snd}, diff --git a/cmd/occollector/app/builder/processor_builder.go b/cmd/occollector/app/builder/processor_builder.go index c8ffea6f..2f22e161 100644 --- a/cmd/occollector/app/builder/processor_builder.go +++ b/cmd/occollector/app/builder/processor_builder.go @@ -108,6 +108,7 @@ type QueuedSpanProcessorCfg struct { SenderConfig interface{} // BatchingConfig sets config parameters related to batching BatchingConfig BatchingConfig `mapstructure:"batching"` + RawConfig *viper.Viper } // AttributesCfg holds configuration for attributes that can be added to all spans @@ -155,6 +156,7 @@ func (qOpts *QueuedSpanProcessorCfg) InitFromViper(v *viper.Viper) *QueuedSpanPr } qOpts.SenderConfig = thsOpts } + qOpts.RawConfig = v return qOpts } diff --git a/cmd/occollector/app/collector/processors.go b/cmd/occollector/app/collector/processors.go index df959c04..fed08a2a 100644 --- a/cmd/occollector/app/collector/processors.go +++ b/cmd/occollector/app/collector/processors.go @@ -16,7 +16,6 @@ package collector import ( "fmt" - "io/ioutil" "os" "time" @@ -38,18 +37,7 @@ import ( func createExporters(v *viper.Viper, logger *zap.Logger) ([]func(), []exporter.TraceExporter, []exporter.MetricsExporter) { // TODO: (@pjanotti) this is slightly modified from agent but in the end duplication, need to consolidate style and visibility. - cfg := builder.GetConfigFile(v) - if cfg == "" { - logger.Info("No config file, exporters can be only configured via the file.") - return nil, nil, nil - } - - cfgBlob, err := ioutil.ReadFile(cfg) - if err != nil { - logger.Fatal("Cannot read config file for exporters", zap.Error(err)) - } - - traceExporters, metricsExporters, doneFns, err := config.ExportersFromYAMLConfig(logger, cfgBlob) + traceExporters, metricsExporters, doneFns, err := config.ExportersFromViperConfig(logger, v) if err != nil { logger.Fatal("Failed to create config for exporters", zap.Error(err)) } @@ -101,9 +89,23 @@ func buildQueuedSpanProcessor( sender.HTTPTimeout(thriftHTTPSenderOpts.Timeout), ) } + doneFns, traceExporters, _ := createExporters(opts.RawConfig, logger) - if spanSender == nil { - logger.Fatal("Unrecognized sender type or no exporters configured", zap.String("SenderType", string(opts.SenderType))) + if spanSender == nil && len(traceExporters) == 0 { + if opts.SenderType != "" { + logger.Fatal("Unrecognized sender type", zap.String("SenderType", string(opts.SenderType))) + } + logger.Fatal("No senders or exporters configured.") + } + + allSendersAndExporters := make([]processor.SpanProcessor, 0, 1+len(traceExporters)) + if spanSender != nil { + allSendersAndExporters = append(allSendersAndExporters, spanSender) + } + for _, traceExporter := range traceExporters { + allSendersAndExporters = append( + allSendersAndExporters, processor.NewTraceExporterProcessor(traceExporter), + ) } var batchingOptions []nodebatcher.Option @@ -134,19 +136,25 @@ func buildQueuedSpanProcessor( } } - // build queued span processor with underlying sender - queuedSpanProcessor = queued.NewQueuedSpanProcessor( - spanSender, - queued.Options.WithLogger(logger), - queued.Options.WithName(opts.Name), - queued.Options.WithNumWorkers(opts.NumWorkers), - queued.Options.WithQueueSize(opts.QueueSize), - queued.Options.WithRetryOnProcessingFailures(opts.RetryOnFailure), - queued.Options.WithBackoffDelay(opts.BackoffDelay), - queued.Options.WithBatching(opts.BatchingConfig.Enable), - queued.Options.WithBatchingOptions(batchingOptions...), - ) - return nil, queuedSpanProcessor, nil + queuedProcessors := make([]processor.SpanProcessor, 0, len(allSendersAndExporters)) + for _, senderOrExporter := range allSendersAndExporters { + // build queued span processor with underlying sender + queuedProcessors = append( + queuedProcessors, + queued.NewQueuedSpanProcessor( + senderOrExporter, + queued.Options.WithLogger(logger), + queued.Options.WithName(opts.Name), + queued.Options.WithNumWorkers(opts.NumWorkers), + queued.Options.WithQueueSize(opts.QueueSize), + queued.Options.WithRetryOnProcessingFailures(opts.RetryOnFailure), + queued.Options.WithBackoffDelay(opts.BackoffDelay), + queued.Options.WithBatching(opts.BatchingConfig.Enable), + queued.Options.WithBatchingOptions(batchingOptions...), + ), + ) + } + return doneFns, processor.NewMultiSpanProcessor(queuedProcessors), nil } func buildSamplingProcessor(cfg *builder.SamplingCfg, nameToSpanProcessor map[string]processor.SpanProcessor, v *viper.Viper, logger *zap.Logger) (processor.SpanProcessor, error) { diff --git a/exporter/exporterparser/README.md b/exporter/exporterparser/README.md index cf8e3c8e..bf5aaf70 100644 --- a/exporter/exporterparser/README.md +++ b/exporter/exporterparser/README.md @@ -81,6 +81,11 @@ queued-exporters: collector-endpoint: "https://ingest.omnition.io" headers: { "x-omnition-api-key": "00000000-0000-0000-0000-000000000001" } timeout: 5s + # Non-sender exporters can now also be used by setting the exporters section in queued-exporters. + exporters: + opencensus: + endpoint: "127.0.0.1:55566" + compression: "gzip" my-org-jaeger: # A second processor with its own configuration options num-workers: 2 queue-size: 100 diff --git a/exporter/exporterparser/datadog.go b/exporter/exporterparser/datadog.go index 71c1c1e3..81c85fa4 100644 --- a/exporter/exporterparser/datadog.go +++ b/exporter/exporterparser/datadog.go @@ -18,6 +18,7 @@ import ( "context" datadog "github.com/DataDog/opencensus-go-exporter-datadog" + "github.com/spf13/viper" "github.com/census-instrumentation/opencensus-service/data" "github.com/census-instrumentation/opencensus-service/exporter" @@ -25,43 +26,38 @@ import ( type datadogConfig struct { // Namespace specifies the namespaces to which metric keys are appended. - Namespace string `yaml:"namespace,omitempty"` + Namespace string `mapstructure:"namespace,omitempty"` // TraceAddr specifies the host[:port] address of the Datadog Trace Agent. // It defaults to localhost:8126. - TraceAddr string `yaml:"trace_addr,omitempty"` + TraceAddr string `mapstructure:"trace_addr,omitempty"` // MetricsAddr specifies the host[:port] address for DogStatsD. It defaults // to localhost:8125. - MetricsAddr string `yaml:"metrics_addr,omitempty"` + MetricsAddr string `mapstructure:"metrics_addr,omitempty"` // Tags specifies a set of global tags to attach to each metric. - Tags []string `yaml:"tags,omitempty"` + Tags []string `mapstructure:"tags,omitempty"` - EnableTracing bool `yaml:"enable_tracing,omitempty"` - EnableMetrics bool `yaml:"enable_metrics,omitempty"` + EnableTracing bool `mapstructure:"enable_tracing,omitempty"` + EnableMetrics bool `mapstructure:"enable_metrics,omitempty"` } type datadogExporter struct { exporter *datadog.Exporter } -// DatadogTraceExportersFromYAML parses the yaml bytes and returns an exporter.TraceExporter targeting +// DatadogTraceExportersFromViper unmarshals the viper and returns an exporter.TraceExporter targeting // Datadog according to the configuration settings. -func DatadogTraceExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { +func DatadogTraceExportersFromViper(v *viper.Viper) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { var cfg struct { - Exporters *struct { - Datadog *datadogConfig `yaml:"datadog"` - } `yaml:"exporters"` + Datadog *datadogConfig `mapstructure:"datadog,omitempty"` } - if err := yamlUnmarshal(config, &cfg); err != nil { + if err := v.Unmarshal(&cfg); err != nil { return nil, nil, nil, err } - if cfg.Exporters == nil { - return nil, nil, nil, nil - } - dc := cfg.Exporters.Datadog + dc := cfg.Datadog if dc == nil { return nil, nil, nil, nil } diff --git a/exporter/exporterparser/exparser.go b/exporter/exporterparser/exparser.go index daa95860..ef9777e8 100644 --- a/exporter/exporterparser/exparser.go +++ b/exporter/exporterparser/exparser.go @@ -13,7 +13,7 @@ // limitations under the License. // Package exporterparser provides support for parsing and creating the -// respective exporters given a YAML configuration payload. +// respective exporters given a viper configuration. // For now it currently only provides statically imported OpenCensus // exporters like: // * Stackdriver Tracing and Monitoring @@ -23,10 +23,8 @@ package exporterparser import ( "context" - "fmt" "go.opencensus.io/trace" - yaml "gopkg.in/yaml.v2" tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" "github.com/census-instrumentation/opencensus-service/data" @@ -53,10 +51,3 @@ func exportSpans(ctx context.Context, exporterName string, te trace.Exporter, td return internal.CombineErrors(errs) } - -func yamlUnmarshal(yamlBlob []byte, dest interface{}) error { - if err := yaml.Unmarshal(yamlBlob, dest); err != nil { - return fmt.Errorf("Cannot YAML unmarshal data: %v", err) - } - return nil -} diff --git a/exporter/exporterparser/jaeger.go b/exporter/exporterparser/jaeger.go index 3bde5126..36827eaf 100644 --- a/exporter/exporterparser/jaeger.go +++ b/exporter/exporterparser/jaeger.go @@ -17,38 +17,35 @@ package exporterparser import ( "context" + "github.com/spf13/viper" + "go.opencensus.io/exporter/jaeger" + "github.com/census-instrumentation/opencensus-service/data" "github.com/census-instrumentation/opencensus-service/exporter" - "go.opencensus.io/exporter/jaeger" ) // Slight modified version of go/src/go.opencensus.io/exporter/jaeger/jaeger.go type jaegerConfig struct { - CollectorEndpoint string `yaml:"collector_endpoint,omitempty"` - Username string `yaml:"username,omitempty"` - Password string `yaml:"password,omitempty"` - ServiceName string `yaml:"service_name,omitempty"` + CollectorEndpoint string `mapstructure:"collector_endpoint,omitempty"` + Username string `mapstructure:"username,omitempty"` + Password string `mapstructure:"password,omitempty"` + ServiceName string `mapstructure:"service_name,omitempty"` } type jaegerExporter struct { exporter *jaeger.Exporter } -// JaegerExportersFromYAML parses the yaml bytes and returns exporter.TraceExporters targeting +// JaegerExportersFromViper unmarshals the viper and returns exporter.TraceExporters targeting // Jaeger according to the configuration settings. -func JaegerExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { +func JaegerExportersFromViper(v *viper.Viper) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { var cfg struct { - Exporters *struct { - Jaeger *jaegerConfig `yaml:"jaeger"` - } `yaml:"exporters"` + Jaeger *jaegerConfig `mapstructure:"jaeger"` } - if err := yamlUnmarshal(config, &cfg); err != nil { + if err := v.Unmarshal(&cfg); err != nil { return nil, nil, nil, err } - if cfg.Exporters == nil { - return nil, nil, nil, nil - } - jc := cfg.Exporters.Jaeger + jc := cfg.Jaeger if jc == nil { return nil, nil, nil, nil } diff --git a/exporter/exporterparser/kafka.go b/exporter/exporterparser/kafka.go index fb5a94e1..a0c11b38 100644 --- a/exporter/exporterparser/kafka.go +++ b/exporter/exporterparser/kafka.go @@ -18,6 +18,7 @@ import ( "context" "fmt" + "github.com/spf13/viper" "github.com/yancl/opencensus-go-exporter-kafka" "github.com/census-instrumentation/opencensus-service/data" @@ -25,8 +26,8 @@ import ( ) type kafkaConfig struct { - Brokers []string `yaml:"brokers,omitempty"` - Topic string `yaml:"topic,omitempty"` + Brokers []string `mapstructure:"brokers,omitempty"` + Topic string `mapstructure:"topic,omitempty"` } type kafkaExporter struct { @@ -35,22 +36,17 @@ type kafkaExporter struct { var _ exporter.TraceExporter = (*kafkaExporter)(nil) -// KafkaExportersFromYAML parses the yaml bytes and returns an exporter.TraceExporter targeting +// KafkaExportersFromViper unmarshals the viper and returns an exporter.TraceExporter targeting // Kafka according to the configuration settings. -func KafkaExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { +func KafkaExportersFromViper(v *viper.Viper) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { var cfg struct { - Exporters *struct { - Kafka *kafkaConfig `yaml:"kafka"` - } `yaml:"exporters"` + Kafka *kafkaConfig `mapstructure:"kafka"` } - if err := yamlUnmarshal(config, &cfg); err != nil { + if err := v.Unmarshal(&cfg); err != nil { return nil, nil, nil, err } - if cfg.Exporters == nil { - return nil, nil, nil, nil - } - kc := cfg.Exporters.Kafka + kc := cfg.Kafka if kc == nil { return nil, nil, nil, nil } diff --git a/exporter/exporterparser/opencensus.go b/exporter/exporterparser/opencensus.go index 1c13bba5..6da45360 100644 --- a/exporter/exporterparser/opencensus.go +++ b/exporter/exporterparser/opencensus.go @@ -19,6 +19,7 @@ import ( "fmt" "contrib.go.opencensus.io/exporter/ocagent" + "github.com/spf13/viper" agenttracepb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/trace/v1" "github.com/census-instrumentation/opencensus-service/data" @@ -29,8 +30,8 @@ import ( ) type opencensusConfig struct { - Endpoint string `yaml:"endpoint,omitempty"` - Compression string `yaml:"compression,omitempty"` + Endpoint string `mapstructure:"endpoint,omitempty"` + Compression string `mapstructure:"compression,omitempty"` // TODO: add insecure, service name options. } @@ -40,21 +41,16 @@ type ocagentExporter struct { var _ exporter.TraceExporter = (*ocagentExporter)(nil) -// OpenCensusTraceExportersFromYAML parses the yaml bytes and returns an exporter.TraceExporter targeting +// OpenCensusTraceExportersFromViper unmarshals the viper and returns an exporter.TraceExporter targeting // OpenCensus Agent/Collector according to the configuration settings. -func OpenCensusTraceExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { +func OpenCensusTraceExportersFromViper(v *viper.Viper) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { var cfg struct { - Exporters *struct { - OpenCensus *opencensusConfig `yaml:"opencensus"` - } `yaml:"exporters"` + OpenCensus *opencensusConfig `mapstructure:"opencensus"` } - if err := yamlUnmarshal(config, &cfg); err != nil { + if err := v.Unmarshal(&cfg); err != nil { return nil, nil, nil, err } - if cfg.Exporters == nil { - return nil, nil, nil, nil - } - ocac := cfg.Exporters.OpenCensus + ocac := cfg.OpenCensus if ocac == nil { return nil, nil, nil, nil } diff --git a/exporter/exporterparser/prometheus.go b/exporter/exporterparser/prometheus.go index c86b1baf..6ba1004b 100644 --- a/exporter/exporterparser/prometheus.go +++ b/exporter/exporterparser/prometheus.go @@ -23,6 +23,7 @@ import ( "github.com/census-instrumentation/opencensus-service/data" "github.com/census-instrumentation/opencensus-service/exporter" + "github.com/spf13/viper" // TODO: once this repository has been transferred to the // official census-ecosystem location, update this import path. @@ -33,34 +34,32 @@ import ( type prometheusConfig struct { // Namespace if set, exports metrics under the provided value. - Namespace string `yaml:"namespace"` + Namespace string `mapstructure:"namespace"` // ConstLabels are values that are applied for every exported metric. - ConstLabels prometheus_golang.Labels `yaml:"const_labels"` + ConstLabels prometheus_golang.Labels `mapstructure:"const_labels"` // The address on which the Prometheus scrape handler will be run on. - Address string `yaml:"address"` + Address string `mapstructure:"address"` } var errBlankPrometheusAddress = errors.New("expecting a non-blank address to run the Prometheus metrics handler") -// PrometheusExportersFromYAML parses the yaml bytes and returns exporter.MetricsExporters +// PrometheusExportersFromViper unmarshals the viper and returns exporter.MetricsExporters // targeting Prometheus according to the configuration settings. // It allows HTTP clients to scrape it on endpoint path "/metrics". -func PrometheusExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { +func PrometheusExportersFromViper(v *viper.Viper) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { var cfg struct { - Exporters *struct { - Prometheus *prometheusConfig `yaml:"prometheus"` - } `yaml:"exporters"` + Prometheus *prometheusConfig `mapstructure:"prometheus"` } - if err := yamlUnmarshal(config, &cfg); err != nil { + if err := v.Unmarshal(&cfg); err != nil { return nil, nil, nil, err } - if cfg.Exporters == nil || cfg.Exporters.Prometheus == nil { + if cfg.Prometheus == nil { return nil, nil, nil, nil } - pcfg := cfg.Exporters.Prometheus + pcfg := cfg.Prometheus addr := strings.TrimSpace(pcfg.Address) if addr == "" { err = errBlankPrometheusAddress diff --git a/exporter/exporterparser/prometheus_test.go b/exporter/exporterparser/prometheus_test.go index 6fc8884f..fecb42d3 100644 --- a/exporter/exporterparser/prometheus_test.go +++ b/exporter/exporterparser/prometheus_test.go @@ -21,9 +21,11 @@ import ( "strings" "testing" + "github.com/golang/protobuf/ptypes/timestamp" + metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1" "github.com/census-instrumentation/opencensus-service/data" - "github.com/golang/protobuf/ptypes/timestamp" + viperutils "github.com/census-instrumentation/opencensus-service/internal/config/viperutils" ) func TestPrometheusExporter(t *testing.T) { @@ -33,14 +35,13 @@ func TestPrometheusExporter(t *testing.T) { }{ { config: ` -exporters: - prometheus: - namespace: "test" - const_labels: { - "foo": "bar", - "code": "one" - } - address: ":8999" +prometheus: + namespace: "test" + const_labels: { + "foo": "bar", + "code": "one" + } + address: ":8999" `, }, } @@ -48,7 +49,8 @@ exporters: for i, tt := range tests { // Run it a few times to ensure that shutdowns exit cleanly. for j := 0; j < 3; j++ { - tes, mes, doneFns, err := PrometheusExportersFromYAML([]byte(tt.config)) + v, _ := viperutils.ViperFromYAMLBytes([]byte(tt.config)) + tes, mes, doneFns, err := PrometheusExportersFromViper(v) if tt.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tt.wantErr) { t.Errorf("#%d iteration #%d: Unexpected error: %v Wanted: %v", i, j, err, tt.wantErr) @@ -74,10 +76,9 @@ exporters: func TestPrometheusExporter_nilDoesntCauseCrash(t *testing.T) { config := []byte(` -exporters: - prometheus:`) - - tes, mes, doneFns, err := PrometheusExportersFromYAML(config) +prometheus:`) + v, _ := viperutils.ViperFromYAMLBytes([]byte(config)) + tes, mes, doneFns, err := PrometheusExportersFromViper(v) if err != nil { t.Errorf("Unexpected parse error: %v", err) } @@ -94,17 +95,17 @@ exporters: func TestPrometheusExporter_endToEnd(t *testing.T) { config := []byte(` -exporters: - prometheus: - namespace: "test" - const_labels: { - "foo": "bar", - "code": "one" - } - address: ":7777" +prometheus: + namespace: "test" + const_labels: { + "foo": "bar", + "code": "one" + } + address: ":7777" `) - _, mes, doneFns, err := PrometheusExportersFromYAML(config) + v, _ := viperutils.ViperFromYAMLBytes([]byte(config)) + _, mes, doneFns, err := PrometheusExportersFromViper(v) defer func() { for _, doneFn := range doneFns { doneFn() diff --git a/exporter/exporterparser/stackdriver.go b/exporter/exporterparser/stackdriver.go index 3f6240ea..c77bba76 100644 --- a/exporter/exporterparser/stackdriver.go +++ b/exporter/exporterparser/stackdriver.go @@ -21,6 +21,7 @@ import ( "time" "contrib.go.opencensus.io/exporter/stackdriver" + "github.com/spf13/viper" "go.opencensus.io/trace" "github.com/census-instrumentation/opencensus-service/data" @@ -28,10 +29,10 @@ import ( ) type stackdriverConfig struct { - ProjectID string `yaml:"project,omitempty"` - EnableTracing bool `yaml:"enable_tracing,omitempty"` - EnableMetrics bool `yaml:"enable_metrics,omitempty"` - MetricPrefix string `yaml:"metric_prefix,omitempty"` + ProjectID string `mapstructure:"project,omitempty"` + EnableTracing bool `mapstructure:"enable_tracing,omitempty"` + EnableMetrics bool `mapstructure:"enable_metrics,omitempty"` + MetricPrefix string `mapstructure:"metric_prefix,omitempty"` } type stackdriverExporter struct { @@ -40,21 +41,16 @@ type stackdriverExporter struct { var _ exporter.TraceExporter = (*stackdriverExporter)(nil) -// StackdriverTraceExportersFromYAML parses the yaml bytes and returns an exporter.TraceExporter targeting +// StackdriverTraceExportersFromViper unmarshals the viper and returns an exporter.TraceExporter targeting // Stackdriver according to the configuration settings. -func StackdriverTraceExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { +func StackdriverTraceExportersFromViper(v *viper.Viper) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { var cfg struct { - Exporters *struct { - Stackdriver *stackdriverConfig `yaml:"stackdriver"` - } `yaml:"exporters"` + Stackdriver *stackdriverConfig `mapstructure:"stackdriver"` } - if err := yamlUnmarshal(config, &cfg); err != nil { + if err := v.Unmarshal(&cfg); err != nil { return nil, nil, nil, err } - if cfg.Exporters == nil { - return nil, nil, nil, nil - } - sc := cfg.Exporters.Stackdriver + sc := cfg.Stackdriver if sc == nil { return nil, nil, nil, nil } diff --git a/exporter/exporterparser/zipkin.go b/exporter/exporterparser/zipkin.go index 130045e5..0d63060b 100644 --- a/exporter/exporterparser/zipkin.go +++ b/exporter/exporterparser/zipkin.go @@ -23,11 +23,11 @@ import ( "sync" "time" - "go.opencensus.io/trace" - zipkinmodel "github.com/openzipkin/zipkin-go/model" zipkinreporter "github.com/openzipkin/zipkin-go/reporter" zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http" + "github.com/spf13/viper" + "go.opencensus.io/trace" commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" @@ -39,10 +39,10 @@ import ( // ZipkinConfig holds the configuration of a Zipkin exporter. type ZipkinConfig struct { - ServiceName string `yaml:"service_name,omitempty"` - Endpoint string `yaml:"endpoint,omitempty"` - LocalEndpointURI string `yaml:"local_endpoint,omitempty"` - UploadPeriod *time.Duration `yaml:"upload_period,omitempty"` + ServiceName string `mapstructure:"service_name,omitempty"` + Endpoint string `mapstructure:"endpoint,omitempty"` + LocalEndpointURI string `mapstructure:"local_endpoint,omitempty"` + UploadPeriod *time.Duration `mapstructure:"upload_period,omitempty"` } // zipkinExporter is a multiplexing exporter that spawns a new OpenCensus-Go Zipkin @@ -77,22 +77,17 @@ func (zc *ZipkinConfig) EndpointURL() string { return endpoint } -// ZipkinExportersFromYAML parses the yaml bytes and returns an exporter.TraceExporter targeting +// ZipkinExportersFromViper unmarshals the viper and returns an exporter.TraceExporter targeting // Zipkin according to the configuration settings. -func ZipkinExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { +func ZipkinExportersFromViper(v *viper.Viper) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) { var cfg struct { - Exporters *struct { - Zipkin *ZipkinConfig `yaml:"zipkin"` - } `yaml:"exporters"` + Zipkin *ZipkinConfig `mapstructure:"zipkin"` } - if err := yamlUnmarshal(config, &cfg); err != nil { + if err := v.Unmarshal(&cfg); err != nil { return nil, nil, nil, err } - if cfg.Exporters == nil { - return nil, nil, nil, nil - } - zc := cfg.Exporters.Zipkin + zc := cfg.Zipkin if zc == nil { return nil, nil, nil, nil } diff --git a/exporter/exporterparser/zipkin_test.go b/exporter/exporterparser/zipkin_test.go index eb32357f..e8e05111 100644 --- a/exporter/exporterparser/zipkin_test.go +++ b/exporter/exporterparser/zipkin_test.go @@ -30,6 +30,7 @@ import ( zipkinmodel "github.com/openzipkin/zipkin-go/model" "github.com/census-instrumentation/opencensus-service/exporter" + "github.com/census-instrumentation/opencensus-service/internal/config/viperutils" "github.com/census-instrumentation/opencensus-service/internal/testutils" "github.com/census-instrumentation/opencensus-service/receiver/zipkin" ) @@ -131,7 +132,7 @@ func TestZipkinEndpointFromNode(t *testing.T) { // "7::80:807f" // // The rest of the fields should match up exactly -func TestZipkinExportersFromYAML_roundtripJSON(t *testing.T) { +func TestZipkinExportersFromViper_roundtripJSON(t *testing.T) { responseReady := make(chan bool) buf := new(bytes.Buffer) cst := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -142,12 +143,12 @@ func TestZipkinExportersFromYAML_roundtripJSON(t *testing.T) { defer cst.Close() config := ` -exporters: - zipkin: - upload_period: 1ms - endpoint: ` + cst.URL - tes, _, doneFns, err := ZipkinExportersFromYAML([]byte(config)) - if err != nil { +zipkin: + upload_period: 1ms + endpoint: ` + cst.URL + v, _ := viperutils.ViperFromYAMLBytes([]byte(config)) + tes, _, doneFns, err := ZipkinExportersFromViper(v) + if len(tes) == 0 || err != nil { t.Fatalf("Failed to parse out exporters: %v", err) } defer func() { diff --git a/internal/config/config.go b/internal/config/config.go index 9ee6a7ff..2372abe2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -21,6 +21,7 @@ import ( "reflect" "strings" + "github.com/spf13/viper" "go.uber.org/zap" yaml "gopkg.in/yaml.v2" @@ -380,7 +381,7 @@ func eqLocalHost(host string) bool { } } -// ExportersFromYAMLConfig parses the config yaml payload and returns the respective exporters +// ExportersFromViperConfig uses the viper configuration payload to returns the respective exporters // from: // + datadog // + stackdriver @@ -389,25 +390,29 @@ func eqLocalHost(host string) bool { // + kafka // + opencensus // + prometheus -func ExportersFromYAMLConfig(logger *zap.Logger, config []byte) ([]exporter.TraceExporter, []exporter.MetricsExporter, []func() error, error) { +func ExportersFromViperConfig(logger *zap.Logger, v *viper.Viper) ([]exporter.TraceExporter, []exporter.MetricsExporter, []func() error, error) { parseFns := []struct { name string - fn func([]byte) ([]exporter.TraceExporter, []exporter.MetricsExporter, []func() error, error) + fn func(*viper.Viper) ([]exporter.TraceExporter, []exporter.MetricsExporter, []func() error, error) }{ - {name: "datadog", fn: exporterparser.DatadogTraceExportersFromYAML}, - {name: "stackdriver", fn: exporterparser.StackdriverTraceExportersFromYAML}, - {name: "zipkin", fn: exporterparser.ZipkinExportersFromYAML}, - {name: "jaeger", fn: exporterparser.JaegerExportersFromYAML}, - {name: "kafka", fn: exporterparser.KafkaExportersFromYAML}, - {name: "opencensus", fn: exporterparser.OpenCensusTraceExportersFromYAML}, - {name: "prometheus", fn: exporterparser.PrometheusExportersFromYAML}, + {name: "datadog", fn: exporterparser.DatadogTraceExportersFromViper}, + {name: "stackdriver", fn: exporterparser.StackdriverTraceExportersFromViper}, + {name: "zipkin", fn: exporterparser.ZipkinExportersFromViper}, + {name: "jaeger", fn: exporterparser.JaegerExportersFromViper}, + {name: "kafka", fn: exporterparser.KafkaExportersFromViper}, + {name: "opencensus", fn: exporterparser.OpenCensusTraceExportersFromViper}, + {name: "prometheus", fn: exporterparser.PrometheusExportersFromViper}, } var traceExporters []exporter.TraceExporter var metricsExporters []exporter.MetricsExporter var doneFns []func() error + exportersViper := v.Sub("exporters") + if exportersViper == nil { + return nil, nil, nil, nil + } for _, cfg := range parseFns { - tes, mes, tesDoneFns, err := cfg.fn(config) + tes, mes, tesDoneFns, err := cfg.fn(exportersViper) if err != nil { err = fmt.Errorf("Failed to create config for %q: %v", cfg.name, err) return nil, nil, nil, err diff --git a/internal/config/viperutils/viper.go b/internal/config/viperutils/viper.go new file mode 100644 index 00000000..4160a49a --- /dev/null +++ b/internal/config/viperutils/viper.go @@ -0,0 +1,18 @@ +package viperutils + +import ( + "bytes" + + "github.com/spf13/viper" +) + +// ViperFromYAMLBytes unmarshals byte content in the YAML file format into +// a viper object +func ViperFromYAMLBytes(yamlBlob []byte) (*viper.Viper, error) { + v := viper.New() + v.SetConfigType("yaml") + if err := v.ReadConfig(bytes.NewBuffer(yamlBlob)); err != nil { + return nil, err + } + return v, nil +}