From ffa94ca529e91c7ce53c9e5eb7328efba89b8ae4 Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Tue, 11 Oct 2022 11:50:09 -0400 Subject: [PATCH] Improve test coverage, and don't send empty batches in OC bridge (#3263) * improve test coverage, and don't send empty batches in OC bridge * Update bridge/opencensus/metric_test.go Co-authored-by: Tyler Yahn * remove 1.18 rule Co-authored-by: Tyler Yahn --- CHANGELOG.md | 1 + bridge/opencensus/go.mod | 6 ++ bridge/opencensus/go.sum | 11 ++- bridge/opencensus/metric.go | 12 ++- bridge/opencensus/metric_test.go | 157 +++++++++++++++++++++++++++++++ bridge/opencensus/test/go.sum | 2 +- example/opencensus/go.sum | 2 +- 7 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 bridge/opencensus/metric_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a68c5a3e2..1fd689d606f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Fixed - Use default view if instrument does not match any registered view of a reader. (#3224, #3237) +- The OpenCensus bridge no longer sends empty batches of metrics. (#3263) ## [0.32.1] Metric SDK (Alpha) - 2022-09-22 diff --git a/bridge/opencensus/go.mod b/bridge/opencensus/go.mod index 4db9c67cbb8..edc9c9066ae 100644 --- a/bridge/opencensus/go.mod +++ b/bridge/opencensus/go.mod @@ -3,6 +3,7 @@ module go.opentelemetry.io/otel/bridge/opencensus go 1.18 require ( + github.com/stretchr/testify v1.7.1 go.opencensus.io v0.23.0 go.opentelemetry.io/otel v1.10.0 go.opentelemetry.io/otel/metric v0.32.1 @@ -12,10 +13,15 @@ require ( ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/kr/pretty v0.1.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) replace go.opentelemetry.io/otel => ../.. diff --git a/bridge/opencensus/go.sum b/bridge/opencensus/go.sum index 1eac8058cc6..6e7bfe06fbf 100644 --- a/bridge/opencensus/go.sum +++ b/bridge/opencensus/go.sum @@ -3,8 +3,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -35,12 +36,18 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -93,6 +100,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/bridge/opencensus/metric.go b/bridge/opencensus/metric.go index 82965b1af5b..df22c874ab8 100644 --- a/bridge/opencensus/metric.go +++ b/bridge/opencensus/metric.go @@ -23,6 +23,7 @@ import ( ocmetricdata "go.opencensus.io/metric/metricdata" "go.opencensus.io/metric/metricexport" + "go.opentelemetry.io/otel" internal "go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric" "go.opentelemetry.io/otel/sdk/instrumentation" "go.opentelemetry.io/otel/sdk/metric" @@ -30,6 +31,8 @@ import ( "go.opentelemetry.io/otel/sdk/resource" ) +const scopeName = "go.opentelemetry.io/otel/bridge/opencensus" + // exporter implements the OpenCensus metric Exporter interface using an // OpenTelemetry base exporter. type exporter struct { @@ -38,7 +41,7 @@ type exporter struct { } // NewMetricExporter returns an OpenCensus exporter that exports to an -// OpenTelemetry exporter. +// OpenTelemetry (push) exporter. func NewMetricExporter(base metric.Exporter, res *resource.Resource) metricexport.Exporter { return &exporter{base: base, res: res} } @@ -48,14 +51,17 @@ func NewMetricExporter(base metric.Exporter, res *resource.Resource) metricexpor func (e *exporter) ExportMetrics(ctx context.Context, ocmetrics []*ocmetricdata.Metric) error { otelmetrics, err := internal.ConvertMetrics(ocmetrics) if err != nil { - return err + otel.Handle(err) + } + if len(otelmetrics) == 0 { + return nil } return e.base.Export(ctx, metricdata.ResourceMetrics{ Resource: e.res, ScopeMetrics: []metricdata.ScopeMetrics{ { Scope: instrumentation.Scope{ - Name: "go.opentelemetry.io/otel/bridge/opencensus", + Name: scopeName, }, Metrics: otelmetrics, }, diff --git a/bridge/opencensus/metric_test.go b/bridge/opencensus/metric_test.go new file mode 100644 index 00000000000..57350668362 --- /dev/null +++ b/bridge/opencensus/metric_test.go @@ -0,0 +1,157 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus" + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + ocmetricdata "go.opencensus.io/metric/metricdata" + ocresource "go.opencensus.io/resource" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/instrumentation" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + "go.opentelemetry.io/otel/sdk/resource" +) + +func TestPushMetricsExporter(t *testing.T) { + now := time.Now() + for _, tc := range []struct { + desc string + input []*ocmetricdata.Metric + inputResource *resource.Resource + exportErr error + expected *metricdata.ResourceMetrics + expectErr bool + }{ + { + desc: "empty batch isn't sent", + }, + { + desc: "export error", + exportErr: fmt.Errorf("failed to export"), + input: []*ocmetricdata.Metric{ + { + Resource: &ocresource.Resource{ + Labels: map[string]string{ + "R1": "V1", + "R2": "V2", + }, + }, + TimeSeries: []*ocmetricdata.TimeSeries{ + { + StartTime: now, + Points: []ocmetricdata.Point{ + {Value: int64(123), Time: now}, + }, + }, + }, + }, + }, + expectErr: true, + }, + { + desc: "success", + input: []*ocmetricdata.Metric{ + { + Resource: &ocresource.Resource{ + Labels: map[string]string{ + "R1": "V1", + "R2": "V2", + }, + }, + TimeSeries: []*ocmetricdata.TimeSeries{ + { + StartTime: now, + Points: []ocmetricdata.Point{ + {Value: int64(123), Time: now}, + }, + }, + }, + }, + }, + inputResource: resource.NewSchemaless( + attribute.String("R1", "V1"), + attribute.String("R2", "V2"), + ), + expected: &metricdata.ResourceMetrics{ + Resource: resource.NewSchemaless( + attribute.String("R1", "V1"), + attribute.String("R2", "V2"), + ), + ScopeMetrics: []metricdata.ScopeMetrics{ + { + Scope: instrumentation.Scope{ + Name: scopeName, + }, + Metrics: []metricdata.Metrics{ + { + Name: "", + Description: "", + Unit: "", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet(), + StartTime: now, + Time: now, + Value: 123, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + fake := &fakeExporter{err: tc.exportErr} + exporter := NewMetricExporter(fake, tc.inputResource) + err := exporter.ExportMetrics(context.Background(), tc.input) + if tc.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + if tc.expected != nil { + require.NotNil(t, fake.data) + metricdatatest.AssertEqual(t, *tc.expected, *fake.data) + } else { + require.Nil(t, fake.data) + } + }) + } +} + +type fakeExporter struct { + metric.Exporter + data *metricdata.ResourceMetrics + err error +} + +func (f *fakeExporter) Export(ctx context.Context, data metricdata.ResourceMetrics) error { + if f.err == nil { + f.data = &data + } + return f.err +} diff --git a/bridge/opencensus/test/go.sum b/bridge/opencensus/test/go.sum index 1eac8058cc6..d06593c620d 100644 --- a/bridge/opencensus/test/go.sum +++ b/bridge/opencensus/test/go.sum @@ -3,8 +3,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= diff --git a/example/opencensus/go.sum b/example/opencensus/go.sum index 1eac8058cc6..d06593c620d 100644 --- a/example/opencensus/go.sum +++ b/example/opencensus/go.sum @@ -3,8 +3,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=