From b3d61dbd6252d1ec58f1cd6cebfa6bc672f1e816 Mon Sep 17 00:00:00 2001 From: Annie Fu <16651409+anniefu@users.noreply.github.com> Date: Tue, 21 Jan 2020 15:24:19 -0800 Subject: [PATCH] Ensure exporter respects ResourceDetector option (#80) * Ensure exporter respects ResourceDetector option * Add test for Trace ResourceDetector --- go.mod | 2 ++ mock_agent_test.go | 13 ++++++- ocagent.go | 6 ++-- ocagent_test.go | 69 ++++++++++++++++++++++++++++++++++--- resource_detector_test.go | 15 ++++---- viewdata_to_metrics_test.go | 40 +++++++++++++++++---- 6 files changed, 124 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index b40fc0c..ffa8ee6 100644 --- a/go.mod +++ b/go.mod @@ -12,3 +12,5 @@ require ( google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610 // indirect google.golang.org/grpc v1.22.0 ) + +go 1.13 diff --git a/mock_agent_test.go b/mock_agent_test.go index 3525199..9101557 100644 --- a/mock_agent_test.go +++ b/mock_agent_test.go @@ -1,4 +1,4 @@ -// Copyright 2018, OpenCensus Authors +// Copyright 2020, OpenCensus Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import ( commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" agenttracepb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/trace/v1" + resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1" tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" ) @@ -42,6 +43,8 @@ type mockAgent struct { traceNodes []*commonpb.Node receivedConfigs []*agenttracepb.CurrentLibraryConfig + resource *resourcepb.Resource + configsToSend chan *agenttracepb.UpdatedLibraryConfig closeConfigsToSendOnce sync.Once @@ -125,6 +128,7 @@ func (ma *mockAgent) Export(tses agenttracepb.TraceService_ExportServer) error { return err } ma.mu.Lock() + ma.resource = req.Resource ma.spans = append(ma.spans, req.Spans...) ma.traceNodes = append(ma.traceNodes, req.Node) ma.mu.Unlock() @@ -214,3 +218,10 @@ func (ma *mockAgent) getTraceNodes() []*commonpb.Node { return traceNodes } + +func (ma *mockAgent) getResource() *resourcepb.Resource { + ma.mu.Lock() + resource := ma.resource + ma.mu.Unlock() + return resource +} diff --git a/ocagent.go b/ocagent.go index 24f4107..144e937 100644 --- a/ocagent.go +++ b/ocagent.go @@ -1,4 +1,4 @@ -// Copyright 2018, OpenCensus Authors +// Copyright 2020, OpenCensus Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -504,7 +504,7 @@ func (ae *Exporter) uploadTraces(sdl []*trace.SpanData) { ae.senderMu.Lock() err := ae.traceExporter.Send(&agenttracepb.ExportTraceServiceRequest{ Spans: protoSpans, - Resource: resourceProtoFromEnv(), + Resource: ae.resource, }) ae.senderMu.Unlock() if err != nil { @@ -537,7 +537,7 @@ func (ae *Exporter) uploadViewData(vdl []*view.Data) { } req := &agentmetricspb.ExportMetricsServiceRequest{ Metrics: protoMetrics, - Resource: resourceProtoFromEnv(), + Resource: ae.resource, // TODO:(@odeke-em) // a) Figure out how to derive a Node from the environment // or better letting users of the exporter configure it. diff --git a/ocagent_test.go b/ocagent_test.go index fd32f2f..81b4e85 100644 --- a/ocagent_test.go +++ b/ocagent_test.go @@ -1,4 +1,4 @@ -// Copyright 2018, OpenCensus Authors +// Copyright 2020, OpenCensus Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import ( "fmt" "net" "os" + "reflect" "strings" "testing" "time" @@ -26,20 +27,68 @@ import ( "contrib.go.opencensus.io/exporter/ocagent" commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" agenttracepb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/trace/v1" + resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1" tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "go.opencensus.io" + + opencensus "go.opencensus.io" + "go.opencensus.io/resource" "go.opencensus.io/trace" ) func TestNewExporter_endToEnd(t *testing.T) { + // Set up a custom resource for testing WithResourceDetector ExporterOption + cr := &resource.Resource{ + Type: "foo", + Labels: map[string]string{ + "test": "label", + }, + } + + crd := func(context.Context) (*resource.Resource, error) { + return cr, nil + } + + tests := []struct { + name string + additionalOpts []ocagent.ExporterOption + expectedResource *resource.Resource + }{ + { + name: "StandardExporter", + expectedResource: &resource.Resource{ + Type: "", + Labels: nil, + }, + }, { + name: "WithResourceDetector", + additionalOpts: []ocagent.ExporterOption{ + ocagent.WithResourceDetector(crd), + }, + expectedResource: cr, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + newExporterEndToEndTest(t, test.additionalOpts, test.expectedResource) + }) + } +} + +func newExporterEndToEndTest(t *testing.T, additionalOpts []ocagent.ExporterOption, expRes *resource.Resource) { ma := runMockAgent(t) defer ma.stop() serviceName := "endToEnd_test" - exp, err := ocagent.NewExporter(ocagent.WithInsecure(), + opts := []ocagent.ExporterOption{ + ocagent.WithInsecure(), ocagent.WithAddress(ma.address), - ocagent.WithReconnectionPeriod(50*time.Millisecond), - ocagent.WithServiceName(serviceName)) + ocagent.WithReconnectionPeriod(50 * time.Millisecond), + ocagent.WithServiceName(serviceName), + } + + opts = append(opts, additionalOpts...) + exp, err := ocagent.NewExporter(opts...) if err != nil { t.Fatalf("Failed to create a new agent exporter: %v", err) } @@ -167,6 +216,7 @@ func TestNewExporter_endToEnd(t *testing.T) { spans := ma.getSpans() traceNodes := ma.getTraceNodes() receivedConfigs := ma.getReceivedConfigs() + resource := ma.getResource() if g, w := len(receivedConfigs), 5; g != w { t.Errorf("ReceivedConfigs: got %d want %d", g, w) @@ -223,6 +273,15 @@ func TestNewExporter_endToEnd(t *testing.T) { t.Errorf("%q: ServiceInfo mismatch\nGot %#v\nWant %#v", tt.name, g, w) } } + + wantResource := &resourcepb.Resource{ + Type: expRes.Type, + Labels: expRes.Labels, + } + + if !reflect.DeepEqual(resource, wantResource) { + t.Errorf("Resource mismatch\nGot %#v\nWant %#v", resource, wantResource) + } } func TestNewExporter_invokeStartThenStopManyTimes(t *testing.T) { diff --git a/resource_detector_test.go b/resource_detector_test.go index eef86ce..eb9d251 100644 --- a/resource_detector_test.go +++ b/resource_detector_test.go @@ -1,4 +1,4 @@ -// Copyright 2019, OpenCensus Authors +// Copyright 2020, OpenCensus Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,6 +24,13 @@ import ( resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1" ) +var ( + customResource = &resource.Resource{ + Type: "foo", + Labels: map[string]string{}, + } +) + func TestResourceDetector(t *testing.T) { ocexp, err := NewExporter( WithInsecure(), @@ -46,9 +53,5 @@ func TestResourceDetector(t *testing.T) { } func customResourceDetector(context.Context) (*resource.Resource, error) { - res := &resource.Resource{ - Type: "foo", - Labels: map[string]string{}, - } - return res, nil + return customResource, nil } diff --git a/viewdata_to_metrics_test.go b/viewdata_to_metrics_test.go index e940ea5..32e5528 100644 --- a/viewdata_to_metrics_test.go +++ b/viewdata_to_metrics_test.go @@ -1,4 +1,4 @@ -// Copyright 2018, OpenCensus Authors +// Copyright 2020, OpenCensus Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import ( agentmetricspb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/metrics/v1" metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1" + resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1" ) type metricsAgent struct { @@ -39,6 +40,31 @@ type metricsAgent struct { } func TestExportMetrics_conversionFromViewData(t *testing.T) { + tests := []struct { + name string + additionalOpts []ExporterOption + expectedResource *resourcepb.Resource + }{ + { + name: "StandardExporter", + expectedResource: resourceProtoFromEnv(), + }, { + name: "WithResourceDetector", + additionalOpts: []ExporterOption{ + WithResourceDetector(customResourceDetector), + }, + expectedResource: resourceToResourcePb(customResource), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + testConversionFromViewData(t, test.additionalOpts, test.expectedResource) + }) + } +} + +func testConversionFromViewData(t *testing.T, additionalOpts []ExporterOption, expRes *resourcepb.Resource) { ln, err := net.Listen("tcp", ":0") if err != nil { t.Fatalf("Failed to get an available TCP address: %v", err) @@ -55,11 +81,13 @@ func TestExportMetrics_conversionFromViewData(t *testing.T) { }() reconnectionPeriod := 2 * time.Millisecond - ocexp, err := NewExporter( + opts := []ExporterOption{ WithInsecure(), - WithAddress(":"+agentPortStr), + WithAddress(":" + agentPortStr), WithReconnectionPeriod(reconnectionPeriod), - ) + } + opts = append(opts, additionalOpts...) + ocexp, err := NewExporter(opts...) if err != nil { t.Fatalf("Failed to create the ocagent exporter: %v", err) } @@ -103,7 +131,7 @@ func TestExportMetrics_conversionFromViewData(t *testing.T) { { Node: NodeWithStartTime(""), // The first message identifying this application. Metrics: nil, - Resource: resourceProtoFromEnv(), + Resource: expRes, }, { Metrics: []*metricspb.Metric{ @@ -135,7 +163,7 @@ func TestExportMetrics_conversionFromViewData(t *testing.T) { }, }, }, - Resource: resourceProtoFromEnv(), + Resource: expRes, }, }