diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e1ae982eb5c..556c5ad0309 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,24 +19,6 @@ updates: schedule: interval: weekly day: sunday - - package-ecosystem: gomod - directory: /bridge/opencensus - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /bridge/opencensus/test - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - package-ecosystem: gomod directory: /bridge/opentracing labels: @@ -73,15 +55,6 @@ updates: schedule: interval: weekly day: sunday - - package-ecosystem: gomod - directory: /example/opencensus - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - package-ecosystem: gomod directory: /example/otel-collector labels: @@ -100,15 +73,6 @@ updates: schedule: interval: weekly day: sunday - - package-ecosystem: gomod - directory: /example/prometheus - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - package-ecosystem: gomod directory: /example/zipkin labels: @@ -136,33 +100,6 @@ updates: schedule: interval: weekly day: sunday - - package-ecosystem: gomod - directory: /exporters/otlp/otlpmetric - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /exporters/otlp/otlpmetric/otlpmetricgrpc - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /exporters/otlp/otlpmetric/otlpmetrichttp - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - package-ecosystem: gomod directory: /exporters/otlp/otlptrace labels: @@ -190,24 +127,6 @@ updates: schedule: interval: weekly day: sunday - - package-ecosystem: gomod - directory: /exporters/prometheus - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - - package-ecosystem: gomod - directory: /exporters/stdout/stdoutmetric - labels: - - dependencies - - go - - Skip Changelog - schedule: - interval: weekly - day: sunday - package-ecosystem: gomod directory: /exporters/stdout/stdouttrace labels: diff --git a/bridge/opencensus/README.md b/bridge/opencensus/README.md deleted file mode 100644 index 07dc57380b3..00000000000 --- a/bridge/opencensus/README.md +++ /dev/null @@ -1,128 +0,0 @@ -# OpenCensus Bridge - -The OpenCensus Bridge helps facilitate the migration of an application from OpenCensus to OpenTelemetry. - -## Caveat about OpenCensus - -Installing a metric or tracing bridge will cause OpenCensus telemetry to be exported by OpenTelemetry exporters. Since OpenCensus telemetry uses globals, installing a bridge will result in telemetry collection from _all_ libraries that use OpenCensus, including some you may not expect. For example ([#1928](https://github.com/open-telemetry/opentelemetry-go/issues/1928)), if a client library generates traces with OpenCensus, installing the bridge will cause those traces to be exported by OpenTelemetry. - -## Tracing - -### The Problem: Mixing OpenCensus and OpenTelemetry libraries - -In a perfect world, one would simply migrate their entire go application --including custom instrumentation, libraries, and exporters-- from OpenCensus to OpenTelemetry all at once. In the real world, dependency constraints, third-party ownership of libraries, or other reasons may require mixing OpenCensus and OpenTelemetry libraries in a single application. - -However, if you create the following spans in a go application: - -```go -ctx, ocSpan := opencensus.StartSpan(context.Background(), "OuterSpan") -defer ocSpan.End() -ctx, otSpan := opentelemetryTracer.Start(ctx, "MiddleSpan") -defer otSpan.End() -ctx, ocSpan := opencensus.StartSpan(ctx, "InnerSpan") -defer ocSpan.End() -``` - -OpenCensus reports (to OpenCensus exporters): - -``` -[--------OuterSpan------------] - [----InnerSpan------] -``` - -OpenTelemetry reports (to OpenTelemetry exporters): - -``` - [-----MiddleSpan--------] -``` - -Instead, I would prefer (to a single set of exporters): - -``` -[--------OuterSpan------------] - [-----MiddleSpan--------] - [----InnerSpan------] -``` - -### The bridge solution - -The bridge implements the OpenCensus trace API using OpenTelemetry. This would cause, for example, a span recorded with OpenCensus' `StartSpan()` method to be equivalent to recording a span using OpenTelemetry's `tracer.Start()` method. Funneling all tracing API calls to OpenTelemetry APIs results in the desired unified span hierarchy. - -### User Journey - -Starting from an application using entirely OpenCensus APIs: - -1. Instantiate OpenTelemetry SDK and Exporters -2. Override OpenCensus' DefaultTracer with the bridge -3. Migrate libraries individually from OpenCensus to OpenTelemetry -4. Remove OpenCensus exporters and configuration - -To override OpenCensus' DefaultTracer with the bridge: - -```go -import ( - octrace "go.opencensus.io/trace" - "go.opentelemetry.io/otel/bridge/opencensus" - "go.opentelemetry.io/otel" -) - -tracer := otel.GetTracerProvider().Tracer("bridge") -octrace.DefaultTracer = opencensus.NewTracer(tracer) -``` - -Be sure to set the `Tracer` name to your instrumentation package name instead of `"bridge"`. - -#### Incompatibilities - -OpenCensus and OpenTelemetry APIs are not entirely compatible. If the bridge finds any incompatibilities, it will log them. Incompatibilities include: - -* Custom OpenCensus Samplers specified during StartSpan are ignored. -* Links cannot be added to OpenCensus spans. -* OpenTelemetry Debug or Deferred trace flags are dropped after an OpenCensus span is created. - -## Metrics - -### The problem: mixing libraries without mixing pipelines - -The problem for monitoring is simpler than the problem for tracing, since there -are no context propagation issues to deal with. However, it still is difficult -for users to migrate an entire applications' monitoring at once. It -should be possible to send metrics generated by OpenCensus libraries to an -OpenTelemetry pipeline so that migrating a metric does not require maintaining -separate export pipelines for OpenCensus and OpenTelemetry. - -### The Exporter "wrapper" solution - -The solution we use here is to allow wrapping an OpenTelemetry exporter such -that it implements the OpenCensus exporter interfaces. This allows a single -exporter to be used for metrics from *both* OpenCensus and OpenTelemetry. - -### User Journey - -Starting from an application using entirely OpenCensus APIs: - -1. Instantiate OpenTelemetry SDK and Exporters. -2. Replace OpenCensus exporters with a wrapped OpenTelemetry exporter from step 1. -3. Migrate libraries individually from OpenCensus to OpenTelemetry -4. Remove OpenCensus Exporters and configuration. - -For example, to swap out the OpenCensus logging exporter for the OpenTelemetry stdout exporter: - -```go -import ( - "go.opencensus.io/metric/metricexport" - "go.opentelemetry.io/otel/bridge/opencensus" - "go.opentelemetry.io/otel/exporters/stdout" - "go.opentelemetry.io/otel" -) -// With OpenCensus, you could have previously configured the logging exporter like this: -// import logexporter "go.opencensus.io/examples/exporter" -// exporter, _ := logexporter.NewLogExporter(logexporter.Options{}) -// Instead, we can create an equivalent using the OpenTelemetry stdout exporter: -openTelemetryExporter, _ := stdout.New(stdout.WithPrettyPrint()) -exporter := opencensus.NewMetricExporter(openTelemetryExporter) - -// Use the wrapped OpenTelemetry exporter like you normally would with OpenCensus -intervalReader, _ := metricexport.NewIntervalReader(&metricexport.Reader{}, exporter) -intervalReader.Start() -``` diff --git a/bridge/opencensus/aggregation.go b/bridge/opencensus/aggregation.go deleted file mode 100644 index 99d2b07afad..00000000000 --- a/bridge/opencensus/aggregation.go +++ /dev/null @@ -1,157 +0,0 @@ -// 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 ( - "errors" - "fmt" - "time" - - "go.opencensus.io/metric/metricdata" - - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" -) - -var ( - errIncompatibleType = errors.New("incompatible type for aggregation") - errEmpty = errors.New("points may not be empty") - errBadPoint = errors.New("point cannot be converted") -) - -type recordFunc func(agg aggregation.Aggregation, end time.Time) error - -// recordAggregationsFromPoints records one OpenTelemetry aggregation for -// each OpenCensus point. Points may not be empty and must be either -// all (int|float)64 or all *metricdata.Distribution. -func recordAggregationsFromPoints(points []metricdata.Point, recorder recordFunc) error { - if len(points) == 0 { - return errEmpty - } - switch t := points[0].Value.(type) { - case int64: - return recordGaugePoints(points, recorder) - case float64: - return recordGaugePoints(points, recorder) - case *metricdata.Distribution: - return recordDistributionPoint(points, recorder) - default: - // TODO add *metricdata.Summary support - return fmt.Errorf("%w: %v", errIncompatibleType, t) - } -} - -var _ aggregation.Aggregation = &ocRawAggregator{} -var _ aggregation.LastValue = &ocRawAggregator{} - -// recordGaugePoints creates an OpenTelemetry aggregation from OpenCensus points. -// Points may not be empty, and must only contain integers or floats. -func recordGaugePoints(pts []metricdata.Point, recorder recordFunc) error { - for _, pt := range pts { - switch t := pt.Value.(type) { - case int64: - if err := recorder(&ocRawAggregator{ - value: number.NewInt64Number(pt.Value.(int64)), - time: pt.Time, - }, pt.Time); err != nil { - return err - } - case float64: - if err := recorder(&ocRawAggregator{ - value: number.NewFloat64Number(pt.Value.(float64)), - time: pt.Time, - }, pt.Time); err != nil { - return err - } - default: - return fmt.Errorf("%w: %v", errIncompatibleType, t) - } - } - return nil -} - -type ocRawAggregator struct { - value number.Number - time time.Time -} - -// Kind returns the kind of aggregation this is. -func (o *ocRawAggregator) Kind() aggregation.Kind { - return aggregation.LastValueKind -} - -// LastValue returns the last point. -func (o *ocRawAggregator) LastValue() (number.Number, time.Time, error) { - return o.value, o.time, nil -} - -var _ aggregation.Aggregation = &ocDistAggregator{} -var _ aggregation.Histogram = &ocDistAggregator{} - -// recordDistributionPoint creates an OpenTelemetry aggregation from -// OpenCensus points. Points may not be empty, and must only contain -// Distributions. The most recent disribution will be used in the aggregation. -func recordDistributionPoint(pts []metricdata.Point, recorder recordFunc) error { - // only use the most recent datapoint for now. - pt := pts[len(pts)-1] - val, ok := pt.Value.(*metricdata.Distribution) - if !ok { - return fmt.Errorf("%w: %v", errBadPoint, pt.Value) - } - bucketCounts := make([]uint64, len(val.Buckets)) - for i, bucket := range val.Buckets { - if bucket.Count < 0 { - return fmt.Errorf("%w: bucket count may not be negative", errBadPoint) - } - bucketCounts[i] = uint64(bucket.Count) - } - if val.Count < 0 { - return fmt.Errorf("%w: count may not be negative", errBadPoint) - } - return recorder(&ocDistAggregator{ - sum: number.NewFloat64Number(val.Sum), - count: uint64(val.Count), - buckets: aggregation.Buckets{ - Boundaries: val.BucketOptions.Bounds, - Counts: bucketCounts, - }, - }, pts[len(pts)-1].Time) -} - -type ocDistAggregator struct { - sum number.Number - count uint64 - buckets aggregation.Buckets -} - -// Kind returns the kind of aggregation this is. -func (o *ocDistAggregator) Kind() aggregation.Kind { - return aggregation.HistogramKind -} - -// Sum returns the sum of values. -func (o *ocDistAggregator) Sum() (number.Number, error) { - return o.sum, nil -} - -// Count returns the number of values. -func (o *ocDistAggregator) Count() (uint64, error) { - return o.count, nil -} - -// Histogram returns the count of events in pre-determined buckets. -func (o *ocDistAggregator) Histogram() (aggregation.Buckets, error) { - return o.buckets, nil -} diff --git a/bridge/opencensus/aggregation_test.go b/bridge/opencensus/aggregation_test.go deleted file mode 100644 index 13093c67336..00000000000 --- a/bridge/opencensus/aggregation_test.go +++ /dev/null @@ -1,322 +0,0 @@ -// 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 ( - "errors" - "testing" - "time" - - "go.opencensus.io/metric/metricdata" - - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" -) - -func TestNewAggregationFromPoints(t *testing.T) { - now := time.Now() - for _, tc := range []struct { - desc string - input []metricdata.Point - expectedKind aggregation.Kind - expectedErr error - }{ - { - desc: "no points", - expectedErr: errEmpty, - }, - { - desc: "int point", - input: []metricdata.Point{ - { - Time: now, - Value: int64(23), - }, - }, - expectedKind: aggregation.LastValueKind, - }, - { - desc: "float point", - input: []metricdata.Point{ - { - Time: now, - Value: float64(23), - }, - }, - expectedKind: aggregation.LastValueKind, - }, - { - desc: "distribution point", - input: []metricdata.Point{ - { - Time: now, - Value: &metricdata.Distribution{ - Count: 2, - Sum: 55, - BucketOptions: &metricdata.BucketOptions{ - Bounds: []float64{20, 30}, - }, - Buckets: []metricdata.Bucket{ - {Count: 1}, - {Count: 1}, - }, - }, - }, - }, - expectedKind: aggregation.HistogramKind, - }, - { - desc: "bad distribution bucket count", - input: []metricdata.Point{ - { - Time: now, - Value: &metricdata.Distribution{ - Count: 2, - Sum: 55, - BucketOptions: &metricdata.BucketOptions{ - Bounds: []float64{20, 30}, - }, - Buckets: []metricdata.Bucket{ - // negative bucket - {Count: -1}, - {Count: 1}, - }, - }, - }, - }, - expectedErr: errBadPoint, - }, - { - desc: "bad distribution count", - input: []metricdata.Point{ - { - Time: now, - Value: &metricdata.Distribution{ - // negative count - Count: -2, - Sum: 55, - BucketOptions: &metricdata.BucketOptions{ - Bounds: []float64{20, 30}, - }, - Buckets: []metricdata.Bucket{ - {Count: 1}, - {Count: 1}, - }, - }, - }, - }, - expectedErr: errBadPoint, - }, - { - desc: "incompatible point type bool", - input: []metricdata.Point{ - { - Time: now, - Value: true, - }, - }, - expectedErr: errIncompatibleType, - }, - { - desc: "dist is incompatible with raw points", - input: []metricdata.Point{ - { - Time: now, - Value: int64(23), - }, - { - Time: now, - Value: &metricdata.Distribution{ - Count: 2, - Sum: 55, - BucketOptions: &metricdata.BucketOptions{ - Bounds: []float64{20, 30}, - }, - Buckets: []metricdata.Bucket{ - {Count: 1}, - {Count: 1}, - }, - }, - }, - }, - expectedErr: errIncompatibleType, - }, - { - desc: "int point is incompatible with dist", - input: []metricdata.Point{ - { - Time: now, - Value: &metricdata.Distribution{ - Count: 2, - Sum: 55, - BucketOptions: &metricdata.BucketOptions{ - Bounds: []float64{20, 30}, - }, - Buckets: []metricdata.Bucket{ - {Count: 1}, - {Count: 1}, - }, - }, - }, - { - Time: now, - Value: int64(23), - }, - }, - expectedErr: errBadPoint, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - var output []aggregation.Aggregation - err := recordAggregationsFromPoints(tc.input, func(agg aggregation.Aggregation, ts time.Time) error { - last := tc.input[len(tc.input)-1] - if ts != last.Time { - t.Errorf("incorrect timestamp %v != %v", ts, last.Time) - } - output = append(output, agg) - return nil - }) - if !errors.Is(err, tc.expectedErr) { - t.Errorf("newAggregationFromPoints(%v) = err(%v), want err(%v)", tc.input, err, tc.expectedErr) - } - for _, out := range output { - if tc.expectedErr == nil && out.Kind() != tc.expectedKind { - t.Errorf("newAggregationFromPoints(%v) = %v, want %v", tc.input, out.Kind(), tc.expectedKind) - } - } - }) - } -} - -func TestLastValueAggregation(t *testing.T) { - now := time.Now() - input := []metricdata.Point{ - {Value: int64(15), Time: now.Add(-time.Minute)}, - {Value: int64(-23), Time: now}, - } - idx := 0 - err := recordAggregationsFromPoints(input, func(agg aggregation.Aggregation, end time.Time) error { - if agg.Kind() != aggregation.LastValueKind { - t.Errorf("recordAggregationsFromPoints(%v) = %v, want %v", input, agg.Kind(), aggregation.LastValueKind) - } - if end != input[idx].Time { - t.Errorf("recordAggregationsFromPoints(%v).end() = %v, want %v", input, end, input[idx].Time) - } - pointsLV, ok := agg.(aggregation.LastValue) - if !ok { - t.Errorf("recordAggregationsFromPoints(%v) = %v does not implement the aggregation.LastValue interface", input, agg) - } - lv, ts, _ := pointsLV.LastValue() - if lv.AsInt64() != input[idx].Value { - t.Errorf("recordAggregationsFromPoints(%v) = %v, want %v", input, lv.AsInt64(), input[idx].Value) - } - if ts != input[idx].Time { - t.Errorf("recordAggregationsFromPoints(%v) = %v, want %v", input, ts, input[idx].Time) - } - idx++ - return nil - }) - if err != nil { - t.Errorf("recordAggregationsFromPoints(%v) = unexpected error %v", input, err) - } -} - -func TestHistogramAggregation(t *testing.T) { - now := time.Now() - input := []metricdata.Point{ - { - Value: &metricdata.Distribution{ - Count: 0, - Sum: 0, - BucketOptions: &metricdata.BucketOptions{ - Bounds: []float64{20, 30}, - }, - Buckets: []metricdata.Bucket{ - {Count: 0}, - {Count: 0}, - }, - }, - }, - { - Time: now, - Value: &metricdata.Distribution{ - Count: 2, - Sum: 55, - BucketOptions: &metricdata.BucketOptions{ - Bounds: []float64{20, 30}, - }, - Buckets: []metricdata.Bucket{ - {Count: 1}, - {Count: 1}, - }, - }, - }, - } - var output aggregation.Aggregation - var end time.Time - err := recordAggregationsFromPoints(input, func(argAgg aggregation.Aggregation, argEnd time.Time) error { - output = argAgg - end = argEnd - return nil - }) - if err != nil { - t.Fatalf("recordAggregationsFromPoints(%v) = err(%v), want ", input, err) - } - if output.Kind() != aggregation.HistogramKind { - t.Errorf("recordAggregationsFromPoints(%v) = %v, want %v", input, output.Kind(), aggregation.HistogramKind) - } - if end != now { - t.Errorf("recordAggregationsFromPoints(%v).end() = %v, want %v", input, end, now) - } - distAgg, ok := output.(aggregation.Histogram) - if !ok { - t.Errorf("recordAggregationsFromPoints(%v) = %v does not implement the aggregation.Points interface", input, output) - } - sum, err := distAgg.Sum() - if err != nil { - t.Fatalf("Unexpected err: %v", err) - } - if sum.AsFloat64() != float64(55) { - t.Errorf("recordAggregationsFromPoints(%v).Sum() = %v, want %v", input, sum.AsFloat64(), float64(55)) - } - count, err := distAgg.Count() - if err != nil { - t.Fatalf("Unexpected err: %v", err) - } - if count != 2 { - t.Errorf("recordAggregationsFromPoints(%v).Count() = %v, want %v", input, count, 2) - } - hist, err := distAgg.Histogram() - if err != nil { - t.Fatalf("Unexpected err: %v", err) - } - inputBucketBoundaries := []float64{20, 30} - if len(hist.Boundaries) != len(inputBucketBoundaries) { - t.Fatalf("recordAggregationsFromPoints(%v).Histogram() produced %d boundaries, want %d boundaries", input, len(hist.Boundaries), len(inputBucketBoundaries)) - } - for i, b := range hist.Boundaries { - if b != inputBucketBoundaries[i] { - t.Errorf("recordAggregationsFromPoints(%v).Histogram().Boundaries[%d] = %v, want %v", input, i, b, inputBucketBoundaries[i]) - } - } - inputBucketCounts := []uint64{1, 1} - if len(hist.Counts) != len(inputBucketCounts) { - t.Fatalf("recordAggregationsFromPoints(%v).Histogram() produced %d buckets, want %d buckets", input, len(hist.Counts), len(inputBucketCounts)) - } - for i, c := range hist.Counts { - if c != inputBucketCounts[i] { - t.Errorf("recordAggregationsFromPoints(%v).Histogram().Counts[%d] = %d, want %d", input, i, c, inputBucketCounts[i]) - } - } -} diff --git a/bridge/opencensus/bridge.go b/bridge/opencensus/bridge.go deleted file mode 100644 index 7e6f31202d6..00000000000 --- a/bridge/opencensus/bridge.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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 ( - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/bridge/opencensus/internal" - "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" - "go.opentelemetry.io/otel/trace" -) - -// NewTracer returns an implementation of the OpenCensus Tracer interface which -// uses OpenTelemetry APIs. Using this implementation of Tracer "upgrades" -// libraries that use OpenCensus to OpenTelemetry to facilitate a migration. -func NewTracer(tracer trace.Tracer) octrace.Tracer { - return internal.NewTracer(tracer) -} - -// OTelSpanContextToOC converts from an OpenTelemetry SpanContext to an -// OpenCensus SpanContext, and handles any incompatibilities with the global -// error handler. -func OTelSpanContextToOC(sc trace.SpanContext) octrace.SpanContext { - return otel2oc.SpanContext(sc) -} - -// OCSpanContextToOTel converts from an OpenCensus SpanContext to an -// OpenTelemetry SpanContext. -func OCSpanContextToOTel(sc octrace.SpanContext) trace.SpanContext { - return oc2otel.SpanContext(sc) -} diff --git a/bridge/opencensus/doc.go b/bridge/opencensus/doc.go deleted file mode 100644 index 80d80da6f78..00000000000 --- a/bridge/opencensus/doc.go +++ /dev/null @@ -1,35 +0,0 @@ -// 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 provides a migration bridge from OpenCensus to -// OpenTelemetry. The NewTracer function should be used to create an -// OpenCensus Tracer from an OpenTelemetry Tracer. This Tracer can be use in -// place of any existing OpenCensus Tracer and will generate OpenTelemetry -// spans for traces. These spans will be exported by the OpenTelemetry -// TracerProvider the original OpenTelemetry Tracer came from. -// -// There are known limitations to this bridge: -// -// - The AddLink method for OpenCensus Spans is not compatible with the -// OpenTelemetry Span. No link can be added to an OpenTelemetry Span once it -// is started. Any calls to this method for the OpenCensus Span will result -// in an error being sent to the OpenTelemetry default ErrorHandler. -// -// - The NewContext method of the OpenCensus Tracer cannot embed an OpenCensus -// Span in a context unless that Span was created by that Tracer. -// -// - Conversion of custom OpenCensus Samplers to OpenTelemetry is not -// implemented. An error will be sent to the OpenTelemetry default -// ErrorHandler if this is attempted. -package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus" diff --git a/bridge/opencensus/exporter.go b/bridge/opencensus/exporter.go deleted file mode 100644 index d40ddc9d665..00000000000 --- a/bridge/opencensus/exporter.go +++ /dev/null @@ -1,186 +0,0 @@ -// 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" - "errors" - "fmt" - "sync" - "time" - - "go.opencensus.io/metric/metricdata" - "go.opencensus.io/metric/metricexport" - ocresource "go.opencensus.io/resource" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/metric/unit" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -var errConversion = errors.New("Unable to convert from OpenCensus to OpenTelemetry") - -// NewMetricExporter returns an OpenCensus exporter that exports to an -// OpenTelemetry exporter -func NewMetricExporter(base export.Exporter) metricexport.Exporter { - return &exporter{base: base} -} - -// exporter implements the OpenCensus metric Exporter interface using an -// OpenTelemetry base exporter. -type exporter struct { - base export.Exporter -} - -// ExportMetrics implements the OpenCensus metric Exporter interface -func (e *exporter) ExportMetrics(ctx context.Context, metrics []*metricdata.Metric) error { - res := resource.Empty() - if len(metrics) != 0 { - res = convertResource(metrics[0].Resource) - } - return e.base.Export(ctx, res, &censusLibraryReader{metrics: metrics}) -} - -type censusLibraryReader struct { - metrics []*metricdata.Metric -} - -func (r censusLibraryReader) ForEach(readerFunc func(instrumentation.Library, export.Reader) error) error { - return readerFunc(instrumentation.Library{ - Name: "OpenCensus Bridge", - }, &metricReader{metrics: r.metrics}) -} - -type metricReader struct { - // RWMutex implements locking for the `Reader` interface. - sync.RWMutex - metrics []*metricdata.Metric -} - -var _ export.Reader = &metricReader{} - -// ForEach iterates through the metrics data, synthesizing an -// export.Record with the appropriate aggregation for the exporter. -func (d *metricReader) ForEach(_ aggregation.TemporalitySelector, f func(export.Record) error) error { - for _, m := range d.metrics { - descriptor, err := convertDescriptor(m.Descriptor) - if err != nil { - otel.Handle(err) - continue - } - for _, ts := range m.TimeSeries { - if len(ts.Points) == 0 { - continue - } - ls, err := convertLabels(m.Descriptor.LabelKeys, ts.LabelValues) - if err != nil { - otel.Handle(err) - continue - } - err = recordAggregationsFromPoints( - ts.Points, - func(agg aggregation.Aggregation, end time.Time) error { - return f(export.NewRecord( - &descriptor, - &ls, - agg, - ts.StartTime, - end, - )) - }) - if err != nil && !errors.Is(err, aggregation.ErrNoData) { - return err - } - } - } - return nil -} - -// convertLabels converts from OpenCensus label keys and values to an -// OpenTelemetry label Set. -func convertLabels(keys []metricdata.LabelKey, values []metricdata.LabelValue) (attribute.Set, error) { - if len(keys) != len(values) { - return attribute.NewSet(), fmt.Errorf("%w different number of label keys (%d) and values (%d)", errConversion, len(keys), len(values)) - } - labels := []attribute.KeyValue{} - for i, lv := range values { - if !lv.Present { - continue - } - labels = append(labels, attribute.KeyValue{ - Key: attribute.Key(keys[i].Key), - Value: attribute.StringValue(lv.Value), - }) - } - return attribute.NewSet(labels...), nil -} - -// convertResource converts an OpenCensus Resource to an OpenTelemetry Resource -// Note: the ocresource.Resource Type field is not used. -func convertResource(res *ocresource.Resource) *resource.Resource { - labels := []attribute.KeyValue{} - if res == nil { - return nil - } - for k, v := range res.Labels { - labels = append(labels, attribute.KeyValue{Key: attribute.Key(k), Value: attribute.StringValue(v)}) - } - return resource.NewSchemaless(labels...) -} - -// convertDescriptor converts an OpenCensus Descriptor to an OpenTelemetry Descriptor -func convertDescriptor(ocDescriptor metricdata.Descriptor) (sdkapi.Descriptor, error) { - var ( - nkind number.Kind - ikind sdkapi.InstrumentKind - ) - switch ocDescriptor.Type { - case metricdata.TypeGaugeInt64: - nkind = number.Int64Kind - ikind = sdkapi.GaugeObserverInstrumentKind - case metricdata.TypeGaugeFloat64: - nkind = number.Float64Kind - ikind = sdkapi.GaugeObserverInstrumentKind - case metricdata.TypeCumulativeInt64: - nkind = number.Int64Kind - ikind = sdkapi.CounterObserverInstrumentKind - case metricdata.TypeCumulativeFloat64: - nkind = number.Float64Kind - ikind = sdkapi.CounterObserverInstrumentKind - default: - // Includes TypeGaugeDistribution, TypeCumulativeDistribution, TypeSummary - return sdkapi.Descriptor{}, fmt.Errorf("%w; descriptor type: %v", errConversion, ocDescriptor.Type) - } - opts := []instrument.Option{ - instrument.WithDescription(ocDescriptor.Description), - } - switch ocDescriptor.Unit { - case metricdata.UnitDimensionless: - opts = append(opts, instrument.WithUnit(unit.Dimensionless)) - case metricdata.UnitBytes: - opts = append(opts, instrument.WithUnit(unit.Bytes)) - case metricdata.UnitMilliseconds: - opts = append(opts, instrument.WithUnit(unit.Milliseconds)) - } - cfg := instrument.NewConfig(opts...) - return sdkapi.NewDescriptor(ocDescriptor.Name, ikind, nkind, cfg.Description(), cfg.Unit()), nil -} diff --git a/bridge/opencensus/exporter_test.go b/bridge/opencensus/exporter_test.go deleted file mode 100644 index 79e195c1f6c..00000000000 --- a/bridge/opencensus/exporter_test.go +++ /dev/null @@ -1,475 +0,0 @@ -// 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 ( - "context" - "errors" - "fmt" - "testing" - "time" - - "go.opencensus.io/metric/metricdata" - ocresource "go.opencensus.io/resource" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/metric/unit" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/controller/controllertest" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -type fakeExporter struct { - export.Exporter - records []export.Record - resource *resource.Resource - err error -} - -func (f *fakeExporter) Export(ctx context.Context, res *resource.Resource, ilr export.InstrumentationLibraryReader) error { - return controllertest.ReadAll(ilr, aggregation.StatelessTemporalitySelector(), - func(_ instrumentation.Library, record export.Record) error { - f.resource = res - f.records = append(f.records, record) - return f.err - }) -} - -type fakeErrorHandler struct { - err error -} - -func (f *fakeErrorHandler) Handle(err error) { - f.err = err -} - -func (f *fakeErrorHandler) matches(err error) error { - // make sure err is cleared for the next test - defer func() { f.err = nil }() - if !errors.Is(f.err, err) { - return fmt.Errorf("err(%v), want err(%v)", f.err, err) - } - return nil -} - -func TestExportMetrics(t *testing.T) { - now := time.Now() - basicDesc := metrictest.NewDescriptor( - "", - sdkapi.GaugeObserverInstrumentKind, - number.Int64Kind, - ) - fakeErrorHandler := &fakeErrorHandler{} - otel.SetErrorHandler(fakeErrorHandler) - for _, tc := range []struct { - desc string - input []*metricdata.Metric - exportErr error - expected []export.Record - expectedResource *resource.Resource - expectedHandledError error - }{ - { - desc: "no metrics", - }, - { - desc: "metric without points is dropped", - input: []*metricdata.Metric{ - { - TimeSeries: []*metricdata.TimeSeries{ - {}, - }, - }, - }, - }, - { - desc: "descriptor conversion error", - input: []*metricdata.Metric{ - // TypeGaugeDistribution isn't supported - {Descriptor: metricdata.Descriptor{Type: metricdata.TypeGaugeDistribution}}, - }, - expectedHandledError: errConversion, - }, - { - desc: "labels conversion error", - input: []*metricdata.Metric{ - { - // No descriptor with label keys. - TimeSeries: []*metricdata.TimeSeries{ - // 1 label value, which doens't exist in keys. - { - LabelValues: []metricdata.LabelValue{{Value: "foo", Present: true}}, - Points: []metricdata.Point{ - {}, - }, - }, - }, - }, - }, - expectedHandledError: errConversion, - }, - { - desc: "unsupported summary point type", - input: []*metricdata.Metric{ - { - TimeSeries: []*metricdata.TimeSeries{ - { - Points: []metricdata.Point{ - {Value: &metricdata.Summary{}}, - }, - }, - }, - }, - }, - exportErr: errIncompatibleType, - }, - { - desc: "success", - input: []*metricdata.Metric{ - { - Resource: &ocresource.Resource{ - Labels: map[string]string{ - "R1": "V1", - "R2": "V2", - }, - }, - TimeSeries: []*metricdata.TimeSeries{ - { - StartTime: now, - Points: []metricdata.Point{ - {Value: int64(123), Time: now}, - }, - }, - }, - }, - }, - expectedResource: resource.NewSchemaless( - attribute.String("R1", "V1"), - attribute.String("R2", "V2"), - ), - expected: []export.Record{ - export.NewRecord( - &basicDesc, - attribute.EmptySet(), - &ocRawAggregator{ - value: number.NewInt64Number(123), - time: now, - }, - now, - now, - ), - }, - }, - { - desc: "export error after success", - input: []*metricdata.Metric{ - { - TimeSeries: []*metricdata.TimeSeries{ - { - StartTime: now, - Points: []metricdata.Point{ - {Value: int64(123), Time: now}, - }, - }, - }, - }, - }, - expected: []export.Record{ - export.NewRecord( - &basicDesc, - attribute.EmptySet(), - &ocRawAggregator{ - value: number.NewInt64Number(123), - time: now, - }, - now, - now, - ), - }, - exportErr: errors.New("failed to export"), - }, - { - desc: "partial success sends correct metrics and drops incorrect metrics with handled err", - input: []*metricdata.Metric{ - { - TimeSeries: []*metricdata.TimeSeries{ - { - StartTime: now, - Points: []metricdata.Point{ - {Value: int64(123), Time: now}, - }, - }, - }, - }, - // TypeGaugeDistribution isn't supported - {Descriptor: metricdata.Descriptor{Type: metricdata.TypeGaugeDistribution}}, - }, - expected: []export.Record{ - export.NewRecord( - &basicDesc, - attribute.EmptySet(), - &ocRawAggregator{ - value: number.NewInt64Number(123), - time: now, - }, - now, - now, - ), - }, - expectedHandledError: errConversion, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - fakeExporter := &fakeExporter{err: tc.exportErr} - err := NewMetricExporter(fakeExporter).ExportMetrics(context.Background(), tc.input) - if !errors.Is(err, tc.exportErr) { - t.Errorf("NewMetricExporter(%+v) = err(%v), want err(%v)", tc.input, err, tc.exportErr) - } - // Check the global error handler, since we don't return errors - // which occur during conversion. - err = fakeErrorHandler.matches(tc.expectedHandledError) - if err != nil { - t.Fatalf("ExportMetrics(%+v) = %v", tc.input, err) - } - output := fakeExporter.records - if len(tc.expected) != len(output) { - t.Fatalf("ExportMetrics(%+v) = %d records, want %d records", tc.input, len(output), len(tc.expected)) - } - if fakeExporter.resource.String() != tc.expectedResource.String() { - t.Errorf("ExportMetrics(%+v)[i].Resource() = %+v, want %+v", tc.input, fakeExporter.resource.String(), tc.expectedResource.String()) - } - for i, expected := range tc.expected { - if output[i].StartTime() != expected.StartTime() { - t.Errorf("ExportMetrics(%+v)[i].StartTime() = %+v, want %+v", tc.input, output[i].StartTime(), expected.StartTime()) - } - if output[i].EndTime() != expected.EndTime() { - t.Errorf("ExportMetrics(%+v)[i].EndTime() = %+v, want %+v", tc.input, output[i].EndTime(), expected.EndTime()) - } - if output[i].Descriptor().Name() != expected.Descriptor().Name() { - t.Errorf("ExportMetrics(%+v)[i].Descriptor() = %+v, want %+v", tc.input, output[i].Descriptor().Name(), expected.Descriptor().Name()) - } - // Don't bother with a complete check of the descriptor. - // That is checked as part of descriptor conversion tests below. - if !output[i].Labels().Equals(expected.Labels()) { - t.Errorf("ExportMetrics(%+v)[i].Labels() = %+v, want %+v", tc.input, output[i].Labels(), expected.Labels()) - } - if output[i].Aggregation().Kind() != expected.Aggregation().Kind() { - t.Errorf("ExportMetrics(%+v)[i].Aggregation() = %+v, want %+v", tc.input, output[i].Aggregation().Kind(), expected.Aggregation().Kind()) - } - // Don't bother checking the contents of the points aggregation. - // Those tests are done with the aggregations themselves - } - }) - } -} - -func TestConvertLabels(t *testing.T) { - setWithMultipleKeys := attribute.NewSet( - attribute.KeyValue{Key: attribute.Key("first"), Value: attribute.StringValue("1")}, - attribute.KeyValue{Key: attribute.Key("second"), Value: attribute.StringValue("2")}, - ) - for _, tc := range []struct { - desc string - inputKeys []metricdata.LabelKey - inputValues []metricdata.LabelValue - expected *attribute.Set - expectedErr error - }{ - { - desc: "no labels", - expected: attribute.EmptySet(), - }, - { - desc: "different numbers of keys and values", - inputKeys: []metricdata.LabelKey{{Key: "foo"}}, - expected: attribute.EmptySet(), - expectedErr: errConversion, - }, - { - desc: "multiple keys and values", - inputKeys: []metricdata.LabelKey{{Key: "first"}, {Key: "second"}}, - inputValues: []metricdata.LabelValue{ - {Value: "1", Present: true}, - {Value: "2", Present: true}, - }, - expected: &setWithMultipleKeys, - }, - { - desc: "multiple keys and values with some not present", - inputKeys: []metricdata.LabelKey{{Key: "first"}, {Key: "second"}, {Key: "third"}}, - inputValues: []metricdata.LabelValue{ - {Value: "1", Present: true}, - {Value: "2", Present: true}, - {Present: false}, - }, - expected: &setWithMultipleKeys, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - output, err := convertLabels(tc.inputKeys, tc.inputValues) - if !errors.Is(err, tc.expectedErr) { - t.Errorf("convertLabels(keys: %v, values: %v) = err(%v), want err(%v)", tc.inputKeys, tc.inputValues, err, tc.expectedErr) - } - if !output.Equals(tc.expected) { - t.Errorf("convertLabels(keys: %v, values: %v) = %+v, want %+v", tc.inputKeys, tc.inputValues, output.ToSlice(), tc.expected.ToSlice()) - } - }) - } -} -func TestConvertResource(t *testing.T) { - for _, tc := range []struct { - desc string - input *ocresource.Resource - expected *resource.Resource - }{ - { - desc: "nil resource", - }, - { - desc: "empty resource", - input: &ocresource.Resource{ - Labels: map[string]string{}, - }, - expected: resource.NewSchemaless(), - }, - { - desc: "resource with labels", - input: &ocresource.Resource{ - Labels: map[string]string{ - "foo": "bar", - "tick": "tock", - }, - }, - expected: resource.NewSchemaless( - attribute.KeyValue{Key: attribute.Key("foo"), Value: attribute.StringValue("bar")}, - attribute.KeyValue{Key: attribute.Key("tick"), Value: attribute.StringValue("tock")}, - ), - }, - } { - t.Run(tc.desc, func(t *testing.T) { - output := convertResource(tc.input) - if !output.Equal(tc.expected) { - t.Errorf("convertResource(%v) = %+v, want %+v", tc.input, output, tc.expected) - } - }) - } -} -func TestConvertDescriptor(t *testing.T) { - for _, tc := range []struct { - desc string - input metricdata.Descriptor - expected sdkapi.Descriptor - expectedErr error - }{ - { - desc: "empty descriptor", - expected: metrictest.NewDescriptor( - "", - sdkapi.GaugeObserverInstrumentKind, - number.Int64Kind, - ), - }, - { - desc: "gauge int64 bytes", - input: metricdata.Descriptor{ - Name: "foo", - Description: "bar", - Unit: metricdata.UnitBytes, - Type: metricdata.TypeGaugeInt64, - }, - expected: metrictest.NewDescriptor( - "foo", - sdkapi.GaugeObserverInstrumentKind, - number.Int64Kind, - instrument.WithDescription("bar"), - instrument.WithUnit(unit.Bytes), - ), - }, - { - desc: "gauge float64 ms", - input: metricdata.Descriptor{ - Name: "foo", - Description: "bar", - Unit: metricdata.UnitMilliseconds, - Type: metricdata.TypeGaugeFloat64, - }, - expected: metrictest.NewDescriptor( - "foo", - sdkapi.GaugeObserverInstrumentKind, - number.Float64Kind, - instrument.WithDescription("bar"), - instrument.WithUnit(unit.Milliseconds), - ), - }, - { - desc: "cumulative int64 dimensionless", - input: metricdata.Descriptor{ - Name: "foo", - Description: "bar", - Unit: metricdata.UnitDimensionless, - Type: metricdata.TypeCumulativeInt64, - }, - expected: metrictest.NewDescriptor( - "foo", - sdkapi.CounterObserverInstrumentKind, - number.Int64Kind, - instrument.WithDescription("bar"), - instrument.WithUnit(unit.Dimensionless), - ), - }, - { - desc: "cumulative float64 dimensionless", - input: metricdata.Descriptor{ - Name: "foo", - Description: "bar", - Unit: metricdata.UnitDimensionless, - Type: metricdata.TypeCumulativeFloat64, - }, - expected: metrictest.NewDescriptor( - "foo", - sdkapi.CounterObserverInstrumentKind, - number.Float64Kind, - instrument.WithDescription("bar"), - instrument.WithUnit(unit.Dimensionless), - ), - }, - { - desc: "incompatible TypeCumulativeDistribution", - input: metricdata.Descriptor{ - Name: "foo", - Description: "bar", - Type: metricdata.TypeCumulativeDistribution, - }, - expectedErr: errConversion, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - output, err := convertDescriptor(tc.input) - if !errors.Is(err, tc.expectedErr) { - t.Errorf("convertDescriptor(%v) = err(%v), want err(%v)", tc.input, err, tc.expectedErr) - } - if output != tc.expected { - t.Errorf("convertDescriptor(%v) = %+v, want %+v", tc.input, output, tc.expected) - } - }) - } -} diff --git a/bridge/opencensus/go.mod b/bridge/opencensus/go.mod deleted file mode 100644 index 468ec0fb503..00000000000 --- a/bridge/opencensus/go.mod +++ /dev/null @@ -1,76 +0,0 @@ -module go.opentelemetry.io/otel/bridge/opencensus - -go 1.16 - -require ( - go.opencensus.io v0.22.6-0.20201102222123-380f4078db9f - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/metric v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/otel/sdk/metric v0.29.0 - go.opentelemetry.io/otel/trace v1.6.3 -) - -replace go.opentelemetry.io/otel => ../.. - -replace go.opentelemetry.io/otel/bridge/opencensus => ./ - -replace go.opentelemetry.io/otel/bridge/opentracing => ../opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../../example/jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../../example/namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../../example/opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../../example/otel-collector - -replace go.opentelemetry.io/otel/example/prometheus => ../../example/prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../../example/zipkin - -replace go.opentelemetry.io/otel/exporters/prometheus => ../../exporters/prometheus - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../exporters/jaeger - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../exporters/zipkin - -replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools - -replace go.opentelemetry.io/otel/sdk => ../../sdk - -replace go.opentelemetry.io/otel/metric => ../../metric - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric - -replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric - -replace go.opentelemetry.io/otel/trace => ../../trace - -replace go.opentelemetry.io/otel/example/passthrough => ../../example/passthrough - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otlp/otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../../exporters/otlp/otlpmetric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../exporters/otlp/otlpmetric/otlpmetricgrpc - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../exporters/stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../exporters/stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../exporters/otlp/otlpmetric/otlpmetrichttp - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ./test - -replace go.opentelemetry.io/otel/example/fib => ../../example/fib - -replace go.opentelemetry.io/otel/schema => ../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../exporters/otlp/internal/retry diff --git a/bridge/opencensus/go.sum b/bridge/opencensus/go.sum deleted file mode 100644 index a123b0ac005..00000000000 --- a/bridge/opencensus/go.sum +++ /dev/null @@ -1,66 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -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.22.6-0.20201102222123-380f4078db9f h1:IUmbcoP9XyEXW+R9AbrZgDvaYVfTbISN92Y5RIV+Mx4= -go.opencensus.io v0.22.6-0.20201102222123-380f4078db9f/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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/internal/handler.go b/bridge/opencensus/internal/handler.go deleted file mode 100644 index 6bf5496169d..00000000000 --- a/bridge/opencensus/internal/handler.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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 internal // import "go.opentelemetry.io/otel/bridge/opencensus/internal" - -import "go.opentelemetry.io/otel" - -// Handle is the package level function to handle errors. It can be -// overwritten for testing. -var Handle = otel.Handle diff --git a/bridge/opencensus/internal/oc2otel/attributes.go b/bridge/opencensus/internal/oc2otel/attributes.go deleted file mode 100644 index 3e1cebdb800..00000000000 --- a/bridge/opencensus/internal/oc2otel/attributes.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 oc2otel // import "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - -import ( - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/attribute" -) - -func Attributes(attr []octrace.Attribute) []attribute.KeyValue { - otelAttr := make([]attribute.KeyValue, len(attr)) - for i, a := range attr { - otelAttr[i] = attribute.KeyValue{ - Key: attribute.Key(a.Key()), - Value: AttributeValue(a.Value()), - } - } - return otelAttr -} - -func AttributeValue(ocval interface{}) attribute.Value { - switch v := ocval.(type) { - case bool: - return attribute.BoolValue(v) - case int64: - return attribute.Int64Value(v) - case float64: - return attribute.Float64Value(v) - case string: - return attribute.StringValue(v) - default: - return attribute.StringValue("unknown") - } -} diff --git a/bridge/opencensus/internal/oc2otel/attributes_test.go b/bridge/opencensus/internal/oc2otel/attributes_test.go deleted file mode 100644 index 44d40ec899a..00000000000 --- a/bridge/opencensus/internal/oc2otel/attributes_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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 oc2otel - -import ( - "testing" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/attribute" -) - -func TestAttributes(t *testing.T) { - in := []octrace.Attribute{ - octrace.BoolAttribute("bool", true), - octrace.Int64Attribute("int64", 49), - octrace.Float64Attribute("float64", 1.618), - octrace.StringAttribute("key", "val"), - } - - want := []attribute.KeyValue{ - attribute.Bool("bool", true), - attribute.Int64("int64", 49), - attribute.Float64("float64", 1.618), - attribute.String("key", "val"), - } - got := Attributes(in) - - if len(got) != len(want) { - t.Errorf("Attributes conversion failed: want %#v, got %#v", want, got) - } - for i := range got { - if g, w := got[i], want[i]; g != w { - t.Errorf("Attributes conversion: want %#v, got %#v", w, g) - } - } -} - -func TestAttributeValueUnknown(t *testing.T) { - got := AttributeValue([]byte{}) - if got != attribute.StringValue("unknown") { - t.Errorf("AttributeValue of unknown wrong: %#v", got) - } -} diff --git a/bridge/opencensus/internal/oc2otel/span_context.go b/bridge/opencensus/internal/oc2otel/span_context.go deleted file mode 100644 index 006226f30ab..00000000000 --- a/bridge/opencensus/internal/oc2otel/span_context.go +++ /dev/null @@ -1,33 +0,0 @@ -// 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 oc2otel // import "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - -import ( - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/trace" -) - -func SpanContext(sc octrace.SpanContext) trace.SpanContext { - var traceFlags trace.TraceFlags - if sc.IsSampled() { - traceFlags = trace.FlagsSampled - } - return trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: trace.TraceID(sc.TraceID), - SpanID: trace.SpanID(sc.SpanID), - TraceFlags: traceFlags, - }) -} diff --git a/bridge/opencensus/internal/oc2otel/span_context_test.go b/bridge/opencensus/internal/oc2otel/span_context_test.go deleted file mode 100644 index ba0f1d0bfcc..00000000000 --- a/bridge/opencensus/internal/oc2otel/span_context_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// 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 oc2otel - -import ( - "testing" - - octrace "go.opencensus.io/trace" - "go.opencensus.io/trace/tracestate" - - "go.opentelemetry.io/otel/trace" -) - -func TestSpanContextConversion(t *testing.T) { - for _, tc := range []struct { - description string - input octrace.SpanContext - expected trace.SpanContext - }{ - { - description: "empty", - }, - { - description: "sampled", - input: octrace.SpanContext{ - TraceID: octrace.TraceID([16]byte{1}), - SpanID: octrace.SpanID([8]byte{2}), - TraceOptions: octrace.TraceOptions(0x1), - }, - expected: trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: trace.TraceID([16]byte{1}), - SpanID: trace.SpanID([8]byte{2}), - TraceFlags: trace.FlagsSampled, - }), - }, - { - description: "not sampled", - input: octrace.SpanContext{ - TraceID: octrace.TraceID([16]byte{1}), - SpanID: octrace.SpanID([8]byte{2}), - TraceOptions: octrace.TraceOptions(0), - }, - expected: trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: trace.TraceID([16]byte{1}), - SpanID: trace.SpanID([8]byte{2}), - }), - }, - { - description: "trace state is ignored", - input: octrace.SpanContext{ - TraceID: octrace.TraceID([16]byte{1}), - SpanID: octrace.SpanID([8]byte{2}), - Tracestate: &tracestate.Tracestate{}, - }, - expected: trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: trace.TraceID([16]byte{1}), - SpanID: trace.SpanID([8]byte{2}), - }), - }, - } { - t.Run(tc.description, func(t *testing.T) { - output := SpanContext(tc.input) - if !output.Equal(tc.expected) { - t.Fatalf("Got %+v spancontext, exepected %+v.", output, tc.expected) - } - }) - } -} diff --git a/bridge/opencensus/internal/oc2otel/tracer_start_options.go b/bridge/opencensus/internal/oc2otel/tracer_start_options.go deleted file mode 100644 index 030df047f35..00000000000 --- a/bridge/opencensus/internal/oc2otel/tracer_start_options.go +++ /dev/null @@ -1,46 +0,0 @@ -// 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 oc2otel // import "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - -import ( - "fmt" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/trace" -) - -func StartOptions(optFuncs []octrace.StartOption) ([]trace.SpanStartOption, error) { - var ocOpts octrace.StartOptions - for _, fn := range optFuncs { - fn(&ocOpts) - } - - var otelOpts []trace.SpanStartOption - switch ocOpts.SpanKind { - case octrace.SpanKindClient: - otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindClient)) - case octrace.SpanKindServer: - otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindServer)) - case octrace.SpanKindUnspecified: - otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindUnspecified)) - } - - var err error - if ocOpts.Sampler != nil { - err = fmt.Errorf("unsupported sampler: %v", ocOpts.Sampler) - } - return otelOpts, err -} diff --git a/bridge/opencensus/internal/oc2otel/tracer_start_options_test.go b/bridge/opencensus/internal/oc2otel/tracer_start_options_test.go deleted file mode 100644 index 6a525424cab..00000000000 --- a/bridge/opencensus/internal/oc2otel/tracer_start_options_test.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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 oc2otel - -import ( - "testing" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/trace" -) - -func TestStartOptionsSpanKind(t *testing.T) { - conv := map[int]trace.SpanKind{ - octrace.SpanKindClient: trace.SpanKindClient, - octrace.SpanKindServer: trace.SpanKindServer, - octrace.SpanKindUnspecified: trace.SpanKindUnspecified, - } - - for oc, otel := range conv { - ocOpts := []octrace.StartOption{octrace.WithSpanKind(oc)} - otelOpts, err := StartOptions(ocOpts) - if err != nil { - t.Errorf("StartOptions errored: %v", err) - continue - } - c := trace.NewSpanStartConfig(otelOpts...) - if c.SpanKind() != otel { - t.Errorf("conversion of SpanKind start option: got %v, want %v", c.SpanKind(), otel) - } - } -} - -func TestStartOptionsSamplerErrors(t *testing.T) { - ocOpts := []octrace.StartOption{octrace.WithSampler(octrace.AlwaysSample())} - _, err := StartOptions(ocOpts) - if err == nil { - t.Error("StartOptions should error Sampler option") - } -} diff --git a/bridge/opencensus/internal/otel2oc/span_context.go b/bridge/opencensus/internal/otel2oc/span_context.go deleted file mode 100644 index 6355eb555fb..00000000000 --- a/bridge/opencensus/internal/otel2oc/span_context.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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 otel2oc // import "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" - -import ( - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/trace" -) - -func SpanContext(sc trace.SpanContext) octrace.SpanContext { - var to octrace.TraceOptions - if sc.IsSampled() { - // OpenCensus doesn't expose functions to directly set sampled - to = 0x1 - } - return octrace.SpanContext{ - TraceID: octrace.TraceID(sc.TraceID()), - SpanID: octrace.SpanID(sc.SpanID()), - TraceOptions: to, - } -} diff --git a/bridge/opencensus/internal/otel2oc/span_context_test.go b/bridge/opencensus/internal/otel2oc/span_context_test.go deleted file mode 100644 index 236aa89689a..00000000000 --- a/bridge/opencensus/internal/otel2oc/span_context_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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 otel2oc - -import ( - "testing" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/trace" -) - -func TestSpanContextConversion(t *testing.T) { - for _, tc := range []struct { - description string - input trace.SpanContext - expected octrace.SpanContext - }{ - { - description: "empty", - }, - { - description: "sampled", - input: trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: trace.TraceID([16]byte{1}), - SpanID: trace.SpanID([8]byte{2}), - TraceFlags: trace.FlagsSampled, - }), - expected: octrace.SpanContext{ - TraceID: octrace.TraceID([16]byte{1}), - SpanID: octrace.SpanID([8]byte{2}), - TraceOptions: octrace.TraceOptions(0x1), - }, - }, - { - description: "not sampled", - input: trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: trace.TraceID([16]byte{1}), - SpanID: trace.SpanID([8]byte{2}), - }), - expected: octrace.SpanContext{ - TraceID: octrace.TraceID([16]byte{1}), - SpanID: octrace.SpanID([8]byte{2}), - TraceOptions: octrace.TraceOptions(0), - }, - }, - } { - t.Run(tc.description, func(t *testing.T) { - output := SpanContext(tc.input) - if output != tc.expected { - t.Fatalf("Got %+v spancontext, exepected %+v.", output, tc.expected) - } - }) - } -} diff --git a/bridge/opencensus/internal/span.go b/bridge/opencensus/internal/span.go deleted file mode 100644 index 21449aa3d3a..00000000000 --- a/bridge/opencensus/internal/span.go +++ /dev/null @@ -1,131 +0,0 @@ -// 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 internal // import "go.opentelemetry.io/otel/bridge/opencensus/internal" - -import ( - "fmt" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/trace" -) - -const ( - // MessageSendEvent is the name of the message send event. - MessageSendEvent = "message send" - // MessageReceiveEvent is the name of the message receive event. - MessageReceiveEvent = "message receive" -) - -var ( - // UncompressedKey is used for the uncompressed byte size attribute. - UncompressedKey = attribute.Key("uncompressed byte size") - // CompressedKey is used for the compressed byte size attribute. - CompressedKey = attribute.Key("compressed byte size") -) - -// Span is an OpenCensus SpanInterface wrapper for an OpenTelemetry Span. -type Span struct { - otelSpan trace.Span -} - -// NewSpan returns an OpenCensus Span wrapping an OpenTelemetry Span. -func NewSpan(s trace.Span) *octrace.Span { - return octrace.NewSpan(&Span{otelSpan: s}) -} - -// IsRecordingEvents returns true if events are being recorded for this span. -func (s *Span) IsRecordingEvents() bool { - return s.otelSpan.IsRecording() -} - -// End ends thi span. -func (s *Span) End() { - s.otelSpan.End() -} - -// SpanContext returns the SpanContext of this span. -func (s *Span) SpanContext() octrace.SpanContext { - return otel2oc.SpanContext(s.otelSpan.SpanContext()) -} - -// SetName sets the name of this span, if it is recording events. -func (s *Span) SetName(name string) { - s.otelSpan.SetName(name) -} - -// SetStatus sets the status of this span, if it is recording events. -func (s *Span) SetStatus(status octrace.Status) { - s.otelSpan.SetStatus(codes.Code(status.Code), status.Message) -} - -// AddAttributes sets attributes in this span. -func (s *Span) AddAttributes(attributes ...octrace.Attribute) { - s.otelSpan.SetAttributes(oc2otel.Attributes(attributes)...) -} - -// Annotate adds an annotation with attributes to this span. -func (s *Span) Annotate(attributes []octrace.Attribute, str string) { - s.otelSpan.AddEvent(str, trace.WithAttributes(oc2otel.Attributes(attributes)...)) -} - -// Annotatef adds a formatted annotation with attributes to this span. -func (s *Span) Annotatef(attributes []octrace.Attribute, format string, a ...interface{}) { - s.Annotate(attributes, fmt.Sprintf(format, a...)) -} - -// AddMessageSendEvent adds a message send event to this span. -func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) { - s.otelSpan.AddEvent(MessageSendEvent, - trace.WithAttributes( - attribute.KeyValue{ - Key: UncompressedKey, - Value: attribute.Int64Value(uncompressedByteSize), - }, - attribute.KeyValue{ - Key: CompressedKey, - Value: attribute.Int64Value(compressedByteSize), - }), - ) -} - -// AddMessageReceiveEvent adds a message receive event to this span. -func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) { - s.otelSpan.AddEvent(MessageReceiveEvent, - trace.WithAttributes( - attribute.KeyValue{ - Key: UncompressedKey, - Value: attribute.Int64Value(uncompressedByteSize), - }, - attribute.KeyValue{ - Key: CompressedKey, - Value: attribute.Int64Value(compressedByteSize), - }), - ) -} - -// AddLink adds a link to this span. -func (s *Span) AddLink(l octrace.Link) { - Handle(fmt.Errorf("ignoring OpenCensus link %+v for span %q because OpenTelemetry doesn't support setting links after creation", l, s.String())) -} - -// String prints a string representation of this span. -func (s *Span) String() string { - return fmt.Sprintf("span %s", s.otelSpan.SpanContext().SpanID().String()) -} diff --git a/bridge/opencensus/internal/span_test.go b/bridge/opencensus/internal/span_test.go deleted file mode 100644 index 7aa023e71c2..00000000000 --- a/bridge/opencensus/internal/span_test.go +++ /dev/null @@ -1,268 +0,0 @@ -// 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 internal_test - -import ( - "testing" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/bridge/opencensus/internal" - "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/trace" -) - -type span struct { - trace.Span - - recording bool - ended bool - sc trace.SpanContext - name string - sCode codes.Code - sMsg string - attrs []attribute.KeyValue - eName string - eOpts []trace.EventOption -} - -func (s *span) IsRecording() bool { return s.recording } -func (s *span) End(...trace.SpanEndOption) { s.ended = true } -func (s *span) SpanContext() trace.SpanContext { return s.sc } -func (s *span) SetName(n string) { s.name = n } -func (s *span) SetStatus(c codes.Code, d string) { s.sCode, s.sMsg = c, d } -func (s *span) SetAttributes(a ...attribute.KeyValue) { s.attrs = a } -func (s *span) AddEvent(n string, o ...trace.EventOption) { s.eName, s.eOpts = n, o } - -func TestSpanIsRecordingEvents(t *testing.T) { - s := &span{recording: true} - ocS := internal.NewSpan(s) - if !ocS.IsRecordingEvents() { - t.Errorf("span.IsRecordingEvents() = false, want true") - } - s.recording = false - if ocS.IsRecordingEvents() { - t.Errorf("span.IsRecordingEvents() = true, want false") - } -} - -func TestSpanEnd(t *testing.T) { - s := new(span) - ocS := internal.NewSpan(s) - if s.ended { - t.Fatal("new span already ended") - } - - ocS.End() - if !s.ended { - t.Error("span.End() did not end OpenTelemetry span") - } -} - -func TestSpanSpanContext(t *testing.T) { - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: [16]byte{1}, - SpanID: [8]byte{1}, - }) - // Do not test the conversion, only that the method is called. - converted := otel2oc.SpanContext(sc) - - s := &span{sc: sc} - ocS := internal.NewSpan(s) - if ocS.SpanContext() != converted { - t.Error("span.SpanContext did not use OpenTelemetry SpanContext") - } -} - -func TestSpanSetName(t *testing.T) { - // OpenCensus does not set a name if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - name := "test name" - ocS.SetName(name) - if s.name != name { - t.Error("span.SetName did not set OpenTelemetry span name") - } -} - -func TestSpanSetStatus(t *testing.T) { - // OpenCensus does not set a status if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - - c, d := codes.Error, "error" - status := octrace.Status{Code: int32(c), Message: d} - ocS.SetStatus(status) - - if s.sCode != c { - t.Error("span.SetStatus failed to set OpenTelemetry status code") - } - if s.sMsg != d { - t.Error("span.SetStatus failed to set OpenTelemetry status description") - } -} - -func TestSpanAddAttributes(t *testing.T) { - attrs := []octrace.Attribute{ - octrace.BoolAttribute("a", true), - } - // Do not test the conversion, only that the method is called. - converted := oc2otel.Attributes(attrs) - - // OpenCensus does not set attributes if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - ocS.AddAttributes(attrs...) - - if len(s.attrs) != len(converted) || s.attrs[0] != converted[0] { - t.Error("span.AddAttributes failed to set OpenTelemetry attributes") - } -} - -func TestSpanAnnotate(t *testing.T) { - name := "annotation" - attrs := []octrace.Attribute{ - octrace.BoolAttribute("a", true), - } - // Do not test the conversion, only that the method is called. - want := oc2otel.Attributes(attrs) - - // OpenCensus does not set events if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - ocS.Annotate(attrs, name) - - if s.eName != name { - t.Error("span.Annotate did not set event name") - } - - config := trace.NewEventConfig(s.eOpts...) - got := config.Attributes() - if len(want) != len(got) || want[0] != got[0] { - t.Error("span.Annotate did not set event options") - } -} - -func TestSpanAnnotatef(t *testing.T) { - format := "annotation %s" - attrs := []octrace.Attribute{ - octrace.BoolAttribute("a", true), - } - // Do not test the conversion, only that the method is called. - want := oc2otel.Attributes(attrs) - - // OpenCensus does not set events if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - ocS.Annotatef(attrs, format, "a") - - if s.eName != "annotation a" { - t.Error("span.Annotatef did not set event name") - } - - config := trace.NewEventConfig(s.eOpts...) - got := config.Attributes() - if len(want) != len(got) || want[0] != got[0] { - t.Error("span.Annotatef did not set event options") - } -} - -func TestSpanAddMessageSendEvent(t *testing.T) { - var u, c int64 = 1, 2 - - // OpenCensus does not set events if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - ocS.AddMessageSendEvent(0, u, c) - - if s.eName != internal.MessageSendEvent { - t.Error("span.AddMessageSendEvent did not set event name") - } - - config := trace.NewEventConfig(s.eOpts...) - got := config.Attributes() - if len(got) != 2 { - t.Fatalf("span.AddMessageSendEvent set %d attributes, want 2", len(got)) - } - - want := attribute.KeyValue{Key: internal.UncompressedKey, Value: attribute.Int64Value(u)} - if got[0] != want { - t.Errorf("span.AddMessageSendEvent wrong uncompressed attribute: %v", got[0]) - } - - want = attribute.KeyValue{Key: internal.CompressedKey, Value: attribute.Int64Value(c)} - if got[1] != want { - t.Errorf("span.AddMessageSendEvent wrong compressed attribute: %v", got[1]) - } -} - -func TestSpanAddMessageReceiveEvent(t *testing.T) { - var u, c int64 = 3, 4 - - // OpenCensus does not set events if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - ocS.AddMessageReceiveEvent(0, u, c) - - if s.eName != internal.MessageReceiveEvent { - t.Error("span.AddMessageReceiveEvent did not set event name") - } - - config := trace.NewEventConfig(s.eOpts...) - got := config.Attributes() - if len(got) != 2 { - t.Fatalf("span.AddMessageReceiveEvent set %d attributes, want 2", len(got)) - } - - want := attribute.KeyValue{Key: internal.UncompressedKey, Value: attribute.Int64Value(u)} - if got[0] != want { - t.Errorf("span.AddMessageReceiveEvent wrong uncompressed attribute: %v", got[0]) - } - - want = attribute.KeyValue{Key: internal.CompressedKey, Value: attribute.Int64Value(c)} - if got[1] != want { - t.Errorf("span.AddMessageReceiveEvent wrong compressed attribute: %v", got[1]) - } -} - -func TestSpanAddLinkFails(t *testing.T) { - h, restore := withHandler() - defer restore() - - // OpenCensus does not try to set links if not recording. - s := &span{recording: true} - ocS := internal.NewSpan(s) - ocS.AddLink(octrace.Link{}) - - if h.err == nil { - t.Error("span.AddLink failed to raise an error") - } -} - -func TestSpanString(t *testing.T) { - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: [16]byte{1}, - SpanID: [8]byte{1}, - }) - - s := &span{sc: sc} - ocS := internal.NewSpan(s) - if expected := "span 0100000000000000"; ocS.String() != expected { - t.Errorf("span.String = %q, not %q", ocS.String(), expected) - } -} diff --git a/bridge/opencensus/internal/tracer.go b/bridge/opencensus/internal/tracer.go deleted file mode 100644 index 4ed70a30afe..00000000000 --- a/bridge/opencensus/internal/tracer.go +++ /dev/null @@ -1,69 +0,0 @@ -// 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 internal // import "go.opentelemetry.io/otel/bridge/opencensus/internal" - -import ( - "context" - "fmt" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - "go.opentelemetry.io/otel/trace" -) - -// Tracer is an OpenCensus Tracer that wraps an OpenTelemetry Tracer. -type Tracer struct { - otelTracer trace.Tracer -} - -// NewTracer returns an OpenCensus Tracer that wraps the OpenTelemetry tracer. -func NewTracer(tracer trace.Tracer) octrace.Tracer { - return &Tracer{otelTracer: tracer} -} - -// StartSpan starts a new child span of the current span in the context. If -// there is no span in the context, it creates a new trace and span. -func (o *Tracer) StartSpan(ctx context.Context, name string, s ...octrace.StartOption) (context.Context, *octrace.Span) { - otelOpts, err := oc2otel.StartOptions(s) - if err != nil { - Handle(fmt.Errorf("starting span %q: %w", name, err)) - } - ctx, sp := o.otelTracer.Start(ctx, name, otelOpts...) - return ctx, NewSpan(sp) -} - -// StartSpanWithRemoteParent starts a new child span of the span from the -// given parent. -func (o *Tracer) StartSpanWithRemoteParent(ctx context.Context, name string, parent octrace.SpanContext, s ...octrace.StartOption) (context.Context, *octrace.Span) { - // make sure span context is zero'd out so we use the remote parent - ctx = trace.ContextWithSpan(ctx, nil) - ctx = trace.ContextWithRemoteSpanContext(ctx, oc2otel.SpanContext(parent)) - return o.StartSpan(ctx, name, s...) -} - -// FromContext returns the Span stored in a context. -func (o *Tracer) FromContext(ctx context.Context) *octrace.Span { - return NewSpan(trace.SpanFromContext(ctx)) -} - -// NewContext returns a new context with the given Span attached. -func (o *Tracer) NewContext(parent context.Context, s *octrace.Span) context.Context { - if otSpan, ok := s.Internal().(*Span); ok { - return trace.ContextWithSpan(parent, otSpan.otelSpan) - } - Handle(fmt.Errorf("unable to create context with span %q, since it was created using a different tracer", s.String())) - return parent -} diff --git a/bridge/opencensus/internal/tracer_test.go b/bridge/opencensus/internal/tracer_test.go deleted file mode 100644 index 1e3518a7efe..00000000000 --- a/bridge/opencensus/internal/tracer_test.go +++ /dev/null @@ -1,161 +0,0 @@ -// 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 internal_test - -import ( - "context" - "testing" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/bridge/opencensus/internal" - "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" - "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" - "go.opentelemetry.io/otel/trace" -) - -type handler struct{ err error } - -func (h *handler) Handle(e error) { h.err = e } - -func withHandler() (*handler, func()) { - h := new(handler) - original := internal.Handle - internal.Handle = h.Handle - return h, func() { internal.Handle = original } -} - -type tracer struct { - ctx context.Context - name string - opts []trace.SpanStartOption -} - -func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { - t.ctx, t.name, t.opts = ctx, name, opts - noop := trace.NewNoopTracerProvider().Tracer("testing") - return noop.Start(ctx, name, opts...) -} - -type ctxKey string - -func TestTracerStartSpan(t *testing.T) { - h, restore := withHandler() - defer restore() - - otelTracer := &tracer{} - ocTracer := internal.NewTracer(otelTracer) - - ctx := context.WithValue(context.Background(), ctxKey("key"), "value") - name := "testing span" - ocTracer.StartSpan(ctx, name, octrace.WithSpanKind(octrace.SpanKindClient)) - if h.err != nil { - t.Fatalf("OC tracer.StartSpan errored: %v", h.err) - } - - if otelTracer.ctx != ctx { - t.Error("OTel tracer.Start called with wrong context") - } - if otelTracer.name != name { - t.Error("OTel tracer.Start called with wrong name") - } - sk := trace.SpanKindClient - c := trace.NewSpanStartConfig(otelTracer.opts...) - if c.SpanKind() != sk { - t.Errorf("OTel tracer.Start called with wrong options: %#v", c) - } -} - -func TestTracerStartSpanReportsErrors(t *testing.T) { - h, restore := withHandler() - defer restore() - - ocTracer := internal.NewTracer(&tracer{}) - ocTracer.StartSpan(context.Background(), "", octrace.WithSampler(octrace.AlwaysSample())) - if h.err == nil { - t.Error("OC tracer.StartSpan no error when converting Sampler") - } -} - -func TestTracerStartSpanWithRemoteParent(t *testing.T) { - otelTracer := new(tracer) - ocTracer := internal.NewTracer(otelTracer) - sc := octrace.SpanContext{TraceID: [16]byte{1}, SpanID: [8]byte{1}} - converted := oc2otel.SpanContext(sc).WithRemote(true) - - ocTracer.StartSpanWithRemoteParent(context.Background(), "", sc) - - got := trace.SpanContextFromContext(otelTracer.ctx) - if !got.Equal(converted) { - t.Error("tracer.StartSpanWithRemoteParent failed to set remote parent") - } -} - -func TestTracerFromContext(t *testing.T) { - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: [16]byte{1}, - SpanID: [8]byte{1}, - }) - ctx := trace.ContextWithSpanContext(context.Background(), sc) - - noop := trace.NewNoopTracerProvider().Tracer("TestTracerFromContext") - // Test using the fact that the No-Op span will propagate a span context . - ctx, _ = noop.Start(ctx, "test") - - got := internal.NewTracer(noop).FromContext(ctx).SpanContext() - // Do not test the convedsion, only that the propagtion. - want := otel2oc.SpanContext(sc) - if got != want { - t.Errorf("tracer.FromContext returned wrong context: %#v", got) - } -} - -func TestTracerNewContext(t *testing.T) { - sc := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: [16]byte{1}, - SpanID: [8]byte{1}, - }) - ctx := trace.ContextWithSpanContext(context.Background(), sc) - - noop := trace.NewNoopTracerProvider().Tracer("TestTracerNewContext") - // Test using the fact that the No-Op span will propagate a span context . - _, s := noop.Start(ctx, "test") - - ocTracer := internal.NewTracer(noop) - ctx = ocTracer.NewContext(context.Background(), internal.NewSpan(s)) - got := trace.SpanContextFromContext(ctx) - - if !got.Equal(sc) { - t.Error("tracer.NewContext did not attach Span to context") - } -} - -type differentSpan struct { - octrace.SpanInterface -} - -func (s *differentSpan) String() string { return "testing span" } - -func TestTracerNewContextErrors(t *testing.T) { - h, restore := withHandler() - defer restore() - - ocTracer := internal.NewTracer(&tracer{}) - ocSpan := octrace.NewSpan(&differentSpan{}) - ocTracer.NewContext(context.Background(), ocSpan) - if h.err == nil { - t.Error("tracer.NewContext did not error for unrecognized span") - } -} diff --git a/bridge/opencensus/test/bridge_test.go b/bridge/opencensus/test/bridge_test.go deleted file mode 100644 index 4caa7e79025..00000000000 --- a/bridge/opencensus/test/bridge_test.go +++ /dev/null @@ -1,290 +0,0 @@ -// 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 test - -import ( - "context" - "testing" - - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel/attribute" - ocbridge "go.opentelemetry.io/otel/bridge/opencensus" - "go.opentelemetry.io/otel/bridge/opencensus/internal" - "go.opentelemetry.io/otel/codes" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - "go.opentelemetry.io/otel/sdk/trace/tracetest" - "go.opentelemetry.io/otel/trace" -) - -func TestMixedAPIs(t *testing.T) { - sr := tracetest.NewSpanRecorder() - tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) - tracer := tp.Tracer("mixedapitracer") - octrace.DefaultTracer = ocbridge.NewTracer(tracer) - - func() { - ctx := context.Background() - var ocspan1 *octrace.Span - ctx, ocspan1 = octrace.StartSpan(ctx, "OpenCensusSpan1") - defer ocspan1.End() - - var otspan1 trace.Span - ctx, otspan1 = tracer.Start(ctx, "OpenTelemetrySpan1") - defer otspan1.End() - - var ocspan2 *octrace.Span - ctx, ocspan2 = octrace.StartSpan(ctx, "OpenCensusSpan2") - defer ocspan2.End() - - var otspan2 trace.Span - _, otspan2 = tracer.Start(ctx, "OpenTelemetrySpan2") - defer otspan2.End() - }() - - spans := sr.Ended() - - if len(spans) != 4 { - for _, span := range spans { - t.Logf("Span: %s", span.Name()) - } - t.Fatalf("Got %d spans, exepected %d.", len(spans), 4) - } - - var parent trace.SpanContext - for i := len(spans) - 1; i >= 0; i-- { - // Verify that OpenCensus spans and OpenTelemetry spans have each - // other as parents. - if psid := spans[i].Parent().SpanID(); psid != parent.SpanID() { - t.Errorf("Span %v had parent %v. Expected %v", spans[i].Name(), psid, parent.SpanID()) - } - parent = spans[i].SpanContext() - } -} - -func TestStartOptions(t *testing.T) { - sr := tracetest.NewSpanRecorder() - tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) - octrace.DefaultTracer = ocbridge.NewTracer(tp.Tracer("startoptionstracer")) - - ctx := context.Background() - _, span := octrace.StartSpan(ctx, "OpenCensusSpan", octrace.WithSpanKind(octrace.SpanKindClient)) - span.End() - - spans := sr.Ended() - - if len(spans) != 1 { - t.Fatalf("Got %d spans, exepected %d", len(spans), 1) - } - - if spans[0].SpanKind() != trace.SpanKindClient { - t.Errorf("Got span kind %v, exepected %d", spans[0].SpanKind(), trace.SpanKindClient) - } -} - -func TestStartSpanWithRemoteParent(t *testing.T) { - sr := tracetest.NewSpanRecorder() - tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) - tracer := tp.Tracer("remoteparent") - octrace.DefaultTracer = ocbridge.NewTracer(tracer) - - ctx := context.Background() - ctx, parent := tracer.Start(ctx, "OpenTelemetrySpan1") - - _, span := octrace.StartSpanWithRemoteParent(ctx, "OpenCensusSpan", ocbridge.OTelSpanContextToOC(parent.SpanContext())) - span.End() - - spans := sr.Ended() - - if len(spans) != 1 { - t.Fatalf("Got %d spans, exepected %d", len(spans), 1) - } - - if psid := spans[0].Parent().SpanID(); psid != parent.SpanContext().SpanID() { - t.Errorf("Span %v, had parent %v. Expected %d", spans[0].Name(), psid, parent.SpanContext().SpanID()) - } -} - -func TestToFromContext(t *testing.T) { - sr := tracetest.NewSpanRecorder() - tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) - tracer := tp.Tracer("tofromcontext") - octrace.DefaultTracer = ocbridge.NewTracer(tracer) - - func() { - ctx := context.Background() - - _, otSpan1 := tracer.Start(ctx, "OpenTelemetrySpan1") - defer otSpan1.End() - - // Use NewContext instead of the context from Start - ctx = octrace.NewContext(ctx, internal.NewSpan(otSpan1)) - - ctx, _ = tracer.Start(ctx, "OpenTelemetrySpan2") - - // Get the opentelemetry span using the OpenCensus FromContext, and end it - otSpan2 := octrace.FromContext(ctx) - defer otSpan2.End() - - }() - - spans := sr.Ended() - - if len(spans) != 2 { - t.Fatalf("Got %d spans, exepected %d.", len(spans), 2) - } - - var parent trace.SpanContext - for i := len(spans) - 1; i >= 0; i-- { - // Verify that OpenCensus spans and OpenTelemetry spans have each - // other as parents. - if psid := spans[i].Parent().SpanID(); psid != parent.SpanID() { - t.Errorf("Span %v had parent %v. Expected %v", spans[i].Name(), psid, parent.SpanID()) - } - parent = spans[i].SpanContext() - } -} - -func TestIsRecordingEvents(t *testing.T) { - sr := tracetest.NewSpanRecorder() - tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) - octrace.DefaultTracer = ocbridge.NewTracer(tp.Tracer("isrecordingevents")) - - ctx := context.Background() - _, ocspan := octrace.StartSpan(ctx, "OpenCensusSpan1") - if !ocspan.IsRecordingEvents() { - t.Errorf("Got %v, expected true", ocspan.IsRecordingEvents()) - } -} - -func attrsMap(s []attribute.KeyValue) map[attribute.Key]attribute.Value { - m := make(map[attribute.Key]attribute.Value, len(s)) - for _, a := range s { - m[a.Key] = a.Value - } - return m -} - -func TestSetThings(t *testing.T) { - sr := tracetest.NewSpanRecorder() - tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr)) - octrace.DefaultTracer = ocbridge.NewTracer(tp.Tracer("setthings")) - - ctx := context.Background() - _, ocspan := octrace.StartSpan(ctx, "OpenCensusSpan1") - ocspan.SetName("span-foo") - ocspan.SetStatus(octrace.Status{Code: 1, Message: "foo"}) - ocspan.AddAttributes( - octrace.BoolAttribute("bool", true), - octrace.Int64Attribute("int64", 12345), - octrace.Float64Attribute("float64", 12.345), - octrace.StringAttribute("string", "stringval"), - ) - ocspan.Annotate( - []octrace.Attribute{octrace.StringAttribute("string", "annotateval")}, - "annotate", - ) - ocspan.Annotatef( - []octrace.Attribute{ - octrace.Int64Attribute("int64", 12345), - octrace.Float64Attribute("float64", 12.345), - }, - "annotate%d", 67890, - ) - ocspan.AddMessageSendEvent(123, 456, 789) - ocspan.AddMessageReceiveEvent(246, 135, 369) - ocspan.End() - - spans := sr.Ended() - - if len(spans) != 1 { - t.Fatalf("Got %d spans, exepected %d.", len(spans), 1) - } - s := spans[0] - - if s.Name() != "span-foo" { - t.Errorf("Got name %v, expected span-foo", s.Name()) - } - - if s.Status().Code != codes.Error { - t.Errorf("Got code %v, expected %v", s.Status().Code, codes.Error) - } - - if s.Status().Description != "foo" { - t.Errorf("Got code %v, expected foo", s.Status().Description) - } - - attrs := attrsMap(s.Attributes()) - if v := attrs[attribute.Key("bool")]; !v.AsBool() { - t.Errorf("Got attributes[bool] %v, expected true", v.AsBool()) - } - if v := attrs[attribute.Key("int64")]; v.AsInt64() != 12345 { - t.Errorf("Got attributes[int64] %v, expected 12345", v.AsInt64()) - } - if v := attrs[attribute.Key("float64")]; v.AsFloat64() != 12.345 { - t.Errorf("Got attributes[float64] %v, expected 12.345", v.AsFloat64()) - } - if v := attrs[attribute.Key("string")]; v.AsString() != "stringval" { - t.Errorf("Got attributes[string] %v, expected stringval", v.AsString()) - } - - if len(s.Events()) != 4 { - t.Fatalf("Got len(events) = %v, expected 4", len(s.Events())) - } - annotateEvent := s.Events()[0] - aeAttrs := attrsMap(annotateEvent.Attributes) - annotatefEvent := s.Events()[1] - afeAttrs := attrsMap(annotatefEvent.Attributes) - sendEvent := s.Events()[2] - receiveEvent := s.Events()[3] - if v := aeAttrs[attribute.Key("string")]; v.AsString() != "annotateval" { - t.Errorf("Got annotateEvent.Attributes[string] = %v, expected annotateval", v.AsString()) - } - if annotateEvent.Name != "annotate" { - t.Errorf("Got annotateEvent.Name = %v, expected annotate", annotateEvent.Name) - } - if v := afeAttrs[attribute.Key("int64")]; v.AsInt64() != 12345 { - t.Errorf("Got annotatefEvent.Attributes[int64] = %v, expected 12345", v.AsInt64()) - } - if v := afeAttrs[attribute.Key("float64")]; v.AsFloat64() != 12.345 { - t.Errorf("Got annotatefEvent.Attributes[float64] = %v, expected 12.345", v.AsFloat64()) - } - if annotatefEvent.Name != "annotate67890" { - t.Errorf("Got annotatefEvent.Name = %v, expected annotate67890", annotatefEvent.Name) - } - if v := aeAttrs[attribute.Key("string")]; v.AsString() != "annotateval" { - t.Errorf("Got annotateEvent.Attributes[string] = %v, expected annotateval", v.AsString()) - } - seAttrs := attrsMap(sendEvent.Attributes) - reAttrs := attrsMap(receiveEvent.Attributes) - if sendEvent.Name != internal.MessageSendEvent { - t.Errorf("Got sendEvent.Name = %v, expected message send", sendEvent.Name) - } - if v := seAttrs[internal.UncompressedKey]; v.AsInt64() != 456 { - t.Errorf("Got sendEvent.Attributes[uncompressedKey] = %v, expected 456", v.AsInt64()) - } - if v := seAttrs[internal.CompressedKey]; v.AsInt64() != 789 { - t.Errorf("Got sendEvent.Attributes[compressedKey] = %v, expected 789", v.AsInt64()) - } - if receiveEvent.Name != internal.MessageReceiveEvent { - t.Errorf("Got receiveEvent.Name = %v, expected message receive", receiveEvent.Name) - } - if v := reAttrs[internal.UncompressedKey]; v.AsInt64() != 135 { - t.Errorf("Got receiveEvent.Attributes[uncompressedKey] = %v, expected 135", v.AsInt64()) - } - if v := reAttrs[internal.CompressedKey]; v.AsInt64() != 369 { - t.Errorf("Got receiveEvent.Attributes[compressedKey] = %v, expected 369", v.AsInt64()) - } -} diff --git a/bridge/opencensus/test/go.mod b/bridge/opencensus/test/go.mod deleted file mode 100644 index 2780a4ddb21..00000000000 --- a/bridge/opencensus/test/go.mod +++ /dev/null @@ -1,75 +0,0 @@ -module go.opentelemetry.io/otel/bridge/opencensus/test - -go 1.16 - -require ( - go.opencensus.io v0.23.0 - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/bridge/opencensus v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/otel/trace v1.6.3 -) - -replace go.opentelemetry.io/otel => ../../.. - -replace go.opentelemetry.io/otel/bridge/opencensus => ../ - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ./ - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../../../example/jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../../../example/namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../../../example/opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../../../example/otel-collector - -replace go.opentelemetry.io/otel/example/passthrough => ../../../example/passthrough - -replace go.opentelemetry.io/otel/example/prometheus => ../../../example/prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../../../example/zipkin - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../../exporters/jaeger - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../../../exporters/otlp/otlpmetric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../../exporters/otlp/otlpmetric/otlpmetricgrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../../exporters/otlp/otlpmetric/otlpmetrichttp - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../../exporters/otlp/otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../../exporters/otlp/otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../../exporters/otlp/otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/exporters/prometheus => ../../../exporters/prometheus - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../../exporters/stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../../exporters/stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../../exporters/zipkin - -replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric - -replace go.opentelemetry.io/otel/internal/tools => ../../../internal/tools - -replace go.opentelemetry.io/otel/metric => ../../../metric - -replace go.opentelemetry.io/otel/sdk => ../../../sdk - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../../sdk/export/metric - -replace go.opentelemetry.io/otel/sdk/metric => ../../../sdk/metric - -replace go.opentelemetry.io/otel/trace => ../../../trace - -replace go.opentelemetry.io/otel/example/fib => ../../../example/fib - -replace go.opentelemetry.io/otel/schema => ../../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../../exporters/otlp/internal/retry diff --git a/bridge/opencensus/test/go.sum b/bridge/opencensus/test/go.sum deleted file mode 100644 index fcb0c9af429..00000000000 --- a/bridge/opencensus/test/go.sum +++ /dev/null @@ -1,113 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -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/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= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -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.22.6-0.20201102222123-380f4078db9f/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -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= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/example/opencensus/go.mod b/example/opencensus/go.mod deleted file mode 100644 index 9ae6e9d54bb..00000000000 --- a/example/opencensus/go.mod +++ /dev/null @@ -1,77 +0,0 @@ -module go.opentelemetry.io/otel/example/opencensus - -go 1.16 - -replace ( - go.opentelemetry.io/otel => ../.. - go.opentelemetry.io/otel/bridge/opencensus => ../../bridge/opencensus - go.opentelemetry.io/otel/sdk => ../../sdk -) - -require ( - go.opencensus.io v0.22.6-0.20201102222123-380f4078db9f - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/bridge/opencensus v0.29.0 - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.29.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.6.3 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/otel/sdk/metric v0.29.0 -) - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../bridge/opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ./ - -replace go.opentelemetry.io/otel/example/otel-collector => ../otel-collector - -replace go.opentelemetry.io/otel/example/prometheus => ../prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../zipkin - -replace go.opentelemetry.io/otel/exporters/prometheus => ../../exporters/prometheus - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../exporters/jaeger - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../exporters/zipkin - -replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools - -replace go.opentelemetry.io/otel/metric => ../../metric - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric - -replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric - -replace go.opentelemetry.io/otel/trace => ../../trace - -replace go.opentelemetry.io/otel/example/passthrough => ../passthrough - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otlp/otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../../exporters/otlp/otlpmetric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../exporters/otlp/otlpmetric/otlpmetricgrpc - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../exporters/stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../exporters/stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../exporters/otlp/otlpmetric/otlpmetrichttp - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../bridge/opencensus/test - -replace go.opentelemetry.io/otel/example/fib => ../fib - -replace go.opentelemetry.io/otel/schema => ../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../exporters/otlp/internal/retry diff --git a/example/opencensus/go.sum b/example/opencensus/go.sum deleted file mode 100644 index 435e0b939e7..00000000000 --- a/example/opencensus/go.sum +++ /dev/null @@ -1,67 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -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.22.6-0.20201102222123-380f4078db9f h1:IUmbcoP9XyEXW+R9AbrZgDvaYVfTbISN92Y5RIV+Mx4= -go.opencensus.io v0.22.6-0.20201102222123-380f4078db9f/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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/example/opencensus/main.go b/example/opencensus/main.go deleted file mode 100644 index ceccb82d083..00000000000 --- a/example/opencensus/main.go +++ /dev/null @@ -1,151 +0,0 @@ -// 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 main - -import ( - "context" - "fmt" - "log" - "time" - - "go.opencensus.io/metric" - "go.opencensus.io/metric/metricdata" - "go.opencensus.io/metric/metricexport" - "go.opencensus.io/metric/metricproducer" - "go.opencensus.io/stats" - "go.opencensus.io/stats/view" - "go.opencensus.io/tag" - octrace "go.opencensus.io/trace" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/bridge/opencensus" - "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" - "go.opentelemetry.io/otel/sdk/metric/export" - sdktrace "go.opentelemetry.io/otel/sdk/trace" -) - -var ( - // instrumenttype differentiates between our gauge and view metrics. - keyType = tag.MustNewKey("instrumenttype") - // Counts the number of lines read in from standard input - countMeasure = stats.Int64("test_count", "A count of something", stats.UnitDimensionless) - countView = &view.View{ - Name: "test_count", - Measure: countMeasure, - Description: "A count of something", - Aggregation: view.Count(), - TagKeys: []tag.Key{keyType}, - } -) - -func main() { - log.Println("Using OpenTelemetry stdout exporters.") - traceExporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint()) - if err != nil { - log.Fatal(fmt.Errorf("error creating trace exporter: %w", err)) - } - metricsExporter, err := stdoutmetric.New(stdoutmetric.WithPrettyPrint()) - if err != nil { - log.Fatal(fmt.Errorf("error creating metric exporter: %w", err)) - } - tracing(traceExporter) - monitoring(metricsExporter) -} - -// tracing demonstrates overriding the OpenCensus DefaultTracer to send spans -// to the OpenTelemetry exporter by calling OpenCensus APIs. -func tracing(otExporter sdktrace.SpanExporter) { - ctx := context.Background() - - log.Println("Configuring OpenCensus. Not Registering any OpenCensus exporters.") - octrace.ApplyConfig(octrace.Config{DefaultSampler: octrace.AlwaysSample()}) - - tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(otExporter)) - otel.SetTracerProvider(tp) - - log.Println("Installing the OpenCensus bridge to make OpenCensus libraries write spans using OpenTelemetry.") - tracer := tp.Tracer("simple") - octrace.DefaultTracer = opencensus.NewTracer(tracer) - tp.ForceFlush(ctx) - - log.Println("Creating OpenCensus span, which should be printed out using the OpenTelemetry stdouttrace exporter.\n-- It should have no parent, since it is the first span.") - ctx, outerOCSpan := octrace.StartSpan(ctx, "OpenCensusOuterSpan") - outerOCSpan.End() - tp.ForceFlush(ctx) - - log.Println("Creating OpenTelemetry span\n-- It should have the OpenCensus span as a parent, since the OpenCensus span was written with using OpenTelemetry APIs.") - ctx, otspan := tracer.Start(ctx, "OpenTelemetrySpan") - otspan.End() - tp.ForceFlush(ctx) - - log.Println("Creating OpenCensus span, which should be printed out using the OpenTelemetry stdouttrace exporter.\n-- It should have the OpenTelemetry span as a parent, since it was written using OpenTelemetry APIs") - _, innerOCSpan := octrace.StartSpan(ctx, "OpenCensusInnerSpan") - innerOCSpan.End() - tp.ForceFlush(ctx) -} - -// monitoring demonstrates creating an IntervalReader using the OpenTelemetry -// exporter to send metrics to the exporter by using either an OpenCensus -// registry or an OpenCensus view. -func monitoring(otExporter export.Exporter) { - log.Println("Using the OpenTelemetry stdoutmetric exporter to export OpenCensus metrics. This allows routing telemetry from both OpenTelemetry and OpenCensus to a single exporter.") - ocExporter := opencensus.NewMetricExporter(otExporter) - intervalReader, err := metricexport.NewIntervalReader(&metricexport.Reader{}, ocExporter) - if err != nil { - log.Fatalf("Failed to create interval reader: %v\n", err) - } - intervalReader.ReportingInterval = 10 * time.Second - log.Println("Emitting metrics using OpenCensus APIs. These should be printed out using the OpenTelemetry stdoutmetric exporter.") - err = intervalReader.Start() - if err != nil { - log.Fatalf("Failed to start interval reader: %v\n", err) - } - defer intervalReader.Stop() - - log.Println("Registering a gauge metric using an OpenCensus registry.") - r := metric.NewRegistry() - metricproducer.GlobalManager().AddProducer(r) - gauge, err := r.AddInt64Gauge( - "test_gauge", - metric.WithDescription("A gauge for testing"), - metric.WithConstLabel(map[metricdata.LabelKey]metricdata.LabelValue{ - {Key: keyType.Name()}: metricdata.NewLabelValue("gauge"), - }), - ) - if err != nil { - log.Fatalf("Failed to add gauge: %v\n", err) - } - entry, err := gauge.GetEntry() - if err != nil { - log.Fatalf("Failed to get gauge entry: %v\n", err) - } - - log.Println("Registering a cumulative metric using an OpenCensus view.") - if err := view.Register(countView); err != nil { - log.Fatalf("Failed to register views: %v", err) - } - ctx, err := tag.New(context.Background(), tag.Insert(keyType, "view")) - if err != nil { - log.Fatalf("Failed to set tag: %v\n", err) - } - for i := int64(1); true; i++ { - // update stats for our gauge - entry.Set(i) - // update stats for our view - stats.Record(ctx, countMeasure.M(1)) - time.Sleep(time.Second) - } -} diff --git a/example/prometheus/go.mod b/example/prometheus/go.mod deleted file mode 100644 index 80b68b0351d..00000000000 --- a/example/prometheus/go.mod +++ /dev/null @@ -1,74 +0,0 @@ -module go.opentelemetry.io/otel/example/prometheus - -go 1.16 - -replace ( - go.opentelemetry.io/otel => ../.. - go.opentelemetry.io/otel/exporters/prometheus => ../../exporters/prometheus - go.opentelemetry.io/otel/sdk => ../../sdk -) - -require ( - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/exporters/prometheus v0.29.0 - go.opentelemetry.io/otel/metric v0.29.0 - go.opentelemetry.io/otel/sdk/metric v0.29.0 -) - -replace go.opentelemetry.io/otel/bridge/opencensus => ../../bridge/opencensus - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../bridge/opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../otel-collector - -replace go.opentelemetry.io/otel/example/prometheus => ./ - -replace go.opentelemetry.io/otel/example/zipkin => ../zipkin - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../exporters/jaeger - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../exporters/zipkin - -replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools - -replace go.opentelemetry.io/otel/metric => ../../metric - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric - -replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric - -replace go.opentelemetry.io/otel/trace => ../../trace - -replace go.opentelemetry.io/otel/example/passthrough => ../passthrough - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otlp/otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../../exporters/otlp/otlpmetric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../exporters/otlp/otlpmetric/otlpmetricgrpc - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../exporters/stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../exporters/stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../exporters/otlp/otlpmetric/otlpmetrichttp - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../bridge/opencensus/test - -replace go.opentelemetry.io/otel/example/fib => ../fib - -replace go.opentelemetry.io/otel/schema => ../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../exporters/otlp/internal/retry diff --git a/example/prometheus/go.sum b/example/prometheus/go.sum deleted file mode 100644 index 039a63a4b81..00000000000 --- a/example/prometheus/go.sum +++ /dev/null @@ -1,478 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -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/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= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -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/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -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= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/example/prometheus/main.go b/example/prometheus/main.go deleted file mode 100644 index 0710fc65c4c..00000000000 --- a/example/prometheus/main.go +++ /dev/null @@ -1,132 +0,0 @@ -// 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 main - -import ( - "context" - "fmt" - "log" - "net/http" - "sync" - "time" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/prometheus" - "go.opentelemetry.io/otel/metric/global" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - selector "go.opentelemetry.io/otel/sdk/metric/selector/simple" -) - -var ( - lemonsKey = attribute.Key("ex.com/lemons") -) - -func initMeter() { - config := prometheus.Config{ - DefaultHistogramBoundaries: []float64{1, 2, 5, 10, 20, 50}, - } - c := controller.New( - processor.NewFactory( - selector.NewWithHistogramDistribution( - histogram.WithExplicitBoundaries(config.DefaultHistogramBoundaries), - ), - aggregation.CumulativeTemporalitySelector(), - processor.WithMemory(true), - ), - ) - exporter, err := prometheus.New(config, c) - if err != nil { - log.Panicf("failed to initialize prometheus exporter %v", err) - } - - global.SetMeterProvider(exporter.MeterProvider()) - - http.HandleFunc("/", exporter.ServeHTTP) - go func() { - _ = http.ListenAndServe(":2222", nil) - }() - - fmt.Println("Prometheus server running on :2222") -} - -func main() { - initMeter() - - meter := global.Meter("ex.com/basic") - - observerLock := new(sync.RWMutex) - observerValueToReport := new(float64) - observerLabelsToReport := new([]attribute.KeyValue) - - gaugeObserver, err := meter.AsyncFloat64().Gauge("ex.com.one") - if err != nil { - log.Panicf("failed to initialize instrument: %v", err) - } - _ = meter.RegisterCallback([]instrument.Asynchronous{gaugeObserver}, func(ctx context.Context) { - (*observerLock).RLock() - value := *observerValueToReport - labels := *observerLabelsToReport - (*observerLock).RUnlock() - gaugeObserver.Observe(ctx, value, labels...) - }) - - histogram, err := meter.SyncFloat64().Histogram("ex.com.two") - if err != nil { - log.Panicf("failed to initialize instrument: %v", err) - } - counter, err := meter.SyncFloat64().Counter("ex.com.three") - if err != nil { - log.Panicf("failed to initialize instrument: %v", err) - } - - commonLabels := []attribute.KeyValue{lemonsKey.Int(10), attribute.String("A", "1"), attribute.String("B", "2"), attribute.String("C", "3")} - notSoCommonLabels := []attribute.KeyValue{lemonsKey.Int(13)} - - ctx := context.Background() - - (*observerLock).Lock() - *observerValueToReport = 1.0 - *observerLabelsToReport = commonLabels - (*observerLock).Unlock() - - histogram.Record(ctx, 2.0, commonLabels...) - counter.Add(ctx, 12.0, commonLabels...) - - time.Sleep(5 * time.Second) - - (*observerLock).Lock() - *observerValueToReport = 1.0 - *observerLabelsToReport = notSoCommonLabels - (*observerLock).Unlock() - histogram.Record(ctx, 2.0, notSoCommonLabels...) - counter.Add(ctx, 22.0, notSoCommonLabels...) - - time.Sleep(5 * time.Second) - - (*observerLock).Lock() - *observerValueToReport = 13.0 - *observerLabelsToReport = commonLabels - (*observerLock).Unlock() - histogram.Record(ctx, 12.0, commonLabels...) - counter.Add(ctx, 13.0, commonLabels...) - - fmt.Println("Example finished updating, please visit :2222") - - select {} -} diff --git a/exporters/otlp/otlpmetric/clients.go b/exporters/otlp/otlpmetric/clients.go deleted file mode 100644 index 6808d464761..00000000000 --- a/exporters/otlp/otlpmetric/clients.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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 otlpmetric // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - -import ( - "context" - - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -// Client manages connections to the collector, handles the -// transformation of data into wire format, and the transmission of that -// data to the collector. -type Client interface { - // Start should establish connection(s) to endpoint(s). It is - // called just once by the exporter, so the implementation - // does not need to worry about idempotence and locking. - Start(ctx context.Context) error - // Stop should close the connections. The function is called - // only once by the exporter, so the implementation does not - // need to worry about idempotence, but it may be called - // concurrently with UploadMetrics, so proper - // locking is required. The function serves as a - // synchronization point - after the function returns, the - // process of closing connections is assumed to be finished. - Stop(ctx context.Context) error - // UploadMetrics should transform the passed metrics to the - // wire format and send it to the collector. May be called - // concurrently. - UploadMetrics(ctx context.Context, protoMetrics *metricpb.ResourceMetrics) error -} diff --git a/exporters/otlp/otlpmetric/exporter.go b/exporters/otlp/otlpmetric/exporter.go deleted file mode 100644 index caf21eaf2a3..00000000000 --- a/exporters/otlp/otlpmetric/exporter.go +++ /dev/null @@ -1,132 +0,0 @@ -// 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 otlpmetric // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - -import ( - "context" - "errors" - "sync" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/metrictransform" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -var ( - errAlreadyStarted = errors.New("already started") -) - -// Exporter exports metrics data in the OTLP wire format. -type Exporter struct { - client Client - temporalitySelector aggregation.TemporalitySelector - - mu sync.RWMutex - started bool - - startOnce sync.Once - stopOnce sync.Once -} - -// Export exports a batch of metrics. -func (e *Exporter) Export(ctx context.Context, res *resource.Resource, ilr export.InstrumentationLibraryReader) error { - rm, err := metrictransform.InstrumentationLibraryReader(ctx, e, res, ilr, 1) - if err != nil { - return err - } - if rm == nil { - return nil - } - - // TODO: There is never more than one resource emitted by this - // call, as per the specification. We can change the - // signature of UploadMetrics correspondingly. Here create a - // singleton list to reduce the size of the current PR: - return e.client.UploadMetrics(ctx, rm) -} - -// Start establishes a connection to the receiving endpoint. -func (e *Exporter) Start(ctx context.Context) error { - var err = errAlreadyStarted - e.startOnce.Do(func() { - e.mu.Lock() - e.started = true - e.mu.Unlock() - err = e.client.Start(ctx) - }) - - return err -} - -// Shutdown flushes all exports and closes all connections to the receiving endpoint. -func (e *Exporter) Shutdown(ctx context.Context) error { - - e.mu.RLock() - started := e.started - e.mu.RUnlock() - - if !started { - return nil - } - - var err error - - e.stopOnce.Do(func() { - err = e.client.Stop(ctx) - e.mu.Lock() - e.started = false - e.mu.Unlock() - }) - - return err -} - -func (e *Exporter) TemporalityFor(descriptor *sdkapi.Descriptor, kind aggregation.Kind) aggregation.Temporality { - return e.temporalitySelector.TemporalityFor(descriptor, kind) -} - -var _ export.Exporter = (*Exporter)(nil) - -// New constructs a new Exporter and starts it. -func New(ctx context.Context, client Client, opts ...Option) (*Exporter, error) { - exp := NewUnstarted(client, opts...) - if err := exp.Start(ctx); err != nil { - return nil, err - } - return exp, nil -} - -// NewUnstarted constructs a new Exporter and does not start it. -func NewUnstarted(client Client, opts ...Option) *Exporter { - cfg := config{ - // Note: the default TemporalitySelector is specified - // as Cumulative: - // https://github.com/open-telemetry/opentelemetry-specification/issues/731 - temporalitySelector: aggregation.CumulativeTemporalitySelector(), - } - - for _, opt := range opts { - cfg = opt.apply(cfg) - } - - e := &Exporter{ - client: client, - temporalitySelector: cfg.temporalitySelector, - } - - return e -} diff --git a/exporters/otlp/otlpmetric/exporter_test.go b/exporters/otlp/otlpmetric/exporter_test.go deleted file mode 100644 index 242079a20c7..00000000000 --- a/exporters/otlp/otlpmetric/exporter_test.go +++ /dev/null @@ -1,848 +0,0 @@ -// 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 otlpmetric_test - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/google/go-cmp/cmp" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/testing/protocmp" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/metrictransform" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" - commonpb "go.opentelemetry.io/proto/otlp/common/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -var ( - // Timestamps used in this test: - - intervalStart = time.Now() - intervalEnd = intervalStart.Add(time.Hour) -) - -type stubClient struct { - rm []*metricpb.ResourceMetrics -} - -func (m *stubClient) Start(ctx context.Context) error { - return nil -} - -func (m *stubClient) Stop(ctx context.Context) error { - return nil -} - -func (m *stubClient) UploadMetrics(ctx context.Context, protoMetrics *metricpb.ResourceMetrics) error { - m.rm = append(m.rm, protoMetrics) - return nil -} - -var _ otlpmetric.Client = (*stubClient)(nil) - -func (m *stubClient) Reset() { - m.rm = nil -} - -func newExporter(t *testing.T, opts ...otlpmetric.Option) (*otlpmetric.Exporter, *stubClient) { - client := &stubClient{} - exp, _ := otlpmetric.New(context.Background(), client, opts...) - return exp, client -} - -func startTime() uint64 { - return uint64(intervalStart.UnixNano()) -} - -func pointTime() uint64 { - return uint64(intervalEnd.UnixNano()) -} - -type testRecord struct { - name string - iKind sdkapi.InstrumentKind - nKind number.Kind - labels []attribute.KeyValue - - meterName string - meterOpts []metric.MeterOption -} - -func record( - name string, - iKind sdkapi.InstrumentKind, - nKind number.Kind, - labels []attribute.KeyValue, - meterName string, - meterOpts ...metric.MeterOption) testRecord { - return testRecord{ - name: name, - iKind: iKind, - nKind: nKind, - labels: labels, - meterName: meterName, - meterOpts: meterOpts, - } -} - -var ( - baseKeyValues = []attribute.KeyValue{attribute.String("host", "test.com")} - cpuKey = attribute.Key("CPU") - - testHistogramBoundaries = []float64{2.0, 4.0, 8.0} - - cpu1Labels = []*commonpb.KeyValue{ - { - Key: "CPU", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_IntValue{ - IntValue: 1, - }, - }, - }, - { - Key: "host", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_StringValue{ - StringValue: "test.com", - }, - }, - }, - } - cpu2Labels = []*commonpb.KeyValue{ - { - Key: "CPU", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_IntValue{ - IntValue: 2, - }, - }, - }, - { - Key: "host", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_StringValue{ - StringValue: "test.com", - }, - }, - }, - } - - testerAResource = resource.NewSchemaless(attribute.String("instance", "tester-a")) - testerAResourcePb = metrictransform.Resource(testerAResource) -) - -const ( - // Most of this test uses an empty instrumentation library name. - testLibName = "" -) - -func TestNoGroupingExport(t *testing.T) { - runMetricExportTests( - t, - nil, - resource.Empty(), - []testRecord{ - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(2)), - testLibName, - ), - }, - []*metricpb.ResourceMetrics{ - { - Resource: nil, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Metrics: []*metricpb.Metric{ - { - Name: "int64-count", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: true, - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu2Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - ) -} - -func TestHistogramInt64MetricGroupingExport(t *testing.T) { - r := record( - "int64-histogram", - sdkapi.HistogramInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ) - sum := 11.0 - expected := []*metricpb.ResourceMetrics{ - { - Resource: nil, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Metrics: []*metricpb.Metric{ - { - Name: "int64-histogram", - Data: &metricpb.Metric_Histogram{ - Histogram: &metricpb.Histogram{ - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.HistogramDataPoint{ - { - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - Count: 2, - Sum: &sum, - ExplicitBounds: testHistogramBoundaries, - BucketCounts: []uint64{1, 0, 0, 1}, - }, - { - Attributes: cpu1Labels, - Count: 2, - Sum: &sum, - ExplicitBounds: testHistogramBoundaries, - BucketCounts: []uint64{1, 0, 0, 1}, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - runMetricExportTests(t, nil, resource.Empty(), []testRecord{r, r}, expected) -} - -func TestHistogramFloat64MetricGroupingExport(t *testing.T) { - r := record( - "float64-histogram", - sdkapi.HistogramInstrumentKind, - number.Float64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ) - sum := 11.0 - expected := []*metricpb.ResourceMetrics{ - { - Resource: nil, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Metrics: []*metricpb.Metric{ - { - Name: "float64-histogram", - Data: &metricpb.Metric_Histogram{ - Histogram: &metricpb.Histogram{ - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.HistogramDataPoint{ - { - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - Count: 2, - Sum: &sum, - ExplicitBounds: testHistogramBoundaries, - BucketCounts: []uint64{1, 0, 0, 1}, - }, - { - Attributes: cpu1Labels, - Count: 2, - Sum: &sum, - ExplicitBounds: testHistogramBoundaries, - BucketCounts: []uint64{1, 0, 0, 1}, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - runMetricExportTests(t, nil, resource.Empty(), []testRecord{r, r}, expected) -} - -func TestCountInt64MetricGroupingExport(t *testing.T) { - r := record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ) - runMetricExportTests( - t, - nil, - resource.Empty(), - []testRecord{r, r}, - []*metricpb.ResourceMetrics{ - { - Resource: nil, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Metrics: []*metricpb.Metric{ - { - Name: "int64-count", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: true, - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - ) -} - -func TestCountFloat64MetricGroupingExport(t *testing.T) { - r := record( - "float64-count", - sdkapi.CounterInstrumentKind, - number.Float64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ) - runMetricExportTests( - t, - nil, - resource.Empty(), - []testRecord{r, r}, - []*metricpb.ResourceMetrics{ - { - Resource: nil, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Metrics: []*metricpb.Metric{ - { - Name: "float64-count", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: true, - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsDouble{AsDouble: 11.0}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsDouble{AsDouble: 11.0}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - ) -} - -func TestResourceMetricGroupingExport(t *testing.T) { - runMetricExportTests( - t, - nil, - testerAResource, - []testRecord{ - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(2)), - testLibName, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ), - }, - []*metricpb.ResourceMetrics{ - { - Resource: testerAResourcePb, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Metrics: []*metricpb.Metric{ - { - Name: "int64-count", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: true, - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu2Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - ) -} - -func TestResourceInstLibMetricGroupingExport(t *testing.T) { - version1 := metric.WithInstrumentationVersion("v1") - version2 := metric.WithInstrumentationVersion("v2") - specialSchema := metric.WithSchemaURL("schurl") - summingLib := "summing-lib" - countingLib := "counting-lib" - runMetricExportTests( - t, - nil, - testerAResource, - []testRecord{ - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - countingLib, - version1, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - countingLib, - version2, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - countingLib, - version1, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(2)), - countingLib, - version1, - ), - record( - "int64-count", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - summingLib, - specialSchema, - ), - }, - []*metricpb.ResourceMetrics{ - { - Resource: testerAResourcePb, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Scope: &commonpb.InstrumentationScope{ - Name: "counting-lib", - Version: "v1", - }, - Metrics: []*metricpb.Metric{ - { - Name: "int64-count", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: true, - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu2Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - { - Scope: &commonpb.InstrumentationScope{ - Name: "counting-lib", - Version: "v2", - }, - Metrics: []*metricpb.Metric{ - { - Name: "int64-count", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: true, - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - { - Scope: &commonpb.InstrumentationScope{ - Name: "summing-lib", - }, - SchemaUrl: "schurl", - Metrics: []*metricpb.Metric{ - { - Name: "int64-count", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: true, - AggregationTemporality: metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - ) -} - -func TestStatelessAggregationTemporality(t *testing.T) { - type testcase struct { - name string - instrumentKind sdkapi.InstrumentKind - aggTemporality metricpb.AggregationTemporality - monotonic bool - } - - for _, k := range []testcase{ - {"counter", sdkapi.CounterInstrumentKind, metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_DELTA, true}, - {"updowncounter", sdkapi.UpDownCounterInstrumentKind, metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_DELTA, false}, - {"counterobserver", sdkapi.CounterObserverInstrumentKind, metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, true}, - {"updowncounterobserver", sdkapi.UpDownCounterObserverInstrumentKind, metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE, false}, - } { - t.Run(k.name, func(t *testing.T) { - runMetricExportTests( - t, - []otlpmetric.Option{ - otlpmetric.WithMetricAggregationTemporalitySelector( - aggregation.StatelessTemporalitySelector(), - ), - }, - testerAResource, - []testRecord{ - record( - "instrument", - k.instrumentKind, - number.Int64Kind, - append(baseKeyValues, cpuKey.Int(1)), - testLibName, - ), - }, - []*metricpb.ResourceMetrics{ - { - Resource: testerAResourcePb, - ScopeMetrics: []*metricpb.ScopeMetrics{ - { - Metrics: []*metricpb.Metric{ - { - Name: "instrument", - Data: &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: k.monotonic, - AggregationTemporality: k.aggTemporality, - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{AsInt: 11}, - Attributes: cpu1Labels, - StartTimeUnixNano: startTime(), - TimeUnixNano: pointTime(), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - ) - }) - } -} - -func runMetricExportTests(t *testing.T, opts []otlpmetric.Option, res *resource.Resource, records []testRecord, expected []*metricpb.ResourceMetrics) { - exp, driver := newExporter(t, opts...) - - libraryRecs := map[instrumentation.Library][]export.Record{} - for _, r := range records { - lcopy := make([]attribute.KeyValue, len(r.labels)) - copy(lcopy, r.labels) - desc := metrictest.NewDescriptor(r.name, r.iKind, r.nKind) - labs := attribute.NewSet(lcopy...) - - var agg, ckpt aggregator.Aggregator - if r.iKind.Adding() { - sums := sum.New(2) - agg, ckpt = &sums[0], &sums[1] - } else { - histos := histogram.New(2, &desc, histogram.WithExplicitBoundaries(testHistogramBoundaries)) - agg, ckpt = &histos[0], &histos[1] - } - - ctx := context.Background() - if r.iKind.Synchronous() { - // For synchronous instruments, perform two updates: 1 and 10 - switch r.nKind { - case number.Int64Kind: - require.NoError(t, agg.Update(ctx, number.NewInt64Number(1), &desc)) - require.NoError(t, agg.Update(ctx, number.NewInt64Number(10), &desc)) - case number.Float64Kind: - require.NoError(t, agg.Update(ctx, number.NewFloat64Number(1), &desc)) - require.NoError(t, agg.Update(ctx, number.NewFloat64Number(10), &desc)) - default: - t.Fatalf("invalid number kind: %v", r.nKind) - } - } else { - // For asynchronous instruments, perform a single update: 11 - switch r.nKind { - case number.Int64Kind: - require.NoError(t, agg.Update(ctx, number.NewInt64Number(11), &desc)) - case number.Float64Kind: - require.NoError(t, agg.Update(ctx, number.NewFloat64Number(11), &desc)) - default: - t.Fatalf("invalid number kind: %v", r.nKind) - } - } - require.NoError(t, agg.SynchronizedMove(ckpt, &desc)) - - meterCfg := metric.NewMeterConfig(r.meterOpts...) - lib := instrumentation.Library{ - Name: r.meterName, - Version: meterCfg.InstrumentationVersion(), - SchemaURL: meterCfg.SchemaURL(), - } - libraryRecs[lib] = append(libraryRecs[lib], export.NewRecord(&desc, &labs, ckpt.Aggregation(), intervalStart, intervalEnd)) - } - assert.NoError(t, exp.Export(context.Background(), res, processortest.MultiInstrumentationLibraryReader(libraryRecs))) - - // assert.ElementsMatch does not equate nested slices of different order, - // therefore this requires the top level slice to be broken down. - // Build a map of Resource/Scope pairs to Metrics, from that validate the - // metric elements match for all expected pairs. Finally, make we saw all - // expected pairs. - keyFor := func(sm *metricpb.ScopeMetrics) string { - return fmt.Sprintf("%s/%s/%s", sm.GetScope().GetName(), sm.GetScope().GetVersion(), sm.GetSchemaUrl()) - } - got := map[string][]*metricpb.Metric{} - for _, rm := range driver.rm { - for _, sm := range rm.ScopeMetrics { - k := keyFor(sm) - got[k] = append(got[k], sm.GetMetrics()...) - } - } - - seen := map[string]struct{}{} - for _, rm := range expected { - for _, sm := range rm.ScopeMetrics { - k := keyFor(sm) - seen[k] = struct{}{} - g, ok := got[k] - if !ok { - t.Errorf("missing metrics for:\n\tInstrumentationScope: %q\n", k) - continue - } - if !assert.Len(t, g, len(sm.GetMetrics())) { - continue - } - for i, expected := range sm.GetMetrics() { - assert.Equal(t, "", cmp.Diff(expected, g[i], protocmp.Transform())) - } - } - } - for k := range got { - if _, ok := seen[k]; !ok { - t.Errorf("did not expect metrics for:\n\tInstrumentationScope: %s\n", k) - } - } -} - -func TestEmptyMetricExport(t *testing.T) { - exp, driver := newExporter(t) - - for _, test := range []struct { - records []export.Record - want []*metricpb.ResourceMetrics - }{ - { - []export.Record(nil), - []*metricpb.ResourceMetrics(nil), - }, - { - []export.Record{}, - []*metricpb.ResourceMetrics(nil), - }, - } { - driver.Reset() - require.NoError(t, exp.Export(context.Background(), resource.Empty(), processortest.MultiInstrumentationLibraryReader(map[instrumentation.Library][]export.Record{ - { - Name: testLibName, - }: test.records, - }))) - assert.Equal(t, test.want, driver.rm) - } -} diff --git a/exporters/otlp/otlpmetric/go.mod b/exporters/otlp/otlpmetric/go.mod deleted file mode 100644 index 732ae1e22a5..00000000000 --- a/exporters/otlp/otlpmetric/go.mod +++ /dev/null @@ -1,80 +0,0 @@ -module go.opentelemetry.io/otel/exporters/otlp/otlpmetric - -go 1.16 - -require ( - github.com/google/go-cmp v0.5.7 - github.com/stretchr/testify v1.7.1 - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.3 - go.opentelemetry.io/otel/metric v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/otel/sdk/metric v0.29.0 - go.opentelemetry.io/proto/otlp v0.15.0 - google.golang.org/grpc v1.45.0 - google.golang.org/protobuf v1.28.0 -) - -replace go.opentelemetry.io/otel => ../../.. - -replace go.opentelemetry.io/otel/sdk => ../../../sdk - -replace go.opentelemetry.io/otel/metric => ../../../metric - -replace go.opentelemetry.io/otel/trace => ../../../trace - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../../sdk/export/metric - -replace go.opentelemetry.io/otel/sdk/metric => ../../../sdk/metric - -replace go.opentelemetry.io/otel/bridge/opencensus => ../../../bridge/opencensus - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../../bridge/opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../../../example/jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../../../example/namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../../../example/opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../../../example/otel-collector - -replace go.opentelemetry.io/otel/example/passthrough => ../../../example/passthrough - -replace go.opentelemetry.io/otel/example/prometheus => ../../../example/prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../../../example/zipkin - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../internal/retry - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ./ - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ./otlpmetricgrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/internal/tools => ../../../internal/tools - -replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../jaeger - -replace go.opentelemetry.io/otel/exporters/prometheus => ../../prometheus - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../zipkin - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ./otlpmetrichttp - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../../bridge/opencensus/test - -replace go.opentelemetry.io/otel/example/fib => ../../../example/fib - -replace go.opentelemetry.io/otel/schema => ../../../schema diff --git a/exporters/otlp/otlpmetric/go.sum b/exporters/otlp/otlpmetric/go.sum deleted file mode 100644 index f69a11110a4..00000000000 --- a/exporters/otlp/otlpmetric/go.sum +++ /dev/null @@ -1,435 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -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/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= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/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= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0 h1:h0bKrvdrT/9sBwEJ6iWUqT/N/xPcS66bL4u3isneJ6w= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/exporters/otlp/otlpmetric/internal/metrictransform/attribute.go b/exporters/otlp/otlpmetric/internal/metrictransform/attribute.go deleted file mode 100644 index 4a59073824c..00000000000 --- a/exporters/otlp/otlpmetric/internal/metrictransform/attribute.go +++ /dev/null @@ -1,158 +0,0 @@ -// 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 metrictransform // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/metrictransform" - -import ( - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/resource" - commonpb "go.opentelemetry.io/proto/otlp/common/v1" -) - -// KeyValues transforms a slice of attribute KeyValues into OTLP key-values. -func KeyValues(attrs []attribute.KeyValue) []*commonpb.KeyValue { - if len(attrs) == 0 { - return nil - } - - out := make([]*commonpb.KeyValue, 0, len(attrs)) - for _, kv := range attrs { - out = append(out, KeyValue(kv)) - } - return out -} - -// Iterator transforms an attribute iterator into OTLP key-values. -func Iterator(iter attribute.Iterator) []*commonpb.KeyValue { - l := iter.Len() - if l == 0 { - return nil - } - - out := make([]*commonpb.KeyValue, 0, l) - for iter.Next() { - out = append(out, KeyValue(iter.Attribute())) - } - return out -} - -// ResourceAttributes transforms a Resource OTLP key-values. -func ResourceAttributes(resource *resource.Resource) []*commonpb.KeyValue { - return Iterator(resource.Iter()) -} - -// KeyValue transforms an attribute KeyValue into an OTLP key-value. -func KeyValue(kv attribute.KeyValue) *commonpb.KeyValue { - return &commonpb.KeyValue{Key: string(kv.Key), Value: Value(kv.Value)} -} - -// Value transforms an attribute Value into an OTLP AnyValue. -func Value(v attribute.Value) *commonpb.AnyValue { - av := new(commonpb.AnyValue) - switch v.Type() { - case attribute.BOOL: - av.Value = &commonpb.AnyValue_BoolValue{ - BoolValue: v.AsBool(), - } - case attribute.BOOLSLICE: - av.Value = &commonpb.AnyValue_ArrayValue{ - ArrayValue: &commonpb.ArrayValue{ - Values: boolSliceValues(v.AsBoolSlice()), - }, - } - case attribute.INT64: - av.Value = &commonpb.AnyValue_IntValue{ - IntValue: v.AsInt64(), - } - case attribute.INT64SLICE: - av.Value = &commonpb.AnyValue_ArrayValue{ - ArrayValue: &commonpb.ArrayValue{ - Values: int64SliceValues(v.AsInt64Slice()), - }, - } - case attribute.FLOAT64: - av.Value = &commonpb.AnyValue_DoubleValue{ - DoubleValue: v.AsFloat64(), - } - case attribute.FLOAT64SLICE: - av.Value = &commonpb.AnyValue_ArrayValue{ - ArrayValue: &commonpb.ArrayValue{ - Values: float64SliceValues(v.AsFloat64Slice()), - }, - } - case attribute.STRING: - av.Value = &commonpb.AnyValue_StringValue{ - StringValue: v.AsString(), - } - case attribute.STRINGSLICE: - av.Value = &commonpb.AnyValue_ArrayValue{ - ArrayValue: &commonpb.ArrayValue{ - Values: stringSliceValues(v.AsStringSlice()), - }, - } - default: - av.Value = &commonpb.AnyValue_StringValue{ - StringValue: "INVALID", - } - } - return av -} - -func boolSliceValues(vals []bool) []*commonpb.AnyValue { - converted := make([]*commonpb.AnyValue, len(vals)) - for i, v := range vals { - converted[i] = &commonpb.AnyValue{ - Value: &commonpb.AnyValue_BoolValue{ - BoolValue: v, - }, - } - } - return converted -} - -func int64SliceValues(vals []int64) []*commonpb.AnyValue { - converted := make([]*commonpb.AnyValue, len(vals)) - for i, v := range vals { - converted[i] = &commonpb.AnyValue{ - Value: &commonpb.AnyValue_IntValue{ - IntValue: v, - }, - } - } - return converted -} - -func float64SliceValues(vals []float64) []*commonpb.AnyValue { - converted := make([]*commonpb.AnyValue, len(vals)) - for i, v := range vals { - converted[i] = &commonpb.AnyValue{ - Value: &commonpb.AnyValue_DoubleValue{ - DoubleValue: v, - }, - } - } - return converted -} - -func stringSliceValues(vals []string) []*commonpb.AnyValue { - converted := make([]*commonpb.AnyValue, len(vals)) - for i, v := range vals { - converted[i] = &commonpb.AnyValue{ - Value: &commonpb.AnyValue_StringValue{ - StringValue: v, - }, - } - } - return converted -} diff --git a/exporters/otlp/otlpmetric/internal/metrictransform/attribute_test.go b/exporters/otlp/otlpmetric/internal/metrictransform/attribute_test.go deleted file mode 100644 index 4c468da694c..00000000000 --- a/exporters/otlp/otlpmetric/internal/metrictransform/attribute_test.go +++ /dev/null @@ -1,259 +0,0 @@ -// 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 metrictransform - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/otel/attribute" - commonpb "go.opentelemetry.io/proto/otlp/common/v1" -) - -type attributeTest struct { - attrs []attribute.KeyValue - expected []*commonpb.KeyValue -} - -func TestAttributes(t *testing.T) { - for _, test := range []attributeTest{ - {nil, nil}, - { - []attribute.KeyValue{ - attribute.Int("int to int", 123), - attribute.Int64("int64 to int64", 1234567), - attribute.Float64("float64 to double", 1.61), - attribute.String("string to string", "string"), - attribute.Bool("bool to bool", true), - }, - []*commonpb.KeyValue{ - { - Key: "int to int", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_IntValue{ - IntValue: 123, - }, - }, - }, - { - Key: "int64 to int64", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_IntValue{ - IntValue: 1234567, - }, - }, - }, - { - Key: "float64 to double", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_DoubleValue{ - DoubleValue: 1.61, - }, - }, - }, - { - Key: "string to string", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_StringValue{ - StringValue: "string", - }, - }, - }, - { - Key: "bool to bool", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_BoolValue{ - BoolValue: true, - }, - }, - }, - }, - }, - } { - got := KeyValues(test.attrs) - if !assert.Len(t, got, len(test.expected)) { - continue - } - for i, actual := range got { - if a, ok := actual.Value.Value.(*commonpb.AnyValue_DoubleValue); ok { - e, ok := test.expected[i].Value.Value.(*commonpb.AnyValue_DoubleValue) - if !ok { - t.Errorf("expected AnyValue_DoubleValue, got %T", test.expected[i].Value.Value) - continue - } - if !assert.InDelta(t, e.DoubleValue, a.DoubleValue, 0.01) { - continue - } - e.DoubleValue = a.DoubleValue - } - assert.Equal(t, test.expected[i], actual) - } - } -} - -func TestArrayAttributes(t *testing.T) { - // Array KeyValue supports only arrays of primitive types: - // "bool", "int", "int64", - // "float64", "string", - for _, test := range []attributeTest{ - {nil, nil}, - { - []attribute.KeyValue{ - { - Key: attribute.Key("invalid"), - Value: attribute.Value{}, - }, - }, - []*commonpb.KeyValue{ - { - Key: "invalid", - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_StringValue{ - StringValue: "INVALID", - }, - }, - }, - }, - }, - { - []attribute.KeyValue{ - attribute.BoolSlice("bool slice to bool array", []bool{true, false}), - attribute.IntSlice("int slice to int64 array", []int{1, 2, 3}), - attribute.Int64Slice("int64 slice to int64 array", []int64{1, 2, 3}), - attribute.Float64Slice("float64 slice to double array", []float64{1.11, 2.22, 3.33}), - attribute.StringSlice("string slice to string array", []string{"foo", "bar", "baz"}), - }, - []*commonpb.KeyValue{ - newOTelBoolArray("bool slice to bool array", []bool{true, false}), - newOTelIntArray("int slice to int64 array", []int64{1, 2, 3}), - newOTelIntArray("int64 slice to int64 array", []int64{1, 2, 3}), - newOTelDoubleArray("float64 slice to double array", []float64{1.11, 2.22, 3.33}), - newOTelStringArray("string slice to string array", []string{"foo", "bar", "baz"}), - }, - }, - } { - actualArrayAttributes := KeyValues(test.attrs) - expectedArrayAttributes := test.expected - if !assert.Len(t, actualArrayAttributes, len(expectedArrayAttributes)) { - continue - } - - for i, actualArrayAttr := range actualArrayAttributes { - expectedArrayAttr := expectedArrayAttributes[i] - expectedKey, actualKey := expectedArrayAttr.Key, actualArrayAttr.Key - if !assert.Equal(t, expectedKey, actualKey) { - continue - } - - expected := expectedArrayAttr.Value.GetArrayValue() - actual := actualArrayAttr.Value.GetArrayValue() - if expected == nil { - assert.Nil(t, actual) - continue - } - if assert.NotNil(t, actual, "expected not nil for %s", actualKey) { - assertExpectedArrayValues(t, expected.Values, actual.Values) - } - } - - } -} - -func assertExpectedArrayValues(t *testing.T, expectedValues, actualValues []*commonpb.AnyValue) { - for i, actual := range actualValues { - expected := expectedValues[i] - if a, ok := actual.Value.(*commonpb.AnyValue_DoubleValue); ok { - e, ok := expected.Value.(*commonpb.AnyValue_DoubleValue) - if !ok { - t.Errorf("expected AnyValue_DoubleValue, got %T", expected.Value) - continue - } - if !assert.InDelta(t, e.DoubleValue, a.DoubleValue, 0.01) { - continue - } - e.DoubleValue = a.DoubleValue - } - assert.Equal(t, expected, actual) - } -} - -func newOTelBoolArray(key string, values []bool) *commonpb.KeyValue { - arrayValues := []*commonpb.AnyValue{} - for _, b := range values { - arrayValues = append(arrayValues, &commonpb.AnyValue{ - Value: &commonpb.AnyValue_BoolValue{ - BoolValue: b, - }, - }) - } - - return newOTelArray(key, arrayValues) -} - -func newOTelIntArray(key string, values []int64) *commonpb.KeyValue { - arrayValues := []*commonpb.AnyValue{} - - for _, i := range values { - arrayValues = append(arrayValues, &commonpb.AnyValue{ - Value: &commonpb.AnyValue_IntValue{ - IntValue: i, - }, - }) - } - - return newOTelArray(key, arrayValues) -} - -func newOTelDoubleArray(key string, values []float64) *commonpb.KeyValue { - arrayValues := []*commonpb.AnyValue{} - - for _, d := range values { - arrayValues = append(arrayValues, &commonpb.AnyValue{ - Value: &commonpb.AnyValue_DoubleValue{ - DoubleValue: d, - }, - }) - } - - return newOTelArray(key, arrayValues) -} - -func newOTelStringArray(key string, values []string) *commonpb.KeyValue { - arrayValues := []*commonpb.AnyValue{} - - for _, s := range values { - arrayValues = append(arrayValues, &commonpb.AnyValue{ - Value: &commonpb.AnyValue_StringValue{ - StringValue: s, - }, - }) - } - - return newOTelArray(key, arrayValues) -} - -func newOTelArray(key string, arrayValues []*commonpb.AnyValue) *commonpb.KeyValue { - return &commonpb.KeyValue{ - Key: key, - Value: &commonpb.AnyValue{ - Value: &commonpb.AnyValue_ArrayValue{ - ArrayValue: &commonpb.ArrayValue{ - Values: arrayValues, - }, - }, - }, - } -} diff --git a/exporters/otlp/otlpmetric/internal/metrictransform/metric.go b/exporters/otlp/otlpmetric/internal/metrictransform/metric.go deleted file mode 100644 index 03a3d250ab0..00000000000 --- a/exporters/otlp/otlpmetric/internal/metrictransform/metric.go +++ /dev/null @@ -1,441 +0,0 @@ -// 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 metrictransform provides translations for opentelemetry-go concepts and -// structures to otlp structures. -package metrictransform // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/metrictransform" - -import ( - "context" - "errors" - "fmt" - "strings" - "sync" - "time" - - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/resource" - commonpb "go.opentelemetry.io/proto/otlp/common/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -var ( - // ErrUnimplementedAgg is returned when a transformation of an unimplemented - // aggregator is attempted. - ErrUnimplementedAgg = errors.New("unimplemented aggregator") - - // ErrIncompatibleAgg is returned when - // aggregation.Kind implies an interface conversion that has - // failed - ErrIncompatibleAgg = errors.New("incompatible aggregation type") - - // ErrUnknownValueType is returned when a transformation of an unknown value - // is attempted. - ErrUnknownValueType = errors.New("invalid value type") - - // ErrContextCanceled is returned when a context cancellation halts a - // transformation. - ErrContextCanceled = errors.New("context canceled") - - // ErrTransforming is returned when an unexected error is encountered transforming. - ErrTransforming = errors.New("transforming failed") -) - -// result is the product of transforming Records into OTLP Metrics. -type result struct { - Metric *metricpb.Metric - Err error -} - -// toNanos returns the number of nanoseconds since the UNIX epoch. -func toNanos(t time.Time) uint64 { - if t.IsZero() { - return 0 - } - return uint64(t.UnixNano()) -} - -// InstrumentationLibraryReader transforms all records contained in a checkpoint into -// batched OTLP ResourceMetrics. -func InstrumentationLibraryReader(ctx context.Context, temporalitySelector aggregation.TemporalitySelector, res *resource.Resource, ilmr export.InstrumentationLibraryReader, numWorkers uint) (*metricpb.ResourceMetrics, error) { - var sms []*metricpb.ScopeMetrics - - err := ilmr.ForEach(func(lib instrumentation.Library, mr export.Reader) error { - - records, errc := source(ctx, temporalitySelector, mr) - - // Start a fixed number of goroutines to transform records. - transformed := make(chan result) - var wg sync.WaitGroup - wg.Add(int(numWorkers)) - for i := uint(0); i < numWorkers; i++ { - go func() { - defer wg.Done() - transformer(ctx, temporalitySelector, records, transformed) - }() - } - go func() { - wg.Wait() - close(transformed) - }() - - // Synchronously collect the transformed records and transmit. - ms, err := sink(ctx, transformed) - if err != nil { - return nil - } - - // source is complete, check for any errors. - if err := <-errc; err != nil { - return err - } - if len(ms) == 0 { - return nil - } - - sms = append(sms, &metricpb.ScopeMetrics{ - Metrics: ms, - SchemaUrl: lib.SchemaURL, - Scope: &commonpb.InstrumentationScope{ - Name: lib.Name, - Version: lib.Version, - }, - }) - return nil - }) - if len(sms) == 0 { - return nil, err - } - - rms := &metricpb.ResourceMetrics{ - Resource: Resource(res), - SchemaUrl: res.SchemaURL(), - ScopeMetrics: sms, - } - - return rms, err -} - -// source starts a goroutine that sends each one of the Records yielded by -// the Reader on the returned chan. Any error encountered will be sent -// on the returned error chan after seeding is complete. -func source(ctx context.Context, temporalitySelector aggregation.TemporalitySelector, mr export.Reader) (<-chan export.Record, <-chan error) { - errc := make(chan error, 1) - out := make(chan export.Record) - // Seed records into process. - go func() { - defer close(out) - // No select is needed since errc is buffered. - errc <- mr.ForEach(temporalitySelector, func(r export.Record) error { - select { - case <-ctx.Done(): - return ErrContextCanceled - case out <- r: - } - return nil - }) - }() - return out, errc -} - -// transformer transforms records read from the passed in chan into -// OTLP Metrics which are sent on the out chan. -func transformer(ctx context.Context, temporalitySelector aggregation.TemporalitySelector, in <-chan export.Record, out chan<- result) { - for r := range in { - m, err := Record(temporalitySelector, r) - // Propagate errors, but do not send empty results. - if err == nil && m == nil { - continue - } - res := result{ - Metric: m, - Err: err, - } - select { - case <-ctx.Done(): - return - case out <- res: - } - } -} - -// sink collects transformed Records and batches them. -// -// Any errors encountered transforming input will be reported with an -// ErrTransforming as well as the completed ResourceMetrics. It is up to the -// caller to handle any incorrect data in these ResourceMetric. -func sink(ctx context.Context, in <-chan result) ([]*metricpb.Metric, error) { - var errStrings []string - - // Group by the MetricDescriptor. - grouped := map[string]*metricpb.Metric{} - for res := range in { - if res.Err != nil { - errStrings = append(errStrings, res.Err.Error()) - continue - } - - mID := res.Metric.GetName() - m, ok := grouped[mID] - if !ok { - grouped[mID] = res.Metric - continue - - } - // Note: There is extra work happening in this code - // that can be improved when the work described in - // #2119 is completed. The SDK has a guarantee that - // no more than one point per period per label set is - // produced, so this fallthrough should never happen. - // The final step of #2119 is to remove all the - // grouping logic here. - switch res.Metric.Data.(type) { - case *metricpb.Metric_Gauge: - m.GetGauge().DataPoints = append(m.GetGauge().DataPoints, res.Metric.GetGauge().DataPoints...) - case *metricpb.Metric_Sum: - m.GetSum().DataPoints = append(m.GetSum().DataPoints, res.Metric.GetSum().DataPoints...) - case *metricpb.Metric_Histogram: - m.GetHistogram().DataPoints = append(m.GetHistogram().DataPoints, res.Metric.GetHistogram().DataPoints...) - case *metricpb.Metric_Summary: - m.GetSummary().DataPoints = append(m.GetSummary().DataPoints, res.Metric.GetSummary().DataPoints...) - default: - err := fmt.Sprintf("unsupported metric type: %T", res.Metric.Data) - errStrings = append(errStrings, err) - } - } - - if len(grouped) == 0 { - return nil, nil - } - - ms := make([]*metricpb.Metric, 0, len(grouped)) - for _, m := range grouped { - ms = append(ms, m) - } - - // Report any transform errors. - if len(errStrings) > 0 { - return ms, fmt.Errorf("%w:\n -%s", ErrTransforming, strings.Join(errStrings, "\n -")) - } - return ms, nil -} - -// Record transforms a Record into an OTLP Metric. An ErrIncompatibleAgg -// error is returned if the Record Aggregator is not supported. -func Record(temporalitySelector aggregation.TemporalitySelector, r export.Record) (*metricpb.Metric, error) { - agg := r.Aggregation() - switch agg.Kind() { - case aggregation.HistogramKind: - h, ok := agg.(aggregation.Histogram) - if !ok { - return nil, fmt.Errorf("%w: %T", ErrIncompatibleAgg, agg) - } - return histogramPoint(r, temporalitySelector.TemporalityFor(r.Descriptor(), aggregation.HistogramKind), h) - - case aggregation.SumKind: - s, ok := agg.(aggregation.Sum) - if !ok { - return nil, fmt.Errorf("%w: %T", ErrIncompatibleAgg, agg) - } - sum, err := s.Sum() - if err != nil { - return nil, err - } - return sumPoint(r, sum, r.StartTime(), r.EndTime(), temporalitySelector.TemporalityFor(r.Descriptor(), aggregation.SumKind), r.Descriptor().InstrumentKind().Monotonic()) - - case aggregation.LastValueKind: - lv, ok := agg.(aggregation.LastValue) - if !ok { - return nil, fmt.Errorf("%w: %T", ErrIncompatibleAgg, agg) - } - value, tm, err := lv.LastValue() - if err != nil { - return nil, err - } - return gaugePoint(r, value, time.Time{}, tm) - - default: - return nil, fmt.Errorf("%w: %T", ErrUnimplementedAgg, agg) - } -} - -func gaugePoint(record export.Record, num number.Number, start, end time.Time) (*metricpb.Metric, error) { - desc := record.Descriptor() - labels := record.Labels() - - m := &metricpb.Metric{ - Name: desc.Name(), - Description: desc.Description(), - Unit: string(desc.Unit()), - } - - switch n := desc.NumberKind(); n { - case number.Int64Kind: - m.Data = &metricpb.Metric_Gauge{ - Gauge: &metricpb.Gauge{ - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{ - AsInt: num.CoerceToInt64(n), - }, - Attributes: Iterator(labels.Iter()), - StartTimeUnixNano: toNanos(start), - TimeUnixNano: toNanos(end), - }, - }, - }, - } - case number.Float64Kind: - m.Data = &metricpb.Metric_Gauge{ - Gauge: &metricpb.Gauge{ - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsDouble{ - AsDouble: num.CoerceToFloat64(n), - }, - Attributes: Iterator(labels.Iter()), - StartTimeUnixNano: toNanos(start), - TimeUnixNano: toNanos(end), - }, - }, - }, - } - default: - return nil, fmt.Errorf("%w: %v", ErrUnknownValueType, n) - } - - return m, nil -} - -func sdkTemporalityToTemporality(temporality aggregation.Temporality) metricpb.AggregationTemporality { - switch temporality { - case aggregation.DeltaTemporality: - return metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_DELTA - case aggregation.CumulativeTemporality: - return metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE - } - return metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_UNSPECIFIED -} - -func sumPoint(record export.Record, num number.Number, start, end time.Time, temporality aggregation.Temporality, monotonic bool) (*metricpb.Metric, error) { - desc := record.Descriptor() - labels := record.Labels() - - m := &metricpb.Metric{ - Name: desc.Name(), - Description: desc.Description(), - Unit: string(desc.Unit()), - } - - switch n := desc.NumberKind(); n { - case number.Int64Kind: - m.Data = &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: monotonic, - AggregationTemporality: sdkTemporalityToTemporality(temporality), - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsInt{ - AsInt: num.CoerceToInt64(n), - }, - Attributes: Iterator(labels.Iter()), - StartTimeUnixNano: toNanos(start), - TimeUnixNano: toNanos(end), - }, - }, - }, - } - case number.Float64Kind: - m.Data = &metricpb.Metric_Sum{ - Sum: &metricpb.Sum{ - IsMonotonic: monotonic, - AggregationTemporality: sdkTemporalityToTemporality(temporality), - DataPoints: []*metricpb.NumberDataPoint{ - { - Value: &metricpb.NumberDataPoint_AsDouble{ - AsDouble: num.CoerceToFloat64(n), - }, - Attributes: Iterator(labels.Iter()), - StartTimeUnixNano: toNanos(start), - TimeUnixNano: toNanos(end), - }, - }, - }, - } - default: - return nil, fmt.Errorf("%w: %v", ErrUnknownValueType, n) - } - - return m, nil -} - -func histogramValues(a aggregation.Histogram) (boundaries []float64, counts []uint64, err error) { - var buckets aggregation.Buckets - if buckets, err = a.Histogram(); err != nil { - return - } - boundaries, counts = buckets.Boundaries, buckets.Counts - if len(counts) != len(boundaries)+1 { - err = ErrTransforming - return - } - return -} - -// histogram transforms a Histogram Aggregator into an OTLP Metric. -func histogramPoint(record export.Record, temporality aggregation.Temporality, a aggregation.Histogram) (*metricpb.Metric, error) { - desc := record.Descriptor() - labels := record.Labels() - boundaries, counts, err := histogramValues(a) - if err != nil { - return nil, err - } - - count, err := a.Count() - if err != nil { - return nil, err - } - - sum, err := a.Sum() - if err != nil { - return nil, err - } - - sumFloat64 := sum.CoerceToFloat64(desc.NumberKind()) - m := &metricpb.Metric{ - Name: desc.Name(), - Description: desc.Description(), - Unit: string(desc.Unit()), - Data: &metricpb.Metric_Histogram{ - Histogram: &metricpb.Histogram{ - AggregationTemporality: sdkTemporalityToTemporality(temporality), - DataPoints: []*metricpb.HistogramDataPoint{ - { - Sum: &sumFloat64, - Attributes: Iterator(labels.Iter()), - StartTimeUnixNano: toNanos(record.StartTime()), - TimeUnixNano: toNanos(record.EndTime()), - Count: uint64(count), - BucketCounts: counts, - ExplicitBounds: boundaries, - }, - }, - }, - }, - } - return m, nil -} diff --git a/exporters/otlp/otlpmetric/internal/metrictransform/metric_test.go b/exporters/otlp/otlpmetric/internal/metrictransform/metric_test.go deleted file mode 100644 index d8f2a1c8b62..00000000000 --- a/exporters/otlp/otlpmetric/internal/metrictransform/metric_test.go +++ /dev/null @@ -1,315 +0,0 @@ -// 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 metrictransform - -import ( - "context" - "errors" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" - "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - commonpb "go.opentelemetry.io/proto/otlp/common/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -var ( - // Timestamps used in this test: - - intervalStart = time.Now() - intervalEnd = intervalStart.Add(time.Hour) -) - -const ( - otelCumulative = metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE - otelDelta = metricpb.AggregationTemporality_AGGREGATION_TEMPORALITY_DELTA -) - -func TestStringKeyValues(t *testing.T) { - tests := []struct { - kvs []attribute.KeyValue - expected []*commonpb.KeyValue - }{ - { - nil, - nil, - }, - { - []attribute.KeyValue{}, - nil, - }, - { - []attribute.KeyValue{ - attribute.Bool("true", true), - attribute.Int64("one", 1), - attribute.Int64("two", 2), - attribute.Float64("three", 3), - attribute.Int("four", 4), - attribute.Int("five", 5), - attribute.Float64("six", 6), - attribute.Int("seven", 7), - attribute.Int("eight", 8), - attribute.String("the", "final word"), - }, - []*commonpb.KeyValue{ - {Key: "eight", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_IntValue{IntValue: 8}}}, - {Key: "five", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_IntValue{IntValue: 5}}}, - {Key: "four", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_IntValue{IntValue: 4}}}, - {Key: "one", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_IntValue{IntValue: 1}}}, - {Key: "seven", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_IntValue{IntValue: 7}}}, - {Key: "six", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_DoubleValue{DoubleValue: 6.0}}}, - {Key: "the", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_StringValue{StringValue: "final word"}}}, - {Key: "three", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_DoubleValue{DoubleValue: 3.0}}}, - {Key: "true", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_BoolValue{BoolValue: true}}}, - {Key: "two", Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_IntValue{IntValue: 2}}}, - }, - }, - } - - for _, test := range tests { - labels := attribute.NewSet(test.kvs...) - assert.Equal(t, test.expected, Iterator(labels.Iter())) - } -} - -func TestSumIntDataPoints(t *testing.T) { - desc := metrictest.NewDescriptor("", sdkapi.HistogramInstrumentKind, number.Int64Kind) - labels := attribute.NewSet(attribute.String("one", "1")) - sums := sum.New(2) - s, ckpt := &sums[0], &sums[1] - - assert.NoError(t, s.Update(context.Background(), number.Number(1), &desc)) - require.NoError(t, s.SynchronizedMove(ckpt, &desc)) - record := export.NewRecord(&desc, &labels, ckpt.Aggregation(), intervalStart, intervalEnd) - - value, err := ckpt.Sum() - require.NoError(t, err) - - if m, err := sumPoint(record, value, record.StartTime(), record.EndTime(), aggregation.CumulativeTemporality, true); assert.NoError(t, err) { - assert.Nil(t, m.GetGauge()) - assert.Equal(t, &metricpb.Sum{ - AggregationTemporality: otelCumulative, - IsMonotonic: true, - DataPoints: []*metricpb.NumberDataPoint{{ - StartTimeUnixNano: uint64(intervalStart.UnixNano()), - TimeUnixNano: uint64(intervalEnd.UnixNano()), - Attributes: []*commonpb.KeyValue{ - { - Key: "one", - Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_StringValue{StringValue: "1"}}, - }, - }, - Value: &metricpb.NumberDataPoint_AsInt{ - AsInt: 1, - }, - }}, - }, m.GetSum()) - assert.Nil(t, m.GetHistogram()) - assert.Nil(t, m.GetSummary()) - } -} - -func TestSumFloatDataPoints(t *testing.T) { - desc := metrictest.NewDescriptor("", sdkapi.HistogramInstrumentKind, number.Float64Kind) - labels := attribute.NewSet(attribute.String("one", "1")) - sums := sum.New(2) - s, ckpt := &sums[0], &sums[1] - - assert.NoError(t, s.Update(context.Background(), number.NewFloat64Number(1), &desc)) - require.NoError(t, s.SynchronizedMove(ckpt, &desc)) - record := export.NewRecord(&desc, &labels, ckpt.Aggregation(), intervalStart, intervalEnd) - value, err := ckpt.Sum() - require.NoError(t, err) - - if m, err := sumPoint(record, value, record.StartTime(), record.EndTime(), aggregation.DeltaTemporality, false); assert.NoError(t, err) { - assert.Nil(t, m.GetGauge()) - assert.Equal(t, &metricpb.Sum{ - IsMonotonic: false, - AggregationTemporality: otelDelta, - DataPoints: []*metricpb.NumberDataPoint{{ - Value: &metricpb.NumberDataPoint_AsDouble{ - AsDouble: 1.0, - }, - StartTimeUnixNano: uint64(intervalStart.UnixNano()), - TimeUnixNano: uint64(intervalEnd.UnixNano()), - Attributes: []*commonpb.KeyValue{ - { - Key: "one", - Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_StringValue{StringValue: "1"}}, - }, - }, - }}}, m.GetSum()) - assert.Nil(t, m.GetHistogram()) - assert.Nil(t, m.GetSummary()) - - } -} - -func TestLastValueIntDataPoints(t *testing.T) { - desc := metrictest.NewDescriptor("", sdkapi.HistogramInstrumentKind, number.Int64Kind) - labels := attribute.NewSet(attribute.String("one", "1")) - lvs := lastvalue.New(2) - lv, ckpt := &lvs[0], &lvs[1] - - assert.NoError(t, lv.Update(context.Background(), number.Number(100), &desc)) - require.NoError(t, lv.SynchronizedMove(ckpt, &desc)) - record := export.NewRecord(&desc, &labels, ckpt.Aggregation(), intervalStart, intervalEnd) - value, timestamp, err := ckpt.LastValue() - require.NoError(t, err) - - if m, err := gaugePoint(record, value, time.Time{}, timestamp); assert.NoError(t, err) { - assert.Equal(t, []*metricpb.NumberDataPoint{{ - StartTimeUnixNano: 0, - TimeUnixNano: uint64(timestamp.UnixNano()), - Attributes: []*commonpb.KeyValue{ - { - Key: "one", - Value: &commonpb.AnyValue{Value: &commonpb.AnyValue_StringValue{StringValue: "1"}}, - }, - }, - Value: &metricpb.NumberDataPoint_AsInt{ - AsInt: 100, - }, - }}, m.GetGauge().DataPoints) - assert.Nil(t, m.GetSum()) - assert.Nil(t, m.GetHistogram()) - assert.Nil(t, m.GetSummary()) - } -} - -func TestSumErrUnknownValueType(t *testing.T) { - desc := metrictest.NewDescriptor("", sdkapi.HistogramInstrumentKind, number.Kind(-1)) - labels := attribute.NewSet() - s := &sum.New(1)[0] - record := export.NewRecord(&desc, &labels, s, intervalStart, intervalEnd) - value, err := s.Sum() - require.NoError(t, err) - - _, err = sumPoint(record, value, record.StartTime(), record.EndTime(), aggregation.CumulativeTemporality, true) - assert.Error(t, err) - if !errors.Is(err, ErrUnknownValueType) { - t.Errorf("expected ErrUnknownValueType, got %v", err) - } -} - -type testAgg struct { - kind aggregation.Kind - agg aggregation.Aggregation -} - -func (t *testAgg) Kind() aggregation.Kind { - return t.kind -} - -func (t *testAgg) Aggregation() aggregation.Aggregation { - return t.agg -} - -// None of these three are used: - -func (t *testAgg) Update(ctx context.Context, number number.Number, descriptor *sdkapi.Descriptor) error { - return nil -} -func (t *testAgg) SynchronizedMove(destination aggregator.Aggregator, descriptor *sdkapi.Descriptor) error { - return nil -} -func (t *testAgg) Merge(aggregator aggregator.Aggregator, descriptor *sdkapi.Descriptor) error { - return nil -} - -type testErrSum struct { - err error -} - -type testErrLastValue struct { - err error -} - -func (te *testErrLastValue) LastValue() (number.Number, time.Time, error) { - return 0, time.Time{}, te.err -} -func (te *testErrLastValue) Kind() aggregation.Kind { - return aggregation.LastValueKind -} - -func (te *testErrSum) Sum() (number.Number, error) { - return 0, te.err -} -func (te *testErrSum) Kind() aggregation.Kind { - return aggregation.SumKind -} - -var _ aggregator.Aggregator = &testAgg{} -var _ aggregation.Aggregation = &testAgg{} -var _ aggregation.Sum = &testErrSum{} -var _ aggregation.LastValue = &testErrLastValue{} - -func TestRecordAggregatorIncompatibleErrors(t *testing.T) { - makeMpb := func(kind aggregation.Kind, agg aggregation.Aggregation) (*metricpb.Metric, error) { - desc := metrictest.NewDescriptor("things", sdkapi.CounterInstrumentKind, number.Int64Kind) - labels := attribute.NewSet() - test := &testAgg{ - kind: kind, - agg: agg, - } - return Record(aggregation.CumulativeTemporalitySelector(), export.NewRecord(&desc, &labels, test, intervalStart, intervalEnd)) - } - - mpb, err := makeMpb(aggregation.SumKind, &lastvalue.New(1)[0]) - - require.Error(t, err) - require.Nil(t, mpb) - require.True(t, errors.Is(err, ErrIncompatibleAgg)) - - mpb, err = makeMpb(aggregation.LastValueKind, &sum.New(1)[0]) - - require.Error(t, err) - require.Nil(t, mpb) - require.True(t, errors.Is(err, ErrIncompatibleAgg)) -} - -func TestRecordAggregatorUnexpectedErrors(t *testing.T) { - makeMpb := func(kind aggregation.Kind, agg aggregation.Aggregation) (*metricpb.Metric, error) { - desc := metrictest.NewDescriptor("things", sdkapi.CounterInstrumentKind, number.Int64Kind) - labels := attribute.NewSet() - return Record(aggregation.CumulativeTemporalitySelector(), export.NewRecord(&desc, &labels, agg, intervalStart, intervalEnd)) - } - - errEx := fmt.Errorf("timeout") - - mpb, err := makeMpb(aggregation.SumKind, &testErrSum{errEx}) - - require.Error(t, err) - require.Nil(t, mpb) - require.True(t, errors.Is(err, errEx)) - - mpb, err = makeMpb(aggregation.LastValueKind, &testErrLastValue{errEx}) - - require.Error(t, err) - require.Nil(t, mpb) - require.True(t, errors.Is(err, errEx)) -} diff --git a/exporters/otlp/otlpmetric/internal/metrictransform/resource.go b/exporters/otlp/otlpmetric/internal/metrictransform/resource.go deleted file mode 100644 index dbf0c5e490a..00000000000 --- a/exporters/otlp/otlpmetric/internal/metrictransform/resource.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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 metrictransform // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/metrictransform" - -import ( - "go.opentelemetry.io/otel/sdk/resource" - resourcepb "go.opentelemetry.io/proto/otlp/resource/v1" -) - -// Resource transforms a Resource into an OTLP Resource. -func Resource(r *resource.Resource) *resourcepb.Resource { - if r == nil { - return nil - } - return &resourcepb.Resource{Attributes: ResourceAttributes(r)} -} diff --git a/exporters/otlp/otlpmetric/internal/metrictransform/resource_test.go b/exporters/otlp/otlpmetric/internal/metrictransform/resource_test.go deleted file mode 100644 index 016d2f1e019..00000000000 --- a/exporters/otlp/otlpmetric/internal/metrictransform/resource_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// 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 metrictransform - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/resource" -) - -func TestNilResource(t *testing.T) { - assert.Empty(t, Resource(nil)) -} - -func TestEmptyResource(t *testing.T) { - assert.Empty(t, Resource(&resource.Resource{})) -} - -/* -* This does not include any testing on the ordering of Resource Attributes. -* They are stored as a map internally to the Resource and their order is not -* guaranteed. - */ - -func TestResourceAttributes(t *testing.T) { - attrs := []attribute.KeyValue{attribute.Int("one", 1), attribute.Int("two", 2)} - - got := Resource(resource.NewSchemaless(attrs...)).GetAttributes() - if !assert.Len(t, attrs, 2) { - return - } - assert.ElementsMatch(t, KeyValues(attrs), got) -} diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig.go b/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig.go deleted file mode 100644 index d59912ddb6e..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig.go +++ /dev/null @@ -1,129 +0,0 @@ -// 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 otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" - -import ( - "crypto/tls" - "io/ioutil" - "net/url" - "os" - "path" - "strings" - "time" - - "go.opentelemetry.io/otel/exporters/otlp/internal/envconfig" -) - -// DefaultEnvOptionsReader is the default environments reader -var DefaultEnvOptionsReader = envconfig.EnvOptionsReader{ - GetEnv: os.Getenv, - ReadFile: ioutil.ReadFile, - Namespace: "OTEL_EXPORTER_OTLP", -} - -// ApplyGRPCEnvConfigs applies the env configurations for gRPC -func ApplyGRPCEnvConfigs(cfg Config) Config { - opts := getOptionsFromEnv() - for _, opt := range opts { - cfg = opt.ApplyGRPCOption(cfg) - } - return cfg -} - -// ApplyHTTPEnvConfigs applies the env configurations for HTTP -func ApplyHTTPEnvConfigs(cfg Config) Config { - opts := getOptionsFromEnv() - for _, opt := range opts { - cfg = opt.ApplyHTTPOption(cfg) - } - return cfg -} - -func getOptionsFromEnv() []GenericOption { - opts := []GenericOption{} - - DefaultEnvOptionsReader.Apply( - envconfig.WithURL("ENDPOINT", func(u *url.URL) { - opts = append(opts, withEndpointScheme(u)) - opts = append(opts, newSplitOption(func(cfg Config) Config { - cfg.Metrics.Endpoint = u.Host - // For OTLP/HTTP endpoint URLs without a per-signal - // configuration, the passed endpoint is used as a base URL - // and the signals are sent to these paths relative to that. - cfg.Metrics.URLPath = path.Join(u.Path, DefaultMetricsPath) - return cfg - }, withEndpointForGRPC(u))) - }), - envconfig.WithURL("METRICS_ENDPOINT", func(u *url.URL) { - opts = append(opts, withEndpointScheme(u)) - opts = append(opts, newSplitOption(func(cfg Config) Config { - cfg.Metrics.Endpoint = u.Host - // For endpoint URLs for OTLP/HTTP per-signal variables, the - // URL MUST be used as-is without any modification. The only - // exception is that if an URL contains no path part, the root - // path / MUST be used. - path := u.Path - if path == "" { - path = "/" - } - cfg.Metrics.URLPath = path - return cfg - }, withEndpointForGRPC(u))) - }), - envconfig.WithTLSConfig("CERTIFICATE", func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }), - envconfig.WithTLSConfig("METRICS_CERTIFICATE", func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }), - envconfig.WithHeaders("HEADERS", func(h map[string]string) { opts = append(opts, WithHeaders(h)) }), - envconfig.WithHeaders("METRICS_HEADERS", func(h map[string]string) { opts = append(opts, WithHeaders(h)) }), - WithEnvCompression("COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }), - WithEnvCompression("METRICS_COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }), - envconfig.WithDuration("TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }), - envconfig.WithDuration("METRICS_TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }), - ) - - return opts -} - -func withEndpointForGRPC(u *url.URL) func(cfg Config) Config { - return func(cfg Config) Config { - // For OTLP/gRPC endpoints, this is the target to which the - // exporter is going to send telemetry. - cfg.Metrics.Endpoint = path.Join(u.Host, u.Path) - return cfg - } -} - -// WithEnvCompression retrieves the specified config and passes it to ConfigFn as a Compression -func WithEnvCompression(n string, fn func(Compression)) func(e *envconfig.EnvOptionsReader) { - return func(e *envconfig.EnvOptionsReader) { - if v, ok := e.GetEnvValue(n); ok { - cp := NoCompression - switch v { - case "gzip": - cp = GzipCompression - } - - fn(cp) - } - } -} - -func withEndpointScheme(u *url.URL) GenericOption { - switch strings.ToLower(u.Scheme) { - case "http", "unix": - return WithInsecure() - default: - return WithSecure() - } -} diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig_test.go b/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig_test.go deleted file mode 100644 index 25021f7328c..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/envconfig_test.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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 otlpconfig diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/options.go b/exporters/otlp/otlpmetric/internal/otlpconfig/options.go deleted file mode 100644 index f2c8ee5d21a..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/options.go +++ /dev/null @@ -1,314 +0,0 @@ -// 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 otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" - -import ( - "crypto/tls" - "fmt" - "time" - - "google.golang.org/grpc" - "google.golang.org/grpc/backoff" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/encoding/gzip" - - "go.opentelemetry.io/otel/exporters/otlp/internal" - "go.opentelemetry.io/otel/exporters/otlp/internal/retry" -) - -const ( - // DefaultMaxAttempts describes how many times the driver - // should retry the sending of the payload in case of a - // retryable error. - DefaultMaxAttempts int = 5 - // DefaultMetricsPath is a default URL path for endpoint that - // receives metrics. - DefaultMetricsPath string = "/v1/metrics" - // DefaultBackoff is a default base backoff time used in the - // exponential backoff strategy. - DefaultBackoff time.Duration = 300 * time.Millisecond - // DefaultTimeout is a default max waiting time for the backend to process - // each span or metrics batch. - DefaultTimeout time.Duration = 10 * time.Second -) - -type ( - SignalConfig struct { - Endpoint string - Insecure bool - TLSCfg *tls.Config - Headers map[string]string - Compression Compression - Timeout time.Duration - URLPath string - - // gRPC configurations - GRPCCredentials credentials.TransportCredentials - } - - Config struct { - // Signal specific configurations - Metrics SignalConfig - - RetryConfig retry.Config - - // gRPC configurations - ReconnectionPeriod time.Duration - ServiceConfig string - DialOptions []grpc.DialOption - GRPCConn *grpc.ClientConn - } -) - -// NewHTTPConfig returns a new Config with all settings applied from opts and -// any unset setting using the default HTTP config values. -func NewHTTPConfig(opts ...HTTPOption) Config { - cfg := Config{ - Metrics: SignalConfig{ - Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorHTTPPort), - URLPath: DefaultMetricsPath, - Compression: NoCompression, - Timeout: DefaultTimeout, - }, - RetryConfig: retry.DefaultConfig, - } - cfg = ApplyHTTPEnvConfigs(cfg) - for _, opt := range opts { - cfg = opt.ApplyHTTPOption(cfg) - } - cfg.Metrics.URLPath = internal.CleanPath(cfg.Metrics.URLPath, DefaultMetricsPath) - return cfg -} - -// NewGRPCConfig returns a new Config with all settings applied from opts and -// any unset setting using the default gRPC config values. -func NewGRPCConfig(opts ...GRPCOption) Config { - cfg := Config{ - Metrics: SignalConfig{ - Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorGRPCPort), - URLPath: DefaultMetricsPath, - Compression: NoCompression, - Timeout: DefaultTimeout, - }, - RetryConfig: retry.DefaultConfig, - } - cfg = ApplyGRPCEnvConfigs(cfg) - for _, opt := range opts { - cfg = opt.ApplyGRPCOption(cfg) - } - - if cfg.ServiceConfig != "" { - cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig)) - } - // Priroritize GRPCCredentials over Insecure (passing both is an error). - if cfg.Metrics.GRPCCredentials != nil { - cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Metrics.GRPCCredentials)) - } else if cfg.Metrics.Insecure { - cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(insecure.NewCredentials())) - } else { - // Default to using the host's root CA. - creds := credentials.NewTLS(nil) - cfg.Metrics.GRPCCredentials = creds - cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(creds)) - } - if cfg.Metrics.Compression == GzipCompression { - cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultCallOptions(grpc.UseCompressor(gzip.Name))) - } - if len(cfg.DialOptions) != 0 { - cfg.DialOptions = append(cfg.DialOptions, cfg.DialOptions...) - } - if cfg.ReconnectionPeriod != 0 { - p := grpc.ConnectParams{ - Backoff: backoff.DefaultConfig, - MinConnectTimeout: cfg.ReconnectionPeriod, - } - cfg.DialOptions = append(cfg.DialOptions, grpc.WithConnectParams(p)) - } - - return cfg -} - -type ( - // GenericOption applies an option to the HTTP or gRPC driver. - GenericOption interface { - ApplyHTTPOption(Config) Config - ApplyGRPCOption(Config) Config - - // A private method to prevent users implementing the - // interface and so future additions to it will not - // violate compatibility. - private() - } - - // HTTPOption applies an option to the HTTP driver. - HTTPOption interface { - ApplyHTTPOption(Config) Config - - // A private method to prevent users implementing the - // interface and so future additions to it will not - // violate compatibility. - private() - } - - // GRPCOption applies an option to the gRPC driver. - GRPCOption interface { - ApplyGRPCOption(Config) Config - - // A private method to prevent users implementing the - // interface and so future additions to it will not - // violate compatibility. - private() - } -) - -// genericOption is an option that applies the same logic -// for both gRPC and HTTP. -type genericOption struct { - fn func(Config) Config -} - -func (g *genericOption) ApplyGRPCOption(cfg Config) Config { - return g.fn(cfg) -} - -func (g *genericOption) ApplyHTTPOption(cfg Config) Config { - return g.fn(cfg) -} - -func (genericOption) private() {} - -func newGenericOption(fn func(cfg Config) Config) GenericOption { - return &genericOption{fn: fn} -} - -// splitOption is an option that applies different logics -// for gRPC and HTTP. -type splitOption struct { - httpFn func(Config) Config - grpcFn func(Config) Config -} - -func (g *splitOption) ApplyGRPCOption(cfg Config) Config { - return g.grpcFn(cfg) -} - -func (g *splitOption) ApplyHTTPOption(cfg Config) Config { - return g.httpFn(cfg) -} - -func (splitOption) private() {} - -func newSplitOption(httpFn func(cfg Config) Config, grpcFn func(cfg Config) Config) GenericOption { - return &splitOption{httpFn: httpFn, grpcFn: grpcFn} -} - -// httpOption is an option that is only applied to the HTTP driver. -type httpOption struct { - fn func(Config) Config -} - -func (h *httpOption) ApplyHTTPOption(cfg Config) Config { - return h.fn(cfg) -} - -func (httpOption) private() {} - -func NewHTTPOption(fn func(cfg Config) Config) HTTPOption { - return &httpOption{fn: fn} -} - -// grpcOption is an option that is only applied to the gRPC driver. -type grpcOption struct { - fn func(Config) Config -} - -func (h *grpcOption) ApplyGRPCOption(cfg Config) Config { - return h.fn(cfg) -} - -func (grpcOption) private() {} - -func NewGRPCOption(fn func(cfg Config) Config) GRPCOption { - return &grpcOption{fn: fn} -} - -// Generic Options - -func WithEndpoint(endpoint string) GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.Metrics.Endpoint = endpoint - return cfg - }) -} - -func WithCompression(compression Compression) GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.Metrics.Compression = compression - return cfg - }) -} - -func WithURLPath(urlPath string) GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.Metrics.URLPath = urlPath - return cfg - }) -} - -func WithRetry(rc retry.Config) GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.RetryConfig = rc - return cfg - }) -} - -func WithTLSClientConfig(tlsCfg *tls.Config) GenericOption { - return newSplitOption(func(cfg Config) Config { - cfg.Metrics.TLSCfg = tlsCfg.Clone() - return cfg - }, func(cfg Config) Config { - cfg.Metrics.GRPCCredentials = credentials.NewTLS(tlsCfg) - return cfg - }) -} - -func WithInsecure() GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.Metrics.Insecure = true - return cfg - }) -} - -func WithSecure() GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.Metrics.Insecure = false - return cfg - }) -} - -func WithHeaders(headers map[string]string) GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.Metrics.Headers = headers - return cfg - }) -} - -func WithTimeout(duration time.Duration) GenericOption { - return newGenericOption(func(cfg Config) Config { - cfg.Metrics.Timeout = duration - return cfg - }) -} diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/options_test.go b/exporters/otlp/otlpmetric/internal/otlpconfig/options_test.go deleted file mode 100644 index 9bfafcf85fe..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/options_test.go +++ /dev/null @@ -1,423 +0,0 @@ -// 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 otlpconfig_test - -import ( - "errors" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/otel/exporters/otlp/internal/envconfig" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" -) - -const ( - WeakCertificate = ` ------BEGIN CERTIFICATE----- -MIIBhzCCASygAwIBAgIRANHpHgAWeTnLZpTSxCKs0ggwCgYIKoZIzj0EAwIwEjEQ -MA4GA1UEChMHb3RlbC1nbzAeFw0yMTA0MDExMzU5MDNaFw0yMTA0MDExNDU5MDNa -MBIxEDAOBgNVBAoTB290ZWwtZ28wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS9 -nWSkmPCxShxnp43F+PrOtbGV7sNfkbQ/kxzi9Ego0ZJdiXxkmv/C05QFddCW7Y0Z -sJCLHGogQsYnWJBXUZOVo2MwYTAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYI -KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAsBgNVHREEJTAjgglsb2NhbGhvc3SHEAAA -AAAAAAAAAAAAAAAAAAGHBH8AAAEwCgYIKoZIzj0EAwIDSQAwRgIhANwZVVKvfvQ/ -1HXsTvgH+xTQswOwSSKYJ1cVHQhqK7ZbAiEAus8NxpTRnp5DiTMuyVmhVNPB+bVH -Lhnm4N/QDk5rek0= ------END CERTIFICATE----- -` - WeakPrivateKey = ` ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgN8HEXiXhvByrJ1zK -SFT6Y2l2KqDWwWzKf+t4CyWrNKehRANCAAS9nWSkmPCxShxnp43F+PrOtbGV7sNf -kbQ/kxzi9Ego0ZJdiXxkmv/C05QFddCW7Y0ZsJCLHGogQsYnWJBXUZOV ------END PRIVATE KEY----- -` -) - -type env map[string]string - -func (e *env) getEnv(env string) string { - return (*e)[env] -} - -type fileReader map[string][]byte - -func (f *fileReader) readFile(filename string) ([]byte, error) { - if b, ok := (*f)[filename]; ok { - return b, nil - } - return nil, errors.New("File not found") -} - -func TestConfigs(t *testing.T) { - tlsCert, err := otlpconfig.CreateTLSConfig([]byte(WeakCertificate)) - assert.NoError(t, err) - - tests := []struct { - name string - opts []otlpconfig.GenericOption - env env - fileReader fileReader - asserts func(t *testing.T, c *otlpconfig.Config, grpcOption bool) - }{ - { - name: "Test default configs", - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - if grpcOption { - assert.Equal(t, "localhost:4317", c.Metrics.Endpoint) - } else { - assert.Equal(t, "localhost:4318", c.Metrics.Endpoint) - } - assert.Equal(t, otlpconfig.NoCompression, c.Metrics.Compression) - assert.Equal(t, map[string]string(nil), c.Metrics.Headers) - assert.Equal(t, 10*time.Second, c.Metrics.Timeout) - }, - }, - - // Endpoint Tests - { - name: "Test With Endpoint", - opts: []otlpconfig.GenericOption{ - otlpconfig.WithEndpoint("someendpoint"), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, "someendpoint", c.Metrics.Endpoint) - }, - }, - { - name: "Test Environment Endpoint", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_ENDPOINT": "https://env.endpoint/prefix", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.False(t, c.Metrics.Insecure) - if grpcOption { - assert.Equal(t, "env.endpoint/prefix", c.Metrics.Endpoint) - } else { - assert.Equal(t, "env.endpoint", c.Metrics.Endpoint) - assert.Equal(t, "/prefix/v1/metrics", c.Metrics.URLPath) - } - }, - }, - { - name: "Test Environment Signal Specific Endpoint", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_ENDPOINT": "https://overrode.by.signal.specific/env/var", - "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "http://env.metrics.endpoint", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.True(t, c.Metrics.Insecure) - assert.Equal(t, "env.metrics.endpoint", c.Metrics.Endpoint) - if !grpcOption { - assert.Equal(t, "/", c.Metrics.URLPath) - } - }, - }, - { - name: "Test Mixed Environment and With Endpoint", - opts: []otlpconfig.GenericOption{ - otlpconfig.WithEndpoint("metrics_endpoint"), - }, - env: map[string]string{ - "OTEL_EXPORTER_OTLP_ENDPOINT": "env_endpoint", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, "metrics_endpoint", c.Metrics.Endpoint) - }, - }, - { - name: "Test Environment Endpoint with HTTP scheme", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_ENDPOINT": "http://env_endpoint", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, "env_endpoint", c.Metrics.Endpoint) - assert.Equal(t, true, c.Metrics.Insecure) - }, - }, - { - name: "Test Environment Endpoint with HTTP scheme and leading & trailingspaces", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_ENDPOINT": " http://env_endpoint ", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, "env_endpoint", c.Metrics.Endpoint) - assert.Equal(t, true, c.Metrics.Insecure) - }, - }, - { - name: "Test Environment Endpoint with HTTPS scheme", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_ENDPOINT": "https://env_endpoint", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, "env_endpoint", c.Metrics.Endpoint) - assert.Equal(t, false, c.Metrics.Insecure) - }, - }, - { - name: "Test Environment Signal Specific Endpoint with uppercase scheme", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_ENDPOINT": "HTTPS://overrode_by_signal_specific", - "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "HtTp://env_metrics_endpoint", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, "env_metrics_endpoint", c.Metrics.Endpoint) - assert.Equal(t, true, c.Metrics.Insecure) - }, - }, - - // Certificate tests - { - name: "Test Default Certificate", - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - if grpcOption { - assert.NotNil(t, c.Metrics.GRPCCredentials) - } else { - assert.Nil(t, c.Metrics.TLSCfg) - } - }, - }, - { - name: "Test With Certificate", - opts: []otlpconfig.GenericOption{ - otlpconfig.WithTLSClientConfig(tlsCert), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - if grpcOption { - //TODO: make sure gRPC's credentials actually works - assert.NotNil(t, c.Metrics.GRPCCredentials) - } else { - // nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR because cert does not come from SystemCertPool. - assert.Equal(t, tlsCert.RootCAs.Subjects(), c.Metrics.TLSCfg.RootCAs.Subjects()) - } - }, - }, - { - name: "Test Environment Certificate", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_CERTIFICATE": "cert_path", - }, - fileReader: fileReader{ - "cert_path": []byte(WeakCertificate), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - if grpcOption { - assert.NotNil(t, c.Metrics.GRPCCredentials) - } else { - // nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR because cert does not come from SystemCertPool. - assert.Equal(t, tlsCert.RootCAs.Subjects(), c.Metrics.TLSCfg.RootCAs.Subjects()) - } - }, - }, - { - name: "Test Environment Signal Specific Certificate", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_CERTIFICATE": "overrode_by_signal_specific", - "OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE": "cert_path", - }, - fileReader: fileReader{ - "cert_path": []byte(WeakCertificate), - "invalid_cert": []byte("invalid certificate file."), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - if grpcOption { - assert.NotNil(t, c.Metrics.GRPCCredentials) - } else { - // nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR because cert does not come from SystemCertPool. - assert.Equal(t, tlsCert.RootCAs.Subjects(), c.Metrics.TLSCfg.RootCAs.Subjects()) - } - }, - }, - { - name: "Test Mixed Environment and With Certificate", - opts: []otlpconfig.GenericOption{}, - env: map[string]string{ - "OTEL_EXPORTER_OTLP_CERTIFICATE": "cert_path", - }, - fileReader: fileReader{ - "cert_path": []byte(WeakCertificate), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - if grpcOption { - assert.NotNil(t, c.Metrics.GRPCCredentials) - } else { - // nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR because cert does not come from SystemCertPool. - assert.Equal(t, 1, len(c.Metrics.TLSCfg.RootCAs.Subjects())) - } - }, - }, - - // Headers tests - { - name: "Test With Headers", - opts: []otlpconfig.GenericOption{ - otlpconfig.WithHeaders(map[string]string{"h1": "v1"}), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, map[string]string{"h1": "v1"}, c.Metrics.Headers) - }, - }, - { - name: "Test Environment Headers", - env: map[string]string{"OTEL_EXPORTER_OTLP_HEADERS": "h1=v1,h2=v2"}, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, map[string]string{"h1": "v1", "h2": "v2"}, c.Metrics.Headers) - }, - }, - { - name: "Test Environment Signal Specific Headers", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_HEADERS": "overrode_by_signal_specific", - "OTEL_EXPORTER_OTLP_METRICS_HEADERS": "h1=v1,h2=v2", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, map[string]string{"h1": "v1", "h2": "v2"}, c.Metrics.Headers) - }, - }, - { - name: "Test Mixed Environment and With Headers", - env: map[string]string{"OTEL_EXPORTER_OTLP_HEADERS": "h1=v1,h2=v2"}, - opts: []otlpconfig.GenericOption{ - otlpconfig.WithHeaders(map[string]string{"m1": "mv1"}), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, map[string]string{"m1": "mv1"}, c.Metrics.Headers) - }, - }, - - // Compression Tests - { - name: "Test With Compression", - opts: []otlpconfig.GenericOption{ - otlpconfig.WithCompression(otlpconfig.GzipCompression), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, otlpconfig.GzipCompression, c.Metrics.Compression) - }, - }, - { - name: "Test Environment Compression", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_COMPRESSION": "gzip", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, otlpconfig.GzipCompression, c.Metrics.Compression) - }, - }, - { - name: "Test Environment Signal Specific Compression", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_METRICS_COMPRESSION": "gzip", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, otlpconfig.GzipCompression, c.Metrics.Compression) - }, - }, - { - name: "Test Mixed Environment and With Compression", - opts: []otlpconfig.GenericOption{ - otlpconfig.WithCompression(otlpconfig.NoCompression), - }, - env: map[string]string{ - "OTEL_EXPORTER_OTLP_METRICS_COMPRESSION": "gzip", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, otlpconfig.NoCompression, c.Metrics.Compression) - }, - }, - - // Timeout Tests - { - name: "Test With Timeout", - opts: []otlpconfig.GenericOption{ - otlpconfig.WithTimeout(time.Duration(5 * time.Second)), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, 5*time.Second, c.Metrics.Timeout) - }, - }, - { - name: "Test Environment Timeout", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_TIMEOUT": "15000", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, c.Metrics.Timeout, 15*time.Second) - }, - }, - { - name: "Test Environment Signal Specific Timeout", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_TIMEOUT": "15000", - "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": "28000", - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, c.Metrics.Timeout, 28*time.Second) - }, - }, - { - name: "Test Mixed Environment and With Timeout", - env: map[string]string{ - "OTEL_EXPORTER_OTLP_TIMEOUT": "15000", - "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": "28000", - }, - opts: []otlpconfig.GenericOption{ - otlpconfig.WithTimeout(5 * time.Second), - }, - asserts: func(t *testing.T, c *otlpconfig.Config, grpcOption bool) { - assert.Equal(t, c.Metrics.Timeout, 5*time.Second) - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - origEOR := otlpconfig.DefaultEnvOptionsReader - otlpconfig.DefaultEnvOptionsReader = envconfig.EnvOptionsReader{ - GetEnv: tt.env.getEnv, - ReadFile: tt.fileReader.readFile, - Namespace: "OTEL_EXPORTER_OTLP", - } - t.Cleanup(func() { otlpconfig.DefaultEnvOptionsReader = origEOR }) - - // Tests Generic options as HTTP Options - cfg := otlpconfig.NewHTTPConfig(asHTTPOptions(tt.opts)...) - tt.asserts(t, &cfg, false) - - // Tests Generic options as gRPC Options - cfg = otlpconfig.NewGRPCConfig(asGRPCOptions(tt.opts)...) - tt.asserts(t, &cfg, true) - }) - } -} - -func asHTTPOptions(opts []otlpconfig.GenericOption) []otlpconfig.HTTPOption { - converted := make([]otlpconfig.HTTPOption, len(opts)) - for i, o := range opts { - converted[i] = otlpconfig.NewHTTPOption(o.ApplyHTTPOption) - } - return converted -} - -func asGRPCOptions(opts []otlpconfig.GenericOption) []otlpconfig.GRPCOption { - converted := make([]otlpconfig.GRPCOption, len(opts)) - for i, o := range opts { - converted[i] = otlpconfig.NewGRPCOption(o.ApplyGRPCOption) - } - return converted -} diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/optiontypes.go b/exporters/otlp/otlpmetric/internal/otlpconfig/optiontypes.go deleted file mode 100644 index 1d6f83f366d..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/optiontypes.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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 otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" - -import "time" - -const ( - // DefaultCollectorGRPCPort is the default gRPC port of the collector. - DefaultCollectorGRPCPort uint16 = 4317 - // DefaultCollectorHTTPPort is the default HTTP port of the collector. - DefaultCollectorHTTPPort uint16 = 4318 - // DefaultCollectorHost is the host address the Exporter will attempt - // connect to if no collector address is provided. - DefaultCollectorHost string = "localhost" -) - -// Compression describes the compression used for payloads sent to the -// collector. -type Compression int - -const ( - // NoCompression tells the driver to send payloads without - // compression. - NoCompression Compression = iota - // GzipCompression tells the driver to send payloads after - // compressing them with gzip. - GzipCompression -) - -// RetrySettings defines configuration for retrying batches in case of export failure -// using an exponential backoff. -type RetrySettings struct { - // Enabled indicates whether to not retry sending batches in case of export failure. - Enabled bool - // InitialInterval the time to wait after the first failure before retrying. - InitialInterval time.Duration - // MaxInterval is the upper bound on backoff interval. Once this value is reached the delay between - // consecutive retries will always be `MaxInterval`. - MaxInterval time.Duration - // MaxElapsedTime is the maximum amount of time (including retries) spent trying to send a request/batch. - // Once this value is reached, the data is discarded. - MaxElapsedTime time.Duration -} diff --git a/exporters/otlp/otlpmetric/internal/otlpconfig/tls.go b/exporters/otlp/otlpmetric/internal/otlpconfig/tls.go deleted file mode 100644 index ae2b03c4473..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpconfig/tls.go +++ /dev/null @@ -1,46 +0,0 @@ -// 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 otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" - -import ( - "crypto/tls" - "crypto/x509" - "errors" - "io/ioutil" -) - -// ReadTLSConfigFromFile reads a PEM certificate file and creates -// a tls.Config that will use this certifate to verify a server certificate. -func ReadTLSConfigFromFile(path string) (*tls.Config, error) { - b, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - - return CreateTLSConfig(b) -} - -// CreateTLSConfig creates a tls.Config from a raw certificate bytes -// to verify a server certificate. -func CreateTLSConfig(certBytes []byte) (*tls.Config, error) { - cp := x509.NewCertPool() - if ok := cp.AppendCertsFromPEM(certBytes); !ok { - return nil, errors.New("failed to append certificate to the cert pool") - } - - return &tls.Config{ - RootCAs: cp, - }, nil -} diff --git a/exporters/otlp/otlpmetric/internal/otlpmetrictest/client.go b/exporters/otlp/otlpmetric/internal/otlpmetrictest/client.go deleted file mode 100644 index c248521ee14..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpmetrictest/client.go +++ /dev/null @@ -1,132 +0,0 @@ -// 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 otlpmetrictest // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - -import ( - "context" - "errors" - "sync" - "testing" - "time" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" -) - -func RunExporterShutdownTest(t *testing.T, factory func() otlpmetric.Client) { - t.Run("testClientStopHonorsTimeout", func(t *testing.T) { - testClientStopHonorsTimeout(t, factory()) - }) - - t.Run("testClientStopHonorsCancel", func(t *testing.T) { - testClientStopHonorsCancel(t, factory()) - }) - - t.Run("testClientStopNoError", func(t *testing.T) { - testClientStopNoError(t, factory()) - }) - - t.Run("testClientStopManyTimes", func(t *testing.T) { - testClientStopManyTimes(t, factory()) - }) -} - -func initializeExporter(t *testing.T, client otlpmetric.Client) *otlpmetric.Exporter { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) - defer cancel() - - e, err := otlpmetric.New(ctx, client) - if err != nil { - t.Fatalf("failed to create exporter") - } - - return e -} - -func testClientStopHonorsTimeout(t *testing.T, client otlpmetric.Client) { - t.Cleanup(func() { - // The test is looking for a failed shut down. Call Stop a second time - // with an un-expired context to give the client a second chance at - // cleaning up. There is not guarantee from the Client interface this - // will succeed, therefore, no need to check the error (just give it a - // best try). - _ = client.Stop(context.Background()) - }) - e := initializeExporter(t, client) - - innerCtx, innerCancel := context.WithTimeout(context.Background(), time.Microsecond) - <-innerCtx.Done() - if err := e.Shutdown(innerCtx); err == nil { - t.Error("expected context DeadlineExceeded error, got nil") - } else if !errors.Is(err, context.DeadlineExceeded) { - t.Errorf("expected context DeadlineExceeded error, got %v", err) - } - innerCancel() -} - -func testClientStopHonorsCancel(t *testing.T, client otlpmetric.Client) { - t.Cleanup(func() { - // The test is looking for a failed shut down. Call Stop a second time - // with an un-expired context to give the client a second chance at - // cleaning up. There is not guarantee from the Client interface this - // will succeed, therefore, no need to check the error (just give it a - // best try). - _ = client.Stop(context.Background()) - }) - e := initializeExporter(t, client) - - ctx, innerCancel := context.WithCancel(context.Background()) - innerCancel() - if err := e.Shutdown(ctx); err == nil { - t.Error("expected context canceled error, got nil") - } else if !errors.Is(err, context.Canceled) { - t.Errorf("expected context canceled error, got %v", err) - } -} - -func testClientStopNoError(t *testing.T, client otlpmetric.Client) { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) - defer cancel() - - e := initializeExporter(t, client) - if err := e.Shutdown(ctx); err != nil { - t.Errorf("shutdown errored: expected nil, got %v", err) - } -} - -func testClientStopManyTimes(t *testing.T, client otlpmetric.Client) { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) - defer cancel() - e := initializeExporter(t, client) - - ch := make(chan struct{}) - wg := sync.WaitGroup{} - const num int = 20 - wg.Add(num) - errs := make([]error, num) - for i := 0; i < num; i++ { - go func(idx int) { - defer wg.Done() - <-ch - errs[idx] = e.Shutdown(ctx) - }(i) - } - close(ch) - wg.Wait() - for _, err := range errs { - if err != nil { - t.Fatalf("failed to shutdown exporter: %v", err) - } - } -} diff --git a/exporters/otlp/otlpmetric/internal/otlpmetrictest/collector.go b/exporters/otlp/otlpmetric/internal/otlpmetrictest/collector.go deleted file mode 100644 index 20915724a53..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpmetrictest/collector.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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 otlpmetrictest // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - -import ( - collectormetricpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -// Collector is an interface that mock collectors should implements, -// so they can be used for the end-to-end testing. -type Collector interface { - Stop() error - GetMetrics() []*metricpb.Metric -} - -// MetricsStorage stores the metrics. Mock collectors could use it to -// store metrics they have received. -type MetricsStorage struct { - metrics []*metricpb.Metric -} - -// NewMetricsStorage creates a new metrics storage. -func NewMetricsStorage() MetricsStorage { - return MetricsStorage{} -} - -// AddMetrics adds metrics to the metrics storage. -func (s *MetricsStorage) AddMetrics(request *collectormetricpb.ExportMetricsServiceRequest) { - for _, rm := range request.GetResourceMetrics() { - // TODO (rghetia) handle multiple resource and library info. - if len(rm.ScopeMetrics) > 0 { - s.metrics = append(s.metrics, rm.ScopeMetrics[0].Metrics...) - } - } -} - -// GetMetrics returns the stored metrics. -func (s *MetricsStorage) GetMetrics() []*metricpb.Metric { - // copy in order to not change. - m := make([]*metricpb.Metric, 0, len(s.metrics)) - return append(m, s.metrics...) -} diff --git a/exporters/otlp/otlpmetric/internal/otlpmetrictest/data.go b/exporters/otlp/otlpmetric/internal/otlpmetrictest/data.go deleted file mode 100644 index 2da921f142c..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpmetrictest/data.go +++ /dev/null @@ -1,71 +0,0 @@ -// 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 otlpmetrictest // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - -import ( - "context" - "fmt" - "time" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -// OneRecordReader is a Reader that returns just one -// filled record. It may be useful for testing driver's metrics -// export. -func OneRecordReader() export.InstrumentationLibraryReader { - desc := metrictest.NewDescriptor( - "foo", - sdkapi.CounterInstrumentKind, - number.Int64Kind, - ) - agg := sum.New(1) - if err := agg[0].Update(context.Background(), number.NewInt64Number(42), &desc); err != nil { - panic(err) - } - start := time.Date(2020, time.December, 8, 19, 15, 0, 0, time.UTC) - end := time.Date(2020, time.December, 8, 19, 16, 0, 0, time.UTC) - labels := attribute.NewSet(attribute.String("abc", "def"), attribute.Int64("one", 1)) - rec := export.NewRecord(&desc, &labels, agg[0].Aggregation(), start, end) - - return processortest.MultiInstrumentationLibraryReader( - map[instrumentation.Library][]export.Record{ - { - Name: "onelib", - }: {rec}, - }) -} - -func EmptyReader() export.InstrumentationLibraryReader { - return processortest.MultiInstrumentationLibraryReader(nil) -} - -// FailReader is a checkpointer that returns an error during -// ForEach. -type FailReader struct{} - -var _ export.InstrumentationLibraryReader = FailReader{} - -// ForEach implements export.Reader. It always fails. -func (FailReader) ForEach(readerFunc func(instrumentation.Library, export.Reader) error) error { - return fmt.Errorf("fail") -} diff --git a/exporters/otlp/otlpmetric/internal/otlpmetrictest/otlptest.go b/exporters/otlp/otlpmetric/internal/otlpmetrictest/otlptest.go deleted file mode 100644 index 3047c0adfc0..00000000000 --- a/exporters/otlp/otlpmetric/internal/otlpmetrictest/otlptest.go +++ /dev/null @@ -1,174 +0,0 @@ -// 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 otlpmetrictest // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - "go.opentelemetry.io/otel/metric/instrument" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -// RunEndToEndTest can be used by protocol driver tests to validate -// themselves. -func RunEndToEndTest(ctx context.Context, t *testing.T, exp *otlpmetric.Exporter, mcMetrics Collector) { - selector := simple.NewWithHistogramDistribution() - proc := processor.NewFactory(selector, aggregation.StatelessTemporalitySelector()) - cont := controller.New(proc, controller.WithExporter(exp)) - require.NoError(t, cont.Start(ctx)) - - meter := cont.Meter("test-meter") - labels := []attribute.KeyValue{attribute.Bool("test", true)} - - type data struct { - iKind sdkapi.InstrumentKind - nKind number.Kind - val int64 - } - instruments := map[string]data{ - "test-int64-counter": {sdkapi.CounterInstrumentKind, number.Int64Kind, 1}, - "test-float64-counter": {sdkapi.CounterInstrumentKind, number.Float64Kind, 1}, - "test-int64-histogram": {sdkapi.HistogramInstrumentKind, number.Int64Kind, 2}, - "test-float64-histogram": {sdkapi.HistogramInstrumentKind, number.Float64Kind, 2}, - "test-int64-gaugeobserver": {sdkapi.GaugeObserverInstrumentKind, number.Int64Kind, 3}, - "test-float64-gaugeobserver": {sdkapi.GaugeObserverInstrumentKind, number.Float64Kind, 3}, - } - for name, data := range instruments { - data := data - switch data.iKind { - case sdkapi.CounterInstrumentKind: - switch data.nKind { - case number.Int64Kind: - c, _ := meter.SyncInt64().Counter(name) - c.Add(ctx, data.val, labels...) - case number.Float64Kind: - c, _ := meter.SyncFloat64().Counter(name) - c.Add(ctx, float64(data.val), labels...) - default: - assert.Failf(t, "unsupported number testing kind", data.nKind.String()) - } - case sdkapi.HistogramInstrumentKind: - switch data.nKind { - case number.Int64Kind: - c, _ := meter.SyncInt64().Histogram(name) - c.Record(ctx, data.val, labels...) - case number.Float64Kind: - c, _ := meter.SyncFloat64().Histogram(name) - c.Record(ctx, float64(data.val), labels...) - default: - assert.Failf(t, "unsupported number testing kind", data.nKind.String()) - } - case sdkapi.GaugeObserverInstrumentKind: - switch data.nKind { - case number.Int64Kind: - g, _ := meter.AsyncInt64().Gauge(name) - _ = meter.RegisterCallback([]instrument.Asynchronous{g}, func(ctx context.Context) { - g.Observe(ctx, data.val, labels...) - }) - case number.Float64Kind: - g, _ := meter.AsyncFloat64().Gauge(name) - _ = meter.RegisterCallback([]instrument.Asynchronous{g}, func(ctx context.Context) { - g.Observe(ctx, float64(data.val), labels...) - }) - default: - assert.Failf(t, "unsupported number testing kind", data.nKind.String()) - } - default: - assert.Failf(t, "unsupported metrics testing kind", data.iKind.String()) - } - } - - // Flush and close. - require.NoError(t, cont.Stop(ctx)) - - // Wait >2 cycles. - <-time.After(40 * time.Millisecond) - - // Now shutdown the exporter - ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - if err := exp.Shutdown(ctx); err != nil { - t.Fatalf("failed to stop the exporter: %v", err) - } - - // Shutdown the collector too so that we can begin - // verification checks of expected data back. - _ = mcMetrics.Stop() - - metrics := mcMetrics.GetMetrics() - assert.Len(t, metrics, len(instruments), "not enough metrics exported") - seen := make(map[string]struct{}, len(instruments)) - for _, m := range metrics { - data, ok := instruments[m.Name] - if !ok { - assert.Failf(t, "unknown metrics", m.Name) - continue - } - seen[m.Name] = struct{}{} - - switch data.iKind { - case sdkapi.CounterInstrumentKind, sdkapi.GaugeObserverInstrumentKind: - var dp []*metricpb.NumberDataPoint - switch data.iKind { - case sdkapi.CounterInstrumentKind: - require.NotNil(t, m.GetSum()) - dp = m.GetSum().GetDataPoints() - case sdkapi.GaugeObserverInstrumentKind: - require.NotNil(t, m.GetGauge()) - dp = m.GetGauge().GetDataPoints() - } - if assert.Len(t, dp, 1) { - switch data.nKind { - case number.Int64Kind: - v := &metricpb.NumberDataPoint_AsInt{AsInt: data.val} - assert.Equal(t, v, dp[0].Value, "invalid value for %q", m.Name) - case number.Float64Kind: - v := &metricpb.NumberDataPoint_AsDouble{AsDouble: float64(data.val)} - assert.Equal(t, v, dp[0].Value, "invalid value for %q", m.Name) - } - } - case sdkapi.HistogramInstrumentKind: - require.NotNil(t, m.GetHistogram()) - if dp := m.GetHistogram().DataPoints; assert.Len(t, dp, 1) { - count := dp[0].Count - assert.Equal(t, uint64(1), count, "invalid count for %q", m.Name) - require.NotNil(t, dp[0].Sum) - assert.Equal(t, float64(data.val*int64(count)), *dp[0].Sum, "invalid sum for %q (value %d)", m.Name, data.val) - } - default: - assert.Failf(t, "invalid metrics kind", data.iKind.String()) - } - } - - for i := range instruments { - if _, ok := seen[i]; !ok { - assert.Fail(t, fmt.Sprintf("no metric(s) exported for %q", i)) - } - } -} diff --git a/exporters/otlp/otlpmetric/options.go b/exporters/otlp/otlpmetric/options.go deleted file mode 100644 index bd8706a74d3..00000000000 --- a/exporters/otlp/otlpmetric/options.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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 otlpmetric // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - -import "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - -// Option are setting options passed to an Exporter on creation. -type Option interface { - apply(config) config -} - -type exporterOptionFunc func(config) config - -func (fn exporterOptionFunc) apply(cfg config) config { - return fn(cfg) -} - -type config struct { - temporalitySelector aggregation.TemporalitySelector -} - -// WithMetricAggregationTemporalitySelector defines the aggregation.TemporalitySelector used -// for selecting aggregation.Temporality (i.e., Cumulative vs. Delta -// aggregation). If not specified otherwise, exporter will use a -// cumulative temporality selector. -func WithMetricAggregationTemporalitySelector(selector aggregation.TemporalitySelector) Option { - return exporterOptionFunc(func(cfg config) config { - cfg.temporalitySelector = selector - return cfg - }) -} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go deleted file mode 100644 index cb67a4fe812..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go +++ /dev/null @@ -1,275 +0,0 @@ -// 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 otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - -import ( - "context" - "errors" - "sync" - "time" - - "google.golang.org/genproto/googleapis/rpc/errdetails" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - - "go.opentelemetry.io/otel/exporters/otlp/internal/retry" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" - colmetricpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -type client struct { - endpoint string - dialOpts []grpc.DialOption - metadata metadata.MD - exportTimeout time.Duration - requestFunc retry.RequestFunc - - // stopCtx is used as a parent context for all exports. Therefore, when it - // is canceled with the stopFunc all exports are canceled. - stopCtx context.Context - // stopFunc cancels stopCtx, stopping any active exports. - stopFunc context.CancelFunc - - // ourConn keeps track of where conn was created: true if created here on - // Start, or false if passed with an option. This is important on Shutdown - // as the conn should only be closed if created here on start. Otherwise, - // it is up to the processes that passed the conn to close it. - ourConn bool - conn *grpc.ClientConn - mscMu sync.RWMutex - msc colmetricpb.MetricsServiceClient -} - -// Compile time check *client implements otlpmetric.Client. -var _ otlpmetric.Client = (*client)(nil) - -// NewClient creates a new gRPC metric client. -func NewClient(opts ...Option) otlpmetric.Client { - return newClient(opts...) -} - -func newClient(opts ...Option) *client { - cfg := otlpconfig.NewGRPCConfig(asGRPCOptions(opts)...) - - ctx, cancel := context.WithCancel(context.Background()) - - c := &client{ - endpoint: cfg.Metrics.Endpoint, - exportTimeout: cfg.Metrics.Timeout, - requestFunc: cfg.RetryConfig.RequestFunc(retryable), - dialOpts: cfg.DialOptions, - stopCtx: ctx, - stopFunc: cancel, - conn: cfg.GRPCConn, - } - - if len(cfg.Metrics.Headers) > 0 { - c.metadata = metadata.New(cfg.Metrics.Headers) - } - - return c -} - -// Start establishes a gRPC connection to the collector. -func (c *client) Start(ctx context.Context) error { - if c.conn == nil { - // If the caller did not provide a ClientConn when the client was - // created, create one using the configuration they did provide. - conn, err := grpc.DialContext(ctx, c.endpoint, c.dialOpts...) - if err != nil { - return err - } - // Keep track that we own the lifecycle of this conn and need to close - // it on Shutdown. - c.ourConn = true - c.conn = conn - } - - // The otlpmetric.Client interface states this method is called just once, - // so no need to check if already started. - c.mscMu.Lock() - c.msc = colmetricpb.NewMetricsServiceClient(c.conn) - c.mscMu.Unlock() - - return nil -} - -var errAlreadyStopped = errors.New("the client is already stopped") - -// Stop shuts down the client. -// -// Any active connections to a remote endpoint are closed if they were created -// by the client. Any gRPC connection passed during creation using -// WithGRPCConn will not be closed. It is the caller's responsibility to -// handle cleanup of that resource. -// -// This method synchronizes with the UploadMetrics method of the client. It -// will wait for any active calls to that method to complete unimpeded, or it -// will cancel any active calls if ctx expires. If ctx expires, the context -// error will be forwarded as the returned error. All client held resources -// will still be released in this situation. -// -// If the client has already stopped, an error will be returned describing -// this. -func (c *client) Stop(ctx context.Context) error { - // Acquire the c.mscMu lock within the ctx lifetime. - acquired := make(chan struct{}) - go func() { - c.mscMu.Lock() - close(acquired) - }() - var err error - select { - case <-ctx.Done(): - // The Stop timeout is reached. Kill any remaining exports to force - // the clear of the lock and save the timeout error to return and - // signal the shutdown timed out before cleanly stopping. - c.stopFunc() - err = ctx.Err() - - // To ensure the client is not left in a dirty state c.msc needs to be - // set to nil. To avoid the race condition when doing this, ensure - // that all the exports are killed (initiated by c.stopFunc). - <-acquired - case <-acquired: - } - // Hold the mscMu lock for the rest of the function to ensure no new - // exports are started. - defer c.mscMu.Unlock() - - // The otlpmetric.Client interface states this method is called only - // once, but there is no guarantee it is called after Start. Ensure the - // client is started before doing anything and let the called know if they - // made a mistake. - if c.msc == nil { - return errAlreadyStopped - } - - // Clear c.msc to signal the client is stopped. - c.msc = nil - - if c.ourConn { - closeErr := c.conn.Close() - // A context timeout error takes precedence over this error. - if err == nil && closeErr != nil { - err = closeErr - } - } - return err -} - -var errShutdown = errors.New("the client is shutdown") - -// UploadMetrics sends a batch of spans. -// -// Retryable errors from the server will be handled according to any -// RetryConfig the client was created with. -func (c *client) UploadMetrics(ctx context.Context, protoMetrics *metricpb.ResourceMetrics) error { - // Hold a read lock to ensure a shut down initiated after this starts does - // not abandon the export. This read lock acquire has less priority than a - // write lock acquire (i.e. Stop), meaning if the client is shutting down - // this will come after the shut down. - c.mscMu.RLock() - defer c.mscMu.RUnlock() - - if c.msc == nil { - return errShutdown - } - - ctx, cancel := c.exportContext(ctx) - defer cancel() - - return c.requestFunc(ctx, func(iCtx context.Context) error { - _, err := c.msc.Export(iCtx, &colmetricpb.ExportMetricsServiceRequest{ - ResourceMetrics: []*metricpb.ResourceMetrics{protoMetrics}, - }) - // nil is converted to OK. - if status.Code(err) == codes.OK { - // Success. - return nil - } - return err - }) -} - -// exportContext returns a copy of parent with an appropriate deadline and -// cancellation function. -// -// It is the callers responsibility to cancel the returned context once its -// use is complete, via the parent or directly with the returned CancelFunc, to -// ensure all resources are correctly released. -func (c *client) exportContext(parent context.Context) (context.Context, context.CancelFunc) { - var ( - ctx context.Context - cancel context.CancelFunc - ) - - if c.exportTimeout > 0 { - ctx, cancel = context.WithTimeout(parent, c.exportTimeout) - } else { - ctx, cancel = context.WithCancel(parent) - } - - if c.metadata.Len() > 0 { - ctx = metadata.NewOutgoingContext(ctx, c.metadata) - } - - // Unify the client stopCtx with the parent. - go func() { - select { - case <-ctx.Done(): - case <-c.stopCtx.Done(): - // Cancel the export as the shutdown has timed out. - cancel() - } - }() - - return ctx, cancel -} - -// retryable returns if err identifies a request that can be retried and a -// duration to wait for if an explicit throttle time is included in err. -func retryable(err error) (bool, time.Duration) { - //func retryable(err error) (bool, time.Duration) { - s := status.Convert(err) - switch s.Code() { - case codes.Canceled, - codes.DeadlineExceeded, - codes.ResourceExhausted, - codes.Aborted, - codes.OutOfRange, - codes.Unavailable, - codes.DataLoss: - return true, throttleDelay(s) - } - - // Not a retry-able error. - return false, 0 -} - -// throttleDelay returns a duration to wait for if an explicit throttle time -// is included in the response status. -func throttleDelay(status *status.Status) time.Duration { - for _, detail := range status.Details() { - if t, ok := detail.(*errdetails.RetryInfo); ok { - return t.RetryDelay.AsDuration() - } - } - return 0 -} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/client_test.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/client_test.go deleted file mode 100644 index dc7eeda51d9..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/client_test.go +++ /dev/null @@ -1,332 +0,0 @@ -// 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 otlpmetricgrpc_test - -import ( - "context" - "fmt" - "net" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/encoding/gzip" - "google.golang.org/grpc/status" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - "go.opentelemetry.io/otel/sdk/resource" -) - -var ( - oneRecord = otlpmetrictest.OneRecordReader() - - testResource = resource.Empty() -) - -func TestNewExporter_endToEnd(t *testing.T) { - tests := []struct { - name string - additionalOpts []otlpmetricgrpc.Option - }{ - { - name: "StandardExporter", - }, - { - name: "WithCompressor", - additionalOpts: []otlpmetricgrpc.Option{ - otlpmetricgrpc.WithCompressor(gzip.Name), - }, - }, - { - name: "WithServiceConfig", - additionalOpts: []otlpmetricgrpc.Option{ - otlpmetricgrpc.WithServiceConfig("{}"), - }, - }, - { - name: "WithDialOptions", - additionalOpts: []otlpmetricgrpc.Option{ - otlpmetricgrpc.WithDialOption(grpc.WithBlock()), - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - newExporterEndToEndTest(t, test.additionalOpts) - }) - } -} - -func newGRPCExporter(t *testing.T, ctx context.Context, endpoint string, additionalOpts ...otlpmetricgrpc.Option) *otlpmetric.Exporter { - opts := []otlpmetricgrpc.Option{ - otlpmetricgrpc.WithInsecure(), - otlpmetricgrpc.WithEndpoint(endpoint), - otlpmetricgrpc.WithReconnectionPeriod(50 * time.Millisecond), - } - - opts = append(opts, additionalOpts...) - client := otlpmetricgrpc.NewClient(opts...) - exp, err := otlpmetric.New(ctx, client) - if err != nil { - t.Fatalf("failed to create a new collector exporter: %v", err) - } - return exp -} - -func newExporterEndToEndTest(t *testing.T, additionalOpts []otlpmetricgrpc.Option) { - mc := runMockCollector(t) - - defer func() { - _ = mc.stop() - }() - - <-time.After(5 * time.Millisecond) - - ctx := context.Background() - exp := newGRPCExporter(t, ctx, mc.endpoint, additionalOpts...) - defer func() { - ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - if err := exp.Shutdown(ctx); err != nil { - panic(err) - } - }() - - otlpmetrictest.RunEndToEndTest(ctx, t, exp, mc) -} - -func TestExporterShutdown(t *testing.T) { - mc := runMockCollector(t) - defer func() { - _ = mc.Stop() - }() - - <-time.After(5 * time.Millisecond) - - otlpmetrictest.RunExporterShutdownTest(t, func() otlpmetric.Client { - return otlpmetricgrpc.NewClient( - otlpmetricgrpc.WithInsecure(), - otlpmetricgrpc.WithEndpoint(mc.endpoint), - otlpmetricgrpc.WithReconnectionPeriod(50*time.Millisecond), - ) - }) -} - -func TestNewExporter_invokeStartThenStopManyTimes(t *testing.T) { - mc := runMockCollector(t) - defer func() { - _ = mc.stop() - }() - - ctx := context.Background() - exp := newGRPCExporter(t, ctx, mc.endpoint) - defer func() { - if err := exp.Shutdown(ctx); err != nil { - panic(err) - } - }() - - // Invoke Start numerous times, should return errAlreadyStarted - for i := 0; i < 10; i++ { - if err := exp.Start(ctx); err == nil || !strings.Contains(err.Error(), "already started") { - t.Fatalf("#%d unexpected Start error: %v", i, err) - } - } - - if err := exp.Shutdown(ctx); err != nil { - t.Fatalf("failed to Shutdown the exporter: %v", err) - } - // Invoke Shutdown numerous times - for i := 0; i < 10; i++ { - if err := exp.Shutdown(ctx); err != nil { - t.Fatalf(`#%d got error (%v) expected none`, i, err) - } - } -} - -// This test takes a long time to run: to skip it, run tests using: -short -func TestNewExporter_collectorOnBadConnection(t *testing.T) { - if testing.Short() { - t.Skipf("Skipping this long running test") - } - - ln, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Failed to grab an available port: %v", err) - } - // Firstly close the "collector's" channel: optimistically this endpoint won't get reused ASAP - // However, our goal of closing it is to simulate an unavailable connection - _ = ln.Close() - - _, collectorPortStr, _ := net.SplitHostPort(ln.Addr().String()) - - endpoint := fmt.Sprintf("localhost:%s", collectorPortStr) - ctx := context.Background() - exp := newGRPCExporter(t, ctx, endpoint) - _ = exp.Shutdown(ctx) -} - -func TestNewExporter_withEndpoint(t *testing.T) { - mc := runMockCollector(t) - defer func() { - _ = mc.stop() - }() - - ctx := context.Background() - exp := newGRPCExporter(t, ctx, mc.endpoint) - _ = exp.Shutdown(ctx) -} - -func TestNewExporter_withHeaders(t *testing.T) { - mc := runMockCollector(t) - defer func() { - _ = mc.stop() - }() - - ctx := context.Background() - exp := newGRPCExporter(t, ctx, mc.endpoint, - otlpmetricgrpc.WithHeaders(map[string]string{"header1": "value1"})) - require.NoError(t, exp.Export(ctx, testResource, oneRecord)) - - defer func() { - _ = exp.Shutdown(ctx) - }() - - headers := mc.getHeaders() - require.Len(t, headers.Get("header1"), 1) - assert.Equal(t, "value1", headers.Get("header1")[0]) -} - -func TestNewExporter_WithTimeout(t *testing.T) { - tts := []struct { - name string - fn func(exp *otlpmetric.Exporter) error - timeout time.Duration - metrics int - spans int - code codes.Code - delay bool - }{ - { - name: "Timeout Metrics", - fn: func(exp *otlpmetric.Exporter) error { - return exp.Export(context.Background(), testResource, oneRecord) - }, - timeout: time.Millisecond * 100, - code: codes.DeadlineExceeded, - delay: true, - }, - - { - name: "No Timeout Metrics", - fn: func(exp *otlpmetric.Exporter) error { - return exp.Export(context.Background(), testResource, oneRecord) - }, - timeout: time.Minute, - metrics: 1, - code: codes.OK, - }, - } - - for _, tt := range tts { - t.Run(tt.name, func(t *testing.T) { - - mc := runMockCollector(t) - if tt.delay { - mc.metricSvc.delay = time.Second * 10 - } - defer func() { - _ = mc.stop() - }() - - ctx := context.Background() - exp := newGRPCExporter(t, ctx, mc.endpoint, otlpmetricgrpc.WithTimeout(tt.timeout), otlpmetricgrpc.WithRetry(otlpmetricgrpc.RetryConfig{Enabled: false})) - defer func() { - _ = exp.Shutdown(ctx) - }() - - err := tt.fn(exp) - - if tt.code == codes.OK { - require.NoError(t, err) - } else { - require.Error(t, err) - } - - s := status.Convert(err) - require.Equal(t, tt.code, s.Code()) - - require.Len(t, mc.getMetrics(), tt.metrics) - }) - } -} - -func TestStartErrorInvalidAddress(t *testing.T) { - client := otlpmetricgrpc.NewClient( - otlpmetricgrpc.WithInsecure(), - // Validate the connection in Start (which should return the error). - otlpmetricgrpc.WithDialOption( - grpc.WithBlock(), - grpc.FailOnNonTempDialError(true), - ), - otlpmetricgrpc.WithEndpoint("invalid"), - otlpmetricgrpc.WithReconnectionPeriod(time.Hour), - ) - err := client.Start(context.Background()) - assert.EqualError(t, err, `connection error: desc = "transport: error while dialing: dial tcp: address invalid: missing port in address"`) -} - -func TestEmptyData(t *testing.T) { - mc := runMockCollector(t) - - defer func() { - _ = mc.stop() - }() - - <-time.After(5 * time.Millisecond) - - ctx := context.Background() - exp := newGRPCExporter(t, ctx, mc.endpoint) - defer func() { - assert.NoError(t, exp.Shutdown(ctx)) - }() - - assert.NoError(t, exp.Export(ctx, testResource, otlpmetrictest.EmptyReader())) -} - -func TestFailedMetricTransform(t *testing.T) { - mc := runMockCollector(t) - - defer func() { - _ = mc.stop() - }() - - <-time.After(5 * time.Millisecond) - - ctx := context.Background() - exp := newGRPCExporter(t, ctx, mc.endpoint) - defer func() { - assert.NoError(t, exp.Shutdown(ctx)) - }() - - assert.Error(t, exp.Export(ctx, testResource, otlpmetrictest.FailReader{})) -} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/client_unit_test.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/client_unit_test.go deleted file mode 100644 index ccd4ade1389..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/client_unit_test.go +++ /dev/null @@ -1,193 +0,0 @@ -// 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 otlpmetricgrpc - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/genproto/googleapis/rpc/errdetails" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/durationpb" -) - -func TestThrottleDuration(t *testing.T) { - c := codes.ResourceExhausted - testcases := []struct { - status *status.Status - expected time.Duration - }{ - { - status: status.New(c, "no retry info"), - expected: 0, - }, - { - status: func() *status.Status { - s, err := status.New(c, "single retry info").WithDetails( - &errdetails.RetryInfo{ - RetryDelay: durationpb.New(15 * time.Millisecond), - }, - ) - require.NoError(t, err) - return s - }(), - expected: 15 * time.Millisecond, - }, - { - status: func() *status.Status { - s, err := status.New(c, "error info").WithDetails( - &errdetails.ErrorInfo{Reason: "no throttle detail"}, - ) - require.NoError(t, err) - return s - }(), - expected: 0, - }, - { - status: func() *status.Status { - s, err := status.New(c, "error and retry info").WithDetails( - &errdetails.ErrorInfo{Reason: "with throttle detail"}, - &errdetails.RetryInfo{ - RetryDelay: durationpb.New(13 * time.Minute), - }, - ) - require.NoError(t, err) - return s - }(), - expected: 13 * time.Minute, - }, - { - status: func() *status.Status { - s, err := status.New(c, "double retry info").WithDetails( - &errdetails.RetryInfo{ - RetryDelay: durationpb.New(13 * time.Minute), - }, - &errdetails.RetryInfo{ - RetryDelay: durationpb.New(15 * time.Minute), - }, - ) - require.NoError(t, err) - return s - }(), - expected: 13 * time.Minute, - }, - } - - for _, tc := range testcases { - t.Run(tc.status.Message(), func(t *testing.T) { - require.Equal(t, tc.expected, throttleDelay(tc.status)) - }) - } -} - -func TestRetryable(t *testing.T) { - retryableCodes := map[codes.Code]bool{ - codes.OK: false, - codes.Canceled: true, - codes.Unknown: false, - codes.InvalidArgument: false, - codes.DeadlineExceeded: true, - codes.NotFound: false, - codes.AlreadyExists: false, - codes.PermissionDenied: false, - codes.ResourceExhausted: true, - codes.FailedPrecondition: false, - codes.Aborted: true, - codes.OutOfRange: true, - codes.Unimplemented: false, - codes.Internal: false, - codes.Unavailable: true, - codes.DataLoss: true, - codes.Unauthenticated: false, - } - - for c, want := range retryableCodes { - got, _ := retryable(status.Error(c, "")) - assert.Equalf(t, want, got, "evaluate(%s)", c) - } -} - -func TestUnstartedStop(t *testing.T) { - client := NewClient() - assert.ErrorIs(t, client.Stop(context.Background()), errAlreadyStopped) -} - -func TestUnstartedUploadMetric(t *testing.T) { - client := NewClient() - assert.ErrorIs(t, client.UploadMetrics(context.Background(), nil), errShutdown) -} - -func TestExportContextHonorsParentDeadline(t *testing.T) { - now := time.Now() - ctx, cancel := context.WithDeadline(context.Background(), now) - t.Cleanup(cancel) - - // Without a client timeout, the parent deadline should be used. - client := newClient(WithTimeout(0)) - eCtx, eCancel := client.exportContext(ctx) - t.Cleanup(eCancel) - - deadline, ok := eCtx.Deadline() - assert.True(t, ok, "deadline not propagated to child context") - assert.Equal(t, now, deadline) -} - -func TestExportContextHonorsClientTimeout(t *testing.T) { - // Setting a timeout should ensure a deadline is set on the context. - client := newClient(WithTimeout(1 * time.Second)) - ctx, cancel := client.exportContext(context.Background()) - t.Cleanup(cancel) - - _, ok := ctx.Deadline() - assert.True(t, ok, "timeout not set as deadline for child context") -} - -func TestExportContextLinksStopSignal(t *testing.T) { - rootCtx := context.Background() - - client := newClient(WithInsecure()) - t.Cleanup(func() { require.NoError(t, client.Stop(rootCtx)) }) - require.NoError(t, client.Start(rootCtx)) - - ctx, cancel := client.exportContext(rootCtx) - t.Cleanup(cancel) - - require.False(t, func() bool { - select { - case <-ctx.Done(): - return true - default: - } - return false - }(), "context should not be done prior to canceling it") - - // The client.stopFunc cancels the client.stopCtx. This should have been - // setup as a parent of ctx. Therefore, it should cancel ctx as well. - client.stopFunc() - - // Assert this with Eventually to account for goroutine scheduler timing. - assert.Eventually(t, func() bool { - select { - case <-ctx.Done(): - return true - default: - } - return false - }, 10*time.Second, time.Microsecond) -} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/example_test.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/example_test.go deleted file mode 100644 index 0b0fbd6967a..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/example_test.go +++ /dev/null @@ -1,203 +0,0 @@ -// 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 otlpmetricgrpc_test - -import ( - "context" - "log" - "time" - - "google.golang.org/grpc/credentials" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - "go.opentelemetry.io/otel/metric/global" - "go.opentelemetry.io/otel/metric/instrument" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" -) - -func Example_insecure() { - ctx := context.Background() - client := otlpmetricgrpc.NewClient(otlpmetricgrpc.WithInsecure()) - exp, err := otlpmetric.New(ctx, client) - if err != nil { - log.Fatalf("Failed to create the collector exporter: %v", err) - } - defer func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - if err := exp.Shutdown(ctx); err != nil { - otel.Handle(err) - } - }() - - pusher := controller.New( - processor.NewFactory( - simple.NewWithHistogramDistribution(), - exp, - ), - controller.WithExporter(exp), - controller.WithCollectPeriod(2*time.Second), - ) - - global.SetMeterProvider(pusher) - - if err := pusher.Start(ctx); err != nil { - log.Fatalf("could not start metric controller: %v", err) - } - defer func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - // pushes any last exports to the receiver - if err := pusher.Stop(ctx); err != nil { - otel.Handle(err) - } - }() - - meter := global.Meter("go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc_test") - - // Recorder metric example - - counter, err := meter.SyncFloat64().Counter("an_important_metric", instrument.WithDescription("Measures the cumulative epicness of the app")) - if err != nil { - log.Fatalf("Failed to create the instrument: %v", err) - } - - for i := 0; i < 10; i++ { - log.Printf("Doing really hard work (%d / 10)\n", i+1) - counter.Add(ctx, 1.0) - } -} - -func Example_withTLS() { - // Please take at look at https://pkg.go.dev/google.golang.org/grpc/credentials#TransportCredentials - // for ways on how to initialize gRPC TransportCredentials. - creds, err := credentials.NewClientTLSFromFile("my-cert.pem", "") - if err != nil { - log.Fatalf("failed to create gRPC client TLS credentials: %v", err) - } - - ctx := context.Background() - client := otlpmetricgrpc.NewClient(otlpmetricgrpc.WithTLSCredentials(creds)) - exp, err := otlpmetric.New(ctx, client) - if err != nil { - log.Fatalf("failed to create the collector exporter: %v", err) - } - defer func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - if err := exp.Shutdown(ctx); err != nil { - otel.Handle(err) - } - }() - - pusher := controller.New( - processor.NewFactory( - simple.NewWithHistogramDistribution(), - exp, - ), - controller.WithExporter(exp), - controller.WithCollectPeriod(2*time.Second), - ) - - global.SetMeterProvider(pusher) - - if err := pusher.Start(ctx); err != nil { - log.Fatalf("could not start metric controller: %v", err) - } - - defer func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - // pushes any last exports to the receiver - if err := pusher.Stop(ctx); err != nil { - otel.Handle(err) - } - }() - - meter := global.Meter("go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc_test") - - // Recorder metric example - counter, err := meter.SyncFloat64().Counter("an_important_metric", instrument.WithDescription("Measures the cumulative epicness of the app")) - if err != nil { - log.Fatalf("Failed to create the instrument: %v", err) - } - - for i := 0; i < 10; i++ { - log.Printf("Doing really hard work (%d / 10)\n", i+1) - counter.Add(ctx, 1.0) - } -} - -func Example_withDifferentSignalCollectors() { - client := otlpmetricgrpc.NewClient( - otlpmetricgrpc.WithInsecure(), - otlpmetricgrpc.WithEndpoint("localhost:30080"), - ) - ctx := context.Background() - exp, err := otlpmetric.New(ctx, client) - if err != nil { - log.Fatalf("failed to create the collector exporter: %v", err) - } - - defer func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - if err := exp.Shutdown(ctx); err != nil { - otel.Handle(err) - } - }() - - pusher := controller.New( - processor.NewFactory( - simple.NewWithHistogramDistribution(), - exp, - ), - controller.WithExporter(exp), - controller.WithCollectPeriod(2*time.Second), - ) - - global.SetMeterProvider(pusher) - - if err := pusher.Start(ctx); err != nil { - log.Fatalf("could not start metric controller: %v", err) - } - defer func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - // pushes any last exports to the receiver - if err := pusher.Stop(ctx); err != nil { - otel.Handle(err) - } - }() - - meter := global.Meter("go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc_test") - - // Recorder metric example - counter, err := meter.SyncFloat64().Counter("an_important_metric", instrument.WithDescription("Measures the cumulative epicness of the app")) - if err != nil { - log.Fatalf("Failed to create the instrument: %v", err) - } - - for i := 0; i < 10; i++ { - log.Printf("Doing really hard work (%d / 10)\n", i+1) - counter.Add(ctx, 1.0) - } - - log.Printf("Done!") -} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/exporter.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/exporter.go deleted file mode 100644 index 197059a6a5b..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/exporter.go +++ /dev/null @@ -1,31 +0,0 @@ -// 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 otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - -import ( - "context" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" -) - -// New constructs a new Exporter and starts it. -func New(ctx context.Context, opts ...Option) (*otlpmetric.Exporter, error) { - return otlpmetric.New(ctx, NewClient(opts...)) -} - -// NewUnstarted constructs a new Exporter and does not start it. -func NewUnstarted(opts ...Option) *otlpmetric.Exporter { - return otlpmetric.NewUnstarted(NewClient(opts...)) -} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/go.mod b/exporters/otlp/otlpmetric/otlpmetricgrpc/go.mod deleted file mode 100644 index 068637c2534..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/go.mod +++ /dev/null @@ -1,81 +0,0 @@ -module go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc - -go 1.16 - -require ( - github.com/stretchr/testify v1.7.1 - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.3 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.29.0 - go.opentelemetry.io/otel/metric v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/otel/sdk/metric v0.29.0 - go.opentelemetry.io/proto/otlp v0.15.0 - google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 - google.golang.org/grpc v1.45.0 - google.golang.org/protobuf v1.28.0 -) - -replace go.opentelemetry.io/otel => ../../../.. - -replace go.opentelemetry.io/otel/sdk => ../../../../sdk - -replace go.opentelemetry.io/otel/sdk/metric => ../../../../sdk/metric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../ - -replace go.opentelemetry.io/otel/metric => ../../../../metric - -replace go.opentelemetry.io/otel/trace => ../../../../trace - -replace go.opentelemetry.io/otel/bridge/opencensus => ../../../../bridge/opencensus - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../../../bridge/opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../../../../example/jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../../../../example/namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../../../../example/opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../../../../example/otel-collector - -replace go.opentelemetry.io/otel/example/passthrough => ../../../../example/passthrough - -replace go.opentelemetry.io/otel/example/prometheus => ../../../../example/prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../../../../example/zipkin - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ./ - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/internal/tools => ../../../../internal/tools - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../../../sdk/export/metric - -replace go.opentelemetry.io/otel/internal/metric => ../../../../internal/metric - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../../jaeger - -replace go.opentelemetry.io/otel/exporters/prometheus => ../../../prometheus - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../../zipkin - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../../stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../../stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../otlpmetrichttp - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../../../bridge/opencensus/test - -replace go.opentelemetry.io/otel/example/fib => ../../../../example/fib - -replace go.opentelemetry.io/otel/schema => ../../../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../internal/retry diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/go.sum b/exporters/otlp/otlpmetric/otlpmetricgrpc/go.sum deleted file mode 100644 index f69a11110a4..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/go.sum +++ /dev/null @@ -1,435 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -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/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= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/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= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0 h1:h0bKrvdrT/9sBwEJ6iWUqT/N/xPcS66bL4u3isneJ6w= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/mock_collector_test.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/mock_collector_test.go deleted file mode 100644 index 3eecfef39c0..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/mock_collector_test.go +++ /dev/null @@ -1,169 +0,0 @@ -// 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 otlpmetricgrpc_test - -import ( - "context" - "fmt" - "net" - "sync" - "testing" - "time" - - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - collectormetricpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -func makeMockCollector(t *testing.T, mockConfig *mockConfig) *mockCollector { - return &mockCollector{ - t: t, - metricSvc: &mockMetricService{ - storage: otlpmetrictest.NewMetricsStorage(), - errors: mockConfig.errors, - }, - } -} - -type mockMetricService struct { - collectormetricpb.UnimplementedMetricsServiceServer - - requests int - errors []error - - headers metadata.MD - mu sync.RWMutex - storage otlpmetrictest.MetricsStorage - delay time.Duration -} - -func (mms *mockMetricService) getHeaders() metadata.MD { - mms.mu.RLock() - defer mms.mu.RUnlock() - return mms.headers -} - -func (mms *mockMetricService) getMetrics() []*metricpb.Metric { - mms.mu.RLock() - defer mms.mu.RUnlock() - return mms.storage.GetMetrics() -} - -func (mms *mockMetricService) Export(ctx context.Context, exp *collectormetricpb.ExportMetricsServiceRequest) (*collectormetricpb.ExportMetricsServiceResponse, error) { - if mms.delay > 0 { - time.Sleep(mms.delay) - } - - mms.mu.Lock() - defer func() { - mms.requests++ - mms.mu.Unlock() - }() - - reply := &collectormetricpb.ExportMetricsServiceResponse{} - if mms.requests < len(mms.errors) { - idx := mms.requests - return reply, mms.errors[idx] - } - - mms.headers, _ = metadata.FromIncomingContext(ctx) - mms.storage.AddMetrics(exp) - return reply, nil -} - -type mockCollector struct { - t *testing.T - - metricSvc *mockMetricService - - endpoint string - stopFunc func() - stopOnce sync.Once -} - -type mockConfig struct { - errors []error - endpoint string -} - -var _ collectormetricpb.MetricsServiceServer = (*mockMetricService)(nil) - -var errAlreadyStopped = fmt.Errorf("already stopped") - -func (mc *mockCollector) stop() error { - var err = errAlreadyStopped - mc.stopOnce.Do(func() { - err = nil - if mc.stopFunc != nil { - mc.stopFunc() - } - }) - // Give it sometime to shutdown. - <-time.After(160 * time.Millisecond) - - // Wait for services to finish reading/writing. - // Getting the lock ensures the metricSvc is done flushing. - mc.metricSvc.mu.Lock() - defer mc.metricSvc.mu.Unlock() - return err -} - -func (mc *mockCollector) Stop() error { - return mc.stop() -} - -func (mc *mockCollector) getHeaders() metadata.MD { - return mc.metricSvc.getHeaders() -} - -func (mc *mockCollector) getMetrics() []*metricpb.Metric { - return mc.metricSvc.getMetrics() -} - -func (mc *mockCollector) GetMetrics() []*metricpb.Metric { - return mc.getMetrics() -} - -// runMockCollector is a helper function to create a mock Collector -func runMockCollector(t *testing.T) *mockCollector { - return runMockCollectorAtEndpoint(t, "localhost:0") -} - -func runMockCollectorAtEndpoint(t *testing.T, endpoint string) *mockCollector { - return runMockCollectorWithConfig(t, &mockConfig{endpoint: endpoint}) -} - -func runMockCollectorWithConfig(t *testing.T, mockConfig *mockConfig) *mockCollector { - ln, err := net.Listen("tcp", mockConfig.endpoint) - if err != nil { - t.Fatalf("Failed to get an endpoint: %v", err) - } - - srv := grpc.NewServer() - mc := makeMockCollector(t, mockConfig) - collectormetricpb.RegisterMetricsServiceServer(srv, mc.metricSvc) - go func() { - _ = srv.Serve(ln) - }() - - mc.endpoint = ln.Addr().String() - // srv.Stop calls Close on mc.ln. - mc.stopFunc = srv.Stop - - return mc -} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/options.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/options.go deleted file mode 100644 index 27769ff6b7c..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/options.go +++ /dev/null @@ -1,190 +0,0 @@ -// 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 otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - -import ( - "fmt" - "time" - - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/otlp/internal/retry" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" -) - -// Option applies an option to the gRPC driver. -type Option interface { - applyGRPCOption(otlpconfig.Config) otlpconfig.Config -} - -func asGRPCOptions(opts []Option) []otlpconfig.GRPCOption { - converted := make([]otlpconfig.GRPCOption, len(opts)) - for i, o := range opts { - converted[i] = otlpconfig.NewGRPCOption(o.applyGRPCOption) - } - return converted -} - -// RetryConfig defines configuration for retrying export of span batches that -// failed to be received by the target endpoint. -// -// This configuration does not define any network retry strategy. That is -// entirely handled by the gRPC ClientConn. -type RetryConfig retry.Config - -type wrappedOption struct { - otlpconfig.GRPCOption -} - -func (w wrappedOption) applyGRPCOption(cfg otlpconfig.Config) otlpconfig.Config { - return w.ApplyGRPCOption(cfg) -} - -// WithInsecure disables client transport security for the exporter's gRPC -// connection just like grpc.WithInsecure() -// (https://pkg.go.dev/google.golang.org/grpc#WithInsecure) does. Note, by -// default, client security is required unless WithInsecure is used. -// -// This option has no effect if WithGRPCConn is used. -func WithInsecure() Option { - return wrappedOption{otlpconfig.WithInsecure()} -} - -// WithEndpoint sets the target endpoint the exporter will connect to. If -// unset, localhost:4317 will be used as a default. -// -// This option has no effect if WithGRPCConn is used. -func WithEndpoint(endpoint string) Option { - return wrappedOption{otlpconfig.WithEndpoint(endpoint)} -} - -// WithReconnectionPeriod set the minimum amount of time between connection -// attempts to the target endpoint. -// -// This option has no effect if WithGRPCConn is used. -func WithReconnectionPeriod(rp time.Duration) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { - cfg.ReconnectionPeriod = rp - return cfg - })} -} - -func compressorToCompression(compressor string) otlpconfig.Compression { - switch compressor { - case "gzip": - return otlpconfig.GzipCompression - } - - otel.Handle(fmt.Errorf("invalid compression type: '%s', using no compression as default", compressor)) - return otlpconfig.NoCompression -} - -// WithCompressor sets the compressor for the gRPC client to use when sending -// requests. It is the responsibility of the caller to ensure that the -// compressor set has been registered with google.golang.org/grpc/encoding. -// This can be done by encoding.RegisterCompressor. Some compressors -// auto-register on import, such as gzip, which can be registered by calling -// `import _ "google.golang.org/grpc/encoding/gzip"`. -// -// This option has no effect if WithGRPCConn is used. -func WithCompressor(compressor string) Option { - return wrappedOption{otlpconfig.WithCompression(compressorToCompression(compressor))} -} - -// WithHeaders will send the provided headers with each gRPC requests. -func WithHeaders(headers map[string]string) Option { - return wrappedOption{otlpconfig.WithHeaders(headers)} -} - -// WithTLSCredentials allows the connection to use TLS credentials when -// talking to the server. It takes in grpc.TransportCredentials instead of say -// a Certificate file or a tls.Certificate, because the retrieving of these -// credentials can be done in many ways e.g. plain file, in code tls.Config or -// by certificate rotation, so it is up to the caller to decide what to use. -// -// This option has no effect if WithGRPCConn is used. -func WithTLSCredentials(creds credentials.TransportCredentials) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { - cfg.Metrics.GRPCCredentials = creds - return cfg - })} -} - -// WithServiceConfig defines the default gRPC service config used. -// -// This option has no effect if WithGRPCConn is used. -func WithServiceConfig(serviceConfig string) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { - cfg.ServiceConfig = serviceConfig - return cfg - })} -} - -// WithDialOption sets explicit grpc.DialOptions to use when making a -// connection. The options here are appended to the internal grpc.DialOptions -// used so they will take precedence over any other internal grpc.DialOptions -// they might conflict with. -// -// This option has no effect if WithGRPCConn is used. -func WithDialOption(opts ...grpc.DialOption) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { - cfg.DialOptions = opts - return cfg - })} -} - -// WithGRPCConn sets conn as the gRPC ClientConn used for all communication. -// -// This option takes precedence over any other option that relates to -// establishing or persisting a gRPC connection to a target endpoint. Any -// other option of those types passed will be ignored. -// -// It is the callers responsibility to close the passed conn. The client -// Shutdown method will not close this connection. -func WithGRPCConn(conn *grpc.ClientConn) Option { - return wrappedOption{otlpconfig.NewGRPCOption(func(cfg otlpconfig.Config) otlpconfig.Config { - cfg.GRPCConn = conn - return cfg - })} -} - -// WithTimeout sets the max amount of time a client will attempt to export a -// batch of spans. This takes precedence over any retry settings defined with -// WithRetry, once this time limit has been reached the export is abandoned -// and the batch of spans is dropped. -// -// If unset, the default timeout will be set to 10 seconds. -func WithTimeout(duration time.Duration) Option { - return wrappedOption{otlpconfig.WithTimeout(duration)} -} - -// WithRetry sets the retry policy for transient retryable errors that may be -// returned by the target endpoint when exporting a batch of spans. -// -// If the target endpoint responds with not only a retryable error, but -// explicitly returns a backoff time in the response. That time will take -// precedence over these settings. -// -// These settings do not define any network retry strategy. That is entirely -// handled by the gRPC ClientConn. -// -// If unset, the default retry policy will be used. It will retry the export -// 5 seconds after receiving a retryable error and increase exponentially -// after each error for no more than a total time of 1 minute. -func WithRetry(settings RetryConfig) Option { - return wrappedOption{otlpconfig.WithRetry(retry.Config(settings))} -} diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/certificate_test.go b/exporters/otlp/otlpmetric/otlpmetrichttp/certificate_test.go deleted file mode 100644 index d75547f6e4c..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/certificate_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// 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 otlpmetrichttp_test - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - cryptorand "crypto/rand" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "math/big" - mathrand "math/rand" - "net" - "time" -) - -type mathRandReader struct{} - -func (mathRandReader) Read(p []byte) (n int, err error) { - return mathrand.Read(p) -} - -var randReader mathRandReader - -type pemCertificate struct { - Certificate []byte - PrivateKey []byte -} - -// Based on https://golang.org/src/crypto/tls/generate_cert.go, -// simplified and weakened. -func generateWeakCertificate() (*pemCertificate, error) { - priv, err := ecdsa.GenerateKey(elliptic.P256(), randReader) - if err != nil { - return nil, err - } - keyUsage := x509.KeyUsageDigitalSignature - notBefore := time.Now() - notAfter := notBefore.Add(time.Hour) - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - serialNumber, err := cryptorand.Int(randReader, serialNumberLimit) - if err != nil { - return nil, err - } - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - Organization: []string{"otel-go"}, - }, - NotBefore: notBefore, - NotAfter: notAfter, - KeyUsage: keyUsage, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - DNSNames: []string{"localhost"}, - IPAddresses: []net.IP{net.IPv6loopback, net.IPv4(127, 0, 0, 1)}, - } - derBytes, err := x509.CreateCertificate(randReader, &template, &template, &priv.PublicKey, priv) - if err != nil { - return nil, err - } - certificateBuffer := new(bytes.Buffer) - if err := pem.Encode(certificateBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { - return nil, err - } - privDERBytes, err := x509.MarshalPKCS8PrivateKey(priv) - if err != nil { - return nil, err - } - privBuffer := new(bytes.Buffer) - if err := pem.Encode(privBuffer, &pem.Block{Type: "PRIVATE KEY", Bytes: privDERBytes}); err != nil { - return nil, err - } - return &pemCertificate{ - Certificate: certificateBuffer.Bytes(), - PrivateKey: privBuffer.Bytes(), - }, nil -} diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/client.go b/exporters/otlp/otlpmetric/otlpmetrichttp/client.go deleted file mode 100644 index dab28ff8fb2..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/client.go +++ /dev/null @@ -1,301 +0,0 @@ -// 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 otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - -import ( - "bytes" - "compress/gzip" - "context" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/url" - "strconv" - "sync" - "time" - - "google.golang.org/protobuf/proto" - - "go.opentelemetry.io/otel/exporters/otlp/internal/retry" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" - colmetricpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -const contentTypeProto = "application/x-protobuf" - -var gzPool = sync.Pool{ - New: func() interface{} { - w := gzip.NewWriter(ioutil.Discard) - return w - }, -} - -// Keep it in sync with golang's DefaultTransport from net/http! We -// have our own copy to avoid handling a situation where the -// DefaultTransport is overwritten with some different implementation -// of http.RoundTripper or it's modified by other package. -var ourTransport = &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, - ForceAttemptHTTP2: true, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, -} - -type client struct { - name string - cfg otlpconfig.SignalConfig - generalCfg otlpconfig.Config - requestFunc retry.RequestFunc - client *http.Client - stopCh chan struct{} - stopOnce sync.Once -} - -// NewClient creates a new HTTP metric client. -func NewClient(opts ...Option) otlpmetric.Client { - cfg := otlpconfig.NewHTTPConfig(asHTTPOptions(opts)...) - - httpClient := &http.Client{ - Transport: ourTransport, - Timeout: cfg.Metrics.Timeout, - } - if cfg.Metrics.TLSCfg != nil { - transport := ourTransport.Clone() - transport.TLSClientConfig = cfg.Metrics.TLSCfg - httpClient.Transport = transport - } - - stopCh := make(chan struct{}) - return &client{ - name: "metrics", - cfg: cfg.Metrics, - generalCfg: cfg, - requestFunc: cfg.RetryConfig.RequestFunc(evaluate), - stopCh: stopCh, - client: httpClient, - } -} - -// Start does nothing in a HTTP client -func (d *client) Start(ctx context.Context) error { - // nothing to do - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - return nil -} - -// Stop shuts down the client and interrupt any in-flight request. -func (d *client) Stop(ctx context.Context) error { - d.stopOnce.Do(func() { - close(d.stopCh) - }) - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - return nil -} - -// UploadMetrics sends a batch of metrics to the collector. -func (d *client) UploadMetrics(ctx context.Context, protoMetrics *metricpb.ResourceMetrics) error { - pbRequest := &colmetricpb.ExportMetricsServiceRequest{ - ResourceMetrics: []*metricpb.ResourceMetrics{protoMetrics}, - } - rawRequest, err := proto.Marshal(pbRequest) - if err != nil { - return err - } - - ctx, cancel := d.contextWithStop(ctx) - defer cancel() - - request, err := d.newRequest(rawRequest) - if err != nil { - return err - } - - return d.requestFunc(ctx, func(ctx context.Context) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - request.reset(ctx) - resp, err := d.client.Do(request.Request) - if err != nil { - return err - } - - var rErr error - switch resp.StatusCode { - case http.StatusOK: - // Success, do not retry. - case http.StatusTooManyRequests, - http.StatusServiceUnavailable: - // Retry-able failure. - rErr = newResponseError(resp.Header) - - // Going to retry, drain the body to reuse the connection. - if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil { - _ = resp.Body.Close() - return err - } - default: - rErr = fmt.Errorf("failed to send %s to %s: %s", d.name, request.URL, resp.Status) - } - - if err := resp.Body.Close(); err != nil { - return err - } - return rErr - }) -} - -func (d *client) newRequest(body []byte) (request, error) { - u := url.URL{Scheme: d.getScheme(), Host: d.cfg.Endpoint, Path: d.cfg.URLPath} - r, err := http.NewRequest(http.MethodPost, u.String(), nil) - if err != nil { - return request{Request: r}, err - } - - for k, v := range d.cfg.Headers { - r.Header.Set(k, v) - } - r.Header.Set("Content-Type", contentTypeProto) - - req := request{Request: r} - switch Compression(d.cfg.Compression) { - case NoCompression: - r.ContentLength = (int64)(len(body)) - req.bodyReader = bodyReader(body) - case GzipCompression: - // Ensure the content length is not used. - r.ContentLength = -1 - r.Header.Set("Content-Encoding", "gzip") - - gz := gzPool.Get().(*gzip.Writer) - defer gzPool.Put(gz) - - var b bytes.Buffer - gz.Reset(&b) - - if _, err := gz.Write(body); err != nil { - return req, err - } - // Close needs to be called to ensure body if fully written. - if err := gz.Close(); err != nil { - return req, err - } - - req.bodyReader = bodyReader(b.Bytes()) - } - - return req, nil -} - -// bodyReader returns a closure returning a new reader for buf. -func bodyReader(buf []byte) func() io.ReadCloser { - return func() io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader(buf)) - } -} - -// request wraps an http.Request with a resettable body reader. -type request struct { - *http.Request - - // bodyReader allows the same body to be used for multiple requests. - bodyReader func() io.ReadCloser -} - -// reset reinitializes the request Body and uses ctx for the request. -func (r *request) reset(ctx context.Context) { - r.Body = r.bodyReader() - r.Request = r.Request.WithContext(ctx) -} - -// retryableError represents a request failure that can be retried. -type retryableError struct { - throttle int64 -} - -// newResponseError returns a retryableError and will extract any explicit -// throttle delay contained in headers. -func newResponseError(header http.Header) error { - var rErr retryableError - if s, ok := header["Retry-After"]; ok { - if t, err := strconv.ParseInt(s[0], 10, 64); err == nil { - rErr.throttle = t - } - } - return rErr -} - -func (e retryableError) Error() string { - return "retry-able request failure" -} - -// evaluate returns if err is retry-able. If it is and it includes an explicit -// throttling delay, that delay is also returned. -func evaluate(err error) (bool, time.Duration) { - if err == nil { - return false, 0 - } - - rErr, ok := err.(retryableError) - if !ok { - return false, 0 - } - - return true, time.Duration(rErr.throttle) -} - -func (d *client) getScheme() string { - if d.cfg.Insecure { - return "http" - } - return "https" -} - -func (d *client) contextWithStop(ctx context.Context) (context.Context, context.CancelFunc) { - // Unify the parent context Done signal with the client's stop - // channel. - ctx, cancel := context.WithCancel(ctx) - go func(ctx context.Context, cancel context.CancelFunc) { - select { - case <-ctx.Done(): - // Nothing to do, either cancelled or deadline - // happened. - case <-d.stopCh: - cancel() - } - }(ctx, cancel) - return ctx, cancel -} diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/client_test.go b/exporters/otlp/otlpmetric/otlpmetrichttp/client_test.go deleted file mode 100644 index 5e614da2640..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/client_test.go +++ /dev/null @@ -1,271 +0,0 @@ -// 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 otlpmetrichttp_test - -import ( - "context" - "net/http" - "os" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - "go.opentelemetry.io/otel/sdk/resource" -) - -const ( - relOtherMetricsPath = "post/metrics/here" - otherMetricsPath = "/post/metrics/here" -) - -var ( - oneRecord = otlpmetrictest.OneRecordReader() - - testResource = resource.Empty() -) - -var ( - testHeaders = map[string]string{ - "Otel-Go-Key-1": "somevalue", - "Otel-Go-Key-2": "someothervalue", - } -) - -func TestEndToEnd(t *testing.T) { - tests := []struct { - name string - opts []otlpmetrichttp.Option - mcCfg mockCollectorConfig - tls bool - }{ - { - name: "no extra options", - opts: nil, - }, - { - name: "with gzip compression", - opts: []otlpmetrichttp.Option{ - otlpmetrichttp.WithCompression(otlpmetrichttp.GzipCompression), - }, - }, - { - name: "with empty paths (forced to defaults)", - opts: []otlpmetrichttp.Option{ - otlpmetrichttp.WithURLPath(""), - }, - }, - { - name: "with relative paths", - opts: []otlpmetrichttp.Option{ - otlpmetrichttp.WithURLPath(relOtherMetricsPath), - }, - mcCfg: mockCollectorConfig{ - MetricsURLPath: otherMetricsPath, - }, - }, - { - name: "with TLS", - opts: nil, - mcCfg: mockCollectorConfig{ - WithTLS: true, - }, - tls: true, - }, - { - name: "with extra headers", - opts: []otlpmetrichttp.Option{ - otlpmetrichttp.WithHeaders(testHeaders), - }, - mcCfg: mockCollectorConfig{ - ExpectedHeaders: testHeaders, - }, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - mc := runMockCollector(t, tc.mcCfg) - defer mc.MustStop(t) - allOpts := []otlpmetrichttp.Option{ - otlpmetrichttp.WithEndpoint(mc.Endpoint()), - } - if tc.tls { - tlsConfig := mc.ClientTLSConfig() - require.NotNil(t, tlsConfig) - allOpts = append(allOpts, otlpmetrichttp.WithTLSClientConfig(tlsConfig)) - } else { - allOpts = append(allOpts, otlpmetrichttp.WithInsecure()) - } - allOpts = append(allOpts, tc.opts...) - client := otlpmetrichttp.NewClient(allOpts...) - ctx := context.Background() - exporter, err := otlpmetric.New(ctx, client) - if assert.NoError(t, err) { - defer func() { - assert.NoError(t, exporter.Shutdown(ctx)) - }() - otlpmetrictest.RunEndToEndTest(ctx, t, exporter, mc) - } - }) - } -} - -func TestExporterShutdown(t *testing.T) { - mc := runMockCollector(t, mockCollectorConfig{}) - defer func() { - _ = mc.Stop() - }() - - <-time.After(5 * time.Millisecond) - - otlpmetrictest.RunExporterShutdownTest(t, func() otlpmetric.Client { - return otlpmetrichttp.NewClient( - otlpmetrichttp.WithInsecure(), - otlpmetrichttp.WithEndpoint(mc.endpoint), - ) - }) -} - -func TestTimeout(t *testing.T) { - delay := make(chan struct{}) - mcCfg := mockCollectorConfig{Delay: delay} - mc := runMockCollector(t, mcCfg) - defer mc.MustStop(t) - defer func() { close(delay) }() - client := otlpmetrichttp.NewClient( - otlpmetrichttp.WithEndpoint(mc.Endpoint()), - otlpmetrichttp.WithInsecure(), - otlpmetrichttp.WithTimeout(time.Nanosecond), - ) - ctx := context.Background() - exporter, err := otlpmetric.New(ctx, client) - require.NoError(t, err) - defer func() { - assert.NoError(t, exporter.Shutdown(ctx)) - }() - err = exporter.Export(ctx, testResource, oneRecord) - assert.Equalf(t, true, os.IsTimeout(err), "expected timeout error, got: %v", err) -} - -func TestEmptyData(t *testing.T) { - mcCfg := mockCollectorConfig{} - mc := runMockCollector(t, mcCfg) - defer mc.MustStop(t) - driver := otlpmetrichttp.NewClient( - otlpmetrichttp.WithEndpoint(mc.Endpoint()), - otlpmetrichttp.WithInsecure(), - ) - ctx := context.Background() - exporter, err := otlpmetric.New(ctx, driver) - require.NoError(t, err) - defer func() { - assert.NoError(t, exporter.Shutdown(ctx)) - }() - assert.NoError(t, err) - err = exporter.Export(ctx, testResource, oneRecord) - assert.NoError(t, err) - assert.NotEmpty(t, mc.GetMetrics()) -} - -func TestCancelledContext(t *testing.T) { - statuses := []int{ - http.StatusBadRequest, - } - mcCfg := mockCollectorConfig{ - InjectHTTPStatus: statuses, - } - mc := runMockCollector(t, mcCfg) - defer mc.MustStop(t) - driver := otlpmetrichttp.NewClient( - otlpmetrichttp.WithEndpoint(mc.Endpoint()), - otlpmetrichttp.WithInsecure(), - ) - ctx, cancel := context.WithCancel(context.Background()) - exporter, err := otlpmetric.New(ctx, driver) - require.NoError(t, err) - defer func() { - assert.NoError(t, exporter.Shutdown(context.Background())) - }() - cancel() - _ = exporter.Export(ctx, testResource, oneRecord) - assert.Empty(t, mc.GetMetrics()) -} - -func TestDeadlineContext(t *testing.T) { - statuses := make([]int, 0, 5) - for i := 0; i < cap(statuses); i++ { - statuses = append(statuses, http.StatusTooManyRequests) - } - mcCfg := mockCollectorConfig{ - InjectHTTPStatus: statuses, - } - mc := runMockCollector(t, mcCfg) - defer mc.MustStop(t) - driver := otlpmetrichttp.NewClient( - otlpmetrichttp.WithEndpoint(mc.Endpoint()), - otlpmetrichttp.WithInsecure(), - otlpmetrichttp.WithBackoff(time.Minute), - ) - ctx := context.Background() - exporter, err := otlpmetric.New(ctx, driver) - require.NoError(t, err) - defer func() { - assert.NoError(t, exporter.Shutdown(context.Background())) - }() - ctx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - err = exporter.Export(ctx, testResource, oneRecord) - assert.Error(t, err) - assert.Empty(t, mc.GetMetrics()) -} - -func TestStopWhileExporting(t *testing.T) { - statuses := make([]int, 0, 5) - for i := 0; i < cap(statuses); i++ { - statuses = append(statuses, http.StatusTooManyRequests) - } - mcCfg := mockCollectorConfig{ - InjectHTTPStatus: statuses, - } - mc := runMockCollector(t, mcCfg) - defer mc.MustStop(t) - driver := otlpmetrichttp.NewClient( - otlpmetrichttp.WithEndpoint(mc.Endpoint()), - otlpmetrichttp.WithInsecure(), - otlpmetrichttp.WithBackoff(time.Minute), - ) - ctx := context.Background() - exporter, err := otlpmetric.New(ctx, driver) - require.NoError(t, err) - defer func() { - assert.NoError(t, exporter.Shutdown(ctx)) - }() - doneCh := make(chan struct{}) - go func() { - err := exporter.Export(ctx, testResource, oneRecord) - assert.Error(t, err) - assert.Empty(t, mc.GetMetrics()) - close(doneCh) - }() - <-time.After(time.Second) - err = exporter.Shutdown(ctx) - assert.NoError(t, err) - <-doneCh -} diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/client_unit_test.go b/exporters/otlp/otlpmetric/otlpmetrichttp/client_unit_test.go deleted file mode 100644 index 4ba01c85e5e..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/client_unit_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// 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 otlpmetrichttp - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestUnreasonableBackoff(t *testing.T) { - cIface := NewClient( - WithEndpoint("http://localhost"), - WithInsecure(), - WithBackoff(-time.Microsecond), - ) - require.IsType(t, &client{}, cIface) - c := cIface.(*client) - assert.True(t, c.generalCfg.RetryConfig.Enabled) - assert.Equal(t, 5*time.Second, c.generalCfg.RetryConfig.InitialInterval) - assert.Equal(t, 300*time.Millisecond, c.generalCfg.RetryConfig.MaxInterval) - assert.Equal(t, time.Minute, c.generalCfg.RetryConfig.MaxElapsedTime) -} - -func TestUnreasonableMaxAttempts(t *testing.T) { - type testcase struct { - name string - maxAttempts int - } - for _, tc := range []testcase{ - { - name: "negative max attempts", - maxAttempts: -3, - }, - { - name: "too large max attempts", - maxAttempts: 10, - }, - } { - t.Run(tc.name, func(t *testing.T) { - cIface := NewClient( - WithEndpoint("http://localhost"), - WithInsecure(), - WithMaxAttempts(tc.maxAttempts), - ) - require.IsType(t, &client{}, cIface) - c := cIface.(*client) - assert.True(t, c.generalCfg.RetryConfig.Enabled) - assert.Equal(t, 5*time.Second, c.generalCfg.RetryConfig.InitialInterval) - assert.Equal(t, 30*time.Second, c.generalCfg.RetryConfig.MaxInterval) - assert.Equal(t, 145*time.Second, c.generalCfg.RetryConfig.MaxElapsedTime) - }) - } -} diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/doc.go b/exporters/otlp/otlpmetric/otlpmetrichttp/doc.go deleted file mode 100644 index d096388320d..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/doc.go +++ /dev/null @@ -1,23 +0,0 @@ -// 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 otlpmetrichttp provides a client that sends metrics to the collector -using HTTP with binary protobuf payloads. - -This package is currently in a pre-GA phase. Backwards incompatible changes -may be introduced in subsequent minor version releases as we work to track the -evolving OpenTelemetry specification and user feedback. -*/ -package otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/exporter.go b/exporters/otlp/otlpmetric/otlpmetrichttp/exporter.go deleted file mode 100644 index de09e7cdcaa..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/exporter.go +++ /dev/null @@ -1,31 +0,0 @@ -// 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 otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - -import ( - "context" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" -) - -// New constructs a new Exporter and starts it. -func New(ctx context.Context, opts ...Option) (*otlpmetric.Exporter, error) { - return otlpmetric.New(ctx, NewClient(opts...)) -} - -// NewUnstarted constructs a new Exporter and does not start it. -func NewUnstarted(opts ...Option) *otlpmetric.Exporter { - return otlpmetric.NewUnstarted(NewClient(opts...)) -} diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/go.mod b/exporters/otlp/otlpmetric/otlpmetrichttp/go.mod deleted file mode 100644 index 501200ad6d5..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/go.mod +++ /dev/null @@ -1,76 +0,0 @@ -module go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp - -go 1.16 - -require ( - github.com/stretchr/testify v1.7.1 - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.3 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/proto/otlp v0.15.0 - google.golang.org/protobuf v1.28.0 -) - -replace go.opentelemetry.io/otel => ../../../.. - -replace go.opentelemetry.io/otel/sdk => ../../../../sdk - -replace go.opentelemetry.io/otel/sdk/metric => ../../../../sdk/metric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../ - -replace go.opentelemetry.io/otel/metric => ../../../../metric - -replace go.opentelemetry.io/otel/trace => ../../../../trace - -replace go.opentelemetry.io/otel/bridge/opencensus => ../../../../bridge/opencensus - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../../../bridge/opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../../../../example/jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../../../../example/namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../../../../example/opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../../../../example/otel-collector - -replace go.opentelemetry.io/otel/example/passthrough => ../../../../example/passthrough - -replace go.opentelemetry.io/otel/example/prometheus => ../../../../example/prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../../../../example/zipkin - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ./ - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/internal/tools => ../../../../internal/tools - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../../../sdk/export/metric - -replace go.opentelemetry.io/otel/internal/metric => ../../../../internal/metric - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../../jaeger - -replace go.opentelemetry.io/otel/exporters/prometheus => ../../../prometheus - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../../zipkin - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../../../stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../../../stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../otlpmetricgrpc - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../../../bridge/opencensus/test - -replace go.opentelemetry.io/otel/example/fib => ../../../../example/fib - -replace go.opentelemetry.io/otel/schema => ../../../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../internal/retry diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/go.sum b/exporters/otlp/otlpmetric/otlpmetrichttp/go.sum deleted file mode 100644 index f69a11110a4..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/go.sum +++ /dev/null @@ -1,435 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -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/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= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/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= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0 h1:h0bKrvdrT/9sBwEJ6iWUqT/N/xPcS66bL4u3isneJ6w= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/mock_collector_test.go b/exporters/otlp/otlpmetric/otlpmetrichttp/mock_collector_test.go deleted file mode 100644 index 876f8608c3d..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/mock_collector_test.go +++ /dev/null @@ -1,240 +0,0 @@ -// 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 otlpmetrichttp_test - -import ( - "bytes" - "compress/gzip" - "context" - "crypto/tls" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "sync" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpmetrictest" - collectormetricpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" -) - -type mockCollector struct { - endpoint string - server *http.Server - - spanLock sync.Mutex - metricsStorage otlpmetrictest.MetricsStorage - - injectHTTPStatus []int - injectContentType string - delay <-chan struct{} - - clientTLSConfig *tls.Config - expectedHeaders map[string]string -} - -func (c *mockCollector) Stop() error { - return c.server.Shutdown(context.Background()) -} - -func (c *mockCollector) MustStop(t *testing.T) { - assert.NoError(t, c.server.Shutdown(context.Background())) -} - -func (c *mockCollector) GetMetrics() []*metricpb.Metric { - c.spanLock.Lock() - defer c.spanLock.Unlock() - return c.metricsStorage.GetMetrics() -} - -func (c *mockCollector) Endpoint() string { - return c.endpoint -} - -func (c *mockCollector) ClientTLSConfig() *tls.Config { - return c.clientTLSConfig -} - -func (c *mockCollector) serveMetrics(w http.ResponseWriter, r *http.Request) { - if c.delay != nil { - select { - case <-c.delay: - case <-r.Context().Done(): - return - } - } - - if !c.checkHeaders(r) { - w.WriteHeader(http.StatusBadRequest) - return - } - response := collectormetricpb.ExportMetricsServiceResponse{} - rawResponse, err := proto.Marshal(&response) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - if injectedStatus := c.getInjectHTTPStatus(); injectedStatus != 0 { - writeReply(w, rawResponse, injectedStatus, c.injectContentType) - return - } - rawRequest, err := readRequest(r) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - - request, err := unmarshalMetricsRequest(rawRequest, r.Header.Get("content-type")) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - return - } - writeReply(w, rawResponse, 0, c.injectContentType) - c.spanLock.Lock() - defer c.spanLock.Unlock() - c.metricsStorage.AddMetrics(request) -} - -func unmarshalMetricsRequest(rawRequest []byte, contentType string) (*collectormetricpb.ExportMetricsServiceRequest, error) { - request := &collectormetricpb.ExportMetricsServiceRequest{} - if contentType != "application/x-protobuf" { - return request, fmt.Errorf("invalid content-type: %s, only application/x-protobuf is supported", contentType) - } - err := proto.Unmarshal(rawRequest, request) - return request, err -} - -func (c *mockCollector) checkHeaders(r *http.Request) bool { - for k, v := range c.expectedHeaders { - got := r.Header.Get(k) - if got != v { - return false - } - } - return true -} - -func (c *mockCollector) getInjectHTTPStatus() int { - if len(c.injectHTTPStatus) == 0 { - return 0 - } - status := c.injectHTTPStatus[0] - c.injectHTTPStatus = c.injectHTTPStatus[1:] - if len(c.injectHTTPStatus) == 0 { - c.injectHTTPStatus = nil - } - return status -} - -func readRequest(r *http.Request) ([]byte, error) { - if r.Header.Get("Content-Encoding") == "gzip" { - return readGzipBody(r.Body) - } - return ioutil.ReadAll(r.Body) -} - -func readGzipBody(body io.Reader) ([]byte, error) { - rawRequest := bytes.Buffer{} - gunzipper, err := gzip.NewReader(body) - if err != nil { - return nil, err - } - defer gunzipper.Close() - _, err = io.Copy(&rawRequest, gunzipper) - if err != nil { - return nil, err - } - return rawRequest.Bytes(), nil -} - -func writeReply(w http.ResponseWriter, rawResponse []byte, injectHTTPStatus int, injectContentType string) { - status := http.StatusOK - if injectHTTPStatus != 0 { - status = injectHTTPStatus - } - contentType := "application/x-protobuf" - if injectContentType != "" { - contentType = injectContentType - } - w.Header().Set("Content-Type", contentType) - w.WriteHeader(status) - _, _ = w.Write(rawResponse) -} - -type mockCollectorConfig struct { - MetricsURLPath string - Port int - InjectHTTPStatus []int - InjectContentType string - Delay <-chan struct{} - WithTLS bool - ExpectedHeaders map[string]string -} - -func (c *mockCollectorConfig) fillInDefaults() { - if c.MetricsURLPath == "" { - c.MetricsURLPath = otlpconfig.DefaultMetricsPath - } -} - -func runMockCollector(t *testing.T, cfg mockCollectorConfig) *mockCollector { - cfg.fillInDefaults() - ln, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", cfg.Port)) - require.NoError(t, err) - _, portStr, err := net.SplitHostPort(ln.Addr().String()) - require.NoError(t, err) - m := &mockCollector{ - endpoint: fmt.Sprintf("localhost:%s", portStr), - metricsStorage: otlpmetrictest.NewMetricsStorage(), - injectHTTPStatus: cfg.InjectHTTPStatus, - injectContentType: cfg.InjectContentType, - delay: cfg.Delay, - expectedHeaders: cfg.ExpectedHeaders, - } - mux := http.NewServeMux() - mux.Handle(cfg.MetricsURLPath, http.HandlerFunc(m.serveMetrics)) - server := &http.Server{ - Handler: mux, - } - if cfg.WithTLS { - pem, err := generateWeakCertificate() - require.NoError(t, err) - tlsCertificate, err := tls.X509KeyPair(pem.Certificate, pem.PrivateKey) - require.NoError(t, err) - server.TLSConfig = &tls.Config{ - Certificates: []tls.Certificate{tlsCertificate}, - } - - m.clientTLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } - go func() { - if cfg.WithTLS { - _ = server.ServeTLS(ln, "", "") - } else { - _ = server.Serve(ln) - } - }() - m.server = server - return m -} diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/options.go b/exporters/otlp/otlpmetric/otlpmetrichttp/options.go deleted file mode 100644 index 8d12c791954..00000000000 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/options.go +++ /dev/null @@ -1,185 +0,0 @@ -// 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 otlpmetrichttp // import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - -import ( - "crypto/tls" - "time" - - "go.opentelemetry.io/otel/exporters/otlp/internal/retry" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/otlpconfig" -) - -// Compression describes the compression used for payloads sent to the -// collector. -type Compression otlpconfig.Compression - -const ( - // NoCompression tells the driver to send payloads without - // compression. - NoCompression = Compression(otlpconfig.NoCompression) - // GzipCompression tells the driver to send payloads after - // compressing them with gzip. - GzipCompression = Compression(otlpconfig.GzipCompression) -) - -// Option applies an option to the HTTP client. -type Option interface { - applyHTTPOption(otlpconfig.Config) otlpconfig.Config -} - -func asHTTPOptions(opts []Option) []otlpconfig.HTTPOption { - converted := make([]otlpconfig.HTTPOption, len(opts)) - for i, o := range opts { - converted[i] = otlpconfig.NewHTTPOption(o.applyHTTPOption) - } - return converted -} - -// RetryConfig defines configuration for retrying batches in case of export -// failure using an exponential backoff. -type RetryConfig retry.Config - -type wrappedOption struct { - otlpconfig.HTTPOption -} - -func (w wrappedOption) applyHTTPOption(cfg otlpconfig.Config) otlpconfig.Config { - return w.ApplyHTTPOption(cfg) -} - -// WithEndpoint allows one to set the address of the collector endpoint that -// the driver will use to send metrics. If unset, it will instead try to use -// the default endpoint (localhost:4318). Note that the endpoint must not -// contain any URL path. -func WithEndpoint(endpoint string) Option { - return wrappedOption{otlpconfig.WithEndpoint(endpoint)} -} - -// WithCompression tells the driver to compress the sent data. -func WithCompression(compression Compression) Option { - return wrappedOption{otlpconfig.WithCompression(otlpconfig.Compression(compression))} -} - -// WithURLPath allows one to override the default URL path used -// for sending metrics. If unset, default ("/v1/metrics") will be used. -func WithURLPath(urlPath string) Option { - return wrappedOption{otlpconfig.WithURLPath(urlPath)} -} - -// WithMaxAttempts allows one to override how many times the driver -// will try to send the payload in case of retryable errors. -// The max attempts is limited to at most 5 retries. If unset, -// default (5) will be used. -// -// Deprecated: Use WithRetry instead. -func WithMaxAttempts(maxAttempts int) Option { - if maxAttempts > 5 || maxAttempts < 0 { - maxAttempts = 5 - } - return wrappedOption{ - otlpconfig.NewHTTPOption(func(cfg otlpconfig.Config) otlpconfig.Config { - cfg.RetryConfig.Enabled = true - - var ( - init = cfg.RetryConfig.InitialInterval - maxI = cfg.RetryConfig.MaxInterval - maxE = cfg.RetryConfig.MaxElapsedTime - ) - - if init == 0 { - init = retry.DefaultConfig.InitialInterval - } - if maxI == 0 { - maxI = retry.DefaultConfig.MaxInterval - } - if maxE == 0 { - maxE = retry.DefaultConfig.MaxElapsedTime - } - attempts := int64(maxE+init) / int64(maxI) - - if int64(maxAttempts) == attempts { - return cfg - } - - maxE = time.Duration(int64(maxAttempts)*int64(maxI)) - init - - cfg.RetryConfig.InitialInterval = init - cfg.RetryConfig.MaxInterval = maxI - cfg.RetryConfig.MaxElapsedTime = maxE - - return cfg - }), - } -} - -// WithBackoff tells the driver to use the duration as a base of the -// exponential backoff strategy. If unset, default (300ms) will be -// used. -// -// Deprecated: Use WithRetry instead. -func WithBackoff(duration time.Duration) Option { - if duration < 0 { - duration = 300 * time.Millisecond - } - return wrappedOption{ - otlpconfig.NewHTTPOption(func(cfg otlpconfig.Config) otlpconfig.Config { - cfg.RetryConfig.Enabled = true - cfg.RetryConfig.MaxInterval = duration - if cfg.RetryConfig.InitialInterval == 0 { - cfg.RetryConfig.InitialInterval = retry.DefaultConfig.InitialInterval - } - if cfg.RetryConfig.MaxElapsedTime == 0 { - cfg.RetryConfig.MaxElapsedTime = retry.DefaultConfig.MaxElapsedTime - } - return cfg - }), - } -} - -// WithTLSClientConfig can be used to set up a custom TLS -// configuration for the client used to send payloads to the -// collector. Use it if you want to use a custom certificate. -func WithTLSClientConfig(tlsCfg *tls.Config) Option { - return wrappedOption{otlpconfig.WithTLSClientConfig(tlsCfg)} -} - -// WithInsecure tells the driver to connect to the collector using the -// HTTP scheme, instead of HTTPS. -func WithInsecure() Option { - return wrappedOption{otlpconfig.WithInsecure()} -} - -// WithHeaders allows one to tell the driver to send additional HTTP -// headers with the payloads. Specifying headers like Content-Length, -// Content-Encoding and Content-Type may result in a broken driver. -func WithHeaders(headers map[string]string) Option { - return wrappedOption{otlpconfig.WithHeaders(headers)} -} - -// WithTimeout tells the driver the max waiting time for the backend to process -// each metrics batch. If unset, the default will be 10 seconds. -func WithTimeout(duration time.Duration) Option { - return wrappedOption{otlpconfig.WithTimeout(duration)} -} - -// WithRetry configures the retry policy for transient errors that may occurs -// when exporting traces. An exponential back-off algorithm is used to ensure -// endpoints are not overwhelmed with retries. If unset, the default retry -// policy will retry after 5 seconds and increase exponentially after each -// error for a total of 1 minute. -func WithRetry(rc RetryConfig) Option { - return wrappedOption{otlpconfig.WithRetry(retry.Config(rc))} -} diff --git a/exporters/prometheus/README.md b/exporters/prometheus/README.md deleted file mode 100644 index ccded2f2829..00000000000 --- a/exporters/prometheus/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# OpenTelemetry-Go Prometheus Exporter - -OpenTelemetry Prometheus exporter - -## Installation - -``` -go get -u go.opentelemetry.io/otel/exporters/prometheus -``` diff --git a/exporters/prometheus/go.mod b/exporters/prometheus/go.mod deleted file mode 100644 index 4db0f072a95..00000000000 --- a/exporters/prometheus/go.mod +++ /dev/null @@ -1,76 +0,0 @@ -module go.opentelemetry.io/otel/exporters/prometheus - -go 1.16 - -require ( - github.com/prometheus/client_golang v1.12.1 - github.com/stretchr/testify v1.7.1 - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/metric v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/otel/sdk/metric v0.29.0 -) - -replace go.opentelemetry.io/otel => ../.. - -replace go.opentelemetry.io/otel/bridge/opencensus => ../../bridge/opencensus - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../bridge/opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../../example/jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../../example/namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../../example/opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../../example/otel-collector - -replace go.opentelemetry.io/otel/example/passthrough => ../../example/passthrough - -replace go.opentelemetry.io/otel/example/prometheus => ../../example/prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../../example/zipkin - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../otlp/otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../otlp/otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../otlp/otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/exporters/prometheus => ./ - -replace go.opentelemetry.io/otel/exporters/jaeger => ../jaeger - -replace go.opentelemetry.io/otel/exporters/zipkin => ../zipkin - -replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric - -replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools - -replace go.opentelemetry.io/otel/metric => ../../metric - -replace go.opentelemetry.io/otel/sdk => ../../sdk - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric - -replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric - -replace go.opentelemetry.io/otel/trace => ../../trace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../otlp/otlpmetric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../otlp/otlpmetric/otlpmetricgrpc - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../stdout/stdoutmetric - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../stdout/stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../otlp/otlpmetric/otlpmetrichttp - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../bridge/opencensus/test - -replace go.opentelemetry.io/otel/example/fib => ../../example/fib - -replace go.opentelemetry.io/otel/schema => ../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../otlp/internal/retry diff --git a/exporters/prometheus/go.sum b/exporters/prometheus/go.sum deleted file mode 100644 index 43be0c26beb..00000000000 --- a/exporters/prometheus/go.sum +++ /dev/null @@ -1,481 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -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/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= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -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/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -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= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/exporters/prometheus/prometheus.go b/exporters/prometheus/prometheus.go deleted file mode 100644 index 1de8778eb53..00000000000 --- a/exporters/prometheus/prometheus.go +++ /dev/null @@ -1,322 +0,0 @@ -// 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 prometheus // import "go.opentelemetry.io/otel/exporters/prometheus" - -// Note that this package does not support a way to export Prometheus -// Summary data points, removed in PR#1412. - -import ( - "context" - "fmt" - "net/http" - "sync" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/sdk/instrumentation" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -// Exporter supports Prometheus pulls. It does not implement the -// sdk/export/metric.Exporter interface--instead it creates a pull -// controller and reads the latest checkpointed data on-scrape. -type Exporter struct { - handler http.Handler - - registerer prometheus.Registerer - gatherer prometheus.Gatherer - - // lock protects access to the controller. The controller - // exposes its own lock, but using a dedicated lock in this - // struct allows the exporter to potentially support multiple - // controllers (e.g., with different resources). - lock sync.RWMutex - controller *controller.Controller -} - -// ErrUnsupportedAggregator is returned for unrepresentable aggregator -// types. -var ErrUnsupportedAggregator = fmt.Errorf("unsupported aggregator type") - -var _ http.Handler = &Exporter{} - -// Config is a set of configs for the tally reporter. -type Config struct { - // Registry is the prometheus registry that will be used as the default Registerer and - // Gatherer if these are not specified. - // - // If not set a new empty Registry is created. - Registry *prometheus.Registry - - // Registerer is the prometheus registerer to register - // metrics with. - // - // If not specified the Registry will be used as default. - Registerer prometheus.Registerer - - // Gatherer is the prometheus gatherer to gather - // metrics with. - // - // If not specified the Registry will be used as default. - Gatherer prometheus.Gatherer - - // DefaultHistogramBoundaries defines the default histogram bucket - // boundaries. - DefaultHistogramBoundaries []float64 -} - -// New returns a new Prometheus exporter using the configured metric -// controller. See controller.New(). -func New(config Config, controller *controller.Controller) (*Exporter, error) { - if config.Registry == nil { - config.Registry = prometheus.NewRegistry() - } - - if config.Registerer == nil { - config.Registerer = config.Registry - } - - if config.Gatherer == nil { - config.Gatherer = config.Registry - } - - e := &Exporter{ - handler: promhttp.HandlerFor(config.Gatherer, promhttp.HandlerOpts{}), - registerer: config.Registerer, - gatherer: config.Gatherer, - controller: controller, - } - - c := &collector{ - exp: e, - } - if err := config.Registerer.Register(c); err != nil { - return nil, fmt.Errorf("cannot register the collector: %w", err) - } - return e, nil -} - -// MeterProvider returns the MeterProvider of this exporter. -func (e *Exporter) MeterProvider() metric.MeterProvider { - return e.controller -} - -// Controller returns the controller object that coordinates collection for the SDK. -func (e *Exporter) Controller() *controller.Controller { - e.lock.RLock() - defer e.lock.RUnlock() - return e.controller -} - -// TemporalityFor implements TemporalitySelector. -func (e *Exporter) TemporalityFor(desc *sdkapi.Descriptor, kind aggregation.Kind) aggregation.Temporality { - return aggregation.CumulativeTemporalitySelector().TemporalityFor(desc, kind) -} - -// ServeHTTP implements http.Handler. -func (e *Exporter) ServeHTTP(w http.ResponseWriter, r *http.Request) { - e.handler.ServeHTTP(w, r) -} - -// collector implements prometheus.Collector interface. -type collector struct { - exp *Exporter -} - -var _ prometheus.Collector = (*collector)(nil) - -// Describe implements prometheus.Collector. -func (c *collector) Describe(ch chan<- *prometheus.Desc) { - c.exp.lock.RLock() - defer c.exp.lock.RUnlock() - - _ = c.exp.Controller().ForEach(func(_ instrumentation.Library, reader export.Reader) error { - return reader.ForEach(c.exp, func(record export.Record) error { - var labelKeys []string - mergeLabels(record, c.exp.controller.Resource(), &labelKeys, nil) - ch <- c.toDesc(record, labelKeys) - return nil - }) - }) -} - -// Collect exports the last calculated Reader state. -// -// Collect is invoked whenever prometheus.Gatherer is also invoked. -// For example, when the HTTP endpoint is invoked by Prometheus. -func (c *collector) Collect(ch chan<- prometheus.Metric) { - c.exp.lock.RLock() - defer c.exp.lock.RUnlock() - - ctrl := c.exp.Controller() - if err := ctrl.Collect(context.Background()); err != nil { - otel.Handle(err) - } - - err := ctrl.ForEach(func(_ instrumentation.Library, reader export.Reader) error { - return reader.ForEach(c.exp, func(record export.Record) error { - - agg := record.Aggregation() - numberKind := record.Descriptor().NumberKind() - instrumentKind := record.Descriptor().InstrumentKind() - - var labelKeys, labels []string - mergeLabels(record, c.exp.controller.Resource(), &labelKeys, &labels) - - desc := c.toDesc(record, labelKeys) - - if hist, ok := agg.(aggregation.Histogram); ok { - if err := c.exportHistogram(ch, hist, numberKind, desc, labels); err != nil { - return fmt.Errorf("exporting histogram: %w", err) - } - } else if sum, ok := agg.(aggregation.Sum); ok && instrumentKind.Monotonic() { - if err := c.exportMonotonicCounter(ch, sum, numberKind, desc, labels); err != nil { - return fmt.Errorf("exporting monotonic counter: %w", err) - } - } else if sum, ok := agg.(aggregation.Sum); ok && !instrumentKind.Monotonic() { - if err := c.exportNonMonotonicCounter(ch, sum, numberKind, desc, labels); err != nil { - return fmt.Errorf("exporting non monotonic counter: %w", err) - } - } else if lastValue, ok := agg.(aggregation.LastValue); ok { - if err := c.exportLastValue(ch, lastValue, numberKind, desc, labels); err != nil { - return fmt.Errorf("exporting last value: %w", err) - } - } else { - return fmt.Errorf("%w: %s", ErrUnsupportedAggregator, agg.Kind()) - } - return nil - }) - }) - if err != nil { - otel.Handle(err) - } -} - -func (c *collector) exportLastValue(ch chan<- prometheus.Metric, lvagg aggregation.LastValue, kind number.Kind, desc *prometheus.Desc, labels []string) error { - lv, _, err := lvagg.LastValue() - if err != nil { - return fmt.Errorf("error retrieving last value: %w", err) - } - - m, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, lv.CoerceToFloat64(kind), labels...) - if err != nil { - return fmt.Errorf("error creating constant metric: %w", err) - } - - ch <- m - return nil -} - -func (c *collector) exportNonMonotonicCounter(ch chan<- prometheus.Metric, sum aggregation.Sum, kind number.Kind, desc *prometheus.Desc, labels []string) error { - v, err := sum.Sum() - if err != nil { - return fmt.Errorf("error retrieving counter: %w", err) - } - - m, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, v.CoerceToFloat64(kind), labels...) - if err != nil { - return fmt.Errorf("error creating constant metric: %w", err) - } - - ch <- m - return nil -} - -func (c *collector) exportMonotonicCounter(ch chan<- prometheus.Metric, sum aggregation.Sum, kind number.Kind, desc *prometheus.Desc, labels []string) error { - v, err := sum.Sum() - if err != nil { - return fmt.Errorf("error retrieving counter: %w", err) - } - - m, err := prometheus.NewConstMetric(desc, prometheus.CounterValue, v.CoerceToFloat64(kind), labels...) - if err != nil { - return fmt.Errorf("error creating constant metric: %w", err) - } - - ch <- m - return nil -} - -func (c *collector) exportHistogram(ch chan<- prometheus.Metric, hist aggregation.Histogram, kind number.Kind, desc *prometheus.Desc, labels []string) error { - buckets, err := hist.Histogram() - if err != nil { - return fmt.Errorf("error retrieving histogram: %w", err) - } - sum, err := hist.Sum() - if err != nil { - return fmt.Errorf("error retrieving sum: %w", err) - } - - var totalCount uint64 - // counts maps from the bucket upper-bound to the cumulative count. - // The bucket with upper-bound +inf is not included. - counts := make(map[float64]uint64, len(buckets.Boundaries)) - for i := range buckets.Boundaries { - boundary := buckets.Boundaries[i] - totalCount += uint64(buckets.Counts[i]) - counts[boundary] = totalCount - } - // Include the +inf bucket in the total count. - totalCount += uint64(buckets.Counts[len(buckets.Counts)-1]) - - m, err := prometheus.NewConstHistogram(desc, totalCount, sum.CoerceToFloat64(kind), counts, labels...) - if err != nil { - return fmt.Errorf("error creating constant histogram: %w", err) - } - - ch <- m - return nil -} - -func (c *collector) toDesc(record export.Record, labelKeys []string) *prometheus.Desc { - desc := record.Descriptor() - return prometheus.NewDesc(sanitize(desc.Name()), desc.Description(), labelKeys, nil) -} - -// mergeLabels merges the export.Record's labels and resources into a -// single set, giving precedence to the record's labels in case of -// duplicate keys. This outputs one or both of the keys and the -// values as a slice, and either argument may be nil to avoid -// allocating an unnecessary slice. -func mergeLabels(record export.Record, res *resource.Resource, keys, values *[]string) { - if keys != nil { - *keys = make([]string, 0, record.Labels().Len()+res.Len()) - } - if values != nil { - *values = make([]string, 0, record.Labels().Len()+res.Len()) - } - - // Duplicate keys are resolved by taking the record label value over - // the resource value. - mi := attribute.NewMergeIterator(record.Labels(), res.Set()) - for mi.Next() { - label := mi.Label() - if keys != nil { - *keys = append(*keys, sanitize(string(label.Key))) - } - if values != nil { - *values = append(*values, label.Value.Emit()) - } - } -} diff --git a/exporters/prometheus/prometheus_test.go b/exporters/prometheus/prometheus_test.go deleted file mode 100644 index 587c8633e78..00000000000 --- a/exporters/prometheus/prometheus_test.go +++ /dev/null @@ -1,228 +0,0 @@ -// 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 prometheus_test - -import ( - "context" - "fmt" - "net/http/httptest" - "sort" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/prometheus" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - selector "go.opentelemetry.io/otel/sdk/metric/selector/simple" - "go.opentelemetry.io/otel/sdk/resource" -) - -type expectedMetric struct { - kind string - name string - help string - values []string -} - -func (e *expectedMetric) lines() []string { - ret := []string{ - fmt.Sprintf("# HELP %s %s", e.name, e.help), - fmt.Sprintf("# TYPE %s %s", e.name, e.kind), - } - - ret = append(ret, e.values...) - - return ret -} - -func expectCounterWithHelp(name, help, value string) expectedMetric { - return expectedMetric{ - kind: "counter", - name: name, - help: help, - values: []string{value}, - } -} - -func expectCounter(name, value string) expectedMetric { - return expectCounterWithHelp(name, "", value) -} - -func expectGauge(name, value string) expectedMetric { - return expectedMetric{ - kind: "gauge", - name: name, - values: []string{value}, - } -} - -func expectHistogram(name string, values ...string) expectedMetric { - return expectedMetric{ - kind: "histogram", - name: name, - values: values, - } -} - -func newPipeline(config prometheus.Config, options ...controller.Option) (*prometheus.Exporter, error) { - c := controller.New( - processor.NewFactory( - selector.NewWithHistogramDistribution( - histogram.WithExplicitBoundaries(config.DefaultHistogramBoundaries), - ), - aggregation.CumulativeTemporalitySelector(), - processor.WithMemory(true), - ), - options..., - ) - return prometheus.New(config, c) -} - -func TestPrometheusExporter(t *testing.T) { - exporter, err := newPipeline( - prometheus.Config{ - DefaultHistogramBoundaries: []float64{-0.5, 1}, - }, - controller.WithCollectPeriod(0), - controller.WithResource(resource.NewSchemaless(attribute.String("R", "V"))), - ) - require.NoError(t, err) - - meter := exporter.MeterProvider().Meter("test") - upDownCounter, err := meter.SyncFloat64().UpDownCounter("updowncounter") - require.NoError(t, err) - counter, err := meter.SyncFloat64().Counter("counter") - require.NoError(t, err) - histogram, err := meter.SyncFloat64().Histogram("histogram") - require.NoError(t, err) - - labels := []attribute.KeyValue{ - attribute.Key("A").String("B"), - attribute.Key("C").String("D"), - } - ctx := context.Background() - - var expected []expectedMetric - - counter.Add(ctx, 10, labels...) - counter.Add(ctx, 5.3, labels...) - - expected = append(expected, expectCounter("counter", `counter{A="B",C="D",R="V"} 15.3`)) - - gaugeObserver, err := meter.AsyncInt64().Gauge("intgaugeobserver") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{gaugeObserver}, func(ctx context.Context) { - gaugeObserver.Observe(ctx, 1, labels...) - }) - require.NoError(t, err) - - expected = append(expected, expectGauge("intgaugeobserver", `intgaugeobserver{A="B",C="D",R="V"} 1`)) - - histogram.Record(ctx, -0.6, labels...) - histogram.Record(ctx, -0.4, labels...) - histogram.Record(ctx, 0.6, labels...) - histogram.Record(ctx, 20, labels...) - - expected = append(expected, expectHistogram("histogram", - `histogram_bucket{A="B",C="D",R="V",le="-0.5"} 1`, - `histogram_bucket{A="B",C="D",R="V",le="1"} 3`, - `histogram_bucket{A="B",C="D",R="V",le="+Inf"} 4`, - `histogram_sum{A="B",C="D",R="V"} 19.6`, - `histogram_count{A="B",C="D",R="V"} 4`, - )) - - upDownCounter.Add(ctx, 10, labels...) - upDownCounter.Add(ctx, -3.2, labels...) - - expected = append(expected, expectGauge("updowncounter", `updowncounter{A="B",C="D",R="V"} 6.8`)) - - counterObserver, err := meter.AsyncFloat64().Counter("floatcounterobserver") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - counterObserver.Observe(ctx, 7.7, labels...) - }) - require.NoError(t, err) - - expected = append(expected, expectCounter("floatcounterobserver", `floatcounterobserver{A="B",C="D",R="V"} 7.7`)) - - upDownCounterObserver, err := meter.AsyncFloat64().UpDownCounter("floatupdowncounterobserver") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{upDownCounterObserver}, func(ctx context.Context) { - upDownCounterObserver.Observe(ctx, -7.7, labels...) - }) - require.NoError(t, err) - - expected = append(expected, expectGauge("floatupdowncounterobserver", `floatupdowncounterobserver{A="B",C="D",R="V"} -7.7`)) - - compareExport(t, exporter, expected) - compareExport(t, exporter, expected) -} - -func compareExport(t *testing.T, exporter *prometheus.Exporter, expected []expectedMetric) { - rec := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/metrics", nil) - exporter.ServeHTTP(rec, req) - - output := rec.Body.String() - lines := strings.Split(output, "\n") - - expectedLines := []string{""} - for _, v := range expected { - expectedLines = append(expectedLines, v.lines()...) - } - - sort.Strings(lines) - sort.Strings(expectedLines) - - require.Equal(t, expectedLines, lines) -} - -func TestPrometheusStatefulness(t *testing.T) { - // Create a meter - exporter, err := newPipeline( - prometheus.Config{}, - controller.WithCollectPeriod(0), - controller.WithResource(resource.Empty()), - ) - require.NoError(t, err) - - meter := exporter.MeterProvider().Meter("test") - - ctx := context.Background() - - counter, err := meter.SyncInt64().Counter("a.counter", instrument.WithDescription("Counts things")) - require.NoError(t, err) - - counter.Add(ctx, 100, attribute.String("key", "value")) - - compareExport(t, exporter, []expectedMetric{ - expectCounterWithHelp("a_counter", "Counts things", `a_counter{key="value"} 100`), - }) - - counter.Add(ctx, 100, attribute.String("key", "value")) - - compareExport(t, exporter, []expectedMetric{ - expectCounterWithHelp("a_counter", "Counts things", `a_counter{key="value"} 200`), - }) -} diff --git a/exporters/prometheus/sanitize.go b/exporters/prometheus/sanitize.go deleted file mode 100644 index cc9eff358cc..00000000000 --- a/exporters/prometheus/sanitize.go +++ /dev/null @@ -1,50 +0,0 @@ -// 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 prometheus // import "go.opentelemetry.io/otel/exporters/prometheus" - -import ( - "strings" - "unicode" -) - -// TODO(paivagustavo): we should provide a more uniform and controlled way of sanitizing. -// Letting users define wether we should try or not to sanitize metric names. -// This is a copy of sdk/internal/sanitize.go - -// sanitize returns a string that is truncated to 100 characters if it's too -// long, and replaces non-alphanumeric characters to underscores. -func sanitize(s string) string { - if len(s) == 0 { - return s - } - // TODO(paivagustavo): change this to use a bytes buffer to avoid a large number of string allocations. - s = strings.Map(sanitizeRune, s) - if unicode.IsDigit(rune(s[0])) { - s = "key_" + s - } - if s[0] == '_' { - s = "key" + s - } - return s -} - -// converts anything that is not a letter or digit to an underscore -func sanitizeRune(r rune) rune { - if unicode.IsLetter(r) || unicode.IsDigit(r) { - return r - } - // Everything else turns into an underscore - return '_' -} diff --git a/exporters/prometheus/sanitize_test.go b/exporters/prometheus/sanitize_test.go deleted file mode 100644 index 7a6b9fd55ee..00000000000 --- a/exporters/prometheus/sanitize_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// 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 prometheus - -import ( - "testing" -) - -func TestSanitize(t *testing.T) { - tests := []struct { - name string - input string - want string - }{ - { - name: "replace character", - input: "test/key-1", - want: "test_key_1", - }, - { - name: "add prefix if starting with digit", - input: "0123456789", - want: "key_0123456789", - }, - { - name: "add prefix if starting with _", - input: "_0123456789", - want: "key_0123456789", - }, - { - name: "starts with _ after sanitization", - input: "/0123456789", - want: "key_0123456789", - }, - { - name: "valid input", - input: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789", - want: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got, want := sanitize(tt.input), tt.want; got != want { - t.Errorf("sanitize() = %q; want %q", got, want) - } - }) - } -} diff --git a/exporters/stdout/stdoutmetric/config.go b/exporters/stdout/stdoutmetric/config.go deleted file mode 100644 index 305800ddbde..00000000000 --- a/exporters/stdout/stdoutmetric/config.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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 stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - -import ( - "io" - "os" - - "go.opentelemetry.io/otel/attribute" -) - -var ( - defaultWriter = os.Stdout - defaultPrettyPrint = false - defaultTimestamps = true - defaultLabelEncoder = attribute.DefaultEncoder() -) - -// config contains options for the STDOUT exporter. -type config struct { - // Writer is the destination. If not set, os.Stdout is used. - Writer io.Writer - - // PrettyPrint will encode the output into readable JSON. Default is - // false. - PrettyPrint bool - - // Timestamps specifies if timestamps should be printed. Default is - // true. - Timestamps bool - - // LabelEncoder encodes the labels. - LabelEncoder attribute.Encoder -} - -// newConfig creates a validated Config configured with options. -func newConfig(options ...Option) (config, error) { - cfg := config{ - Writer: defaultWriter, - PrettyPrint: defaultPrettyPrint, - Timestamps: defaultTimestamps, - LabelEncoder: defaultLabelEncoder, - } - for _, opt := range options { - cfg = opt.apply(cfg) - - } - return cfg, nil -} - -// Option sets the value of an option for a Config. -type Option interface { - apply(config) config -} - -// WithWriter sets the export stream destination. -func WithWriter(w io.Writer) Option { - return writerOption{w} -} - -type writerOption struct { - W io.Writer -} - -func (o writerOption) apply(cfg config) config { - cfg.Writer = o.W - return cfg -} - -// WithPrettyPrint sets the export stream format to use JSON. -func WithPrettyPrint() Option { - return prettyPrintOption(true) -} - -type prettyPrintOption bool - -func (o prettyPrintOption) apply(cfg config) config { - cfg.PrettyPrint = bool(o) - return cfg -} - -// WithoutTimestamps sets the export stream to not include timestamps. -func WithoutTimestamps() Option { - return timestampsOption(false) -} - -type timestampsOption bool - -func (o timestampsOption) apply(cfg config) config { - cfg.Timestamps = bool(o) - return cfg -} - -// WithLabelEncoder sets the label encoder used in export. -func WithLabelEncoder(enc attribute.Encoder) Option { - return labelEncoderOption{enc} -} - -type labelEncoderOption struct { - LabelEncoder attribute.Encoder -} - -func (o labelEncoderOption) apply(cfg config) config { - cfg.LabelEncoder = o.LabelEncoder - return cfg -} diff --git a/exporters/stdout/stdoutmetric/doc.go b/exporters/stdout/stdoutmetric/doc.go deleted file mode 100644 index 4cf41f32121..00000000000 --- a/exporters/stdout/stdoutmetric/doc.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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 stdout contains an OpenTelemetry exporter for metric telemetry -// to be written to an output destination as JSON. -// -// This package is currently in a pre-GA phase. Backwards incompatible changes -// may be introduced in subsequent minor version releases as we work to track -// the evolving OpenTelemetry specification and user feedback. -package stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" diff --git a/exporters/stdout/stdoutmetric/example_test.go b/exporters/stdout/stdoutmetric/example_test.go deleted file mode 100644 index 1d85a422235..00000000000 --- a/exporters/stdout/stdoutmetric/example_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// 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 stdoutmetric_test - -import ( - "context" - "log" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/global" - "go.opentelemetry.io/otel/metric/instrument/syncint64" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" -) - -const ( - instrumentationName = "github.com/instrumentron" - instrumentationVersion = "v0.1.0" -) - -var ( - loopCounter syncint64.Counter - paramValue syncint64.Histogram - - nameKey = attribute.Key("function.name") -) - -func add(ctx context.Context, x, y int64) int64 { - nameKV := nameKey.String("add") - - loopCounter.Add(ctx, 1, nameKV) - paramValue.Record(ctx, x, nameKV) - paramValue.Record(ctx, y, nameKV) - - return x + y -} - -func multiply(ctx context.Context, x, y int64) int64 { - nameKV := nameKey.String("multiply") - - loopCounter.Add(ctx, 1, nameKV) - paramValue.Record(ctx, x, nameKV) - paramValue.Record(ctx, y, nameKV) - - return x * y -} - -func InstallExportPipeline(ctx context.Context) func() { - exporter, err := stdoutmetric.New(stdoutmetric.WithPrettyPrint()) - if err != nil { - log.Fatalf("creating stdoutmetric exporter: %v", err) - } - - pusher := controller.New( - processor.NewFactory( - simple.NewWithInexpensiveDistribution(), - exporter, - ), - controller.WithExporter(exporter), - ) - if err = pusher.Start(ctx); err != nil { - log.Fatalf("starting push controller: %v", err) - } - - global.SetMeterProvider(pusher) - meter := global.Meter(instrumentationName, metric.WithInstrumentationVersion(instrumentationVersion)) - - loopCounter, err = meter.SyncInt64().Counter("function.loops") - if err != nil { - log.Fatalf("creating instrument: %v", err) - } - paramValue, err = meter.SyncInt64().Histogram("function.param") - if err != nil { - log.Fatalf("creating instrument: %v", err) - } - - return func() { - if err := pusher.Stop(ctx); err != nil { - log.Fatalf("stopping push controller: %v", err) - } - } -} - -func Example() { - ctx := context.Background() - - // TODO: Registers a meter Provider globally. - cleanup := InstallExportPipeline(ctx) - defer cleanup() - - log.Println("the answer is", add(ctx, multiply(ctx, multiply(ctx, 2, 2), 10), 2)) -} diff --git a/exporters/stdout/stdoutmetric/exporter.go b/exporters/stdout/stdoutmetric/exporter.go deleted file mode 100644 index e1ea02339c0..00000000000 --- a/exporters/stdout/stdoutmetric/exporter.go +++ /dev/null @@ -1,36 +0,0 @@ -// 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 stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - -import "go.opentelemetry.io/otel/sdk/metric/export" - -type Exporter struct { - metricExporter -} - -var ( - _ export.Exporter = &Exporter{} -) - -// New creates an Exporter with the passed options. -func New(options ...Option) (*Exporter, error) { - cfg, err := newConfig(options...) - if err != nil { - return nil, err - } - return &Exporter{ - metricExporter: metricExporter{cfg}, - }, nil -} diff --git a/exporters/stdout/stdoutmetric/go.mod b/exporters/stdout/stdoutmetric/go.mod deleted file mode 100644 index 82efdb5dea7..00000000000 --- a/exporters/stdout/stdoutmetric/go.mod +++ /dev/null @@ -1,76 +0,0 @@ -module go.opentelemetry.io/otel/exporters/stdout/stdoutmetric - -go 1.16 - -replace ( - go.opentelemetry.io/otel => ../../.. - go.opentelemetry.io/otel/sdk => ../../../sdk -) - -require ( - github.com/stretchr/testify v1.7.1 - go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/metric v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 - go.opentelemetry.io/otel/sdk/metric v0.29.0 -) - -replace go.opentelemetry.io/otel/bridge/opencensus => ../../../bridge/opencensus - -replace go.opentelemetry.io/otel/bridge/opentracing => ../../../bridge/opentracing - -replace go.opentelemetry.io/otel/example/jaeger => ../../../example/jaeger - -replace go.opentelemetry.io/otel/example/namedtracer => ../../../example/namedtracer - -replace go.opentelemetry.io/otel/example/opencensus => ../../../example/opencensus - -replace go.opentelemetry.io/otel/example/otel-collector => ../../../example/otel-collector - -replace go.opentelemetry.io/otel/example/prometheus => ../../../example/prometheus - -replace go.opentelemetry.io/otel/example/zipkin => ../../../example/zipkin - -replace go.opentelemetry.io/otel/exporters/prometheus => ../../prometheus - -replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ./ - -replace go.opentelemetry.io/otel/exporters/jaeger => ../../jaeger - -replace go.opentelemetry.io/otel/exporters/zipkin => ../../zipkin - -replace go.opentelemetry.io/otel/internal/tools => ../../../internal/tools - -replace go.opentelemetry.io/otel/metric => ../../../metric - -replace go.opentelemetry.io/otel/sdk/export/metric => ../../../sdk/export/metric - -replace go.opentelemetry.io/otel/sdk/metric => ../../../sdk/metric - -replace go.opentelemetry.io/otel/trace => ../../../trace - -replace go.opentelemetry.io/otel/example/passthrough => ../../../example/passthrough - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../otlp/otlptrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../otlp/otlptrace/otlptracegrpc - -replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../otlp/otlptrace/otlptracehttp - -replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../../otlp/otlpmetric - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../otlp/otlpmetric/otlpmetricgrpc - -replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../stdouttrace - -replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../../otlp/otlpmetric/otlpmetrichttp - -replace go.opentelemetry.io/otel/bridge/opencensus/test => ../../../bridge/opencensus/test - -replace go.opentelemetry.io/otel/example/fib => ../../../example/fib - -replace go.opentelemetry.io/otel/schema => ../../../schema - -replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../otlp/internal/retry diff --git a/exporters/stdout/stdoutmetric/go.sum b/exporters/stdout/stdoutmetric/go.sum deleted file mode 100644 index 9ab648da527..00000000000 --- a/exporters/stdout/stdoutmetric/go.sum +++ /dev/null @@ -1,23 +0,0 @@ -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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= diff --git a/exporters/stdout/stdoutmetric/metric.go b/exporters/stdout/stdoutmetric/metric.go deleted file mode 100644 index c816c035b1c..00000000000 --- a/exporters/stdout/stdoutmetric/metric.go +++ /dev/null @@ -1,145 +0,0 @@ -// 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 stdoutmetric // import "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - -import ( - "context" - "encoding/json" - "fmt" - "strings" - "time" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -type metricExporter struct { - config config -} - -var _ export.Exporter = &metricExporter{} - -type line struct { - Name string `json:"Name"` - Sum interface{} `json:"Sum,omitempty"` - Count interface{} `json:"Count,omitempty"` - LastValue interface{} `json:"Last,omitempty"` - - // Note: this is a pointer because omitempty doesn't work when time.IsZero() - Timestamp *time.Time `json:"Timestamp,omitempty"` -} - -func (e *metricExporter) TemporalityFor(desc *sdkapi.Descriptor, kind aggregation.Kind) aggregation.Temporality { - return aggregation.StatelessTemporalitySelector().TemporalityFor(desc, kind) -} - -func (e *metricExporter) Export(_ context.Context, res *resource.Resource, reader export.InstrumentationLibraryReader) error { - var aggError error - var batch []line - aggError = reader.ForEach(func(lib instrumentation.Library, mr export.Reader) error { - - var instLabels []attribute.KeyValue - if name := lib.Name; name != "" { - instLabels = append(instLabels, attribute.String("instrumentation.name", name)) - if version := lib.Version; version != "" { - instLabels = append(instLabels, attribute.String("instrumentation.version", version)) - } - if schema := lib.SchemaURL; schema != "" { - instLabels = append(instLabels, attribute.String("instrumentation.schema_url", schema)) - } - } - instSet := attribute.NewSet(instLabels...) - encodedInstLabels := instSet.Encoded(e.config.LabelEncoder) - - return mr.ForEach(e, func(record export.Record) error { - desc := record.Descriptor() - agg := record.Aggregation() - kind := desc.NumberKind() - encodedResource := res.Encoded(e.config.LabelEncoder) - - var expose line - - if sum, ok := agg.(aggregation.Sum); ok { - value, err := sum.Sum() - if err != nil { - return err - } - expose.Sum = value.AsInterface(kind) - } else if lv, ok := agg.(aggregation.LastValue); ok { - value, timestamp, err := lv.LastValue() - if err != nil { - return err - } - expose.LastValue = value.AsInterface(kind) - - if e.config.Timestamps { - expose.Timestamp = ×tamp - } - } - - var encodedLabels string - iter := record.Labels().Iter() - if iter.Len() > 0 { - encodedLabels = record.Labels().Encoded(e.config.LabelEncoder) - } - - var sb strings.Builder - - sb.WriteString(desc.Name()) - - if len(encodedLabels) > 0 || len(encodedResource) > 0 || len(encodedInstLabels) > 0 { - sb.WriteRune('{') - sb.WriteString(encodedResource) - if len(encodedInstLabels) > 0 && len(encodedResource) > 0 { - sb.WriteRune(',') - } - sb.WriteString(encodedInstLabels) - if len(encodedLabels) > 0 && (len(encodedInstLabels) > 0 || len(encodedResource) > 0) { - sb.WriteRune(',') - } - sb.WriteString(encodedLabels) - sb.WriteRune('}') - } - - expose.Name = sb.String() - - batch = append(batch, expose) - return nil - }) - }) - if len(batch) == 0 { - return aggError - } - - data, err := e.marshal(batch) - if err != nil { - return err - } - fmt.Fprintln(e.config.Writer, string(data)) - - return aggError -} - -// marshal v with appropriate indentation. -func (e *metricExporter) marshal(v interface{}) ([]byte, error) { - if e.config.PrettyPrint { - return json.MarshalIndent(v, "", "\t") - } - return json.Marshal(v) -} diff --git a/exporters/stdout/stdoutmetric/metric_test.go b/exporters/stdout/stdoutmetric/metric_test.go deleted file mode 100644 index 33e2831dbd7..00000000000 --- a/exporters/stdout/stdoutmetric/metric_test.go +++ /dev/null @@ -1,260 +0,0 @@ -// 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 stdoutmetric_test - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" - "go.opentelemetry.io/otel/metric" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/resource" -) - -type testFixture struct { - t *testing.T - ctx context.Context - cont *controller.Controller - meter metric.Meter - exporter *stdoutmetric.Exporter - output *bytes.Buffer -} - -var testResource = resource.NewSchemaless(attribute.String("R", "V")) - -func newFixture(t *testing.T, opts ...stdoutmetric.Option) testFixture { - return newFixtureWithResource(t, testResource, opts...) -} - -func newFixtureWithResource(t *testing.T, res *resource.Resource, opts ...stdoutmetric.Option) testFixture { - buf := &bytes.Buffer{} - opts = append(opts, stdoutmetric.WithWriter(buf)) - opts = append(opts, stdoutmetric.WithoutTimestamps()) - exp, err := stdoutmetric.New(opts...) - if err != nil { - t.Fatal("Error building fixture: ", err) - } - aggSel := processortest.AggregatorSelector() - proc := processor.NewFactory(aggSel, aggregation.StatelessTemporalitySelector()) - cont := controller.New(proc, - controller.WithExporter(exp), - controller.WithResource(res), - ) - ctx := context.Background() - require.NoError(t, cont.Start(ctx)) - meter := cont.Meter("test") - - return testFixture{ - t: t, - ctx: ctx, - exporter: exp, - cont: cont, - meter: meter, - output: buf, - } -} - -func (fix testFixture) Output() string { - return strings.TrimSpace(fix.output.String()) -} - -func TestStdoutTimestamp(t *testing.T) { - var buf bytes.Buffer - aggSel := processortest.AggregatorSelector() - proc := processor.NewFactory(aggSel, aggregation.CumulativeTemporalitySelector()) - exporter, err := stdoutmetric.New( - stdoutmetric.WithWriter(&buf), - ) - if err != nil { - t.Fatal("Invalid config: ", err) - } - cont := controller.New(proc, - controller.WithExporter(exporter), - controller.WithResource(testResource), - ) - ctx := context.Background() - - require.NoError(t, cont.Start(ctx)) - meter := cont.Meter("test") - counter, err := meter.SyncInt64().Counter("name.lastvalue") - require.NoError(t, err) - - before := time.Now() - // Ensure the timestamp is after before. - time.Sleep(time.Nanosecond) - - counter.Add(ctx, 1) - - require.NoError(t, cont.Stop(ctx)) - - // Ensure the timestamp is before after. - time.Sleep(time.Nanosecond) - after := time.Now() - - var printed []interface{} - if err := json.Unmarshal(buf.Bytes(), &printed); err != nil { - t.Fatal("JSON parse error: ", err) - } - - require.Len(t, printed, 1) - lastValue, ok := printed[0].(map[string]interface{}) - require.True(t, ok, "last value format") - require.Contains(t, lastValue, "Timestamp") - lastValueTS := lastValue["Timestamp"].(string) - lastValueTimestamp, err := time.Parse(time.RFC3339Nano, lastValueTS) - if err != nil { - t.Fatal("JSON parse error: ", lastValueTS, ": ", err) - } - - assert.True(t, lastValueTimestamp.After(before)) - assert.True(t, lastValueTimestamp.Before(after)) -} - -func TestStdoutCounterFormat(t *testing.T) { - fix := newFixture(t) - - counter, err := fix.meter.SyncInt64().Counter("name.sum") - require.NoError(t, err) - counter.Add(fix.ctx, 123, attribute.String("A", "B"), attribute.String("C", "D")) - - require.NoError(t, fix.cont.Stop(fix.ctx)) - - require.Equal(t, `[{"Name":"name.sum{R=V,instrumentation.name=test,A=B,C=D}","Sum":123}]`, fix.Output()) -} - -func TestStdoutLastValueFormat(t *testing.T) { - fix := newFixture(t) - - counter, err := fix.meter.SyncFloat64().Counter("name.lastvalue") - require.NoError(t, err) - counter.Add(fix.ctx, 123.456, attribute.String("A", "B"), attribute.String("C", "D")) - - require.NoError(t, fix.cont.Stop(fix.ctx)) - - require.Equal(t, `[{"Name":"name.lastvalue{R=V,instrumentation.name=test,A=B,C=D}","Last":123.456}]`, fix.Output()) -} - -func TestStdoutHistogramFormat(t *testing.T) { - fix := newFixture(t, stdoutmetric.WithPrettyPrint()) - - inst, err := fix.meter.SyncFloat64().Histogram("name.histogram") - require.NoError(t, err) - - for i := 0; i < 1000; i++ { - inst.Record(fix.ctx, float64(i)+0.5, attribute.String("A", "B"), attribute.String("C", "D")) - } - require.NoError(t, fix.cont.Stop(fix.ctx)) - - // TODO: Stdout does not export `Count` for histogram, nor the buckets. - require.Equal(t, `[ - { - "Name": "name.histogram{R=V,instrumentation.name=test,A=B,C=D}", - "Sum": 500000 - } -]`, fix.Output()) -} - -func TestStdoutNoData(t *testing.T) { - runTwoAggs := func(aggName string) { - t.Run(aggName, func(t *testing.T) { - t.Parallel() - - fix := newFixture(t) - _, err := fix.meter.SyncFloat64().Counter(fmt.Sprint("name.", aggName)) - require.NoError(t, err) - require.NoError(t, fix.cont.Stop(fix.ctx)) - - require.Equal(t, "", fix.Output()) - }) - } - - runTwoAggs("lastvalue") -} - -func TestStdoutResource(t *testing.T) { - type testCase struct { - name string - expect string - res *resource.Resource - attrs []attribute.KeyValue - } - newCase := func(name, expect string, res *resource.Resource, attrs ...attribute.KeyValue) testCase { - return testCase{ - name: name, - expect: expect, - res: res, - attrs: attrs, - } - } - testCases := []testCase{ - newCase("resource and attribute", - "R1=V1,R2=V2,instrumentation.name=test,A=B,C=D", - resource.NewSchemaless(attribute.String("R1", "V1"), attribute.String("R2", "V2")), - attribute.String("A", "B"), - attribute.String("C", "D")), - newCase("only resource", - "R1=V1,R2=V2,instrumentation.name=test", - resource.NewSchemaless(attribute.String("R1", "V1"), attribute.String("R2", "V2")), - ), - newCase("empty resource", - "instrumentation.name=test,A=B,C=D", - resource.Empty(), - attribute.String("A", "B"), - attribute.String("C", "D"), - ), - newCase("default resource", - fmt.Sprint(resource.Default().Encoded(attribute.DefaultEncoder()), - ",instrumentation.name=test,A=B,C=D"), - resource.Default(), - attribute.String("A", "B"), - attribute.String("C", "D"), - ), - // We explicitly do not de-duplicate between resources - // and metric labels in this exporter. - newCase("resource deduplication", - "R1=V1,R2=V2,instrumentation.name=test,R1=V3,R2=V4", - resource.NewSchemaless(attribute.String("R1", "V1"), attribute.String("R2", "V2")), - attribute.String("R1", "V3"), - attribute.String("R2", "V4")), - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - ctx := context.Background() - fix := newFixtureWithResource(t, tc.res) - - counter, err := fix.meter.SyncFloat64().Counter("name.lastvalue") - require.NoError(t, err) - counter.Add(ctx, 123.456, tc.attrs...) - - require.NoError(t, fix.cont.Stop(fix.ctx)) - - require.Equal(t, `[{"Name":"name.lastvalue{`+tc.expect+`}","Last":123.456}]`, fix.Output()) - }) - } -} diff --git a/sdk/metric/aggregator/aggregator.go b/sdk/metric/aggregator/aggregator.go deleted file mode 100644 index 59d42b1a80a..00000000000 --- a/sdk/metric/aggregator/aggregator.go +++ /dev/null @@ -1,114 +0,0 @@ -// 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 aggregator // import "go.opentelemetry.io/otel/sdk/metric/aggregator" - -import ( - "context" - "fmt" - "math" - - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -// Aggregator implements a specific aggregation behavior, e.g., a -// behavior to track a sequence of updates to an instrument. Counter -// instruments commonly use a simple Sum aggregator, but for the -// distribution instruments (Histogram, GaugeObserver) there are a -// number of possible aggregators with different cost and accuracy -// tradeoffs. -// -// Note that any Aggregator may be attached to any instrument--this is -// the result of the OpenTelemetry API/SDK separation. It is possible -// to attach a Sum aggregator to a Histogram instrument. -type Aggregator interface { - // Aggregation returns an Aggregation interface to access the - // current state of this Aggregator. The caller is - // responsible for synchronization and must not call any the - // other methods in this interface concurrently while using - // the Aggregation. - Aggregation() aggregation.Aggregation - - // Update receives a new measured value and incorporates it - // into the aggregation. Update() calls may be called - // concurrently. - // - // Descriptor.NumberKind() should be consulted to determine - // whether the provided number is an int64 or float64. - // - // The Context argument comes from user-level code and could be - // inspected for a `correlation.Map` or `trace.SpanContext`. - Update(ctx context.Context, number number.Number, descriptor *sdkapi.Descriptor) error - - // SynchronizedMove is called during collection to finish one - // period of aggregation by atomically saving the - // currently-updating state into the argument Aggregator AND - // resetting the current value to the zero state. - // - // SynchronizedMove() is called concurrently with Update(). These - // two methods must be synchronized with respect to each - // other, for correctness. - // - // After saving a synchronized copy, the Aggregator can be converted - // into one or more of the interfaces in the `aggregation` sub-package, - // according to kind of Aggregator that was selected. - // - // This method will return an InconsistentAggregatorError if - // this Aggregator cannot be copied into the destination due - // to an incompatible type. - // - // This call has no Context argument because it is expected to - // perform only computation. - // - // When called with a nil `destination`, this Aggregator is reset - // and the current value is discarded. - SynchronizedMove(destination Aggregator, descriptor *sdkapi.Descriptor) error - - // Merge combines the checkpointed state from the argument - // Aggregator into this Aggregator. Merge is not synchronized - // with respect to Update or SynchronizedMove. - // - // The owner of an Aggregator being merged is responsible for - // synchronization of both Aggregator states. - Merge(aggregator Aggregator, descriptor *sdkapi.Descriptor) error -} - -// NewInconsistentAggregatorError formats an error describing an attempt to -// Checkpoint or Merge different-type aggregators. The result can be unwrapped as -// an ErrInconsistentType. -func NewInconsistentAggregatorError(a1, a2 Aggregator) error { - return fmt.Errorf("%w: %T and %T", aggregation.ErrInconsistentType, a1, a2) -} - -// RangeTest is a common routine for testing for valid input values. -// This rejects NaN values. This rejects negative values when the -// metric instrument does not support negative values, including -// monotonic counter metrics and absolute Histogram metrics. -func RangeTest(num number.Number, descriptor *sdkapi.Descriptor) error { - numberKind := descriptor.NumberKind() - - if numberKind == number.Float64Kind && math.IsNaN(num.AsFloat64()) { - return aggregation.ErrNaNInput - } - - switch descriptor.InstrumentKind() { - case sdkapi.CounterInstrumentKind, sdkapi.CounterObserverInstrumentKind: - if num.IsNegative(numberKind) { - return aggregation.ErrNegativeInput - } - } - return nil -} diff --git a/sdk/metric/aggregator/aggregator_test.go b/sdk/metric/aggregator/aggregator_test.go deleted file mode 100644 index aab8393c932..00000000000 --- a/sdk/metric/aggregator/aggregator_test.go +++ /dev/null @@ -1,104 +0,0 @@ -// 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 aggregator_test // import "go.opentelemetry.io/otel/sdk/metric/aggregator" - -import ( - "errors" - "math" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" - "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -func TestInconsistentAggregatorErr(t *testing.T) { - err := aggregator.NewInconsistentAggregatorError(&sum.New(1)[0], &lastvalue.New(1)[0]) - require.Equal( - t, - "inconsistent aggregator types: *sum.Aggregator and *lastvalue.Aggregator", - err.Error(), - ) - require.True(t, errors.Is(err, aggregation.ErrInconsistentType)) -} - -func testRangeNaN(t *testing.T, desc *sdkapi.Descriptor) { - // If the descriptor uses int64 numbers, this won't register as NaN - nan := number.NewFloat64Number(math.NaN()) - err := aggregator.RangeTest(nan, desc) - - if desc.NumberKind() == number.Float64Kind { - require.Equal(t, aggregation.ErrNaNInput, err) - } else { - require.Nil(t, err) - } -} - -func testRangeNegative(t *testing.T, desc *sdkapi.Descriptor) { - var neg, pos number.Number - - if desc.NumberKind() == number.Float64Kind { - pos = number.NewFloat64Number(+1) - neg = number.NewFloat64Number(-1) - } else { - pos = number.NewInt64Number(+1) - neg = number.NewInt64Number(-1) - } - - posErr := aggregator.RangeTest(pos, desc) - negErr := aggregator.RangeTest(neg, desc) - - require.Nil(t, posErr) - require.Equal(t, negErr, aggregation.ErrNegativeInput) -} - -func TestRangeTest(t *testing.T) { - // Only Counters implement a range test. - for _, nkind := range []number.Kind{number.Float64Kind, number.Int64Kind} { - t.Run(nkind.String(), func(t *testing.T) { - desc := metrictest.NewDescriptor( - "name", - sdkapi.CounterInstrumentKind, - nkind, - ) - testRangeNegative(t, &desc) - }) - } -} - -func TestNaNTest(t *testing.T) { - for _, nkind := range []number.Kind{number.Float64Kind, number.Int64Kind} { - t.Run(nkind.String(), func(t *testing.T) { - for _, mkind := range []sdkapi.InstrumentKind{ - sdkapi.CounterInstrumentKind, - sdkapi.HistogramInstrumentKind, - sdkapi.GaugeObserverInstrumentKind, - } { - desc := metrictest.NewDescriptor( - "name", - mkind, - nkind, - ) - testRangeNaN(t, &desc) - } - }) - } -} diff --git a/sdk/metric/aggregator/aggregatortest/test.go b/sdk/metric/aggregator/aggregatortest/test.go deleted file mode 100644 index b9ea62da9bd..00000000000 --- a/sdk/metric/aggregator/aggregatortest/test.go +++ /dev/null @@ -1,280 +0,0 @@ -// 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 aggregatortest // import "go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" - -import ( - "context" - "errors" - "math/rand" - "os" - "sort" - "testing" - "unsafe" - - "github.com/stretchr/testify/require" - - ottest "go.opentelemetry.io/otel/internal/internaltest" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -const Magnitude = 1000 - -type Profile struct { - NumberKind number.Kind - Random func(sign int) number.Number -} - -type NoopAggregator struct{} -type NoopAggregation struct{} - -var _ aggregator.Aggregator = NoopAggregator{} -var _ aggregation.Aggregation = NoopAggregation{} - -func newProfiles() []Profile { - rnd := rand.New(rand.NewSource(rand.Int63())) - return []Profile{ - { - NumberKind: number.Int64Kind, - Random: func(sign int) number.Number { - return number.NewInt64Number(int64(sign) * int64(rnd.Intn(Magnitude+1))) - }, - }, - { - NumberKind: number.Float64Kind, - Random: func(sign int) number.Number { - return number.NewFloat64Number(float64(sign) * rnd.Float64() * Magnitude) - }, - }, - } -} - -func NewAggregatorTest(mkind sdkapi.InstrumentKind, nkind number.Kind) *sdkapi.Descriptor { - desc := metrictest.NewDescriptor("test.name", mkind, nkind) - return &desc -} - -func RunProfiles(t *testing.T, f func(*testing.T, Profile)) { - for _, profile := range newProfiles() { - t.Run(profile.NumberKind.String(), func(t *testing.T) { - f(t, profile) - }) - } -} - -// TestMain ensures local struct alignment prior to running tests. -func TestMain(m *testing.M) { - fields := []ottest.FieldOffset{ - { - Name: "Numbers.numbers", - Offset: unsafe.Offsetof(Numbers{}.numbers), - }, - } - if !ottest.Aligned8Byte(fields, os.Stderr) { - os.Exit(1) - } - - os.Exit(m.Run()) -} - -type Numbers struct { - // numbers has to be aligned for 64-bit atomic operations. - numbers []number.Number - kind number.Kind -} - -func NewNumbers(kind number.Kind) Numbers { - return Numbers{ - kind: kind, - } -} - -func (n *Numbers) Append(v number.Number) { - n.numbers = append(n.numbers, v) -} - -func (n *Numbers) Sort() { - sort.Sort(n) -} - -func (n *Numbers) Less(i, j int) bool { - return n.numbers[i].CompareNumber(n.kind, n.numbers[j]) < 0 -} - -func (n *Numbers) Len() int { - return len(n.numbers) -} - -func (n *Numbers) Swap(i, j int) { - n.numbers[i], n.numbers[j] = n.numbers[j], n.numbers[i] -} - -func (n *Numbers) Sum() number.Number { - var sum number.Number - for _, num := range n.numbers { - sum.AddNumber(n.kind, num) - } - return sum -} - -func (n *Numbers) Count() uint64 { - return uint64(len(n.numbers)) -} - -func (n *Numbers) Min() number.Number { - return n.numbers[0] -} - -func (n *Numbers) Max() number.Number { - return n.numbers[len(n.numbers)-1] -} - -func (n *Numbers) Points() []number.Number { - return n.numbers -} - -// CheckedUpdate performs the same range test the SDK does on behalf of the aggregator. -func CheckedUpdate(t *testing.T, agg aggregator.Aggregator, number number.Number, descriptor *sdkapi.Descriptor) { - ctx := context.Background() - - // Note: Aggregator tests are written assuming that the SDK - // has performed the RangeTest. Therefore we skip errors that - // would have been detected by the RangeTest. - err := aggregator.RangeTest(number, descriptor) - if err != nil { - return - } - - if err := agg.Update(ctx, number, descriptor); err != nil { - t.Error("Unexpected Update failure", err) - } -} - -func CheckedMerge(t *testing.T, aggInto, aggFrom aggregator.Aggregator, descriptor *sdkapi.Descriptor) { - if err := aggInto.Merge(aggFrom, descriptor); err != nil { - t.Error("Unexpected Merge failure", err) - } -} - -func (NoopAggregation) Kind() aggregation.Kind { - return aggregation.Kind("Noop") -} - -func (NoopAggregator) Aggregation() aggregation.Aggregation { - return NoopAggregation{} -} - -func (NoopAggregator) Update(context.Context, number.Number, *sdkapi.Descriptor) error { - return nil -} - -func (NoopAggregator) SynchronizedMove(aggregator.Aggregator, *sdkapi.Descriptor) error { - return nil -} - -func (NoopAggregator) Merge(aggregator.Aggregator, *sdkapi.Descriptor) error { - return nil -} - -func SynchronizedMoveResetTest(t *testing.T, mkind sdkapi.InstrumentKind, nf func(*sdkapi.Descriptor) aggregator.Aggregator) { - t.Run("reset on nil", func(t *testing.T) { - // Ensures that SynchronizedMove(nil, descriptor) discards and - // resets the aggregator. - RunProfiles(t, func(t *testing.T, profile Profile) { - descriptor := NewAggregatorTest( - mkind, - profile.NumberKind, - ) - agg := nf(descriptor) - - for i := 0; i < 10; i++ { - x1 := profile.Random(+1) - CheckedUpdate(t, agg, x1, descriptor) - } - - require.NoError(t, agg.SynchronizedMove(nil, descriptor)) - - if count, ok := agg.(aggregation.Count); ok { - c, err := count.Count() - require.Equal(t, uint64(0), c) - require.NoError(t, err) - } - - if sum, ok := agg.(aggregation.Sum); ok { - s, err := sum.Sum() - require.Equal(t, number.Number(0), s) - require.NoError(t, err) - } - - if lv, ok := agg.(aggregation.LastValue); ok { - v, _, err := lv.LastValue() - require.Equal(t, number.Number(0), v) - require.Error(t, err) - require.True(t, errors.Is(err, aggregation.ErrNoData)) - } - }) - }) - - t.Run("no reset on incorrect type", func(t *testing.T) { - // Ensures that SynchronizedMove(wrong_type, descriptor) does not - // reset the aggregator. - RunProfiles(t, func(t *testing.T, profile Profile) { - descriptor := NewAggregatorTest( - mkind, - profile.NumberKind, - ) - agg := nf(descriptor) - - var input number.Number - const inval = 100 - if profile.NumberKind == number.Int64Kind { - input = number.NewInt64Number(inval) - } else { - input = number.NewFloat64Number(inval) - } - - CheckedUpdate(t, agg, input, descriptor) - - err := agg.SynchronizedMove(NoopAggregator{}, descriptor) - require.Error(t, err) - require.True(t, errors.Is(err, aggregation.ErrInconsistentType)) - - // Test that the aggregator was not reset - - if count, ok := agg.(aggregation.Count); ok { - c, err := count.Count() - require.Equal(t, uint64(1), c) - require.NoError(t, err) - } - - if sum, ok := agg.(aggregation.Sum); ok { - s, err := sum.Sum() - require.Equal(t, input, s) - require.NoError(t, err) - } - - if lv, ok := agg.(aggregation.LastValue); ok { - v, _, err := lv.LastValue() - require.Equal(t, input, v) - require.NoError(t, err) - } - - }) - }) - -} diff --git a/sdk/metric/aggregator/histogram/benchmark_test.go b/sdk/metric/aggregator/histogram/benchmark_test.go deleted file mode 100644 index 597af3eb714..00000000000 --- a/sdk/metric/aggregator/histogram/benchmark_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// 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 histogram_test - -import ( - "context" - "math/rand" - "testing" - - "go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -const inputRange = 1e6 - -func benchmarkHistogramSearchFloat64(b *testing.B, size int) { - boundaries := make([]float64, size) - - for i := range boundaries { - boundaries[i] = rand.Float64() * inputRange - } - - values := make([]float64, b.N) - for i := range values { - values[i] = rand.Float64() * inputRange - } - desc := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, number.Float64Kind) - agg := &histogram.New(1, desc, histogram.WithExplicitBoundaries(boundaries))[0] - ctx := context.Background() - - b.ReportAllocs() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - _ = agg.Update(ctx, number.NewFloat64Number(values[i]), desc) - } -} - -func BenchmarkHistogramSearchFloat64_1(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 1) -} -func BenchmarkHistogramSearchFloat64_8(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 8) -} -func BenchmarkHistogramSearchFloat64_16(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 16) -} -func BenchmarkHistogramSearchFloat64_32(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 32) -} -func BenchmarkHistogramSearchFloat64_64(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 64) -} -func BenchmarkHistogramSearchFloat64_128(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 128) -} -func BenchmarkHistogramSearchFloat64_256(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 256) -} -func BenchmarkHistogramSearchFloat64_512(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 512) -} -func BenchmarkHistogramSearchFloat64_1024(b *testing.B) { - benchmarkHistogramSearchFloat64(b, 1024) -} - -func benchmarkHistogramSearchInt64(b *testing.B, size int) { - boundaries := make([]float64, size) - - for i := range boundaries { - boundaries[i] = rand.Float64() * inputRange - } - - values := make([]int64, b.N) - for i := range values { - values[i] = int64(rand.Float64() * inputRange) - } - desc := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, number.Int64Kind) - agg := &histogram.New(1, desc, histogram.WithExplicitBoundaries(boundaries))[0] - ctx := context.Background() - - b.ReportAllocs() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - _ = agg.Update(ctx, number.NewInt64Number(values[i]), desc) - } -} - -func BenchmarkHistogramSearchInt64_1(b *testing.B) { - benchmarkHistogramSearchInt64(b, 1) -} -func BenchmarkHistogramSearchInt64_8(b *testing.B) { - benchmarkHistogramSearchInt64(b, 8) -} -func BenchmarkHistogramSearchInt64_16(b *testing.B) { - benchmarkHistogramSearchInt64(b, 16) -} -func BenchmarkHistogramSearchInt64_32(b *testing.B) { - benchmarkHistogramSearchInt64(b, 32) -} -func BenchmarkHistogramSearchInt64_64(b *testing.B) { - benchmarkHistogramSearchInt64(b, 64) -} -func BenchmarkHistogramSearchInt64_128(b *testing.B) { - benchmarkHistogramSearchInt64(b, 128) -} -func BenchmarkHistogramSearchInt64_256(b *testing.B) { - benchmarkHistogramSearchInt64(b, 256) -} -func BenchmarkHistogramSearchInt64_512(b *testing.B) { - benchmarkHistogramSearchInt64(b, 512) -} -func BenchmarkHistogramSearchInt64_1024(b *testing.B) { - benchmarkHistogramSearchInt64(b, 1024) -} diff --git a/sdk/metric/aggregator/histogram/histogram.go b/sdk/metric/aggregator/histogram/histogram.go deleted file mode 100644 index f4d94b38c5e..00000000000 --- a/sdk/metric/aggregator/histogram/histogram.go +++ /dev/null @@ -1,269 +0,0 @@ -// 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 histogram // import "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - -import ( - "context" - "sort" - "sync" - - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -// Note: This code uses a Mutex to govern access to the exclusive -// aggregator state. This is in contrast to a lock-free approach -// (as in the Go prometheus client) that was reverted here: -// https://github.com/open-telemetry/opentelemetry-go/pull/669 - -type ( - // Aggregator observe events and counts them in pre-determined buckets. - // It also calculates the sum and count of all events. - Aggregator struct { - lock sync.Mutex - boundaries []float64 - kind number.Kind - state *state - } - - // config describes how the histogram is aggregated. - config struct { - // explicitBoundaries support arbitrary bucketing schemes. This - // is the general case. - explicitBoundaries []float64 - } - - // Option configures a histogram config. - Option interface { - // apply sets one or more config fields. - apply(*config) - } - - // state represents the state of a histogram, consisting of - // the sum and counts for all observed values and - // the less than equal bucket count for the pre-determined boundaries. - state struct { - bucketCounts []uint64 - sum number.Number - count uint64 - } -) - -// WithExplicitBoundaries sets the ExplicitBoundaries configuration option of a config. -func WithExplicitBoundaries(explicitBoundaries []float64) Option { - return explicitBoundariesOption{explicitBoundaries} -} - -type explicitBoundariesOption struct { - boundaries []float64 -} - -func (o explicitBoundariesOption) apply(config *config) { - config.explicitBoundaries = o.boundaries -} - -// defaultExplicitBoundaries have been copied from prometheus.DefBuckets. -// -// Note we anticipate the use of a high-precision histogram sketch as -// the standard histogram aggregator for OTLP export. -// (https://github.com/open-telemetry/opentelemetry-specification/issues/982). -var defaultFloat64ExplicitBoundaries = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} - -// defaultInt64ExplicitBoundaryMultiplier determines the default -// integer histogram boundaries. -const defaultInt64ExplicitBoundaryMultiplier = 1e6 - -// defaultInt64ExplicitBoundaries applies a multiplier to the default -// float64 boundaries: [ 5K, 10K, 25K, ..., 2.5M, 5M, 10M ] -var defaultInt64ExplicitBoundaries = func(bounds []float64) (asint []float64) { - for _, f := range bounds { - asint = append(asint, defaultInt64ExplicitBoundaryMultiplier*f) - } - return -}(defaultFloat64ExplicitBoundaries) - -var _ aggregator.Aggregator = &Aggregator{} -var _ aggregation.Sum = &Aggregator{} -var _ aggregation.Count = &Aggregator{} -var _ aggregation.Histogram = &Aggregator{} - -// New returns a new aggregator for computing Histograms. -// -// A Histogram observe events and counts them in pre-defined buckets. -// And also provides the total sum and count of all observations. -// -// Note that this aggregator maintains each value using independent -// atomic operations, which introduces the possibility that -// checkpoints are inconsistent. -func New(cnt int, desc *sdkapi.Descriptor, opts ...Option) []Aggregator { - var cfg config - - if desc.NumberKind() == number.Int64Kind { - cfg.explicitBoundaries = defaultInt64ExplicitBoundaries - } else { - cfg.explicitBoundaries = defaultFloat64ExplicitBoundaries - } - - for _, opt := range opts { - opt.apply(&cfg) - } - - aggs := make([]Aggregator, cnt) - - // Boundaries MUST be ordered otherwise the histogram could not - // be properly computed. - sortedBoundaries := make([]float64, len(cfg.explicitBoundaries)) - - copy(sortedBoundaries, cfg.explicitBoundaries) - sort.Float64s(sortedBoundaries) - - for i := range aggs { - aggs[i] = Aggregator{ - kind: desc.NumberKind(), - boundaries: sortedBoundaries, - } - aggs[i].state = aggs[i].newState() - } - return aggs -} - -// Aggregation returns an interface for reading the state of this aggregator. -func (c *Aggregator) Aggregation() aggregation.Aggregation { - return c -} - -// Kind returns aggregation.HistogramKind. -func (c *Aggregator) Kind() aggregation.Kind { - return aggregation.HistogramKind -} - -// Sum returns the sum of all values in the checkpoint. -func (c *Aggregator) Sum() (number.Number, error) { - return c.state.sum, nil -} - -// Count returns the number of values in the checkpoint. -func (c *Aggregator) Count() (uint64, error) { - return c.state.count, nil -} - -// Histogram returns the count of events in pre-determined buckets. -func (c *Aggregator) Histogram() (aggregation.Buckets, error) { - return aggregation.Buckets{ - Boundaries: c.boundaries, - Counts: c.state.bucketCounts, - }, nil -} - -// SynchronizedMove saves the current state into oa and resets the current state to -// the empty set. Since no locks are taken, there is a chance that -// the independent Sum, Count and Bucket Count are not consistent with each -// other. -func (c *Aggregator) SynchronizedMove(oa aggregator.Aggregator, desc *sdkapi.Descriptor) error { - o, _ := oa.(*Aggregator) - - if oa != nil && o == nil { - return aggregator.NewInconsistentAggregatorError(c, oa) - } - - if o != nil { - // Swap case: This is the ordinary case for a - // synchronous instrument, where the SDK allocates two - // Aggregators and lock contention is anticipated. - // Reset the target state before swapping it under the - // lock below. - o.clearState() - } - - c.lock.Lock() - if o != nil { - c.state, o.state = o.state, c.state - } else { - // No swap case: This is the ordinary case for an - // asynchronous instrument, where the SDK allocates a - // single Aggregator and there is no anticipated lock - // contention. - c.clearState() - } - c.lock.Unlock() - - return nil -} - -func (c *Aggregator) newState() *state { - return &state{ - bucketCounts: make([]uint64, len(c.boundaries)+1), - } -} - -func (c *Aggregator) clearState() { - for i := range c.state.bucketCounts { - c.state.bucketCounts[i] = 0 - } - c.state.sum = 0 - c.state.count = 0 -} - -// Update adds the recorded measurement to the current data set. -func (c *Aggregator) Update(_ context.Context, number number.Number, desc *sdkapi.Descriptor) error { - kind := desc.NumberKind() - asFloat := number.CoerceToFloat64(kind) - - bucketID := len(c.boundaries) - for i, boundary := range c.boundaries { - if asFloat < boundary { - bucketID = i - break - } - } - // Note: Binary-search was compared using the benchmarks. The following - // code is equivalent to the linear search above: - // - // bucketID := sort.Search(len(c.boundaries), func(i int) bool { - // return asFloat < c.boundaries[i] - // }) - // - // The binary search wins for very large boundary sets, but - // the linear search performs better up through arrays between - // 256 and 512 elements, which is a relatively large histogram, so we - // continue to prefer linear search. - - c.lock.Lock() - defer c.lock.Unlock() - - c.state.count++ - c.state.sum.AddNumber(kind, number) - c.state.bucketCounts[bucketID]++ - - return nil -} - -// Merge combines two histograms that have the same buckets into a single one. -func (c *Aggregator) Merge(oa aggregator.Aggregator, desc *sdkapi.Descriptor) error { - o, _ := oa.(*Aggregator) - if o == nil { - return aggregator.NewInconsistentAggregatorError(c, oa) - } - - c.state.sum.AddNumber(desc.NumberKind(), o.state.sum) - c.state.count += o.state.count - - for i := 0; i < len(c.state.bucketCounts); i++ { - c.state.bucketCounts[i] += o.state.bucketCounts[i] - } - return nil -} diff --git a/sdk/metric/aggregator/histogram/histogram_test.go b/sdk/metric/aggregator/histogram/histogram_test.go deleted file mode 100644 index b22bd149e5e..00000000000 --- a/sdk/metric/aggregator/histogram/histogram_test.go +++ /dev/null @@ -1,296 +0,0 @@ -// 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 histogram_test - -import ( - "context" - "math" - "math/rand" - "sort" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -const count = 100 - -type policy struct { - name string - absolute bool - sign func() int -} - -var ( - positiveOnly = policy{ - name: "absolute", - absolute: true, - sign: func() int { return +1 }, - } - negativeOnly = policy{ - name: "negative", - absolute: false, - sign: func() int { return -1 }, - } - positiveAndNegative = policy{ - name: "positiveAndNegative", - absolute: false, - sign: func() int { - if rand.Uint32() > math.MaxUint32/2 { - return -1 - } - return 1 - }, - } - - testBoundaries = []float64{500, 250, 750} -) - -func new2(desc *sdkapi.Descriptor, options ...histogram.Option) (_, _ *histogram.Aggregator) { - alloc := histogram.New(2, desc, options...) - return &alloc[0], &alloc[1] -} - -func new4(desc *sdkapi.Descriptor, options ...histogram.Option) (_, _, _, _ *histogram.Aggregator) { - alloc := histogram.New(4, desc, options...) - return &alloc[0], &alloc[1], &alloc[2], &alloc[3] -} - -func checkZero(t *testing.T, agg *histogram.Aggregator, desc *sdkapi.Descriptor) { - asum, err := agg.Sum() - require.Equal(t, number.Number(0), asum, "Empty checkpoint sum = 0") - require.NoError(t, err) - - count, err := agg.Count() - require.Equal(t, uint64(0), count, "Empty checkpoint count = 0") - require.NoError(t, err) - - buckets, err := agg.Histogram() - require.NoError(t, err) - - require.Equal(t, len(buckets.Counts), len(testBoundaries)+1, "There should be b + 1 counts, where b is the number of boundaries") - for i, bCount := range buckets.Counts { - require.Equal(t, uint64(0), uint64(bCount), "Bucket #%d must have 0 observed values", i) - } -} - -func TestHistogramAbsolute(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - testHistogram(t, profile, positiveOnly) - }) -} - -func TestHistogramNegativeOnly(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - testHistogram(t, profile, negativeOnly) - }) -} - -func TestHistogramPositiveAndNegative(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - testHistogram(t, profile, positiveAndNegative) - }) -} - -// Validates count, sum and buckets for a given profile and policy -func testHistogram(t *testing.T, profile aggregatortest.Profile, policy policy) { - descriptor := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, profile.NumberKind) - - agg, ckpt := new2(descriptor, histogram.WithExplicitBoundaries(testBoundaries)) - - // This needs to repeat at least 3 times to uncover a failure to reset - // for the overall sum and count fields, since the third time through - // is the first time a `histogram.state` object is reused. - for repeat := 0; repeat < 3; repeat++ { - all := aggregatortest.NewNumbers(profile.NumberKind) - - for i := 0; i < count; i++ { - x := profile.Random(policy.sign()) - all.Append(x) - aggregatortest.CheckedUpdate(t, agg, x, descriptor) - } - - require.NoError(t, agg.SynchronizedMove(ckpt, descriptor)) - - checkZero(t, agg, descriptor) - - checkHistogram(t, all, profile, ckpt) - } -} - -func TestHistogramInitial(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - descriptor := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, profile.NumberKind) - - agg := &histogram.New(1, descriptor, histogram.WithExplicitBoundaries(testBoundaries))[0] - buckets, err := agg.Histogram() - - require.NoError(t, err) - require.Equal(t, len(buckets.Counts), len(testBoundaries)+1) - require.Equal(t, len(buckets.Boundaries), len(testBoundaries)) - }) -} - -func TestHistogramMerge(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - descriptor := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, profile.NumberKind) - - agg1, agg2, ckpt1, ckpt2 := new4(descriptor, histogram.WithExplicitBoundaries(testBoundaries)) - - all := aggregatortest.NewNumbers(profile.NumberKind) - - for i := 0; i < count; i++ { - x := profile.Random(+1) - all.Append(x) - aggregatortest.CheckedUpdate(t, agg1, x, descriptor) - } - for i := 0; i < count; i++ { - x := profile.Random(+1) - all.Append(x) - aggregatortest.CheckedUpdate(t, agg2, x, descriptor) - } - - require.NoError(t, agg1.SynchronizedMove(ckpt1, descriptor)) - require.NoError(t, agg2.SynchronizedMove(ckpt2, descriptor)) - - aggregatortest.CheckedMerge(t, ckpt1, ckpt2, descriptor) - - checkHistogram(t, all, profile, ckpt1) - }) -} - -func TestHistogramNotSet(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - descriptor := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, profile.NumberKind) - - agg, ckpt := new2(descriptor, histogram.WithExplicitBoundaries(testBoundaries)) - - err := agg.SynchronizedMove(ckpt, descriptor) - require.NoError(t, err) - - checkZero(t, agg, descriptor) - checkZero(t, ckpt, descriptor) - }) -} - -// checkHistogram ensures the correct aggregated state between `all` -// (test aggregator) and `agg` (code under test). -func checkHistogram(t *testing.T, all aggregatortest.Numbers, profile aggregatortest.Profile, agg *histogram.Aggregator) { - - all.Sort() - - asum, err := agg.Sum() - require.NoError(t, err) - - sum := all.Sum() - require.InEpsilon(t, - sum.CoerceToFloat64(profile.NumberKind), - asum.CoerceToFloat64(profile.NumberKind), - 0.000000001) - - count, err := agg.Count() - require.NoError(t, err) - require.Equal(t, all.Count(), count) - - buckets, err := agg.Histogram() - require.NoError(t, err) - - require.Equal(t, len(buckets.Counts), len(testBoundaries)+1, - "There should be b + 1 counts, where b is the number of boundaries") - - sortedBoundaries := make([]float64, len(testBoundaries)) - copy(sortedBoundaries, testBoundaries) - - sort.Float64s(sortedBoundaries) - - require.EqualValues(t, sortedBoundaries, buckets.Boundaries) - - counts := make([]uint64, len(sortedBoundaries)+1) - idx := 0 - for _, p := range all.Points() { - for idx < len(sortedBoundaries) && p.CoerceToFloat64(profile.NumberKind) >= sortedBoundaries[idx] { - idx++ - } - counts[idx]++ - } - for i, v := range counts { - bCount := uint64(buckets.Counts[i]) - require.Equal(t, v, bCount, "Wrong bucket #%d count: %v != %v", i, counts, buckets.Counts) - } -} - -func TestSynchronizedMoveReset(t *testing.T) { - aggregatortest.SynchronizedMoveResetTest( - t, - sdkapi.HistogramInstrumentKind, - func(desc *sdkapi.Descriptor) aggregator.Aggregator { - return &histogram.New(1, desc, histogram.WithExplicitBoundaries(testBoundaries))[0] - }, - ) -} - -func TestHistogramDefaultBoundaries(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - ctx := context.Background() - descriptor := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, profile.NumberKind) - - agg, ckpt := new2(descriptor) - - bounds := []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} // len 11 - values := append(bounds, 100) // len 12 - expect := []uint64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} // len 12 - - for _, value := range values { - var num number.Number - - value -= .001 // Avoid exact boundaries - - if descriptor.NumberKind() == number.Int64Kind { - value *= 1e6 - num = number.NewInt64Number(int64(value)) - } else { - num = number.NewFloat64Number(value) - } - - require.NoError(t, agg.Update(ctx, num, descriptor)) - } - - bucks, err := agg.Histogram() - require.NoError(t, err) - - // Check for proper lengths, 1 count in each bucket. - require.Equal(t, len(values), len(bucks.Counts)) - require.Equal(t, len(bounds), len(bucks.Boundaries)) - require.EqualValues(t, expect, bucks.Counts) - - require.Equal(t, expect, bucks.Counts) - - // Move and repeat the test on `ckpt`. - err = agg.SynchronizedMove(ckpt, descriptor) - require.NoError(t, err) - - bucks, err = ckpt.Histogram() - require.NoError(t, err) - - require.Equal(t, len(values), len(bucks.Counts)) - require.Equal(t, len(bounds), len(bucks.Boundaries)) - require.EqualValues(t, expect, bucks.Counts) - }) -} diff --git a/sdk/metric/aggregator/lastvalue/lastvalue.go b/sdk/metric/aggregator/lastvalue/lastvalue.go deleted file mode 100644 index 7e88f6b8db3..00000000000 --- a/sdk/metric/aggregator/lastvalue/lastvalue.go +++ /dev/null @@ -1,134 +0,0 @@ -// 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 lastvalue // import "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" - -import ( - "context" - "sync/atomic" - "time" - "unsafe" - - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type ( - - // Aggregator aggregates lastValue events. - Aggregator struct { - // value is an atomic pointer to *lastValueData. It is never nil. - value unsafe.Pointer - } - - // lastValueData stores the current value of a lastValue along with - // a sequence number to determine the winner of a race. - lastValueData struct { - // value is the int64- or float64-encoded Set() data - // - // value needs to be aligned for 64-bit atomic operations. - value number.Number - - // timestamp indicates when this record was submitted. - // this can be used to pick a winner when multiple - // records contain lastValue data for the same labels due - // to races. - timestamp time.Time - } -) - -var _ aggregator.Aggregator = &Aggregator{} -var _ aggregation.LastValue = &Aggregator{} - -// An unset lastValue has zero timestamp and zero value. -var unsetLastValue = &lastValueData{} - -// New returns a new lastValue aggregator. This aggregator retains the -// last value and timestamp that were recorded. -func New(cnt int) []Aggregator { - aggs := make([]Aggregator, cnt) - for i := range aggs { - aggs[i] = Aggregator{ - value: unsafe.Pointer(unsetLastValue), - } - } - return aggs -} - -// Aggregation returns an interface for reading the state of this aggregator. -func (g *Aggregator) Aggregation() aggregation.Aggregation { - return g -} - -// Kind returns aggregation.LastValueKind. -func (g *Aggregator) Kind() aggregation.Kind { - return aggregation.LastValueKind -} - -// LastValue returns the last-recorded lastValue value and the -// corresponding timestamp. The error value aggregation.ErrNoData -// will be returned if (due to a race condition) the checkpoint was -// computed before the first value was set. -func (g *Aggregator) LastValue() (number.Number, time.Time, error) { - gd := (*lastValueData)(g.value) - if gd == unsetLastValue { - return 0, time.Time{}, aggregation.ErrNoData - } - return gd.value.AsNumber(), gd.timestamp, nil -} - -// SynchronizedMove atomically saves the current value. -func (g *Aggregator) SynchronizedMove(oa aggregator.Aggregator, _ *sdkapi.Descriptor) error { - if oa == nil { - atomic.StorePointer(&g.value, unsafe.Pointer(unsetLastValue)) - return nil - } - o, _ := oa.(*Aggregator) - if o == nil { - return aggregator.NewInconsistentAggregatorError(g, oa) - } - o.value = atomic.SwapPointer(&g.value, unsafe.Pointer(unsetLastValue)) - return nil -} - -// Update atomically sets the current "last" value. -func (g *Aggregator) Update(_ context.Context, number number.Number, desc *sdkapi.Descriptor) error { - ngd := &lastValueData{ - value: number, - timestamp: time.Now(), - } - atomic.StorePointer(&g.value, unsafe.Pointer(ngd)) - return nil -} - -// Merge combines state from two aggregators. The most-recently set -// value is chosen. -func (g *Aggregator) Merge(oa aggregator.Aggregator, desc *sdkapi.Descriptor) error { - o, _ := oa.(*Aggregator) - if o == nil { - return aggregator.NewInconsistentAggregatorError(g, oa) - } - - ggd := (*lastValueData)(atomic.LoadPointer(&g.value)) - ogd := (*lastValueData)(atomic.LoadPointer(&o.value)) - - if ggd.timestamp.After(ogd.timestamp) { - return nil - } - - g.value = unsafe.Pointer(ogd) - return nil -} diff --git a/sdk/metric/aggregator/lastvalue/lastvalue_test.go b/sdk/metric/aggregator/lastvalue/lastvalue_test.go deleted file mode 100644 index 16f9614c25a..00000000000 --- a/sdk/metric/aggregator/lastvalue/lastvalue_test.go +++ /dev/null @@ -1,146 +0,0 @@ -// 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 lastvalue - -import ( - "errors" - "math/rand" - "os" - "testing" - "time" - "unsafe" - - "github.com/stretchr/testify/require" - - ottest "go.opentelemetry.io/otel/internal/internaltest" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -const count = 100 - -var _ aggregator.Aggregator = &Aggregator{} - -// Ensure struct alignment prior to running tests. -func TestMain(m *testing.M) { - fields := []ottest.FieldOffset{ - { - Name: "lastValueData.value", - Offset: unsafe.Offsetof(lastValueData{}.value), - }, - } - if !ottest.Aligned8Byte(fields, os.Stderr) { - os.Exit(1) - } - - os.Exit(m.Run()) -} - -func new2() (_, _ *Aggregator) { - alloc := New(2) - return &alloc[0], &alloc[1] -} - -func new4() (_, _, _, _ *Aggregator) { - alloc := New(4) - return &alloc[0], &alloc[1], &alloc[2], &alloc[3] -} - -func checkZero(t *testing.T, agg *Aggregator) { - lv, ts, err := agg.LastValue() - require.True(t, errors.Is(err, aggregation.ErrNoData)) - require.Equal(t, time.Time{}, ts) - require.Equal(t, number.Number(0), lv) -} - -func TestLastValueUpdate(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - agg, ckpt := new2() - - record := aggregatortest.NewAggregatorTest(sdkapi.GaugeObserverInstrumentKind, profile.NumberKind) - - var last number.Number - for i := 0; i < count; i++ { - x := profile.Random(rand.Intn(1)*2 - 1) - last = x - aggregatortest.CheckedUpdate(t, agg, x, record) - } - - err := agg.SynchronizedMove(ckpt, record) - require.NoError(t, err) - - lv, _, err := ckpt.LastValue() - require.Equal(t, last, lv, "Same last value - non-monotonic") - require.Nil(t, err) - }) -} - -func TestLastValueMerge(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - agg1, agg2, ckpt1, ckpt2 := new4() - - descriptor := aggregatortest.NewAggregatorTest(sdkapi.GaugeObserverInstrumentKind, profile.NumberKind) - - first1 := profile.Random(+1) - first2 := profile.Random(+1) - first1.AddNumber(profile.NumberKind, first2) - - aggregatortest.CheckedUpdate(t, agg1, first1, descriptor) - // Ensure these should not have the same timestamp. - time.Sleep(time.Nanosecond) - aggregatortest.CheckedUpdate(t, agg2, first2, descriptor) - - require.NoError(t, agg1.SynchronizedMove(ckpt1, descriptor)) - require.NoError(t, agg2.SynchronizedMove(ckpt2, descriptor)) - - checkZero(t, agg1) - checkZero(t, agg2) - - _, t1, err := ckpt1.LastValue() - require.Nil(t, err) - _, t2, err := ckpt2.LastValue() - require.Nil(t, err) - require.True(t, t1.Before(t2)) - - aggregatortest.CheckedMerge(t, ckpt1, ckpt2, descriptor) - - lv, ts, err := ckpt1.LastValue() - require.Nil(t, err) - require.Equal(t, t2, ts, "Merged timestamp - non-monotonic") - require.Equal(t, first2, lv, "Merged value - non-monotonic") - }) -} - -func TestLastValueNotSet(t *testing.T) { - descriptor := aggregatortest.NewAggregatorTest(sdkapi.GaugeObserverInstrumentKind, number.Int64Kind) - - g, ckpt := new2() - require.NoError(t, g.SynchronizedMove(ckpt, descriptor)) - - checkZero(t, g) -} - -func TestSynchronizedMoveReset(t *testing.T) { - aggregatortest.SynchronizedMoveResetTest( - t, - sdkapi.GaugeObserverInstrumentKind, - func(desc *sdkapi.Descriptor) aggregator.Aggregator { - return &New(1)[0] - }, - ) -} diff --git a/sdk/metric/aggregator/sum/sum.go b/sdk/metric/aggregator/sum/sum.go deleted file mode 100644 index d5c70e59bdf..00000000000 --- a/sdk/metric/aggregator/sum/sum.go +++ /dev/null @@ -1,88 +0,0 @@ -// 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 sum // import "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - -import ( - "context" - - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -// Aggregator aggregates counter events. -type Aggregator struct { - // current holds current increments to this counter record - // current needs to be aligned for 64-bit atomic operations. - value number.Number -} - -var _ aggregator.Aggregator = &Aggregator{} -var _ aggregation.Sum = &Aggregator{} - -// New returns a new counter aggregator implemented by atomic -// operations. This aggregator implements the aggregation.Sum -// export interface. -func New(cnt int) []Aggregator { - return make([]Aggregator, cnt) -} - -// Aggregation returns an interface for reading the state of this aggregator. -func (c *Aggregator) Aggregation() aggregation.Aggregation { - return c -} - -// Kind returns aggregation.SumKind. -func (c *Aggregator) Kind() aggregation.Kind { - return aggregation.SumKind -} - -// Sum returns the last-checkpointed sum. This will never return an -// error. -func (c *Aggregator) Sum() (number.Number, error) { - return c.value, nil -} - -// SynchronizedMove atomically saves the current value into oa and resets the -// current sum to zero. -func (c *Aggregator) SynchronizedMove(oa aggregator.Aggregator, _ *sdkapi.Descriptor) error { - if oa == nil { - c.value.SetRawAtomic(0) - return nil - } - o, _ := oa.(*Aggregator) - if o == nil { - return aggregator.NewInconsistentAggregatorError(c, oa) - } - o.value = c.value.SwapNumberAtomic(number.Number(0)) - return nil -} - -// Update atomically adds to the current value. -func (c *Aggregator) Update(_ context.Context, num number.Number, desc *sdkapi.Descriptor) error { - c.value.AddNumberAtomic(desc.NumberKind(), num) - return nil -} - -// Merge combines two counters by adding their sums. -func (c *Aggregator) Merge(oa aggregator.Aggregator, desc *sdkapi.Descriptor) error { - o, _ := oa.(*Aggregator) - if o == nil { - return aggregator.NewInconsistentAggregatorError(c, oa) - } - c.value.AddNumber(desc.NumberKind(), o.value) - return nil -} diff --git a/sdk/metric/aggregator/sum/sum_test.go b/sdk/metric/aggregator/sum/sum_test.go deleted file mode 100644 index c92594a460c..00000000000 --- a/sdk/metric/aggregator/sum/sum_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// 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 sum - -import ( - "os" - "testing" - "unsafe" - - "github.com/stretchr/testify/require" - - ottest "go.opentelemetry.io/otel/internal/internaltest" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -const count = 100 - -// Ensure struct alignment prior to running tests. -func TestMain(m *testing.M) { - fields := []ottest.FieldOffset{ - { - Name: "Aggregator.value", - Offset: unsafe.Offsetof(Aggregator{}.value), - }, - } - if !ottest.Aligned8Byte(fields, os.Stderr) { - os.Exit(1) - } - - os.Exit(m.Run()) -} - -func new2() (_, _ *Aggregator) { - alloc := New(2) - return &alloc[0], &alloc[1] -} - -func new4() (_, _, _, _ *Aggregator) { - alloc := New(4) - return &alloc[0], &alloc[1], &alloc[2], &alloc[3] -} - -func checkZero(t *testing.T, agg *Aggregator, desc *sdkapi.Descriptor) { - kind := desc.NumberKind() - - sum, err := agg.Sum() - require.NoError(t, err) - require.Equal(t, kind.Zero(), sum) -} - -func TestCounterSum(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - agg, ckpt := new2() - - descriptor := aggregatortest.NewAggregatorTest(sdkapi.CounterInstrumentKind, profile.NumberKind) - - sum := number.Number(0) - for i := 0; i < count; i++ { - x := profile.Random(+1) - sum.AddNumber(profile.NumberKind, x) - aggregatortest.CheckedUpdate(t, agg, x, descriptor) - } - - err := agg.SynchronizedMove(ckpt, descriptor) - require.NoError(t, err) - - checkZero(t, agg, descriptor) - - asum, err := ckpt.Sum() - require.Equal(t, sum, asum, "Same sum - monotonic") - require.Nil(t, err) - }) -} - -func TestHistogramSum(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - agg, ckpt := new2() - - descriptor := aggregatortest.NewAggregatorTest(sdkapi.HistogramInstrumentKind, profile.NumberKind) - - sum := number.Number(0) - - for i := 0; i < count; i++ { - r1 := profile.Random(+1) - r2 := profile.Random(-1) - aggregatortest.CheckedUpdate(t, agg, r1, descriptor) - aggregatortest.CheckedUpdate(t, agg, r2, descriptor) - sum.AddNumber(profile.NumberKind, r1) - sum.AddNumber(profile.NumberKind, r2) - } - - require.NoError(t, agg.SynchronizedMove(ckpt, descriptor)) - checkZero(t, agg, descriptor) - - asum, err := ckpt.Sum() - require.Equal(t, sum, asum, "Same sum - monotonic") - require.Nil(t, err) - }) -} - -func TestCounterMerge(t *testing.T) { - aggregatortest.RunProfiles(t, func(t *testing.T, profile aggregatortest.Profile) { - agg1, agg2, ckpt1, ckpt2 := new4() - - descriptor := aggregatortest.NewAggregatorTest(sdkapi.CounterInstrumentKind, profile.NumberKind) - - sum := number.Number(0) - for i := 0; i < count; i++ { - x := profile.Random(+1) - sum.AddNumber(profile.NumberKind, x) - aggregatortest.CheckedUpdate(t, agg1, x, descriptor) - aggregatortest.CheckedUpdate(t, agg2, x, descriptor) - } - - require.NoError(t, agg1.SynchronizedMove(ckpt1, descriptor)) - require.NoError(t, agg2.SynchronizedMove(ckpt2, descriptor)) - - checkZero(t, agg1, descriptor) - checkZero(t, agg2, descriptor) - - aggregatortest.CheckedMerge(t, ckpt1, ckpt2, descriptor) - - sum.AddNumber(descriptor.NumberKind(), sum) - - asum, err := ckpt1.Sum() - require.Equal(t, sum, asum, "Same sum - monotonic") - require.Nil(t, err) - }) -} - -func TestSynchronizedMoveReset(t *testing.T) { - aggregatortest.SynchronizedMoveResetTest( - t, - sdkapi.CounterObserverInstrumentKind, - func(desc *sdkapi.Descriptor) aggregator.Aggregator { - return &New(1)[0] - }, - ) -} diff --git a/sdk/metric/alignment_test.go b/sdk/metric/alignment_test.go deleted file mode 100644 index e0839aa95ee..00000000000 --- a/sdk/metric/alignment_test.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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 metric - -import ( - "os" - "testing" - "unsafe" - - ottest "go.opentelemetry.io/otel/internal/internaltest" -) - -// Ensure struct alignment prior to running tests. -func TestMain(m *testing.M) { - offsets := map[string]uintptr{ - "record.refMapped.value": unsafe.Offsetof(record{}.refMapped.value), - "record.updateCount": unsafe.Offsetof(record{}.updateCount), - } - var r []ottest.FieldOffset - for name, offset := range offsets { - r = append(r, ottest.FieldOffset{ - Name: name, - Offset: offset, - }) - } - if !ottest.Aligned8Byte(r, os.Stderr) { - os.Exit(1) - } - - os.Exit(m.Run()) -} diff --git a/sdk/metric/atomicfields.go b/sdk/metric/atomicfields.go deleted file mode 100644 index 7cea2e54374..00000000000 --- a/sdk/metric/atomicfields.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 metric // import "go.opentelemetry.io/otel/sdk/metric" - -import "unsafe" - -// Deprecated: will be removed soon. -func AtomicFieldOffsets() map[string]uintptr { - return map[string]uintptr{ - "record.refMapped.value": unsafe.Offsetof(record{}.refMapped.value), - "record.updateCount": unsafe.Offsetof(record{}.updateCount), - } -} diff --git a/sdk/metric/benchmark_test.go b/sdk/metric/benchmark_test.go deleted file mode 100644 index cb06dcc75fb..00000000000 --- a/sdk/metric/benchmark_test.go +++ /dev/null @@ -1,397 +0,0 @@ -// 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 metric_test - -import ( - "context" - "fmt" - "math/rand" - "testing" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/global" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/metric/instrument/syncfloat64" - "go.opentelemetry.io/otel/metric/instrument/syncint64" - sdk "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type benchFixture struct { - meter metric.Meter - accumulator *sdk.Accumulator - B *testing.B - export.AggregatorSelector -} - -func newFixture(b *testing.B) *benchFixture { - b.ReportAllocs() - bf := &benchFixture{ - B: b, - AggregatorSelector: processortest.AggregatorSelector(), - } - - bf.accumulator = sdk.NewAccumulator(bf) - bf.meter = sdkapi.WrapMeterImpl(bf.accumulator) - return bf -} - -func (f *benchFixture) Process(export.Accumulation) error { - return nil -} - -func (f *benchFixture) Meter(_ string, _ ...metric.MeterOption) metric.Meter { - return f.meter -} - -func (f *benchFixture) iCounter(name string) syncint64.Counter { - ctr, err := f.meter.SyncInt64().Counter(name) - if err != nil { - f.B.Error(err) - } - return ctr -} -func (f *benchFixture) fCounter(name string) syncfloat64.Counter { - ctr, err := f.meter.SyncFloat64().Counter(name) - if err != nil { - f.B.Error(err) - } - return ctr -} -func (f *benchFixture) iHistogram(name string) syncint64.Histogram { - ctr, err := f.meter.SyncInt64().Histogram(name) - if err != nil { - f.B.Error(err) - } - return ctr -} -func (f *benchFixture) fHistogram(name string) syncfloat64.Histogram { - ctr, err := f.meter.SyncFloat64().Histogram(name) - if err != nil { - f.B.Error(err) - } - return ctr -} - -func makeLabels(n int) []attribute.KeyValue { - used := map[string]bool{} - l := make([]attribute.KeyValue, n) - for i := 0; i < n; i++ { - var k string - for { - k = fmt.Sprint("k", rand.Intn(1000000000)) - if !used[k] { - used[k] = true - break - } - } - l[i] = attribute.String(k, fmt.Sprint("v", rand.Intn(1000000000))) - } - return l -} - -func benchmarkLabels(b *testing.B, n int) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(n) - cnt := fix.iCounter("int64.sum") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - cnt.Add(ctx, 1, labs...) - } -} - -func BenchmarkInt64CounterAddWithLabels_1(b *testing.B) { - benchmarkLabels(b, 1) -} - -func BenchmarkInt64CounterAddWithLabels_2(b *testing.B) { - benchmarkLabels(b, 2) -} - -func BenchmarkInt64CounterAddWithLabels_4(b *testing.B) { - benchmarkLabels(b, 4) -} - -func BenchmarkInt64CounterAddWithLabels_8(b *testing.B) { - benchmarkLabels(b, 8) -} - -func BenchmarkInt64CounterAddWithLabels_16(b *testing.B) { - benchmarkLabels(b, 16) -} - -// Note: performance does not depend on label set size for the -// benchmarks below--all are benchmarked for a single attribute. - -// Iterators - -var benchmarkIteratorVar attribute.KeyValue - -func benchmarkIterator(b *testing.B, n int) { - labels := attribute.NewSet(makeLabels(n)...) - b.ResetTimer() - for i := 0; i < b.N; i++ { - iter := labels.Iter() - for iter.Next() { - benchmarkIteratorVar = iter.Label() - } - } -} - -func BenchmarkIterator_0(b *testing.B) { - benchmarkIterator(b, 0) -} - -func BenchmarkIterator_1(b *testing.B) { - benchmarkIterator(b, 1) -} - -func BenchmarkIterator_2(b *testing.B) { - benchmarkIterator(b, 2) -} - -func BenchmarkIterator_4(b *testing.B) { - benchmarkIterator(b, 4) -} - -func BenchmarkIterator_8(b *testing.B) { - benchmarkIterator(b, 8) -} - -func BenchmarkIterator_16(b *testing.B) { - benchmarkIterator(b, 16) -} - -// Counters - -func BenchmarkGlobalInt64CounterAddWithSDK(b *testing.B) { - // Compare with BenchmarkInt64CounterAdd() to see overhead of global - // package. This is in the SDK to avoid the API from depending on the - // SDK. - ctx := context.Background() - fix := newFixture(b) - - global.SetMeterProvider(fix) - - labs := []attribute.KeyValue{attribute.String("A", "B")} - - cnt := fix.iCounter("int64.sum") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - cnt.Add(ctx, 1, labs...) - } -} - -func BenchmarkInt64CounterAdd(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - cnt := fix.iCounter("int64.sum") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - cnt.Add(ctx, 1, labs...) - } -} - -func BenchmarkFloat64CounterAdd(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - cnt := fix.fCounter("float64.sum") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - cnt.Add(ctx, 1.1, labs...) - } -} - -// LastValue - -func BenchmarkInt64LastValueAdd(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - mea := fix.iHistogram("int64.lastvalue") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - mea.Record(ctx, int64(i), labs...) - } -} - -func BenchmarkFloat64LastValueAdd(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - mea := fix.fHistogram("float64.lastvalue") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - mea.Record(ctx, float64(i), labs...) - } -} - -// Histograms - -func BenchmarkInt64HistogramAdd(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - mea := fix.iHistogram("int64.histogram") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - mea.Record(ctx, int64(i), labs...) - } -} - -func BenchmarkFloat64HistogramAdd(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - mea := fix.fHistogram("float64.histogram") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - mea.Record(ctx, float64(i), labs...) - } -} - -// Observers - -func BenchmarkObserverRegistration(b *testing.B) { - fix := newFixture(b) - names := make([]string, 0, b.N) - for i := 0; i < b.N; i++ { - names = append(names, fmt.Sprintf("test.%d.lastvalue", i)) - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - ctr, _ := fix.meter.AsyncInt64().Counter(names[i]) - _ = fix.meter.RegisterCallback([]instrument.Asynchronous{ctr}, func(context.Context) {}) - } -} - -func BenchmarkGaugeObserverObservationInt64(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - ctr, _ := fix.meter.AsyncInt64().Counter("test.lastvalue") - err := fix.meter.RegisterCallback([]instrument.Asynchronous{ctr}, func(ctx context.Context) { - for i := 0; i < b.N; i++ { - ctr.Observe(ctx, (int64)(i), labs...) - } - }) - if err != nil { - b.Errorf("could not register callback: %v", err) - b.FailNow() - } - - b.ResetTimer() - - fix.accumulator.Collect(ctx) -} - -func BenchmarkGaugeObserverObservationFloat64(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(1) - ctr, _ := fix.meter.AsyncFloat64().Counter("test.lastvalue") - err := fix.meter.RegisterCallback([]instrument.Asynchronous{ctr}, func(ctx context.Context) { - for i := 0; i < b.N; i++ { - ctr.Observe(ctx, (float64)(i), labs...) - } - }) - if err != nil { - b.Errorf("could not register callback: %v", err) - b.FailNow() - } - - b.ResetTimer() - - fix.accumulator.Collect(ctx) -} - -// BatchRecord - -func benchmarkBatchRecord8Labels(b *testing.B, numInst int) { - const numLabels = 8 - ctx := context.Background() - fix := newFixture(b) - labs := makeLabels(numLabels) - var meas []syncint64.Counter - - for i := 0; i < numInst; i++ { - meas = append(meas, fix.iCounter(fmt.Sprintf("int64.%d.sum", i))) - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - for _, ctr := range meas { - ctr.Add(ctx, 1, labs...) - } - } -} - -func BenchmarkBatchRecord8Labels_1Instrument(b *testing.B) { - benchmarkBatchRecord8Labels(b, 1) -} - -func BenchmarkBatchRecord_8Labels_2Instruments(b *testing.B) { - benchmarkBatchRecord8Labels(b, 2) -} - -func BenchmarkBatchRecord_8Labels_4Instruments(b *testing.B) { - benchmarkBatchRecord8Labels(b, 4) -} - -func BenchmarkBatchRecord_8Labels_8Instruments(b *testing.B) { - benchmarkBatchRecord8Labels(b, 8) -} - -// Record creation - -func BenchmarkRepeatedDirectCalls(b *testing.B) { - ctx := context.Background() - fix := newFixture(b) - - c := fix.iCounter("int64.sum") - k := attribute.String("bench", "true") - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - c.Add(ctx, 1, k) - fix.accumulator.Collect(ctx) - } -} diff --git a/sdk/metric/controller/basic/config.go b/sdk/metric/controller/basic/config.go deleted file mode 100644 index f3a9830c6af..00000000000 --- a/sdk/metric/controller/basic/config.go +++ /dev/null @@ -1,131 +0,0 @@ -// 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 basic // import "go.opentelemetry.io/otel/sdk/metric/controller/basic" - -import ( - "time" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/resource" -) - -// config contains configuration for a basic Controller. -type config struct { - // Resource is the OpenTelemetry resource associated with all Meters - // created by the Controller. - Resource *resource.Resource - - // CollectPeriod is the interval between calls to Collect a - // checkpoint. - // - // When pulling metrics and not exporting, this is the minimum - // time between calls to Collect. In a pull-only - // configuration, collection is performed on demand; set - // CollectPeriod to 0 always recompute the export record set. - // - // When exporting metrics, this must be > 0. - // - // Default value is 10s. - CollectPeriod time.Duration - - // CollectTimeout is the timeout of the Context passed to - // Collect() and subsequently to Observer instrument callbacks. - // - // Default value is 10s. If zero, no Collect timeout is applied. - CollectTimeout time.Duration - - // Exporter is used for exporting metric data. - // - // Note: Exporters such as Prometheus that pull data do not implement - // export.Exporter. These will directly call Collect() and ForEach(). - Exporter export.Exporter - - // PushTimeout is the timeout of the Context when a exporter is configured. - // - // Default value is 10s. If zero, no Export timeout is applied. - PushTimeout time.Duration -} - -// Option is the interface that applies the value to a configuration option. -type Option interface { - // apply sets the Option value of a Config. - apply(config) config -} - -// WithResource sets the Resource configuration option of a Config by merging it -// with the Resource configuration in the environment. -func WithResource(r *resource.Resource) Option { - return resourceOption{r} -} - -type resourceOption struct{ *resource.Resource } - -func (o resourceOption) apply(cfg config) config { - res, err := resource.Merge(cfg.Resource, o.Resource) - if err != nil { - otel.Handle(err) - } - cfg.Resource = res - return cfg -} - -// WithCollectPeriod sets the CollectPeriod configuration option of a Config. -func WithCollectPeriod(period time.Duration) Option { - return collectPeriodOption(period) -} - -type collectPeriodOption time.Duration - -func (o collectPeriodOption) apply(cfg config) config { - cfg.CollectPeriod = time.Duration(o) - return cfg -} - -// WithCollectTimeout sets the CollectTimeout configuration option of a Config. -func WithCollectTimeout(timeout time.Duration) Option { - return collectTimeoutOption(timeout) -} - -type collectTimeoutOption time.Duration - -func (o collectTimeoutOption) apply(cfg config) config { - cfg.CollectTimeout = time.Duration(o) - return cfg -} - -// WithExporter sets the exporter configuration option of a Config. -func WithExporter(exporter export.Exporter) Option { - return exporterOption{exporter} -} - -type exporterOption struct{ exporter export.Exporter } - -func (o exporterOption) apply(cfg config) config { - cfg.Exporter = o.exporter - return cfg -} - -// WithPushTimeout sets the PushTimeout configuration option of a Config. -func WithPushTimeout(timeout time.Duration) Option { - return pushTimeoutOption(timeout) -} - -type pushTimeoutOption time.Duration - -func (o pushTimeoutOption) apply(cfg config) config { - cfg.PushTimeout = time.Duration(o) - return cfg -} diff --git a/sdk/metric/controller/basic/config_test.go b/sdk/metric/controller/basic/config_test.go deleted file mode 100644 index 32757b8a966..00000000000 --- a/sdk/metric/controller/basic/config_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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 basic - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/resource" -) - -func TestWithResource(t *testing.T) { - r := resource.NewSchemaless(attribute.String("A", "a")) - - c := config{} - c = WithResource(r).apply(c) - assert.Equal(t, r.Equivalent(), c.Resource.Equivalent()) - - // Ensure overwriting works. - c = config{Resource: &resource.Resource{}} - c = WithResource(r).apply(c) - assert.Equal(t, r.Equivalent(), c.Resource.Equivalent()) -} diff --git a/sdk/metric/controller/basic/controller.go b/sdk/metric/controller/basic/controller.go deleted file mode 100644 index de0da5484c9..00000000000 --- a/sdk/metric/controller/basic/controller.go +++ /dev/null @@ -1,380 +0,0 @@ -// 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 basic // import "go.opentelemetry.io/otel/sdk/metric/controller/basic" - -import ( - "context" - "fmt" - "sync" - "time" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/sdk/instrumentation" - sdk "go.opentelemetry.io/otel/sdk/metric" - controllerTime "go.opentelemetry.io/otel/sdk/metric/controller/time" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/registry" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -// DefaultPeriod is used for: -// -// - the minimum time between calls to Collect() -// - the timeout for Export() -// - the timeout for Collect(). -const DefaultPeriod = 10 * time.Second - -// ErrControllerStarted indicates that a controller was started more -// than once. -var ErrControllerStarted = fmt.Errorf("controller already started") - -// Controller organizes and synchronizes collection of metric data in -// both "pull" and "push" configurations. This supports two distinct -// modes: -// -// - Push and Pull: Start() must be called to begin calling the exporter; -// Collect() is called periodically by a background thread after starting -// the controller. -// - Pull-Only: Start() is optional in this case, to call Collect periodically. -// If Start() is not called, Collect() can be called manually to initiate -// collection -// -// The controller supports mixing push and pull access to metric data -// using the export.Reader RWLock interface. Collection will -// be blocked by a pull request in the basic controller. -type Controller struct { - // lock synchronizes Start() and Stop(). - lock sync.Mutex - libraries sync.Map - checkpointerFactory export.CheckpointerFactory - - resource *resource.Resource - exporter export.Exporter - wg sync.WaitGroup - stopCh chan struct{} - clock controllerTime.Clock - ticker controllerTime.Ticker - - collectPeriod time.Duration - collectTimeout time.Duration - pushTimeout time.Duration - - // collectedTime is used only in configurations with no - // exporter, when ticker != nil. - collectedTime time.Time -} - -var _ export.InstrumentationLibraryReader = &Controller{} -var _ metric.MeterProvider = &Controller{} - -func (c *Controller) Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter { - cfg := metric.NewMeterConfig(opts...) - library := instrumentation.Library{ - Name: instrumentationName, - Version: cfg.InstrumentationVersion(), - SchemaURL: cfg.SchemaURL(), - } - - m, ok := c.libraries.Load(library) - if !ok { - checkpointer := c.checkpointerFactory.NewCheckpointer() - m, _ = c.libraries.LoadOrStore( - library, - registry.NewUniqueInstrumentMeterImpl(&accumulatorCheckpointer{ - Accumulator: sdk.NewAccumulator(checkpointer), - checkpointer: checkpointer, - library: library, - })) - } - return sdkapi.WrapMeterImpl(m.(*registry.UniqueInstrumentMeterImpl)) -} - -type accumulatorCheckpointer struct { - *sdk.Accumulator - checkpointer export.Checkpointer - library instrumentation.Library -} - -var _ sdkapi.MeterImpl = &accumulatorCheckpointer{} - -// New constructs a Controller using the provided checkpointer factory -// and options (including optional exporter) to configure a metric -// export pipeline. -func New(checkpointerFactory export.CheckpointerFactory, opts ...Option) *Controller { - c := config{ - CollectPeriod: DefaultPeriod, - CollectTimeout: DefaultPeriod, - PushTimeout: DefaultPeriod, - } - for _, opt := range opts { - c = opt.apply(c) - } - if c.Resource == nil { - c.Resource = resource.Default() - } else { - var err error - c.Resource, err = resource.Merge(resource.Environment(), c.Resource) - if err != nil { - otel.Handle(err) - } - } - return &Controller{ - checkpointerFactory: checkpointerFactory, - exporter: c.Exporter, - resource: c.Resource, - stopCh: nil, - clock: controllerTime.RealClock{}, - - collectPeriod: c.CollectPeriod, - collectTimeout: c.CollectTimeout, - pushTimeout: c.PushTimeout, - } -} - -// SetClock supports setting a mock clock for testing. This must be -// called before Start(). -func (c *Controller) SetClock(clock controllerTime.Clock) { - c.lock.Lock() - defer c.lock.Unlock() - c.clock = clock -} - -// Resource returns the *resource.Resource associated with this -// controller. -func (c *Controller) Resource() *resource.Resource { - return c.resource -} - -// Start begins a ticker that periodically collects and exports -// metrics with the configured interval. This is required for calling -// a configured Exporter (see WithExporter) and is otherwise optional -// when only pulling metric data. -// -// The passed context is passed to Collect() and subsequently to -// asynchronous instrument callbacks. Returns an error when the -// controller was already started. -// -// Note that it is not necessary to Start a controller when only -// pulling data; use the Collect() and ForEach() methods directly in -// this case. -func (c *Controller) Start(ctx context.Context) error { - c.lock.Lock() - defer c.lock.Unlock() - - if c.stopCh != nil { - return ErrControllerStarted - } - - c.wg.Add(1) - c.stopCh = make(chan struct{}) - c.ticker = c.clock.Ticker(c.collectPeriod) - go c.runTicker(ctx, c.stopCh) - return nil -} - -// Stop waits for the background goroutine to return and then collects -// and exports metrics one last time before returning. The passed -// context is passed to the final Collect() and subsequently to the -// final asynchronous instruments. -// -// Note that Stop() will not cancel an ongoing collection or export. -func (c *Controller) Stop(ctx context.Context) error { - if lastCollection := func() bool { - c.lock.Lock() - defer c.lock.Unlock() - - if c.stopCh == nil { - return false - } - - close(c.stopCh) - c.stopCh = nil - c.wg.Wait() - c.ticker.Stop() - c.ticker = nil - return true - }(); !lastCollection { - return nil - } - return c.collect(ctx) -} - -// runTicker collection on ticker events until the stop channel is closed. -func (c *Controller) runTicker(ctx context.Context, stopCh chan struct{}) { - defer c.wg.Done() - for { - select { - case <-stopCh: - return - case <-c.ticker.C(): - if err := c.collect(ctx); err != nil { - otel.Handle(err) - } - } - } -} - -// collect computes a checkpoint and optionally exports it. -func (c *Controller) collect(ctx context.Context) error { - if err := c.checkpoint(ctx); err != nil { - return err - } - if c.exporter == nil { - return nil - } - - // Note: this is not subject to collectTimeout. This blocks the next - // collection despite collectTimeout because it holds a lock. - return c.export(ctx) -} - -// accumulatorList returns a snapshot of current accumulators -// registered to this controller. This briefly locks the controller. -func (c *Controller) accumulatorList() []*accumulatorCheckpointer { - var r []*accumulatorCheckpointer - c.libraries.Range(func(key, value interface{}) bool { - acc, ok := value.(*registry.UniqueInstrumentMeterImpl).MeterImpl().(*accumulatorCheckpointer) - if ok { - r = append(r, acc) - } - return true - }) - return r -} - -// checkpoint calls the Accumulator and Checkpointer interfaces to -// compute the Reader. This applies the configured collection -// timeout. Note that this does not try to cancel a Collect or Export -// when Stop() is called. -func (c *Controller) checkpoint(ctx context.Context) error { - for _, impl := range c.accumulatorList() { - if err := c.checkpointSingleAccumulator(ctx, impl); err != nil { - return err - } - } - return nil -} - -// checkpointSingleAccumulator checkpoints a single instrumentation -// library's accumulator, which involves calling -// checkpointer.StartCollection, accumulator.Collect, and -// checkpointer.FinishCollection in sequence. -func (c *Controller) checkpointSingleAccumulator(ctx context.Context, ac *accumulatorCheckpointer) error { - ckpt := ac.checkpointer.Reader() - ckpt.Lock() - defer ckpt.Unlock() - - ac.checkpointer.StartCollection() - - if c.collectTimeout > 0 { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, c.collectTimeout) - defer cancel() - } - - _ = ac.Accumulator.Collect(ctx) - - var err error - select { - case <-ctx.Done(): - err = ctx.Err() - default: - // The context wasn't done, ok. - } - - // Finish the checkpoint whether the accumulator timed out or not. - if cerr := ac.checkpointer.FinishCollection(); cerr != nil { - if err == nil { - err = cerr - } else { - err = fmt.Errorf("%s: %w", cerr.Error(), err) - } - } - - return err -} - -// export calls the exporter with a read lock on the Reader, -// applying the configured export timeout. -func (c *Controller) export(ctx context.Context) error { - if c.pushTimeout > 0 { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, c.pushTimeout) - defer cancel() - } - - return c.exporter.Export(ctx, c.resource, c) -} - -// ForEach implements export.InstrumentationLibraryReader. -func (c *Controller) ForEach(readerFunc func(l instrumentation.Library, r export.Reader) error) error { - for _, acPair := range c.accumulatorList() { - reader := acPair.checkpointer.Reader() - // TODO: We should not fail fast; instead accumulate errors. - if err := func() error { - reader.RLock() - defer reader.RUnlock() - return readerFunc(acPair.library, reader) - }(); err != nil { - return err - } - } - return nil -} - -// IsRunning returns true if the controller was started via Start(), -// indicating that the current export.Reader is being kept -// up-to-date. -func (c *Controller) IsRunning() bool { - c.lock.Lock() - defer c.lock.Unlock() - return c.ticker != nil -} - -// Collect requests a collection. The collection will be skipped if -// the last collection is aged less than the configured collection -// period. -func (c *Controller) Collect(ctx context.Context) error { - if c.IsRunning() { - // When there's a non-nil ticker, there's a goroutine - // computing checkpoints with the collection period. - return ErrControllerStarted - } - if !c.shouldCollect() { - return nil - } - - return c.checkpoint(ctx) -} - -// shouldCollect returns true if the collector should collect now, -// based on the timestamp, the last collection time, and the -// configured period. -func (c *Controller) shouldCollect() bool { - c.lock.Lock() - defer c.lock.Unlock() - - if c.collectPeriod == 0 { - return true - } - now := c.clock.Now() - if now.Sub(c.collectedTime) < c.collectPeriod { - return false - } - c.collectedTime = now - return true -} diff --git a/sdk/metric/controller/basic/controller_test.go b/sdk/metric/controller/basic/controller_test.go deleted file mode 100644 index 26dcf4bb286..00000000000 --- a/sdk/metric/controller/basic/controller_test.go +++ /dev/null @@ -1,493 +0,0 @@ -// 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 basic_test - -import ( - "context" - "errors" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - ottest "go.opentelemetry.io/otel/internal/internaltest" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/instrumentation" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/controller/controllertest" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -const envVar = "OTEL_RESOURCE_ATTRIBUTES" - -func getMap(t *testing.T, cont *controller.Controller) map[string]float64 { - out := processortest.NewOutput(attribute.DefaultEncoder()) - - require.NoError(t, cont.ForEach( - func(_ instrumentation.Library, reader export.Reader) error { - return reader.ForEach( - aggregation.CumulativeTemporalitySelector(), - func(record export.Record) error { - return out.AddRecord(record) - }, - ) - })) - return out.Map() -} - -type testContextKey string - -func testContext() context.Context { - ctx := context.Background() - return context.WithValue(ctx, testContextKey("A"), "B") -} - -func checkTestContext(t *testing.T, ctx context.Context) { - require.Equal(t, "B", ctx.Value(testContextKey("A"))) -} - -func TestControllerUsesResource(t *testing.T) { - const envVal = "T=U,key=value" - store, err := ottest.SetEnvVariables(map[string]string{ - envVar: envVal, - }) - - require.NoError(t, err) - defer func() { require.NoError(t, store.Restore()) }() - - cases := []struct { - name string - options []controller.Option - wanted string - }{ - { - name: "explicitly empty resource", - options: []controller.Option{controller.WithResource(resource.Empty())}, - wanted: envVal, - }, - { - name: "uses default if no resource option", - options: nil, - wanted: resource.Default().Encoded(attribute.DefaultEncoder()), - }, - { - name: "explicit resource", - options: []controller.Option{controller.WithResource(resource.NewSchemaless(attribute.String("R", "S")))}, - wanted: "R=S," + envVal, - }, - { - name: "multi resource", - options: []controller.Option{ - controller.WithResource(resource.NewSchemaless(attribute.String("R", "WRONG"))), - controller.WithResource(resource.NewSchemaless(attribute.String("R", "S"))), - controller.WithResource(resource.NewSchemaless(attribute.String("W", "X"))), - controller.WithResource(resource.NewSchemaless(attribute.String("T", "V"))), - }, - wanted: "R=S,T=V,W=X,key=value", - }, - { - name: "user override environment", - options: []controller.Option{ - controller.WithResource(resource.NewSchemaless(attribute.String("T", "V"))), - controller.WithResource(resource.NewSchemaless(attribute.String("key", "I win"))), - }, - wanted: "T=V,key=I win", - }, - } - for _, c := range cases { - t.Run(fmt.Sprintf("case-%s", c.name), func(t *testing.T) { - sel := aggregation.CumulativeTemporalitySelector() - exp := processortest.New(sel, attribute.DefaultEncoder()) - cont := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - exp, - ), - append(c.options, controller.WithExporter(exp))..., - ) - ctx := context.Background() - require.NoError(t, cont.Start(ctx)) - - ctr, _ := cont.Meter("named").SyncFloat64().Counter("calls.sum") - ctr.Add(context.Background(), 1.) - - // Collect once - require.NoError(t, cont.Stop(ctx)) - - expect := map[string]float64{ - "calls.sum//" + c.wanted: 1., - } - require.EqualValues(t, expect, exp.Values()) - }) - } -} - -func TestStartNoExporter(t *testing.T) { - cont := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - aggregation.CumulativeTemporalitySelector(), - ), - controller.WithCollectPeriod(time.Second), - controller.WithResource(resource.Empty()), - ) - mock := controllertest.NewMockClock() - cont.SetClock(mock) - meter := cont.Meter("go.opentelemetry.io/otel/sdk/metric/controller/basic_test#StartNoExporter") - - calls := int64(0) - - counterObserver, err := meter.AsyncInt64().Counter("calls.lastvalue") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - calls++ - checkTestContext(t, ctx) - counterObserver.Observe(ctx, calls, attribute.String("A", "B")) - }) - require.NoError(t, err) - - // Collect() has not been called. The controller is unstarted. - expect := map[string]float64{} - - // The time advances, but doesn't change the result (not collected). - require.EqualValues(t, expect, getMap(t, cont)) - mock.Add(time.Second) - require.EqualValues(t, expect, getMap(t, cont)) - mock.Add(time.Second) - - expect = map[string]float64{ - "calls.lastvalue/A=B/": 1, - } - - // Collect once - ctx := testContext() - - require.NoError(t, cont.Collect(ctx)) - - require.EqualValues(t, expect, getMap(t, cont)) - mock.Add(time.Second) - require.EqualValues(t, expect, getMap(t, cont)) - mock.Add(time.Second) - - // Again - expect = map[string]float64{ - "calls.lastvalue/A=B/": 2, - } - - require.NoError(t, cont.Collect(ctx)) - - require.EqualValues(t, expect, getMap(t, cont)) - mock.Add(time.Second) - require.EqualValues(t, expect, getMap(t, cont)) - - // Start the controller - require.NoError(t, cont.Start(ctx)) - - for i := 1; i <= 3; i++ { - expect = map[string]float64{ - "calls.lastvalue/A=B/": 2 + float64(i), - } - - mock.Add(time.Second) - require.EqualValues(t, expect, getMap(t, cont)) - } -} - -func TestObserverCanceled(t *testing.T) { - cont := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - aggregation.CumulativeTemporalitySelector(), - ), - controller.WithCollectPeriod(0), - controller.WithCollectTimeout(time.Millisecond), - controller.WithResource(resource.Empty()), - ) - meter := cont.Meter("go.opentelemetry.io/otel/sdk/metric/controller/basic_test#ObserverCanceled") - - calls := int64(0) - - counterObserver, err := meter.AsyncInt64().Counter("done.lastvalue") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - <-ctx.Done() - calls++ - counterObserver.Observe(ctx, calls) - }) - require.NoError(t, err) - - // This relies on the context timing out - err = cont.Collect(context.Background()) - require.Error(t, err) - require.True(t, errors.Is(err, context.DeadlineExceeded)) - - expect := map[string]float64{ - "done.lastvalue//": 1, - } - - require.EqualValues(t, expect, getMap(t, cont)) -} - -func TestObserverContext(t *testing.T) { - cont := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - aggregation.CumulativeTemporalitySelector(), - ), - controller.WithCollectTimeout(0), - controller.WithResource(resource.Empty()), - ) - meter := cont.Meter("go.opentelemetry.io/otel/sdk/metric/controller/basic_test#ObserverContext") - - counterObserver, err := meter.AsyncInt64().Counter("done.lastvalue") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - time.Sleep(10 * time.Millisecond) - checkTestContext(t, ctx) - counterObserver.Observe(ctx, 1) - }) - require.NoError(t, err) - - ctx := testContext() - - require.NoError(t, cont.Collect(ctx)) - - expect := map[string]float64{ - "done.lastvalue//": 1, - } - - require.EqualValues(t, expect, getMap(t, cont)) -} - -type blockingExporter struct { - calls int - exporter *processortest.Exporter -} - -func newBlockingExporter() *blockingExporter { - return &blockingExporter{ - exporter: processortest.New( - aggregation.CumulativeTemporalitySelector(), - attribute.DefaultEncoder(), - ), - } -} - -func (b *blockingExporter) Export(ctx context.Context, res *resource.Resource, output export.InstrumentationLibraryReader) error { - var err error - _ = b.exporter.Export(ctx, res, output) - if b.calls == 0 { - // timeout once - <-ctx.Done() - err = ctx.Err() - } - b.calls++ - return err -} - -func (*blockingExporter) TemporalityFor(*sdkapi.Descriptor, aggregation.Kind) aggregation.Temporality { - return aggregation.CumulativeTemporality -} - -func TestExportTimeout(t *testing.T) { - exporter := newBlockingExporter() - cont := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - aggregation.CumulativeTemporalitySelector(), - ), - controller.WithCollectPeriod(time.Second), - controller.WithPushTimeout(time.Millisecond), - controller.WithExporter(exporter), - controller.WithResource(resource.Empty()), - ) - mock := controllertest.NewMockClock() - cont.SetClock(mock) - meter := cont.Meter("go.opentelemetry.io/otel/sdk/metric/controller/basic_test#ExportTimeout") - - calls := int64(0) - counterObserver, err := meter.AsyncInt64().Counter("one.lastvalue") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - calls++ - counterObserver.Observe(ctx, calls) - }) - require.NoError(t, err) - - require.NoError(t, cont.Start(context.Background())) - - // Initial empty state - expect := map[string]float64{} - require.EqualValues(t, expect, exporter.exporter.Values()) - - // Collect after 1s, timeout - mock.Add(time.Second) - - err = testHandler.Flush() - require.Error(t, err) - require.True(t, errors.Is(err, context.DeadlineExceeded)) - - expect = map[string]float64{ - "one.lastvalue//": 1, - } - require.EqualValues(t, expect, exporter.exporter.Values()) - - // Collect again - mock.Add(time.Second) - expect = map[string]float64{ - "one.lastvalue//": 2, - } - require.EqualValues(t, expect, exporter.exporter.Values()) - - err = testHandler.Flush() - require.NoError(t, err) -} - -func TestCollectAfterStopThenStartAgain(t *testing.T) { - exp := processortest.New( - aggregation.CumulativeTemporalitySelector(), - attribute.DefaultEncoder(), - ) - cont := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - exp, - ), - controller.WithCollectPeriod(time.Second), - controller.WithExporter(exp), - controller.WithResource(resource.Empty()), - ) - mock := controllertest.NewMockClock() - cont.SetClock(mock) - - meter := cont.Meter("go.opentelemetry.io/otel/sdk/metric/controller/basic_test#CollectAfterStopThenStartAgain") - - calls := 0 - counterObserver, err := meter.AsyncInt64().Counter("one.lastvalue") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - calls++ - counterObserver.Observe(ctx, int64(calls)) - }) - require.NoError(t, err) - - // No collections happen (because mock clock does not advance): - require.NoError(t, cont.Start(context.Background())) - require.True(t, cont.IsRunning()) - - // There's one collection run by Stop(): - require.NoError(t, cont.Stop(context.Background())) - - require.EqualValues(t, map[string]float64{ - "one.lastvalue//": 1, - }, exp.Values()) - require.NoError(t, testHandler.Flush()) - - // Manual collect after Stop still works, subject to - // CollectPeriod. - require.NoError(t, cont.Collect(context.Background())) - require.EqualValues(t, map[string]float64{ - "one.lastvalue//": 2, - }, getMap(t, cont)) - - require.NoError(t, testHandler.Flush()) - require.False(t, cont.IsRunning()) - - // Start again, see that collection proceeds. However, - // explicit collection should still fail. - require.NoError(t, cont.Start(context.Background())) - require.True(t, cont.IsRunning()) - err = cont.Collect(context.Background()) - require.Error(t, err) - require.Equal(t, controller.ErrControllerStarted, err) - - require.NoError(t, cont.Stop(context.Background())) - require.EqualValues(t, map[string]float64{ - "one.lastvalue//": 3, - }, exp.Values()) - require.False(t, cont.IsRunning()) - - // Time has not advanced yet. Now let the ticker perform - // collection: - require.NoError(t, cont.Start(context.Background())) - mock.Add(time.Second) - require.EqualValues(t, map[string]float64{ - "one.lastvalue//": 4, - }, exp.Values()) - - mock.Add(time.Second) - require.EqualValues(t, map[string]float64{ - "one.lastvalue//": 5, - }, exp.Values()) - require.NoError(t, cont.Stop(context.Background())) - require.EqualValues(t, map[string]float64{ - "one.lastvalue//": 6, - }, exp.Values()) -} - -func TestRegistryFunction(t *testing.T) { - exp := processortest.New( - aggregation.CumulativeTemporalitySelector(), - attribute.DefaultEncoder(), - ) - cont := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - exp, - ), - controller.WithCollectPeriod(time.Second), - controller.WithExporter(exp), - controller.WithResource(resource.Empty()), - ) - - m1 := cont.Meter("test") - m2 := cont.Meter("test") - - require.NotNil(t, m1) - require.Equal(t, m1, m2) - - c1, err := m1.SyncInt64().Counter("counter.sum") - require.NoError(t, err) - - c2, err := m1.SyncInt64().Counter("counter.sum") - require.NoError(t, err) - - require.Equal(t, c1, c2) - - ctx := context.Background() - - require.NoError(t, cont.Start(ctx)) - - c1.Add(ctx, 10) - c2.Add(ctx, 10) - - require.NoError(t, cont.Stop(ctx)) - - require.EqualValues(t, map[string]float64{ - "counter.sum//": 20, - }, exp.Values()) -} diff --git a/sdk/metric/controller/basic/pull_test.go b/sdk/metric/controller/basic/pull_test.go deleted file mode 100644 index 2284e68a71d..00000000000 --- a/sdk/metric/controller/basic/pull_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// 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 basic_test - -import ( - "context" - "runtime" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/controller/controllertest" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/resource" -) - -func TestPullNoCollect(t *testing.T) { - puller := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - aggregation.CumulativeTemporalitySelector(), - processor.WithMemory(true), - ), - controller.WithCollectPeriod(0), - controller.WithResource(resource.Empty()), - ) - - ctx := context.Background() - meter := puller.Meter("nocache") - counter, err := meter.SyncInt64().Counter("counter.sum") - require.NoError(t, err) - - counter.Add(ctx, 10, attribute.String("A", "B")) - - require.NoError(t, puller.Collect(ctx)) - records := processortest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, controllertest.ReadAll(puller, aggregation.CumulativeTemporalitySelector(), records.AddInstrumentationLibraryRecord)) - - require.EqualValues(t, map[string]float64{ - "counter.sum/A=B/": 10, - }, records.Map()) - - counter.Add(ctx, 10, attribute.String("A", "B")) - - require.NoError(t, puller.Collect(ctx)) - records = processortest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, controllertest.ReadAll(puller, aggregation.CumulativeTemporalitySelector(), records.AddInstrumentationLibraryRecord)) - - require.EqualValues(t, map[string]float64{ - "counter.sum/A=B/": 20, - }, records.Map()) -} - -func TestPullWithCollect(t *testing.T) { - puller := controller.New( - processor.NewFactory( - processortest.AggregatorSelector(), - aggregation.CumulativeTemporalitySelector(), - processor.WithMemory(true), - ), - controller.WithCollectPeriod(time.Second), - controller.WithResource(resource.Empty()), - ) - mock := controllertest.NewMockClock() - puller.SetClock(mock) - - ctx := context.Background() - meter := puller.Meter("nocache") - counter, err := meter.SyncInt64().Counter("counter.sum") - require.NoError(t, err) - - counter.Add(ctx, 10, attribute.String("A", "B")) - - require.NoError(t, puller.Collect(ctx)) - records := processortest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, controllertest.ReadAll(puller, aggregation.CumulativeTemporalitySelector(), records.AddInstrumentationLibraryRecord)) - - require.EqualValues(t, map[string]float64{ - "counter.sum/A=B/": 10, - }, records.Map()) - - counter.Add(ctx, 10, attribute.String("A", "B")) - - // Cached value! - require.NoError(t, puller.Collect(ctx)) - records = processortest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, controllertest.ReadAll(puller, aggregation.CumulativeTemporalitySelector(), records.AddInstrumentationLibraryRecord)) - - require.EqualValues(t, map[string]float64{ - "counter.sum/A=B/": 10, - }, records.Map()) - - mock.Add(time.Second) - runtime.Gosched() - - // Re-computed value! - require.NoError(t, puller.Collect(ctx)) - records = processortest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, controllertest.ReadAll(puller, aggregation.CumulativeTemporalitySelector(), records.AddInstrumentationLibraryRecord)) - - require.EqualValues(t, map[string]float64{ - "counter.sum/A=B/": 20, - }, records.Map()) - -} diff --git a/sdk/metric/controller/basic/push_test.go b/sdk/metric/controller/basic/push_test.go deleted file mode 100644 index 67bbddfdc84..00000000000 --- a/sdk/metric/controller/basic/push_test.go +++ /dev/null @@ -1,230 +0,0 @@ -// 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 basic_test - -import ( - "context" - "errors" - "fmt" - "runtime" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/controller/controllertest" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/resource" -) - -var testResource = resource.NewSchemaless(attribute.String("R", "V")) - -type handler struct { - sync.Mutex - err error -} - -func (h *handler) Handle(err error) { - h.Lock() - h.err = err - h.Unlock() -} - -func (h *handler) Flush() error { - h.Lock() - err := h.err - h.err = nil - h.Unlock() - return err -} - -var testHandler *handler - -func init() { - testHandler = new(handler) - otel.SetErrorHandler(testHandler) -} - -func newExporter() *processortest.Exporter { - return processortest.New( - aggregation.StatelessTemporalitySelector(), - attribute.DefaultEncoder(), - ) -} - -func newCheckpointerFactory() export.CheckpointerFactory { - return processortest.NewCheckpointerFactory( - processortest.AggregatorSelector(), - attribute.DefaultEncoder(), - ) -} - -func TestPushDoubleStop(t *testing.T) { - ctx := context.Background() - exporter := newExporter() - checkpointer := newCheckpointerFactory() - p := controller.New(checkpointer, controller.WithExporter(exporter)) - require.NoError(t, p.Start(ctx)) - require.NoError(t, p.Stop(ctx)) - require.NoError(t, p.Stop(ctx)) -} - -func TestPushDoubleStart(t *testing.T) { - ctx := context.Background() - exporter := newExporter() - checkpointer := newCheckpointerFactory() - p := controller.New(checkpointer, controller.WithExporter(exporter)) - require.NoError(t, p.Start(ctx)) - err := p.Start(ctx) - require.Error(t, err) - require.True(t, errors.Is(err, controller.ErrControllerStarted)) - require.NoError(t, p.Stop(ctx)) -} - -func TestPushTicker(t *testing.T) { - exporter := newExporter() - checkpointer := newCheckpointerFactory() - p := controller.New( - checkpointer, - controller.WithExporter(exporter), - controller.WithCollectPeriod(time.Second), - controller.WithResource(testResource), - ) - meter := p.Meter("name") - - mock := controllertest.NewMockClock() - p.SetClock(mock) - - ctx := context.Background() - - counter, err := meter.SyncInt64().Counter("counter.sum") - require.NoError(t, err) - - require.NoError(t, p.Start(ctx)) - - counter.Add(ctx, 3) - - require.EqualValues(t, map[string]float64{}, exporter.Values()) - - mock.Add(time.Second) - runtime.Gosched() - - require.EqualValues(t, map[string]float64{ - "counter.sum//R=V": 3, - }, exporter.Values()) - - require.Equal(t, 1, exporter.ExportCount()) - exporter.Reset() - - counter.Add(ctx, 7) - - mock.Add(time.Second) - runtime.Gosched() - - require.EqualValues(t, map[string]float64{ - "counter.sum//R=V": 10, - }, exporter.Values()) - - require.Equal(t, 1, exporter.ExportCount()) - exporter.Reset() - - require.NoError(t, p.Stop(ctx)) -} - -func TestPushExportError(t *testing.T) { - injector := func(name string, e error) func(r export.Record) error { - return func(r export.Record) error { - if r.Descriptor().Name() == name { - return e - } - return nil - } - } - var errAggregator = fmt.Errorf("unexpected error") - var tests = []struct { - name string - injectedError error - expected map[string]float64 - expectedError error - }{ - {"errNone", nil, map[string]float64{ - "counter1.sum/X=Y/R=V": 3, - "counter2.sum//R=V": 5, - }, nil}, - {"errNoData", aggregation.ErrNoData, map[string]float64{ - "counter2.sum//R=V": 5, - }, nil}, - {"errUnexpected", errAggregator, map[string]float64{}, errAggregator}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - exporter := newExporter() - exporter.InjectErr = injector("counter1.sum", tt.injectedError) - - // This test validates the error handling - // behavior of the basic Processor is honored - // by the push processor. - checkpointer := processor.NewFactory(processortest.AggregatorSelector(), exporter) - p := controller.New( - checkpointer, - controller.WithExporter(exporter), - controller.WithCollectPeriod(time.Second), - controller.WithResource(testResource), - ) - - mock := controllertest.NewMockClock() - p.SetClock(mock) - - ctx := context.Background() - - meter := p.Meter("name") - counter1, err := meter.SyncInt64().Counter("counter1.sum") - require.NoError(t, err) - counter2, err := meter.SyncInt64().Counter("counter2.sum") - require.NoError(t, err) - - require.NoError(t, p.Start(ctx)) - runtime.Gosched() - - counter1.Add(ctx, 3, attribute.String("X", "Y")) - counter2.Add(ctx, 5) - - require.Equal(t, 0, exporter.ExportCount()) - require.Nil(t, testHandler.Flush()) - - mock.Add(time.Second) - runtime.Gosched() - - require.Equal(t, 1, exporter.ExportCount()) - if tt.expectedError == nil { - require.EqualValues(t, tt.expected, exporter.Values()) - require.NoError(t, testHandler.Flush()) - } else { - err := testHandler.Flush() - require.Error(t, err) - require.Equal(t, tt.expectedError, err) - } - - require.NoError(t, p.Stop(ctx)) - }) - } -} diff --git a/sdk/metric/controller/controllertest/controller_test.go b/sdk/metric/controller/controllertest/controller_test.go deleted file mode 100644 index 394d806238b..00000000000 --- a/sdk/metric/controller/controllertest/controller_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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 controllertest // import "go.opentelemetry.io/otel/sdk/metric/controller/controllertest" - -import ( - "context" - "sync" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/metric/global" - "go.opentelemetry.io/otel/metric/instrument" - controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" -) - -type errorCatcher struct { - lock sync.Mutex - errors []error -} - -func (e *errorCatcher) Handle(err error) { - e.lock.Lock() - defer e.lock.Unlock() - - e.errors = append(e.errors, err) -} - -func TestEndToEnd(t *testing.T) { - h := &errorCatcher{} - otel.SetErrorHandler(h) - - meter := global.Meter("go.opentelemetry.io/otel/sdk/metric/controller/controllertest_EndToEnd") - gauge, err := meter.AsyncInt64().Gauge("test") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{gauge}, func(context.Context) {}) - require.NoError(t, err) - - c := controller.New(basic.NewFactory(simple.NewWithInexpensiveDistribution(), aggregation.CumulativeTemporalitySelector())) - - global.SetMeterProvider(c) - - gauge, err = meter.AsyncInt64().Gauge("test2") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{gauge}, func(context.Context) {}) - require.NoError(t, err) - - h.lock.Lock() - require.Len(t, h.errors, 0) - -} diff --git a/sdk/metric/controller/controllertest/test.go b/sdk/metric/controller/controllertest/test.go deleted file mode 100644 index ed0bb88f1a3..00000000000 --- a/sdk/metric/controller/controllertest/test.go +++ /dev/null @@ -1,76 +0,0 @@ -// 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 controllertest // import "go.opentelemetry.io/otel/sdk/metric/controller/controllertest" - -import ( - "time" - - "github.com/benbjohnson/clock" - - "go.opentelemetry.io/otel/sdk/instrumentation" - controllerTime "go.opentelemetry.io/otel/sdk/metric/controller/time" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" -) - -type MockClock struct { - mock *clock.Mock -} - -type MockTicker struct { - ticker *clock.Ticker -} - -var _ controllerTime.Clock = MockClock{} -var _ controllerTime.Ticker = MockTicker{} - -func NewMockClock() MockClock { - return MockClock{clock.NewMock()} -} - -func (c MockClock) Now() time.Time { - return c.mock.Now() -} - -func (c MockClock) Ticker(period time.Duration) controllerTime.Ticker { - return MockTicker{c.mock.Ticker(period)} -} - -func (c MockClock) Add(d time.Duration) { - c.mock.Add(d) -} - -func (t MockTicker) Stop() { - t.ticker.Stop() -} - -func (t MockTicker) C() <-chan time.Time { - return t.ticker.C -} - -// ReadAll is a helper for tests that want a flat iterator over all -// metrics instead of a two-level iterator (instrumentation library, -// metric). -func ReadAll( - reader export.InstrumentationLibraryReader, - kind aggregation.TemporalitySelector, - apply func(instrumentation.Library, export.Record) error, -) error { - return reader.ForEach(func(library instrumentation.Library, reader export.Reader) error { - return reader.ForEach(kind, func(record export.Record) error { - return apply(library, record) - }) - }) -} diff --git a/sdk/metric/controller/time/time.go b/sdk/metric/controller/time/time.go deleted file mode 100644 index 08bc44dbf73..00000000000 --- a/sdk/metric/controller/time/time.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 time // import "go.opentelemetry.io/otel/sdk/metric/controller/time" - -import ( - "time" - lib "time" -) - -// Several types below are created to match "github.com/benbjohnson/clock" -// so that it remains a test-only dependency. - -type Clock interface { - Now() lib.Time - Ticker(duration lib.Duration) Ticker -} - -type Ticker interface { - Stop() - C() <-chan lib.Time -} - -type RealClock struct { -} - -type RealTicker struct { - ticker *lib.Ticker -} - -var _ Clock = RealClock{} -var _ Ticker = RealTicker{} - -func (RealClock) Now() time.Time { - return time.Now() -} - -func (RealClock) Ticker(period time.Duration) Ticker { - return RealTicker{time.NewTicker(period)} -} - -func (t RealTicker) Stop() { - t.ticker.Stop() -} - -func (t RealTicker) C() <-chan time.Time { - return t.ticker.C -} diff --git a/sdk/metric/correct_test.go b/sdk/metric/correct_test.go deleted file mode 100644 index 1b24a209c76..00000000000 --- a/sdk/metric/correct_test.go +++ /dev/null @@ -1,575 +0,0 @@ -// 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 metric_test - -import ( - "context" - "fmt" - "math" - "sync" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/metric/instrument/asyncint64" - "go.opentelemetry.io/otel/metric/nonrecording" - metricsdk "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type handler struct { - sync.Mutex - err error -} - -func (h *handler) Handle(err error) { - h.Lock() - h.err = err - h.Unlock() -} - -func (h *handler) Reset() { - h.Lock() - h.err = nil - h.Unlock() -} - -func (h *handler) Flush() error { - h.Lock() - err := h.err - h.err = nil - h.Unlock() - return err -} - -var testHandler *handler - -func init() { - testHandler = new(handler) - otel.SetErrorHandler(testHandler) -} - -type testSelector struct { - selector export.AggregatorSelector - newAggCount int -} - -func (ts *testSelector) AggregatorFor(desc *sdkapi.Descriptor, aggPtrs ...*aggregator.Aggregator) { - ts.newAggCount += len(aggPtrs) - processortest.AggregatorSelector().AggregatorFor(desc, aggPtrs...) -} - -func newSDK(t *testing.T) (metric.Meter, *metricsdk.Accumulator, *testSelector, *processortest.Processor) { - testHandler.Reset() - testSelector := &testSelector{selector: processortest.AggregatorSelector()} - processor := processortest.NewProcessor( - testSelector, - attribute.DefaultEncoder(), - ) - accum := metricsdk.NewAccumulator( - processor, - ) - meter := sdkapi.WrapMeterImpl(accum) - return meter, accum, testSelector, processor -} - -func TestInputRangeCounter(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - counter, err := meter.SyncInt64().Counter("name.sum") - require.NoError(t, err) - - counter.Add(ctx, -1) - require.Equal(t, aggregation.ErrNegativeInput, testHandler.Flush()) - - checkpointed := sdk.Collect(ctx) - require.Equal(t, 0, checkpointed) - - processor.Reset() - counter.Add(ctx, 1) - checkpointed = sdk.Collect(ctx) - require.Equal(t, map[string]float64{ - "name.sum//": 1, - }, processor.Values()) - require.Equal(t, 1, checkpointed) - require.Nil(t, testHandler.Flush()) -} - -func TestInputRangeUpDownCounter(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - counter, err := meter.SyncInt64().UpDownCounter("name.sum") - require.NoError(t, err) - - counter.Add(ctx, -1) - counter.Add(ctx, -1) - counter.Add(ctx, 2) - counter.Add(ctx, 1) - - checkpointed := sdk.Collect(ctx) - require.Equal(t, map[string]float64{ - "name.sum//": 1, - }, processor.Values()) - require.Equal(t, 1, checkpointed) - require.Nil(t, testHandler.Flush()) -} - -func TestInputRangeHistogram(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - histogram, err := meter.SyncFloat64().Histogram("name.histogram") - require.NoError(t, err) - - histogram.Record(ctx, math.NaN()) - require.Equal(t, aggregation.ErrNaNInput, testHandler.Flush()) - - checkpointed := sdk.Collect(ctx) - require.Equal(t, 0, checkpointed) - - histogram.Record(ctx, 1) - histogram.Record(ctx, 2) - - processor.Reset() - checkpointed = sdk.Collect(ctx) - - require.Equal(t, map[string]float64{ - "name.histogram//": 3, - }, processor.Values()) - require.Equal(t, 1, checkpointed) - require.Nil(t, testHandler.Flush()) -} - -func TestDisabledInstrument(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - histogram, err := meter.SyncFloat64().Histogram("name.disabled") - require.NoError(t, err) - - histogram.Record(ctx, -1) - checkpointed := sdk.Collect(ctx) - - require.Equal(t, 0, checkpointed) - require.Equal(t, map[string]float64{}, processor.Values()) -} - -func TestRecordNaN(t *testing.T) { - ctx := context.Background() - meter, _, _, _ := newSDK(t) - - c, err := meter.SyncFloat64().Counter("name.sum") - require.NoError(t, err) - - require.Nil(t, testHandler.Flush()) - c.Add(ctx, math.NaN()) - require.Error(t, testHandler.Flush()) -} - -func TestSDKLabelsDeduplication(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - counter, err := meter.SyncInt64().Counter("name.sum") - require.NoError(t, err) - - const ( - maxKeys = 21 - keySets = 2 - repeats = 3 - ) - var keysA []attribute.Key - var keysB []attribute.Key - - for i := 0; i < maxKeys; i++ { - keysA = append(keysA, attribute.Key(fmt.Sprintf("A%03d", i))) - keysB = append(keysB, attribute.Key(fmt.Sprintf("B%03d", i))) - } - - allExpect := map[string]float64{} - for numKeys := 0; numKeys < maxKeys; numKeys++ { - - var kvsA []attribute.KeyValue - var kvsB []attribute.KeyValue - for r := 0; r < repeats; r++ { - for i := 0; i < numKeys; i++ { - kvsA = append(kvsA, keysA[i].Int(r)) - kvsB = append(kvsB, keysB[i].Int(r)) - } - } - - var expectA []attribute.KeyValue - var expectB []attribute.KeyValue - for i := 0; i < numKeys; i++ { - expectA = append(expectA, keysA[i].Int(repeats-1)) - expectB = append(expectB, keysB[i].Int(repeats-1)) - } - - counter.Add(ctx, 1, kvsA...) - counter.Add(ctx, 1, kvsA...) - format := func(attrs []attribute.KeyValue) string { - str := attribute.DefaultEncoder().Encode(newSetIter(attrs...)) - return fmt.Sprint("name.sum/", str, "/") - } - allExpect[format(expectA)] += 2 - - if numKeys != 0 { - // In this case A and B sets are the same. - counter.Add(ctx, 1, kvsB...) - counter.Add(ctx, 1, kvsB...) - allExpect[format(expectB)] += 2 - } - - } - - sdk.Collect(ctx) - - require.EqualValues(t, allExpect, processor.Values()) -} - -func newSetIter(kvs ...attribute.KeyValue) attribute.Iterator { - labels := attribute.NewSet(kvs...) - return labels.Iter() -} - -func TestDefaultLabelEncoder(t *testing.T) { - encoder := attribute.DefaultEncoder() - - encoded := encoder.Encode(newSetIter(attribute.String("A", "B"), attribute.String("C", "D"))) - require.Equal(t, `A=B,C=D`, encoded) - - encoded = encoder.Encode(newSetIter(attribute.String("A", "B,c=d"), attribute.String(`C\`, "D"))) - require.Equal(t, `A=B\,c\=d,C\\=D`, encoded) - - encoded = encoder.Encode(newSetIter(attribute.String(`\`, `=`), attribute.String(`,`, `\`))) - require.Equal(t, `\,=\\,\\=\=`, encoded) - - // Note: the label encoder does not sort or de-dup values, - // that is done in Labels(...). - encoded = encoder.Encode(newSetIter( - attribute.Int("I", 1), - attribute.Int64("I64", 1), - attribute.Float64("F64", 1), - attribute.Float64("F64", 1), - attribute.String("S", "1"), - attribute.Bool("B", true), - )) - require.Equal(t, "B=true,F64=1,I=1,I64=1,S=1", encoded) -} - -func TestObserverCollection(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - mult := 1 - - gaugeF, err := meter.AsyncFloat64().Gauge("float.gauge.lastvalue") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ - gaugeF, - }, func(ctx context.Context) { - gaugeF.Observe(ctx, float64(mult), attribute.String("A", "B")) - // last value wins - gaugeF.Observe(ctx, float64(-mult), attribute.String("A", "B")) - gaugeF.Observe(ctx, float64(-mult), attribute.String("C", "D")) - }) - require.NoError(t, err) - - gaugeI, err := meter.AsyncInt64().Gauge("int.gauge.lastvalue") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ - gaugeI, - }, func(ctx context.Context) { - gaugeI.Observe(ctx, int64(-mult), attribute.String("A", "B")) - gaugeI.Observe(ctx, int64(mult)) - // last value wins - gaugeI.Observe(ctx, int64(mult), attribute.String("A", "B")) - gaugeI.Observe(ctx, int64(mult)) - }) - require.NoError(t, err) - - counterF, err := meter.AsyncFloat64().Counter("float.counterobserver.sum") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ - counterF, - }, func(ctx context.Context) { - counterF.Observe(ctx, float64(mult), attribute.String("A", "B")) - counterF.Observe(ctx, float64(2*mult), attribute.String("A", "B")) - counterF.Observe(ctx, float64(mult), attribute.String("C", "D")) - }) - require.NoError(t, err) - - counterI, err := meter.AsyncInt64().Counter("int.counterobserver.sum") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ - counterI, - }, func(ctx context.Context) { - counterI.Observe(ctx, int64(2*mult), attribute.String("A", "B")) - counterI.Observe(ctx, int64(mult)) - // last value wins - counterI.Observe(ctx, int64(mult), attribute.String("A", "B")) - counterI.Observe(ctx, int64(mult)) - }) - require.NoError(t, err) - - updowncounterF, err := meter.AsyncFloat64().UpDownCounter("float.updowncounterobserver.sum") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ - updowncounterF, - }, func(ctx context.Context) { - updowncounterF.Observe(ctx, float64(mult), attribute.String("A", "B")) - updowncounterF.Observe(ctx, float64(-2*mult), attribute.String("A", "B")) - updowncounterF.Observe(ctx, float64(mult), attribute.String("C", "D")) - }) - require.NoError(t, err) - - updowncounterI, err := meter.AsyncInt64().UpDownCounter("int.updowncounterobserver.sum") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ - updowncounterI, - }, func(ctx context.Context) { - updowncounterI.Observe(ctx, int64(2*mult), attribute.String("A", "B")) - updowncounterI.Observe(ctx, int64(mult)) - // last value wins - updowncounterI.Observe(ctx, int64(mult), attribute.String("A", "B")) - updowncounterI.Observe(ctx, int64(-mult)) - }) - require.NoError(t, err) - - unused, err := meter.AsyncInt64().Gauge("empty.gauge.sum") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ - unused, - }, func(ctx context.Context) { - }) - require.NoError(t, err) - - for mult = 0; mult < 3; mult++ { - processor.Reset() - - collected := sdk.Collect(ctx) - require.Equal(t, collected, len(processor.Values())) - - mult := float64(mult) - require.EqualValues(t, map[string]float64{ - "float.gauge.lastvalue/A=B/": -mult, - "float.gauge.lastvalue/C=D/": -mult, - "int.gauge.lastvalue//": mult, - "int.gauge.lastvalue/A=B/": mult, - - "float.counterobserver.sum/A=B/": 3 * mult, - "float.counterobserver.sum/C=D/": mult, - "int.counterobserver.sum//": 2 * mult, - "int.counterobserver.sum/A=B/": 3 * mult, - - "float.updowncounterobserver.sum/A=B/": -mult, - "float.updowncounterobserver.sum/C=D/": mult, - "int.updowncounterobserver.sum//": 0, - "int.updowncounterobserver.sum/A=B/": 3 * mult, - }, processor.Values()) - } -} - -func TestCounterObserverInputRange(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - // TODO: these tests are testing for negative values, not for _descending values_. Fix. - counterF, _ := meter.AsyncFloat64().Counter("float.counterobserver.sum") - err := meter.RegisterCallback([]instrument.Asynchronous{ - counterF, - }, func(ctx context.Context) { - counterF.Observe(ctx, -2, attribute.String("A", "B")) - require.Equal(t, aggregation.ErrNegativeInput, testHandler.Flush()) - counterF.Observe(ctx, -1, attribute.String("C", "D")) - require.Equal(t, aggregation.ErrNegativeInput, testHandler.Flush()) - }) - require.NoError(t, err) - counterI, _ := meter.AsyncInt64().Counter("int.counterobserver.sum") - err = meter.RegisterCallback([]instrument.Asynchronous{ - counterI, - }, func(ctx context.Context) { - counterI.Observe(ctx, -1, attribute.String("A", "B")) - require.Equal(t, aggregation.ErrNegativeInput, testHandler.Flush()) - counterI.Observe(ctx, -1) - require.Equal(t, aggregation.ErrNegativeInput, testHandler.Flush()) - }) - require.NoError(t, err) - - collected := sdk.Collect(ctx) - - require.Equal(t, 0, collected) - require.EqualValues(t, map[string]float64{}, processor.Values()) - - // check that the error condition was reset - require.NoError(t, testHandler.Flush()) -} - -func TestObserverBatch(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - floatGaugeObs, _ := meter.AsyncFloat64().Gauge("float.gauge.lastvalue") - intGaugeObs, _ := meter.AsyncInt64().Gauge("int.gauge.lastvalue") - floatCounterObs, _ := meter.AsyncFloat64().Counter("float.counterobserver.sum") - intCounterObs, _ := meter.AsyncInt64().Counter("int.counterobserver.sum") - floatUpDownCounterObs, _ := meter.AsyncFloat64().UpDownCounter("float.updowncounterobserver.sum") - intUpDownCounterObs, _ := meter.AsyncInt64().UpDownCounter("int.updowncounterobserver.sum") - - err := meter.RegisterCallback([]instrument.Asynchronous{ - floatGaugeObs, - intGaugeObs, - floatCounterObs, - intCounterObs, - floatUpDownCounterObs, - intUpDownCounterObs, - }, func(ctx context.Context) { - ab := attribute.String("A", "B") - floatGaugeObs.Observe(ctx, 1, ab) - floatGaugeObs.Observe(ctx, -1, ab) - intGaugeObs.Observe(ctx, -1, ab) - intGaugeObs.Observe(ctx, 1, ab) - floatCounterObs.Observe(ctx, 1000, ab) - intCounterObs.Observe(ctx, 100, ab) - floatUpDownCounterObs.Observe(ctx, -1000, ab) - intUpDownCounterObs.Observe(ctx, -100, ab) - - cd := attribute.String("C", "D") - floatGaugeObs.Observe(ctx, -1, cd) - floatCounterObs.Observe(ctx, -1, cd) - floatUpDownCounterObs.Observe(ctx, -1, cd) - - intGaugeObs.Observe(ctx, 1) - intGaugeObs.Observe(ctx, 1) - intCounterObs.Observe(ctx, 10) - floatCounterObs.Observe(ctx, 1.1) - intUpDownCounterObs.Observe(ctx, 10) - }) - require.NoError(t, err) - - collected := sdk.Collect(ctx) - - require.Equal(t, collected, len(processor.Values())) - - require.EqualValues(t, map[string]float64{ - "float.counterobserver.sum//": 1.1, - "float.counterobserver.sum/A=B/": 1000, - "int.counterobserver.sum//": 10, - "int.counterobserver.sum/A=B/": 100, - - "int.updowncounterobserver.sum/A=B/": -100, - "float.updowncounterobserver.sum/A=B/": -1000, - "int.updowncounterobserver.sum//": 10, - "float.updowncounterobserver.sum/C=D/": -1, - - "float.gauge.lastvalue/A=B/": -1, - "float.gauge.lastvalue/C=D/": -1, - "int.gauge.lastvalue//": 1, - "int.gauge.lastvalue/A=B/": 1, - }, processor.Values()) -} - -// TestRecordPersistence ensures that a direct-called instrument that -// is repeatedly used each interval results in a persistent record, so -// that its encoded labels will be cached across collection intervals. -func TestRecordPersistence(t *testing.T) { - ctx := context.Background() - meter, sdk, selector, _ := newSDK(t) - - c, err := meter.SyncFloat64().Counter("name.sum") - require.NoError(t, err) - - uk := attribute.String("bound", "false") - - for i := 0; i < 100; i++ { - c.Add(ctx, 1, uk) - sdk.Collect(ctx) - } - - require.Equal(t, 2, selector.newAggCount) -} - -func TestIncorrectInstruments(t *testing.T) { - // The Batch observe/record APIs are susceptible to - // uninitialized instruments. - var observer asyncint64.Gauge - - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - // Now try with uninitialized instruments. - err := meter.RegisterCallback([]instrument.Asynchronous{ - observer, - }, func(ctx context.Context) { - observer.Observe(ctx, 1) - }) - require.ErrorIs(t, err, metricsdk.ErrBadInstrument) - - collected := sdk.Collect(ctx) - err = testHandler.Flush() - require.NoError(t, err) - require.Equal(t, 0, collected) - - // Now try with instruments from another SDK. - noopMeter := nonrecording.NewNoopMeter() - observer, _ = noopMeter.AsyncInt64().Gauge("observer") - - err = meter.RegisterCallback( - []instrument.Asynchronous{observer}, - func(ctx context.Context) { - observer.Observe(ctx, 1) - }, - ) - require.ErrorIs(t, err, metricsdk.ErrBadInstrument) - - collected = sdk.Collect(ctx) - require.Equal(t, 0, collected) - require.EqualValues(t, map[string]float64{}, processor.Values()) - - err = testHandler.Flush() - require.NoError(t, err) -} - -func TestSyncInAsync(t *testing.T) { - ctx := context.Background() - meter, sdk, _, processor := newSDK(t) - - counter, _ := meter.SyncFloat64().Counter("counter.sum") - gauge, _ := meter.AsyncInt64().Gauge("observer.lastvalue") - - err := meter.RegisterCallback([]instrument.Asynchronous{ - gauge, - }, func(ctx context.Context) { - gauge.Observe(ctx, 10) - counter.Add(ctx, 100) - }) - require.NoError(t, err) - - sdk.Collect(ctx) - - require.EqualValues(t, map[string]float64{ - "counter.sum//": 100, - "observer.lastvalue//": 10, - }, processor.Values()) -} diff --git a/sdk/metric/doc.go b/sdk/metric/doc.go deleted file mode 100644 index e3270211be1..00000000000 --- a/sdk/metric/doc.go +++ /dev/null @@ -1,139 +0,0 @@ -// 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 metric implements the OpenTelemetry metric API. - -This package is currently in a pre-GA phase. Backwards incompatible changes -may be introduced in subsequent minor version releases as we work to track the -evolving OpenTelemetry specification and user feedback. - -The Accumulator type supports configurable metrics export behavior through a -collection of export interfaces that support various export strategies, -described below. - -The OpenTelemetry metric API consists of methods for constructing synchronous -and asynchronous instruments. There are two constructors per instrument for -the two kinds of number (int64, float64). - -Synchronous instruments are managed by a sync.Map containing a *record -with the current state for each synchronous instrument. A lock-free -algorithm is used to protect against races when adding and removing -items from the sync.Map. - -Asynchronous instruments are managed by an internal -AsyncInstrumentState, which coordinates calling batch and single -instrument callbacks. - -Internal Structure - -Each observer also has its own kind of record stored in the SDK. This -record contains a set of recorders for every specific label set used in the -callback. - -A sync.Map maintains the mapping of current instruments and label sets to -internal records. To find a record, the SDK consults the Map to -locate an existing record, otherwise it constructs a new record. The SDK -maintains a count of the number of references to each record, ensuring -that records are not reclaimed from the Map while they are still active -from the user's perspective. - -Metric collection is performed via a single-threaded call to Collect that -sweeps through all records in the SDK, checkpointing their state. When a -record is discovered that has no references and has not been updated since -the prior collection pass, it is removed from the Map. - -Both synchronous and asynchronous instruments have an associated -aggregator, which maintains the current state resulting from all metric -events since its last checkpoint. Aggregators may be lock-free or they may -use locking, but they should expect to be called concurrently. Aggregators -must be capable of merging with another aggregator of the same type. - -Export Pipeline - -While the SDK serves to maintain a current set of records and -coordinate collection, the behavior of a metrics export pipeline is -configured through the export types in -go.opentelemetry.io/otel/sdk/metric/export. It is important to keep -in mind the context these interfaces are called from. There are two -contexts, instrumentation context, where a user-level goroutine that -enters the SDK resulting in a new record, and collection context, -where a system-level thread performs a collection pass through the -SDK. - -Descriptor is a struct that describes the metric instrument to the -export pipeline, containing the name, units, description, metric kind, -number kind (int64 or float64). A Descriptor accompanies metric data -as it passes through the export pipeline. - -The AggregatorSelector interface supports choosing the method of -aggregation to apply to a particular instrument, by delegating the -construction of an Aggregator to this interface. Given the Descriptor, -the AggregatorFor method returns an implementation of Aggregator. If this -interface returns nil, the metric will be disabled. The aggregator should -be matched to the capabilities of the exporter. Selecting the aggregator -for Adding instruments is relatively straightforward, but many options -are available for aggregating distributions from Grouping instruments. - -Aggregator is an interface which implements a concrete strategy for -aggregating metric updates. Several Aggregator implementations are -provided by the SDK. Aggregators may be lock-free or use locking, -depending on their structure and semantics. Aggregators implement an -Update method, called in instrumentation context, to receive a single -metric event. Aggregators implement a Checkpoint method, called in -collection context, to save a checkpoint of the current state. -Aggregators implement a Merge method, also called in collection -context, that combines state from two aggregators into one. Each SDK -record has an associated aggregator. - -Processor is an interface which sits between the SDK and an exporter. -The Processor embeds an AggregatorSelector, used by the SDK to assign -new Aggregators. The Processor supports a Process() API for submitting -checkpointed aggregators to the processor, and a Reader() API -for producing a complete checkpoint for the exporter. Two default -Processor implementations are provided, the "defaultkeys" Processor groups -aggregate metrics by their recommended Descriptor.Keys(), the -"simple" Processor aggregates metrics at full dimensionality. - -LabelEncoder is an optional optimization that allows an exporter to -provide the serialization logic for labels. This allows avoiding -duplicate serialization of labels, once as a unique key in the SDK (or -Processor) and once in the exporter. - -Reader is an interface between the Processor and the Exporter. -After completing a collection pass, the Processor.Reader() method -returns a Reader, which the Exporter uses to iterate over all -the updated metrics. - -Record is a struct containing the state of an individual exported -metric. This is the result of one collection interface for one -instrument and one label set. - -Labels is a struct containing an ordered set of labels, the -corresponding unique encoding, and the encoder that produced it. - -Exporter is the final stage of an export pipeline. It is called with -a Reader capable of enumerating all the updated metrics. - -Controller is not an export interface per se, but it orchestrates the -export pipeline. For example, a "push" controller will establish a -periodic timer to regularly collect and export metrics. A "pull" -controller will await a pull request before initiating metric -collection. Either way, the job of the controller is to call the SDK -Collect() method, then read the checkpoint, then invoke the exporter. -Controllers are expected to implement the public metric.MeterProvider -API, meaning they can be installed as the global Meter provider. - -*/ -package metric // import "go.opentelemetry.io/otel/sdk/metric" diff --git a/sdk/metric/export/aggregation/aggregation.go b/sdk/metric/export/aggregation/aggregation.go deleted file mode 100644 index ea09fa68344..00000000000 --- a/sdk/metric/export/aggregation/aggregation.go +++ /dev/null @@ -1,119 +0,0 @@ -// 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 aggregation // import "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - -import ( - "fmt" - "time" - - "go.opentelemetry.io/otel/sdk/metric/number" -) - -// These interfaces describe the various ways to access state from an -// Aggregation. - -type ( - // Aggregation is an interface returned by the Aggregator - // containing an interval of metric data. - Aggregation interface { - // Kind returns a short identifying string to identify - // the Aggregator that was used to produce the - // Aggregation (e.g., "Sum"). - Kind() Kind - } - - // Sum returns an aggregated sum. - Sum interface { - Aggregation - Sum() (number.Number, error) - } - - // Count returns the number of values that were aggregated. - Count interface { - Aggregation - Count() (uint64, error) - } - - // LastValue returns the latest value that was aggregated. - LastValue interface { - Aggregation - LastValue() (number.Number, time.Time, error) - } - - // Buckets represents histogram buckets boundaries and counts. - // - // For a Histogram with N defined boundaries, e.g, [x, y, z]. - // There are N+1 counts: [-inf, x), [x, y), [y, z), [z, +inf] - Buckets struct { - // Boundaries are floating point numbers, even when - // aggregating integers. - Boundaries []float64 - - // Counts holds the count in each bucket. - Counts []uint64 - } - - // Histogram returns the count of events in pre-determined buckets. - Histogram interface { - Aggregation - Count() (uint64, error) - Sum() (number.Number, error) - Histogram() (Buckets, error) - } -) - -type ( - // Kind is a short name for the Aggregator that produces an - // Aggregation, used for descriptive purpose only. Kind is a - // string to allow user-defined Aggregators. - // - // When deciding how to handle an Aggregation, Exporters are - // encouraged to decide based on conversion to the above - // interfaces based on strength, not on Kind value, when - // deciding how to expose metric data. This enables - // user-supplied Aggregators to replace builtin Aggregators. - // - // For example, test for a Histogram before testing for a - // Sum, and so on. - Kind string -) - -// Kind description constants. -const ( - SumKind Kind = "Sum" - HistogramKind Kind = "Histogram" - LastValueKind Kind = "Lastvalue" -) - -// Sentinel errors for Aggregation interface. -var ( - ErrNegativeInput = fmt.Errorf("negative value is out of range for this instrument") - ErrNaNInput = fmt.Errorf("NaN value is an invalid input") - ErrInconsistentType = fmt.Errorf("inconsistent aggregator types") - - // ErrNoCumulativeToDelta is returned when requesting delta - // export kind for a precomputed sum instrument. - ErrNoCumulativeToDelta = fmt.Errorf("cumulative to delta not implemented") - - // ErrNoData is returned when (due to a race with collection) - // the Aggregator is check-pointed before the first value is set. - // The aggregator should simply be skipped in this case. - ErrNoData = fmt.Errorf("no data collected by this aggregator") -) - -// String returns the string value of Kind. -func (k Kind) String() string { - return string(k) -} diff --git a/sdk/metric/export/aggregation/temporality.go b/sdk/metric/export/aggregation/temporality.go deleted file mode 100644 index 0612fe06af0..00000000000 --- a/sdk/metric/export/aggregation/temporality.go +++ /dev/null @@ -1,117 +0,0 @@ -// 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. - -//go:generate stringer -type=Temporality - -package aggregation // import "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - -import ( - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -// Temporality indicates the temporal aggregation exported by an exporter. -// These bits may be OR-d together when multiple exporters are in use. -type Temporality uint8 - -const ( - // CumulativeTemporality indicates that an Exporter expects a - // Cumulative Aggregation. - CumulativeTemporality Temporality = 1 - - // DeltaTemporality indicates that an Exporter expects a - // Delta Aggregation. - DeltaTemporality Temporality = 2 -) - -// Includes returns if t includes support for other temporality. -func (t Temporality) Includes(other Temporality) bool { - return t&other != 0 -} - -// MemoryRequired returns whether an exporter of this temporality requires -// memory to export correctly. -func (t Temporality) MemoryRequired(mkind sdkapi.InstrumentKind) bool { - switch mkind { - case sdkapi.HistogramInstrumentKind, sdkapi.GaugeObserverInstrumentKind, - sdkapi.CounterInstrumentKind, sdkapi.UpDownCounterInstrumentKind: - // Delta-oriented instruments: - return t.Includes(CumulativeTemporality) - - case sdkapi.CounterObserverInstrumentKind, sdkapi.UpDownCounterObserverInstrumentKind: - // Cumulative-oriented instruments: - return t.Includes(DeltaTemporality) - } - // Something unexpected is happening--we could panic. This - // will become an error when the exporter tries to access a - // checkpoint, presumably, so let it be. - return false -} - -type ( - constantTemporalitySelector Temporality - statelessTemporalitySelector struct{} -) - -var ( - _ TemporalitySelector = constantTemporalitySelector(0) - _ TemporalitySelector = statelessTemporalitySelector{} -) - -// ConstantTemporalitySelector returns an TemporalitySelector that returns -// a constant Temporality. -func ConstantTemporalitySelector(t Temporality) TemporalitySelector { - return constantTemporalitySelector(t) -} - -// CumulativeTemporalitySelector returns an TemporalitySelector that -// always returns CumulativeTemporality. -func CumulativeTemporalitySelector() TemporalitySelector { - return ConstantTemporalitySelector(CumulativeTemporality) -} - -// DeltaTemporalitySelector returns an TemporalitySelector that -// always returns DeltaTemporality. -func DeltaTemporalitySelector() TemporalitySelector { - return ConstantTemporalitySelector(DeltaTemporality) -} - -// StatelessTemporalitySelector returns an TemporalitySelector that -// always returns the Temporality that avoids long-term memory -// requirements. -func StatelessTemporalitySelector() TemporalitySelector { - return statelessTemporalitySelector{} -} - -// TemporalityFor implements TemporalitySelector. -func (c constantTemporalitySelector) TemporalityFor(_ *sdkapi.Descriptor, _ Kind) Temporality { - return Temporality(c) -} - -// TemporalityFor implements TemporalitySelector. -func (s statelessTemporalitySelector) TemporalityFor(desc *sdkapi.Descriptor, kind Kind) Temporality { - if kind == SumKind && desc.InstrumentKind().PrecomputedSum() { - return CumulativeTemporality - } - return DeltaTemporality -} - -// TemporalitySelector is a sub-interface of Exporter used to indicate -// whether the Processor should compute Delta or Cumulative -// Aggregations. -type TemporalitySelector interface { - // TemporalityFor should return the correct Temporality that - // should be used when exporting data for the given metric - // instrument and Aggregator kind. - TemporalityFor(descriptor *sdkapi.Descriptor, aggregationKind Kind) Temporality -} diff --git a/sdk/metric/export/aggregation/temporality_string.go b/sdk/metric/export/aggregation/temporality_string.go deleted file mode 100644 index 3edbeb4592d..00000000000 --- a/sdk/metric/export/aggregation/temporality_string.go +++ /dev/null @@ -1,25 +0,0 @@ -// Code generated by "stringer -type=Temporality"; DO NOT EDIT. - -package aggregation - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[CumulativeTemporality-1] - _ = x[DeltaTemporality-2] -} - -const _Temporality_name = "CumulativeTemporalityDeltaTemporality" - -var _Temporality_index = [...]uint8{0, 21, 37} - -func (i Temporality) String() string { - i -= 1 - if i >= Temporality(len(_Temporality_index)-1) { - return "Temporality(" + strconv.FormatInt(int64(i+1), 10) + ")" - } - return _Temporality_name[_Temporality_index[i]:_Temporality_index[i+1]] -} diff --git a/sdk/metric/export/aggregation/temporality_test.go b/sdk/metric/export/aggregation/temporality_test.go deleted file mode 100644 index 69b976da773..00000000000 --- a/sdk/metric/export/aggregation/temporality_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// 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 aggregation - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -func TestTemporalityIncludes(t *testing.T) { - require.True(t, CumulativeTemporality.Includes(CumulativeTemporality)) - require.True(t, DeltaTemporality.Includes(CumulativeTemporality|DeltaTemporality)) -} - -var deltaMemoryTemporalties = []sdkapi.InstrumentKind{ - sdkapi.CounterObserverInstrumentKind, - sdkapi.UpDownCounterObserverInstrumentKind, -} - -var cumulativeMemoryTemporalties = []sdkapi.InstrumentKind{ - sdkapi.HistogramInstrumentKind, - sdkapi.GaugeObserverInstrumentKind, - sdkapi.CounterInstrumentKind, - sdkapi.UpDownCounterInstrumentKind, -} - -func TestTemporalityMemoryRequired(t *testing.T) { - for _, kind := range deltaMemoryTemporalties { - require.True(t, DeltaTemporality.MemoryRequired(kind)) - require.False(t, CumulativeTemporality.MemoryRequired(kind)) - } - - for _, kind := range cumulativeMemoryTemporalties { - require.True(t, CumulativeTemporality.MemoryRequired(kind)) - require.False(t, DeltaTemporality.MemoryRequired(kind)) - } -} - -func TestTemporalitySelectors(t *testing.T) { - cAggTemp := CumulativeTemporalitySelector() - dAggTemp := DeltaTemporalitySelector() - sAggTemp := StatelessTemporalitySelector() - - for _, ikind := range append(deltaMemoryTemporalties, cumulativeMemoryTemporalties...) { - desc := metrictest.NewDescriptor("instrument", ikind, number.Int64Kind) - - var akind Kind - if ikind.Adding() { - akind = SumKind - } else { - akind = HistogramKind - } - require.Equal(t, CumulativeTemporality, cAggTemp.TemporalityFor(&desc, akind)) - require.Equal(t, DeltaTemporality, dAggTemp.TemporalityFor(&desc, akind)) - require.False(t, sAggTemp.TemporalityFor(&desc, akind).MemoryRequired(ikind)) - } -} diff --git a/sdk/metric/export/metric.go b/sdk/metric/export/metric.go deleted file mode 100644 index 7937995e5cc..00000000000 --- a/sdk/metric/export/metric.go +++ /dev/null @@ -1,281 +0,0 @@ -// 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 export // import "go.opentelemetry.io/otel/sdk/metric/export" - -import ( - "context" - "sync" - "time" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -// Processor is responsible for deciding which kind of aggregation to -// use (via AggregatorSelector), gathering exported results from the -// SDK during collection, and deciding over which dimensions to group -// the exported data. -// -// The SDK supports binding only one of these interfaces, as it has -// the sole responsibility of determining which Aggregator to use for -// each record. -// -// The embedded AggregatorSelector interface is called (concurrently) -// in instrumentation context to select the appropriate Aggregator for -// an instrument. -// -// The `Process` method is called during collection in a -// single-threaded context from the SDK, after the aggregator is -// checkpointed, allowing the processor to build the set of metrics -// currently being exported. -type Processor interface { - // AggregatorSelector is responsible for selecting the - // concrete type of Aggregator used for a metric in the SDK. - // - // This may be a static decision based on fields of the - // Descriptor, or it could use an external configuration - // source to customize the treatment of each metric - // instrument. - // - // The result from AggregatorSelector.AggregatorFor should be - // the same type for a given Descriptor or else nil. The same - // type should be returned for a given descriptor, because - // Aggregators only know how to Merge with their own type. If - // the result is nil, the metric instrument will be disabled. - // - // Note that the SDK only calls AggregatorFor when new records - // require an Aggregator. This does not provide a way to - // disable metrics with active records. - AggregatorSelector - - // Process is called by the SDK once per internal record, - // passing the export Accumulation (a Descriptor, the corresponding - // Labels, and the checkpointed Aggregator). This call has no - // Context argument because it is expected to perform only - // computation. An SDK is not expected to call exporters from - // with Process, use a controller for that (see - // ./controllers/{pull,push}. - Process(accum Accumulation) error -} - -// AggregatorSelector supports selecting the kind of Aggregator to -// use at runtime for a specific metric instrument. -type AggregatorSelector interface { - // AggregatorFor allocates a variable number of aggregators of - // a kind suitable for the requested export. This method - // initializes a `...*Aggregator`, to support making a single - // allocation. - // - // When the call returns without initializing the *Aggregator - // to a non-nil value, the metric instrument is explicitly - // disabled. - // - // This must return a consistent type to avoid confusion in - // later stages of the metrics export process, i.e., when - // Merging or Checkpointing aggregators for a specific - // instrument. - // - // Note: This is context-free because the aggregator should - // not relate to the incoming context. This call should not - // block. - AggregatorFor(descriptor *sdkapi.Descriptor, aggregator ...*aggregator.Aggregator) -} - -// Checkpointer is the interface used by a Controller to coordinate -// the Processor with Accumulator(s) and Exporter(s). The -// StartCollection() and FinishCollection() methods start and finish a -// collection interval. Controllers call the Accumulator(s) during -// collection to process Accumulations. -type Checkpointer interface { - // Processor processes metric data for export. The Process - // method is bracketed by StartCollection and FinishCollection - // calls. The embedded AggregatorSelector can be called at - // any time. - Processor - - // Reader returns the current data set. This may be - // called before and after collection. The - // implementation is required to return the same value - // throughout its lifetime, since Reader exposes a - // sync.Locker interface. The caller is responsible for - // locking the Reader before initiating collection. - Reader() Reader - - // StartCollection begins a collection interval. - StartCollection() - - // FinishCollection ends a collection interval. - FinishCollection() error -} - -// CheckpointerFactory is an interface for producing configured -// Checkpointer instances. -type CheckpointerFactory interface { - NewCheckpointer() Checkpointer -} - -// Exporter handles presentation of the checkpoint of aggregate -// metrics. This is the final stage of a metrics export pipeline, -// where metric data are formatted for a specific system. -type Exporter interface { - // Export is called immediately after completing a collection - // pass in the SDK. - // - // The Context comes from the controller that initiated - // collection. - // - // The InstrumentationLibraryReader interface refers to the - // Processor that just completed collection. - Export(ctx context.Context, resource *resource.Resource, reader InstrumentationLibraryReader) error - - // TemporalitySelector is an interface used by the Processor - // in deciding whether to compute Delta or Cumulative - // Aggregations when passing Records to this Exporter. - aggregation.TemporalitySelector -} - -// InstrumentationLibraryReader is an interface for exporters to iterate -// over one instrumentation library of metric data at a time. -type InstrumentationLibraryReader interface { - // ForEach calls the passed function once per instrumentation library, - // allowing the caller to emit metrics grouped by the library that - // produced them. - ForEach(readerFunc func(instrumentation.Library, Reader) error) error -} - -// Reader allows a controller to access a complete checkpoint of -// aggregated metrics from the Processor for a single library of -// metric data. This is passed to the Exporter which may then use -// ForEach to iterate over the collection of aggregated metrics. -type Reader interface { - // ForEach iterates over aggregated checkpoints for all - // metrics that were updated during the last collection - // period. Each aggregated checkpoint returned by the - // function parameter may return an error. - // - // The TemporalitySelector argument is used to determine - // whether the Record is computed using Delta or Cumulative - // aggregation. - // - // ForEach tolerates ErrNoData silently, as this is - // expected from the Meter implementation. Any other kind - // of error will immediately halt ForEach and return - // the error to the caller. - ForEach(tempSelector aggregation.TemporalitySelector, recordFunc func(Record) error) error - - // Locker supports locking the checkpoint set. Collection - // into the checkpoint set cannot take place (in case of a - // stateful processor) while it is locked. - // - // The Processor attached to the Accumulator MUST be called - // with the lock held. - sync.Locker - - // RLock acquires a read lock corresponding to this Locker. - RLock() - // RUnlock releases a read lock corresponding to this Locker. - RUnlock() -} - -// Metadata contains the common elements for exported metric data that -// are shared by the Accumulator->Processor and Processor->Exporter -// steps. -type Metadata struct { - descriptor *sdkapi.Descriptor - labels *attribute.Set -} - -// Accumulation contains the exported data for a single metric instrument -// and label set, as prepared by an Accumulator for the Processor. -type Accumulation struct { - Metadata - aggregator aggregator.Aggregator -} - -// Record contains the exported data for a single metric instrument -// and label set, as prepared by the Processor for the Exporter. -// This includes the effective start and end time for the aggregation. -type Record struct { - Metadata - aggregation aggregation.Aggregation - start time.Time - end time.Time -} - -// Descriptor describes the metric instrument being exported. -func (m Metadata) Descriptor() *sdkapi.Descriptor { - return m.descriptor -} - -// Labels describes the labels associated with the instrument and the -// aggregated data. -func (m Metadata) Labels() *attribute.Set { - return m.labels -} - -// NewAccumulation allows Accumulator implementations to construct new -// Accumulations to send to Processors. The Descriptor, Labels, -// and Aggregator represent aggregate metric events received over a single -// collection period. -func NewAccumulation(descriptor *sdkapi.Descriptor, labels *attribute.Set, aggregator aggregator.Aggregator) Accumulation { - return Accumulation{ - Metadata: Metadata{ - descriptor: descriptor, - labels: labels, - }, - aggregator: aggregator, - } -} - -// Aggregator returns the checkpointed aggregator. It is safe to -// access the checkpointed state without locking. -func (r Accumulation) Aggregator() aggregator.Aggregator { - return r.aggregator -} - -// NewRecord allows Processor implementations to construct export -// records. The Descriptor, Labels, and Aggregator represent -// aggregate metric events received over a single collection period. -func NewRecord(descriptor *sdkapi.Descriptor, labels *attribute.Set, aggregation aggregation.Aggregation, start, end time.Time) Record { - return Record{ - Metadata: Metadata{ - descriptor: descriptor, - labels: labels, - }, - aggregation: aggregation, - start: start, - end: end, - } -} - -// Aggregation returns the aggregation, an interface to the record and -// its aggregator, dependent on the kind of both the input and exporter. -func (r Record) Aggregation() aggregation.Aggregation { - return r.aggregation -} - -// StartTime is the start time of the interval covered by this aggregation. -func (r Record) StartTime() time.Time { - return r.start -} - -// EndTime is the end time of the interval covered by this aggregation. -func (r Record) EndTime() time.Time { - return r.end -} diff --git a/sdk/metric/export/metric_test.go b/sdk/metric/export/metric_test.go deleted file mode 100644 index 5337d11c9e8..00000000000 --- a/sdk/metric/export/metric_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// 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 export - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" -) - -var testSlice = []attribute.KeyValue{ - attribute.String("bar", "baz"), - attribute.Int("foo", 42), -} - -func newIter(slice []attribute.KeyValue) attribute.Iterator { - labels := attribute.NewSet(slice...) - return labels.Iter() -} - -func TestLabelIterator(t *testing.T) { - iter := newIter(testSlice) - require.Equal(t, 2, iter.Len()) - - require.True(t, iter.Next()) - require.Equal(t, attribute.String("bar", "baz"), iter.Label()) - idx, kv := iter.IndexedLabel() - require.Equal(t, 0, idx) - require.Equal(t, attribute.String("bar", "baz"), kv) - require.Equal(t, 2, iter.Len()) - - require.True(t, iter.Next()) - require.Equal(t, attribute.Int("foo", 42), iter.Label()) - idx, kv = iter.IndexedLabel() - require.Equal(t, 1, idx) - require.Equal(t, attribute.Int("foo", 42), kv) - require.Equal(t, 2, iter.Len()) - - require.False(t, iter.Next()) - require.Equal(t, 2, iter.Len()) -} - -func TestEmptyLabelIterator(t *testing.T) { - iter := newIter(nil) - require.Equal(t, 0, iter.Len()) - require.False(t, iter.Next()) -} - -func TestIteratorToSlice(t *testing.T) { - iter := newIter(testSlice) - got := iter.ToSlice() - require.Equal(t, testSlice, got) - - iter = newIter(nil) - got = iter.ToSlice() - require.Nil(t, got) -} diff --git a/sdk/metric/go.mod b/sdk/metric/go.mod index 14031ee16d6..a7cf0da0525 100644 --- a/sdk/metric/go.mod +++ b/sdk/metric/go.mod @@ -39,11 +39,8 @@ replace go.opentelemetry.io/otel/sdk/metric => ./ replace go.opentelemetry.io/otel/trace => ../../trace require ( - github.com/benbjohnson/clock v1.3.0 github.com/stretchr/testify v1.7.1 go.opentelemetry.io/otel v1.6.3 - go.opentelemetry.io/otel/metric v0.29.0 - go.opentelemetry.io/otel/sdk v1.6.3 ) replace go.opentelemetry.io/otel/example/passthrough => ../../example/passthrough diff --git a/sdk/metric/go.sum b/sdk/metric/go.sum index 9ab648da527..79af86d6596 100644 --- a/sdk/metric/go.sum +++ b/sdk/metric/go.sum @@ -1,21 +1,14 @@ -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/sdk/metric/histogram_stress_test.go b/sdk/metric/histogram_stress_test.go deleted file mode 100644 index abc8b967c60..00000000000 --- a/sdk/metric/histogram_stress_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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 metric_test - -import ( - "context" - "math/rand" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -func TestStressInt64Histogram(t *testing.T) { - desc := metrictest.NewDescriptor("some_metric", sdkapi.HistogramInstrumentKind, number.Int64Kind) - - alloc := histogram.New(2, &desc, histogram.WithExplicitBoundaries([]float64{25, 50, 75})) - h, ckpt := &alloc[0], &alloc[1] - - ctx, cancelFunc := context.WithCancel(context.Background()) - defer cancelFunc() - go func() { - rnd := rand.New(rand.NewSource(time.Now().Unix())) - for { - select { - case <-ctx.Done(): - return - default: - _ = h.Update(ctx, number.NewInt64Number(rnd.Int63()%100), &desc) - } - } - }() - - startTime := time.Now() - for time.Since(startTime) < time.Second { - require.NoError(t, h.SynchronizedMove(ckpt, &desc)) - - b, _ := ckpt.Histogram() - c, _ := ckpt.Count() - - var realCount uint64 - for _, c := range b.Counts { - realCount += c - } - - if realCount != c { - t.Fail() - } - } -} diff --git a/sdk/metric/metrictest/alignment_test.go b/sdk/metric/metrictest/alignment_test.go deleted file mode 100644 index 183d46bda82..00000000000 --- a/sdk/metric/metrictest/alignment_test.go +++ /dev/null @@ -1,42 +0,0 @@ -// 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 metrictest - -import ( - "os" - "testing" - "unsafe" - - "go.opentelemetry.io/otel/internal/internaltest" -) - -// TestMain ensures struct alignment prior to running tests. -func TestMain(m *testing.M) { - fields := []internaltest.FieldOffset{ - { - Name: "Batch.Measurments", - Offset: unsafe.Offsetof(Batch{}.Measurements), - }, - { - Name: "Measurement.Number", - Offset: unsafe.Offsetof(Measurement{}.Number), - }, - } - if !internaltest.Aligned8Byte(fields, os.Stderr) { - os.Exit(1) - } - - os.Exit(m.Run()) -} diff --git a/sdk/metric/metrictest/meter.go b/sdk/metric/metrictest/meter.go deleted file mode 100644 index 8222441e48f..00000000000 --- a/sdk/metric/metrictest/meter.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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 metrictest // import "go.opentelemetry.io/otel/sdk/metric/metrictest" - -import ( - "context" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type ( - - // Library is the same as "sdk/instrumentation".Library but there is - // a package cycle to use it. - Library struct { - InstrumentationName string - InstrumentationVersion string - SchemaURL string - } - - Batch struct { - // Measurement needs to be aligned for 64-bit atomic operations. - Measurements []Measurement - Ctx context.Context - Labels []attribute.KeyValue - Library Library - } - - Measurement struct { - // Number needs to be aligned for 64-bit atomic operations. - Number number.Number - Instrument sdkapi.InstrumentImpl - } -) - -// NewDescriptor is a test helper for constructing test metric -// descriptors using standard options. -func NewDescriptor(name string, ikind sdkapi.InstrumentKind, nkind number.Kind, opts ...instrument.Option) sdkapi.Descriptor { - cfg := instrument.NewConfig(opts...) - return sdkapi.NewDescriptor(name, ikind, nkind, cfg.Description(), cfg.Unit()) -} diff --git a/sdk/metric/processor/basic/basic.go b/sdk/metric/processor/basic/basic.go deleted file mode 100644 index 096044c043c..00000000000 --- a/sdk/metric/processor/basic/basic.go +++ /dev/null @@ -1,382 +0,0 @@ -// 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 basic // import "go.opentelemetry.io/otel/sdk/metric/processor/basic" - -import ( - "errors" - "fmt" - "sync" - "time" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type ( - Processor struct { - aggregation.TemporalitySelector - export.AggregatorSelector - - state - } - - stateKey struct { - // TODO: This code is organized to support multiple - // accumulators which could theoretically produce the - // data for the same instrument, and this code has - // logic to combine data properly from multiple - // accumulators. However, the use of - // *sdkapi.Descriptor in the stateKey makes such - // combination impossible, because each accumulator - // allocates its own instruments. This can be fixed - // by using the instrument name and kind instead of - // the descriptor pointer. See - // https://github.com/open-telemetry/opentelemetry-go/issues/862. - descriptor *sdkapi.Descriptor - distinct attribute.Distinct - } - - stateValue struct { - // labels corresponds to the stateKey.distinct field. - labels *attribute.Set - - // updated indicates the last sequence number when this value had - // Process() called by an accumulator. - updated int64 - - // stateful indicates that a cumulative aggregation is - // being maintained, taken from the process start time. - stateful bool - - // currentOwned indicates that "current" was allocated - // by the processor in order to merge results from - // multiple Accumulators during a single collection - // round, which may happen either because: - // (1) multiple Accumulators output the same Accumulation. - // (2) one Accumulator is configured with dimensionality reduction. - currentOwned bool - - // current refers to the output from a single Accumulator - // (if !currentOwned) or it refers to an Aggregator - // owned by the processor used to accumulate multiple - // values in a single collection round. - current aggregator.Aggregator - - // cumulative, if non-nil, refers to an Aggregator owned - // by the processor used to store the last cumulative - // value. - cumulative aggregator.Aggregator - } - - state struct { - config config - - // RWMutex implements locking for the `Reader` interface. - sync.RWMutex - values map[stateKey]*stateValue - - processStart time.Time - intervalStart time.Time - intervalEnd time.Time - - // startedCollection and finishedCollection are the - // number of StartCollection() and FinishCollection() - // calls, used to ensure that the sequence of starts - // and finishes are correctly balanced. - - startedCollection int64 - finishedCollection int64 - } -) - -var _ export.Processor = &Processor{} -var _ export.Checkpointer = &Processor{} -var _ export.Reader = &state{} - -// ErrInconsistentState is returned when the sequence of collection's starts and finishes are incorrectly balanced. -var ErrInconsistentState = fmt.Errorf("inconsistent processor state") - -// ErrInvalidTemporality is returned for unknown metric.Temporality. -var ErrInvalidTemporality = fmt.Errorf("invalid aggregation temporality") - -// New returns a basic Processor that is also a Checkpointer using the provided -// AggregatorSelector to select Aggregators. The TemporalitySelector -// is consulted to determine the kind(s) of exporter that will consume -// data, so that this Processor can prepare to compute Cumulative Aggregations -// as needed. -func New(aselector export.AggregatorSelector, tselector aggregation.TemporalitySelector, opts ...Option) *Processor { - return NewFactory(aselector, tselector, opts...).NewCheckpointer().(*Processor) -} - -type factory struct { - aselector export.AggregatorSelector - tselector aggregation.TemporalitySelector - config config -} - -func NewFactory(aselector export.AggregatorSelector, tselector aggregation.TemporalitySelector, opts ...Option) export.CheckpointerFactory { - var config config - for _, opt := range opts { - config = opt.applyProcessor(config) - } - return factory{ - aselector: aselector, - tselector: tselector, - config: config, - } -} - -var _ export.CheckpointerFactory = factory{} - -func (f factory) NewCheckpointer() export.Checkpointer { - now := time.Now() - p := &Processor{ - AggregatorSelector: f.aselector, - TemporalitySelector: f.tselector, - state: state{ - values: map[stateKey]*stateValue{}, - processStart: now, - intervalStart: now, - config: f.config, - }, - } - return p - -} - -// Process implements export.Processor. -func (b *Processor) Process(accum export.Accumulation) error { - if b.startedCollection != b.finishedCollection+1 { - return ErrInconsistentState - } - desc := accum.Descriptor() - key := stateKey{ - descriptor: desc, - distinct: accum.Labels().Equivalent(), - } - agg := accum.Aggregator() - - // Check if there is an existing value. - value, ok := b.state.values[key] - if !ok { - stateful := b.TemporalityFor(desc, agg.Aggregation().Kind()).MemoryRequired(desc.InstrumentKind()) - - newValue := &stateValue{ - labels: accum.Labels(), - updated: b.state.finishedCollection, - stateful: stateful, - current: agg, - } - if stateful { - if desc.InstrumentKind().PrecomputedSum() { - // To convert precomputed sums to - // deltas requires two aggregators to - // be allocated, one for the prior - // value and one for the output delta. - // This functionality was removed from - // the basic processor in PR #2350. - return aggregation.ErrNoCumulativeToDelta - } - // In this case allocate one aggregator to - // save the current state. - b.AggregatorFor(desc, &newValue.cumulative) - } - b.state.values[key] = newValue - return nil - } - - // Advance the update sequence number. - sameCollection := b.state.finishedCollection == value.updated - value.updated = b.state.finishedCollection - - // At this point in the code, we have located an existing - // value for some stateKey. This can be because: - // - // (a) stateful aggregation is being used, the entry was - // entered during a prior collection, and this is the first - // time processing an accumulation for this stateKey in the - // current collection. Since this is the first time - // processing an accumulation for this stateKey during this - // collection, we don't know yet whether there are multiple - // accumulators at work. If there are multiple accumulators, - // they'll hit case (b) the second time through. - // - // (b) multiple accumulators are being used, whether stateful - // or not. - // - // Case (a) occurs when the instrument and the exporter - // require memory to work correctly, either because the - // instrument reports a PrecomputedSum to a DeltaExporter or - // the reverse, a non-PrecomputedSum instrument with a - // CumulativeExporter. This logic is encapsulated in - // Temporality.MemoryRequired(InstrumentKind). - // - // Case (b) occurs when the variable `sameCollection` is true, - // indicating that the stateKey for Accumulation has already - // been seen in the same collection. When this happens, it - // implies that multiple Accumulators are being used, or that - // a single Accumulator has been configured with a label key - // filter. - - if !sameCollection { - if !value.currentOwned { - // This is the first Accumulation we've seen - // for this stateKey during this collection. - // Just keep a reference to the Accumulator's - // Aggregator. All the other cases copy - // Aggregator state. - value.current = agg - return nil - } - return agg.SynchronizedMove(value.current, desc) - } - - // If the current is not owned, take ownership of a copy - // before merging below. - if !value.currentOwned { - tmp := value.current - b.AggregatorSelector.AggregatorFor(desc, &value.current) - value.currentOwned = true - if err := tmp.SynchronizedMove(value.current, desc); err != nil { - return err - } - } - - // Combine this Accumulation with the prior Accumulation. - return value.current.Merge(agg, desc) -} - -// Reader returns the associated Reader. Use the -// Reader Locker interface to synchronize access to this -// object. The Reader.ForEach() method cannot be called -// concurrently with Process(). -func (b *Processor) Reader() export.Reader { - return &b.state -} - -// StartCollection signals to the Processor one or more Accumulators -// will begin calling Process() calls during collection. -func (b *Processor) StartCollection() { - if b.startedCollection != 0 { - b.intervalStart = b.intervalEnd - } - b.startedCollection++ -} - -// FinishCollection signals to the Processor that a complete -// collection has finished and that ForEach will be called to access -// the Reader. -func (b *Processor) FinishCollection() error { - b.intervalEnd = time.Now() - if b.startedCollection != b.finishedCollection+1 { - return ErrInconsistentState - } - defer func() { b.finishedCollection++ }() - - for key, value := range b.values { - mkind := key.descriptor.InstrumentKind() - stale := value.updated != b.finishedCollection - stateless := !value.stateful - - // The following branch updates stateful aggregators. Skip - // these updates if the aggregator is not stateful or if the - // aggregator is stale. - if stale || stateless { - // If this processor does not require memeory, - // stale, stateless entries can be removed. - // This implies that they were not updated - // over the previous full collection interval. - if stale && stateless && !b.config.Memory { - delete(b.values, key) - } - continue - } - - // The only kind of aggregators that are not stateless - // are the ones needing delta to cumulative - // conversion. Merge aggregator state in this case. - if !mkind.PrecomputedSum() { - // This line is equivalent to: - // value.cumulative = value.cumulative + value.current - if err := value.cumulative.Merge(value.current, key.descriptor); err != nil { - return err - } - } - } - return nil -} - -// ForEach iterates through the Reader, passing an -// export.Record with the appropriate Cumulative or Delta aggregation -// to an exporter. -func (b *state) ForEach(exporter aggregation.TemporalitySelector, f func(export.Record) error) error { - if b.startedCollection != b.finishedCollection { - return ErrInconsistentState - } - for key, value := range b.values { - mkind := key.descriptor.InstrumentKind() - - var agg aggregation.Aggregation - var start time.Time - - aggTemp := exporter.TemporalityFor(key.descriptor, value.current.Aggregation().Kind()) - - switch aggTemp { - case aggregation.CumulativeTemporality: - // If stateful, the sum has been computed. If stateless, the - // input was already cumulative. Either way, use the checkpointed - // value: - if value.stateful { - agg = value.cumulative.Aggregation() - } else { - agg = value.current.Aggregation() - } - start = b.processStart - - case aggregation.DeltaTemporality: - // Precomputed sums are a special case. - if mkind.PrecomputedSum() { - // This functionality was removed from - // the basic processor in PR #2350. - return aggregation.ErrNoCumulativeToDelta - } - agg = value.current.Aggregation() - start = b.intervalStart - - default: - return fmt.Errorf("%v: %w", aggTemp, ErrInvalidTemporality) - } - - // If the processor does not have Config.Memory and it was not updated - // in the prior round, do not visit this value. - if !b.config.Memory && value.updated != (b.finishedCollection-1) { - continue - } - - if err := f(export.NewRecord( - key.descriptor, - value.labels, - agg, - start, - b.intervalEnd, - )); err != nil && !errors.Is(err, aggregation.ErrNoData) { - return err - } - } - return nil -} diff --git a/sdk/metric/processor/basic/basic_test.go b/sdk/metric/processor/basic/basic_test.go deleted file mode 100644 index 80d0e2a20d8..00000000000 --- a/sdk/metric/processor/basic/basic_test.go +++ /dev/null @@ -1,513 +0,0 @@ -// 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 basic_test - -import ( - "context" - "errors" - "fmt" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/instrumentation" - sdk "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - processorTest "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -func requireNotAfter(t *testing.T, t1, t2 time.Time) { - require.False(t, t1.After(t2), "expected %v ≤ %v", t1, t2) -} - -// TestProcessor tests all the non-error paths in this package. -func TestProcessor(t *testing.T) { - type exportCase struct { - kind aggregation.Temporality - } - type instrumentCase struct { - kind sdkapi.InstrumentKind - } - type numberCase struct { - kind number.Kind - } - type aggregatorCase struct { - kind aggregation.Kind - } - - for _, tc := range []exportCase{ - {kind: aggregation.CumulativeTemporality}, - {kind: aggregation.DeltaTemporality}, - } { - t.Run(tc.kind.String(), func(t *testing.T) { - for _, ic := range []instrumentCase{ - {kind: sdkapi.CounterInstrumentKind}, - {kind: sdkapi.UpDownCounterInstrumentKind}, - {kind: sdkapi.HistogramInstrumentKind}, - {kind: sdkapi.CounterObserverInstrumentKind}, - {kind: sdkapi.UpDownCounterObserverInstrumentKind}, - {kind: sdkapi.GaugeObserverInstrumentKind}, - } { - t.Run(ic.kind.String(), func(t *testing.T) { - for _, nc := range []numberCase{ - {kind: number.Int64Kind}, - {kind: number.Float64Kind}, - } { - t.Run(nc.kind.String(), func(t *testing.T) { - for _, ac := range []aggregatorCase{ - {kind: aggregation.SumKind}, - {kind: aggregation.HistogramKind}, - {kind: aggregation.LastValueKind}, - } { - t.Run(ac.kind.String(), func(t *testing.T) { - testProcessor( - t, - tc.kind, - ic.kind, - nc.kind, - ac.kind, - ) - }) - } - }) - } - }) - } - }) - } -} - -func asNumber(nkind number.Kind, value int64) number.Number { - if nkind == number.Int64Kind { - return number.NewInt64Number(value) - } - return number.NewFloat64Number(float64(value)) -} - -func updateFor(t *testing.T, desc *sdkapi.Descriptor, selector export.AggregatorSelector, value int64, labs ...attribute.KeyValue) export.Accumulation { - ls := attribute.NewSet(labs...) - var agg aggregator.Aggregator - selector.AggregatorFor(desc, &agg) - require.NoError(t, agg.Update(context.Background(), asNumber(desc.NumberKind(), value), desc)) - - return export.NewAccumulation(desc, &ls, agg) -} - -func testProcessor( - t *testing.T, - aggTemp aggregation.Temporality, - mkind sdkapi.InstrumentKind, - nkind number.Kind, - akind aggregation.Kind, -) { - // This code tests for errors when the export kind is Delta - // and the instrument kind is PrecomputedSum(). - expectConversion := !(aggTemp == aggregation.DeltaTemporality && mkind.PrecomputedSum()) - requireConversion := func(t *testing.T, err error) { - if expectConversion { - require.NoError(t, err) - } else { - require.Equal(t, aggregation.ErrNoCumulativeToDelta, err) - } - } - - // Note: this selector uses the instrument name to dictate - // aggregation kind. - selector := processorTest.AggregatorSelector() - - labs1 := []attribute.KeyValue{attribute.String("L1", "V")} - labs2 := []attribute.KeyValue{attribute.String("L2", "V")} - - testBody := func(t *testing.T, hasMemory bool, nAccum, nCheckpoint int) { - processor := basic.New(selector, aggregation.ConstantTemporalitySelector(aggTemp), basic.WithMemory(hasMemory)) - - instSuffix := fmt.Sprint(".", strings.ToLower(akind.String())) - - desc1 := metrictest.NewDescriptor(fmt.Sprint("inst1", instSuffix), mkind, nkind) - desc2 := metrictest.NewDescriptor(fmt.Sprint("inst2", instSuffix), mkind, nkind) - - for nc := 0; nc < nCheckpoint; nc++ { - - // The input is 10 per update, scaled by - // the number of checkpoints for - // cumulative instruments: - input := int64(10) - cumulativeMultiplier := int64(nc + 1) - if mkind.PrecomputedSum() { - input *= cumulativeMultiplier - } - - processor.StartCollection() - - for na := 0; na < nAccum; na++ { - requireConversion(t, processor.Process(updateFor(t, &desc1, selector, input, labs1...))) - requireConversion(t, processor.Process(updateFor(t, &desc2, selector, input, labs2...))) - } - - // Note: in case of !expectConversion, we still get no error here - // because the Process() skipped entering state for those records. - require.NoError(t, processor.FinishCollection()) - - if nc < nCheckpoint-1 { - continue - } - - reader := processor.Reader() - - for _, repetitionAfterEmptyInterval := range []bool{false, true} { - if repetitionAfterEmptyInterval { - // We're repeating the test after another - // interval with no updates. - processor.StartCollection() - require.NoError(t, processor.FinishCollection()) - } - - // Test the final checkpoint state. - records1 := processorTest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, reader.ForEach(aggregation.ConstantTemporalitySelector(aggTemp), records1.AddRecord)) - - if !expectConversion { - require.EqualValues(t, map[string]float64{}, records1.Map()) - continue - } - - var multiplier int64 - - if mkind.Asynchronous() { - // Asynchronous tests accumulate results multiply by the - // number of Accumulators, unless LastValue aggregation. - // If a precomputed sum, we expect cumulative inputs. - if mkind.PrecomputedSum() { - require.NotEqual(t, aggTemp, aggregation.DeltaTemporality) - if akind == aggregation.LastValueKind { - multiplier = cumulativeMultiplier - } else { - multiplier = cumulativeMultiplier * int64(nAccum) - } - } else { - if aggTemp == aggregation.CumulativeTemporality && akind != aggregation.LastValueKind { - multiplier = cumulativeMultiplier * int64(nAccum) - } else if akind == aggregation.LastValueKind { - multiplier = 1 - } else { - multiplier = int64(nAccum) - } - } - } else { - // Synchronous accumulate results from multiple accumulators, - // use that number as the baseline multiplier. - multiplier = int64(nAccum) - if aggTemp == aggregation.CumulativeTemporality { - // If a cumulative exporter, include prior checkpoints. - multiplier *= cumulativeMultiplier - } - if akind == aggregation.LastValueKind { - // If a last-value aggregator, set multiplier to 1.0. - multiplier = 1 - } - } - - exp := map[string]float64{} - if hasMemory || !repetitionAfterEmptyInterval { - exp = map[string]float64{ - fmt.Sprintf("inst1%s/L1=V/", instSuffix): float64(multiplier * 10), // labels1 - fmt.Sprintf("inst2%s/L2=V/", instSuffix): float64(multiplier * 10), // labels2 - } - } - - require.EqualValues(t, exp, records1.Map(), "with repetition=%v", repetitionAfterEmptyInterval) - } - } - } - - for _, hasMem := range []bool{false, true} { - t.Run(fmt.Sprintf("HasMemory=%v", hasMem), func(t *testing.T) { - // For 1 to 3 checkpoints: - for nAccum := 1; nAccum <= 3; nAccum++ { - t.Run(fmt.Sprintf("NumAccum=%d", nAccum), func(t *testing.T) { - // For 1 to 3 accumulators: - for nCheckpoint := 1; nCheckpoint <= 3; nCheckpoint++ { - t.Run(fmt.Sprintf("NumCkpt=%d", nCheckpoint), func(t *testing.T) { - testBody(t, hasMem, nAccum, nCheckpoint) - }) - } - }) - } - }) - } -} - -type bogusExporter struct{} - -func (bogusExporter) TemporalityFor(*sdkapi.Descriptor, aggregation.Kind) aggregation.Temporality { - return 100 -} - -func (bogusExporter) Export(context.Context, export.Reader) error { - panic("Not called") -} - -func TestBasicInconsistent(t *testing.T) { - // Test double-start - b := basic.New(processorTest.AggregatorSelector(), aggregation.StatelessTemporalitySelector()) - - b.StartCollection() - b.StartCollection() - require.Equal(t, basic.ErrInconsistentState, b.FinishCollection()) - - // Test finish without start - b = basic.New(processorTest.AggregatorSelector(), aggregation.StatelessTemporalitySelector()) - - require.Equal(t, basic.ErrInconsistentState, b.FinishCollection()) - - // Test no finish - b = basic.New(processorTest.AggregatorSelector(), aggregation.StatelessTemporalitySelector()) - - b.StartCollection() - require.Equal( - t, - basic.ErrInconsistentState, - b.ForEach( - aggregation.StatelessTemporalitySelector(), - func(export.Record) error { return nil }, - ), - ) - - // Test no start - b = basic.New(processorTest.AggregatorSelector(), aggregation.StatelessTemporalitySelector()) - - desc := metrictest.NewDescriptor("inst", sdkapi.CounterInstrumentKind, number.Int64Kind) - accum := export.NewAccumulation(&desc, attribute.EmptySet(), aggregatortest.NoopAggregator{}) - require.Equal(t, basic.ErrInconsistentState, b.Process(accum)) - - // Test invalid kind: - b = basic.New(processorTest.AggregatorSelector(), aggregation.StatelessTemporalitySelector()) - b.StartCollection() - require.NoError(t, b.Process(accum)) - require.NoError(t, b.FinishCollection()) - - err := b.ForEach( - bogusExporter{}, - func(export.Record) error { return nil }, - ) - require.True(t, errors.Is(err, basic.ErrInvalidTemporality)) - -} - -func TestBasicTimestamps(t *testing.T) { - beforeNew := time.Now() - time.Sleep(time.Nanosecond) - b := basic.New(processorTest.AggregatorSelector(), aggregation.StatelessTemporalitySelector()) - time.Sleep(time.Nanosecond) - afterNew := time.Now() - - desc := metrictest.NewDescriptor("inst", sdkapi.CounterInstrumentKind, number.Int64Kind) - accum := export.NewAccumulation(&desc, attribute.EmptySet(), aggregatortest.NoopAggregator{}) - - b.StartCollection() - _ = b.Process(accum) - require.NoError(t, b.FinishCollection()) - - var start1, end1 time.Time - - require.NoError(t, b.ForEach(aggregation.StatelessTemporalitySelector(), func(rec export.Record) error { - start1 = rec.StartTime() - end1 = rec.EndTime() - return nil - })) - - // The first start time is set in the constructor. - requireNotAfter(t, beforeNew, start1) - requireNotAfter(t, start1, afterNew) - - for i := 0; i < 2; i++ { - b.StartCollection() - require.NoError(t, b.Process(accum)) - require.NoError(t, b.FinishCollection()) - - var start2, end2 time.Time - - require.NoError(t, b.ForEach(aggregation.StatelessTemporalitySelector(), func(rec export.Record) error { - start2 = rec.StartTime() - end2 = rec.EndTime() - return nil - })) - - // Subsequent intervals have their start and end aligned. - require.Equal(t, start2, end1) - requireNotAfter(t, start1, end1) - requireNotAfter(t, start2, end2) - - start1 = start2 - end1 = end2 - } -} - -func TestStatefulNoMemoryCumulative(t *testing.T) { - aggTempSel := aggregation.CumulativeTemporalitySelector() - - desc := metrictest.NewDescriptor("inst.sum", sdkapi.CounterInstrumentKind, number.Int64Kind) - selector := processorTest.AggregatorSelector() - - processor := basic.New(selector, aggTempSel, basic.WithMemory(false)) - reader := processor.Reader() - - for i := 1; i < 3; i++ { - // Empty interval - processor.StartCollection() - require.NoError(t, processor.FinishCollection()) - - // Verify zero elements - records := processorTest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, reader.ForEach(aggTempSel, records.AddRecord)) - require.EqualValues(t, map[string]float64{}, records.Map()) - - // Add 10 - processor.StartCollection() - _ = processor.Process(updateFor(t, &desc, selector, 10, attribute.String("A", "B"))) - require.NoError(t, processor.FinishCollection()) - - // Verify one element - records = processorTest.NewOutput(attribute.DefaultEncoder()) - require.NoError(t, reader.ForEach(aggTempSel, records.AddRecord)) - require.EqualValues(t, map[string]float64{ - "inst.sum/A=B/": float64(i * 10), - }, records.Map()) - } -} - -func TestMultiObserverSum(t *testing.T) { - for _, test := range []struct { - name string - aggregation.TemporalitySelector - expectProcessErr error - }{ - {"cumulative", aggregation.CumulativeTemporalitySelector(), nil}, - {"delta", aggregation.DeltaTemporalitySelector(), aggregation.ErrNoCumulativeToDelta}, - } { - t.Run(test.name, func(t *testing.T) { - aggTempSel := test.TemporalitySelector - desc := metrictest.NewDescriptor("observe.sum", sdkapi.CounterObserverInstrumentKind, number.Int64Kind) - selector := processorTest.AggregatorSelector() - - processor := basic.New(selector, aggTempSel, basic.WithMemory(false)) - reader := processor.Reader() - - for i := 1; i < 3; i++ { - // Add i*10*3 times - processor.StartCollection() - require.True(t, errors.Is(processor.Process(updateFor(t, &desc, selector, int64(i*10), attribute.String("A", "B"))), test.expectProcessErr)) - require.True(t, errors.Is(processor.Process(updateFor(t, &desc, selector, int64(i*10), attribute.String("A", "B"))), test.expectProcessErr)) - require.True(t, errors.Is(processor.Process(updateFor(t, &desc, selector, int64(i*10), attribute.String("A", "B"))), test.expectProcessErr)) - require.NoError(t, processor.FinishCollection()) - - // Verify one element - records := processorTest.NewOutput(attribute.DefaultEncoder()) - if test.expectProcessErr == nil { - require.NoError(t, reader.ForEach(aggTempSel, records.AddRecord)) - require.EqualValues(t, map[string]float64{ - "observe.sum/A=B/": float64(3 * 10 * i), - }, records.Map()) - } else { - require.NoError(t, reader.ForEach(aggTempSel, records.AddRecord)) - require.EqualValues(t, map[string]float64{}, records.Map()) - } - } - }) - } -} - -func TestCounterObserverEndToEnd(t *testing.T) { - ctx := context.Background() - eselector := aggregation.CumulativeTemporalitySelector() - proc := basic.New( - processorTest.AggregatorSelector(), - eselector, - ) - accum := sdk.NewAccumulator(proc) - meter := sdkapi.WrapMeterImpl(accum) - - var calls int64 - ctr, err := meter.AsyncInt64().Counter("observer.sum") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{ctr}, func(ctx context.Context) { - calls++ - ctr.Observe(ctx, calls) - }) - require.NoError(t, err) - reader := proc.Reader() - - var startTime [3]time.Time - var endTime [3]time.Time - - for i := range startTime { - data := proc.Reader() - data.Lock() - proc.StartCollection() - accum.Collect(ctx) - require.NoError(t, proc.FinishCollection()) - - exporter := processortest.New(eselector, attribute.DefaultEncoder()) - require.NoError(t, exporter.Export(ctx, resource.Empty(), processortest.OneInstrumentationLibraryReader( - instrumentation.Library{ - Name: "test", - }, reader))) - - require.EqualValues(t, map[string]float64{ - "observer.sum//": float64(i + 1), - }, exporter.Values()) - - var record export.Record - require.NoError(t, data.ForEach(eselector, func(r export.Record) error { - record = r - return nil - })) - - // Try again, but ask for a Delta - require.Equal( - t, - aggregation.ErrNoCumulativeToDelta, - data.ForEach( - aggregation.ConstantTemporalitySelector(aggregation.DeltaTemporality), - func(r export.Record) error { - t.Fail() - return nil - }, - ), - ) - - startTime[i] = record.StartTime() - endTime[i] = record.EndTime() - data.Unlock() - } - - require.Equal(t, startTime[0], startTime[1]) - require.Equal(t, startTime[0], startTime[2]) - requireNotAfter(t, endTime[0], endTime[1]) - requireNotAfter(t, endTime[1], endTime[2]) -} diff --git a/sdk/metric/processor/basic/config.go b/sdk/metric/processor/basic/config.go deleted file mode 100644 index 5170864d7e9..00000000000 --- a/sdk/metric/processor/basic/config.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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 basic // import "go.opentelemetry.io/otel/sdk/metric/processor/basic" - -// config contains the options for configuring a basic metric processor. -type config struct { - // Memory controls whether the processor remembers metric - // instruments and label sets that were previously reported. - // When Memory is true, Reader.ForEach() will visit - // metrics that were not updated in the most recent interval. - Memory bool -} - -type Option interface { - applyProcessor(config) config -} - -// WithMemory sets the memory behavior of a Processor. If this is -// true, the processor will report metric instruments and label sets -// that were previously reported but not updated in the most recent -// interval. -func WithMemory(memory bool) Option { - return memoryOption(memory) -} - -type memoryOption bool - -func (m memoryOption) applyProcessor(cfg config) config { - cfg.Memory = bool(m) - return cfg -} diff --git a/sdk/metric/processor/processortest/test.go b/sdk/metric/processor/processortest/test.go deleted file mode 100644 index 8931fc833f8..00000000000 --- a/sdk/metric/processor/processortest/test.go +++ /dev/null @@ -1,424 +0,0 @@ -// 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 processortest // import "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - -import ( - "context" - "fmt" - "strings" - "sync" - "time" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" - "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -type ( - // mapKey is the unique key for a metric, consisting of its - // unique descriptor, distinct labels, and distinct resource - // attributes. - mapKey struct { - desc *sdkapi.Descriptor - labels attribute.Distinct - resource attribute.Distinct - } - - // mapValue is value stored in a processor used to produce a - // Reader. - mapValue struct { - labels *attribute.Set - resource *resource.Resource - aggregator aggregator.Aggregator - } - - // Output implements export.Reader. - Output struct { - m map[mapKey]mapValue - labelEncoder attribute.Encoder - sync.RWMutex - } - - // testAggregatorSelector returns aggregators consistent with - // the test variables below, needed for testing stateful - // processors, which clone Aggregators using AggregatorFor(desc). - testAggregatorSelector struct{} - - // testCheckpointer is a export.Checkpointer. - testCheckpointer struct { - started int - finished int - *Processor - } - - // Processor is a testing implementation of export.Processor that - // assembles its results as a map[string]float64. - Processor struct { - export.AggregatorSelector - output *Output - } - - // Exporter is a testing implementation of export.Exporter that - // assembles its results as a map[string]float64. - Exporter struct { - aggregation.TemporalitySelector - output *Output - exportCount int - - // InjectErr supports returning conditional errors from - // the Export() routine. This must be set before the - // Exporter is first used. - InjectErr func(export.Record) error - } -) - -type testFactory struct { - selector export.AggregatorSelector - encoder attribute.Encoder -} - -func NewCheckpointerFactory(selector export.AggregatorSelector, encoder attribute.Encoder) export.CheckpointerFactory { - return testFactory{ - selector: selector, - encoder: encoder, - } -} - -func NewCheckpointer(p *Processor) export.Checkpointer { - return &testCheckpointer{ - Processor: p, - } -} - -func (f testFactory) NewCheckpointer() export.Checkpointer { - return NewCheckpointer(NewProcessor(f.selector, f.encoder)) -} - -// NewProcessor returns a new testing Processor implementation. -// Verify expected outputs using Values(), e.g.: -// -// require.EqualValues(t, map[string]float64{ -// "counter.sum/A=1,B=2/R=V": 100, -// }, processor.Values()) -// -// Where in the example A=1,B=2 is the encoded labels and R=V is the -// encoded resource value. -func NewProcessor(selector export.AggregatorSelector, encoder attribute.Encoder) *Processor { - return &Processor{ - AggregatorSelector: selector, - output: NewOutput(encoder), - } -} - -// Process implements export.Processor. -func (p *Processor) Process(accum export.Accumulation) error { - return p.output.AddAccumulation(accum) -} - -// Values returns the mapping from label set to point values for the -// accumulations that were processed. Point values are chosen as -// either the Sum or the LastValue, whichever is implemented. (All -// the built-in Aggregators implement one of these interfaces.) -func (p *Processor) Values() map[string]float64 { - return p.output.Map() -} - -// Reset clears the state of this test processor. -func (p *Processor) Reset() { - p.output.Reset() -} - -// StartCollection implements export.Checkpointer. -func (c *testCheckpointer) StartCollection() { - if c.started != c.finished { - panic(fmt.Sprintf("collection was already started: %d != %d", c.started, c.finished)) - } - - c.started++ -} - -// FinishCollection implements export.Checkpointer. -func (c *testCheckpointer) FinishCollection() error { - if c.started-1 != c.finished { - return fmt.Errorf("collection was not started: %d != %d", c.started, c.finished) - } - - c.finished++ - return nil -} - -// Reader implements export.Checkpointer. -func (c *testCheckpointer) Reader() export.Reader { - return c.Processor.output -} - -// AggregatorSelector returns a policy that is consistent with the -// test descriptors above. I.e., it returns sum.New() for counter -// instruments and lastvalue.New() for lastValue instruments. -func AggregatorSelector() export.AggregatorSelector { - return testAggregatorSelector{} -} - -// AggregatorFor implements export.AggregatorSelector. -func (testAggregatorSelector) AggregatorFor(desc *sdkapi.Descriptor, aggPtrs ...*aggregator.Aggregator) { - - switch { - case strings.HasSuffix(desc.Name(), ".disabled"): - for i := range aggPtrs { - *aggPtrs[i] = nil - } - case strings.HasSuffix(desc.Name(), ".sum"): - aggs := sum.New(len(aggPtrs)) - for i := range aggPtrs { - *aggPtrs[i] = &aggs[i] - } - case strings.HasSuffix(desc.Name(), ".lastvalue"): - aggs := lastvalue.New(len(aggPtrs)) - for i := range aggPtrs { - *aggPtrs[i] = &aggs[i] - } - case strings.HasSuffix(desc.Name(), ".histogram"): - aggs := histogram.New(len(aggPtrs), desc) - for i := range aggPtrs { - *aggPtrs[i] = &aggs[i] - } - default: - panic(fmt.Sprint("Invalid instrument name for test AggregatorSelector: ", desc.Name())) - } -} - -// NewOutput is a helper for testing an expected set of Accumulations -// (from an Accumulator) or an expected set of Records (from a -// Processor). If testing with an Accumulator, it may be simpler to -// use the test Processor in this package. -func NewOutput(labelEncoder attribute.Encoder) *Output { - return &Output{ - m: make(map[mapKey]mapValue), - labelEncoder: labelEncoder, - } -} - -// ForEach implements export.Reader. -func (o *Output) ForEach(_ aggregation.TemporalitySelector, ff func(export.Record) error) error { - for key, value := range o.m { - if err := ff(export.NewRecord( - key.desc, - value.labels, - value.aggregator.Aggregation(), - time.Time{}, - time.Time{}, - )); err != nil { - return err - } - } - return nil -} - -// AddRecord adds a string representation of the exported metric data -// to a map for use in testing. The value taken from the record is -// either the Sum() or the LastValue() of its Aggregation(), whichever -// is defined. Record timestamps are ignored. -func (o *Output) AddRecord(rec export.Record) error { - return o.AddRecordWithResource(rec, resource.Empty()) -} - -func (o *Output) AddInstrumentationLibraryRecord(_ instrumentation.Library, rec export.Record) error { - return o.AddRecordWithResource(rec, resource.Empty()) -} - -func (o *Output) AddRecordWithResource(rec export.Record, res *resource.Resource) error { - key := mapKey{ - desc: rec.Descriptor(), - labels: rec.Labels().Equivalent(), - resource: res.Equivalent(), - } - if _, ok := o.m[key]; !ok { - var agg aggregator.Aggregator - testAggregatorSelector{}.AggregatorFor(rec.Descriptor(), &agg) - o.m[key] = mapValue{ - aggregator: agg, - labels: rec.Labels(), - resource: res, - } - } - return o.m[key].aggregator.Merge(rec.Aggregation().(aggregator.Aggregator), rec.Descriptor()) -} - -// Map returns the calculated values for test validation from a set of -// Accumulations or a set of Records. When mapping records or -// accumulations into floating point values, the Sum() or LastValue() -// is chosen, whichever is implemented by the underlying Aggregator. -func (o *Output) Map() map[string]float64 { - r := make(map[string]float64) - err := o.ForEach(aggregation.StatelessTemporalitySelector(), func(record export.Record) error { - for key, entry := range o.m { - encoded := entry.labels.Encoded(o.labelEncoder) - rencoded := entry.resource.Encoded(o.labelEncoder) - value := 0.0 - if s, ok := entry.aggregator.(aggregation.Sum); ok { - sum, _ := s.Sum() - value = sum.CoerceToFloat64(key.desc.NumberKind()) - } else if l, ok := entry.aggregator.(aggregation.LastValue); ok { - last, _, _ := l.LastValue() - value = last.CoerceToFloat64(key.desc.NumberKind()) - } else { - panic(fmt.Sprintf("Unhandled aggregator type: %T", entry.aggregator)) - } - name := fmt.Sprint(key.desc.Name(), "/", encoded, "/", rencoded) - r[name] = value - } - return nil - }) - if err != nil { - panic(fmt.Sprint("Unexpected processor error: ", err)) - } - return r -} - -// Reset restores the Output to its initial state, with no accumulated -// metric data. -func (o *Output) Reset() { - o.m = map[mapKey]mapValue{} -} - -// AddAccumulation adds a string representation of the exported metric -// data to a map for use in testing. The value taken from the -// accumulation is either the Sum() or the LastValue() of its -// Aggregator().Aggregation(), whichever is defined. -func (o *Output) AddAccumulation(acc export.Accumulation) error { - return o.AddRecord( - export.NewRecord( - acc.Descriptor(), - acc.Labels(), - acc.Aggregator().Aggregation(), - time.Time{}, - time.Time{}, - ), - ) -} - -// New returns a new testing Exporter implementation. -// Verify exporter outputs using Values(), e.g.,: -// -// require.EqualValues(t, map[string]float64{ -// "counter.sum/A=1,B=2/R=V": 100, -// }, exporter.Values()) -// -// Where in the example A=1,B=2 is the encoded labels and R=V is the -// encoded resource value. -func New(selector aggregation.TemporalitySelector, encoder attribute.Encoder) *Exporter { - return &Exporter{ - TemporalitySelector: selector, - output: NewOutput(encoder), - } -} - -func (e *Exporter) Export(_ context.Context, res *resource.Resource, ckpt export.InstrumentationLibraryReader) error { - e.output.Lock() - defer e.output.Unlock() - e.exportCount++ - return ckpt.ForEach(func(library instrumentation.Library, mr export.Reader) error { - return mr.ForEach(e.TemporalitySelector, func(r export.Record) error { - if e.InjectErr != nil { - if err := e.InjectErr(r); err != nil { - return err - } - } - return e.output.AddRecordWithResource(r, res) - }) - }) -} - -// Values returns the mapping from label set to point values for the -// accumulations that were processed. Point values are chosen as -// either the Sum or the LastValue, whichever is implemented. (All -// the built-in Aggregators implement one of these interfaces.) -func (e *Exporter) Values() map[string]float64 { - e.output.Lock() - defer e.output.Unlock() - return e.output.Map() -} - -// ExportCount returns the number of times Export() has been called -// since the last Reset(). -func (e *Exporter) ExportCount() int { - e.output.Lock() - defer e.output.Unlock() - return e.exportCount -} - -// Reset sets the exporter's output to the initial, empty state and -// resets the export count to zero. -func (e *Exporter) Reset() { - e.output.Lock() - defer e.output.Unlock() - e.output.Reset() - e.exportCount = 0 -} - -func OneInstrumentationLibraryReader(l instrumentation.Library, r export.Reader) export.InstrumentationLibraryReader { - return oneLibraryReader{l, r} -} - -type oneLibraryReader struct { - library instrumentation.Library - reader export.Reader -} - -func (o oneLibraryReader) ForEach(readerFunc func(instrumentation.Library, export.Reader) error) error { - return readerFunc(o.library, o.reader) -} - -func MultiInstrumentationLibraryReader(records map[instrumentation.Library][]export.Record) export.InstrumentationLibraryReader { - return instrumentationLibraryReader{records: records} -} - -type instrumentationLibraryReader struct { - records map[instrumentation.Library][]export.Record -} - -var _ export.InstrumentationLibraryReader = instrumentationLibraryReader{} - -func (m instrumentationLibraryReader) ForEach(fn func(instrumentation.Library, export.Reader) error) error { - for library, records := range m.records { - if err := fn(library, &metricReader{records: records}); err != nil { - return err - } - } - return nil -} - -type metricReader struct { - sync.RWMutex - records []export.Record -} - -var _ export.Reader = &metricReader{} - -func (m *metricReader) ForEach(_ aggregation.TemporalitySelector, fn func(export.Record) error) error { - for _, record := range m.records { - if err := fn(record); err != nil && err != aggregation.ErrNoData { - return err - } - } - return nil -} diff --git a/sdk/metric/processor/processortest/test_test.go b/sdk/metric/processor/processortest/test_test.go deleted file mode 100644 index c157ad47e3e..00000000000 --- a/sdk/metric/processor/processortest/test_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// 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 processortest_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/instrumentation" - metricsdk "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - processorTest "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -func generateTestData(t *testing.T, proc export.Processor) { - ctx := context.Background() - accum := metricsdk.NewAccumulator(proc) - meter := sdkapi.WrapMeterImpl(accum) - - counter, err := meter.SyncFloat64().Counter("counter.sum") - require.NoError(t, err) - - counter.Add(ctx, 100, attribute.String("K1", "V1")) - counter.Add(ctx, 101, attribute.String("K1", "V2")) - - counterObserver, err := meter.AsyncInt64().Counter("observer.sum") - require.NoError(t, err) - - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - counterObserver.Observe(ctx, 10, attribute.String("K1", "V1")) - counterObserver.Observe(ctx, 11, attribute.String("K1", "V2")) - }) - require.NoError(t, err) - - accum.Collect(ctx) -} - -func TestProcessorTesting(t *testing.T) { - // Test the Processor test helper using a real Accumulator to - // generate Accumulations. - checkpointer := processorTest.NewCheckpointer( - processorTest.NewProcessor( - processorTest.AggregatorSelector(), - attribute.DefaultEncoder(), - ), - ) - generateTestData(t, checkpointer) - - res := resource.NewSchemaless(attribute.String("R", "V")) - expect := map[string]float64{ - "counter.sum/K1=V1/R=V": 100, - "counter.sum/K1=V2/R=V": 101, - "observer.sum/K1=V1/R=V": 10, - "observer.sum/K1=V2/R=V": 11, - } - - // Export the data and validate it again. - exporter := processorTest.New( - aggregation.StatelessTemporalitySelector(), - attribute.DefaultEncoder(), - ) - - err := exporter.Export(context.Background(), res, processortest.OneInstrumentationLibraryReader( - instrumentation.Library{ - Name: "test", - }, - checkpointer.Reader(), - )) - require.NoError(t, err) - require.EqualValues(t, expect, exporter.Values()) -} diff --git a/sdk/metric/processor/reducer/doc.go b/sdk/metric/processor/reducer/doc.go deleted file mode 100644 index 700a9c97844..00000000000 --- a/sdk/metric/processor/reducer/doc.go +++ /dev/null @@ -1,60 +0,0 @@ -// 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 reducer implements a metrics Processor component to reduce labels. - -This package is currently in a pre-GA phase. Backwards incompatible changes -may be introduced in subsequent minor version releases as we work to track the -evolving OpenTelemetry specification and user feedback. - -The metrics Processor component this package implements applies a -`attribute.Filter` to each processed `export.Accumulation` to remove labels before -passing the result to another Processor. This Processor can be used to reduce -inherent dimensionality in the data, as a way to control the cost of -collecting high cardinality metric data. - -For example, to compose a push controller with a reducer and a basic -metric processor: - -type someFilter struct{ - // configuration for this filter - // ... -} - -func (someFilter) LabelFilterFor(_ *sdkapi.Descriptor) attribute.Filter { - return func(label kv.KeyValue) bool { - // return true to keep this label, false to drop this label - // ... - } -} - -func setupMetrics(exporter export.Exporter) (stop func()) { - basicProcessorFactory := basic.NewFactory( - simple.NewWithHistogramDistribution(), - exporter, - ) - - reducerProcessor := reducer.NewFactory(someFilter{...}, basicProcessorFactory) - - controller := controller.New( - reducerProcessor, - exporter, - opts..., - ) - controller.Start() - global.SetMeterProvider(controller.Provider()) - return controller.Stop -*/ -package reducer // import "go.opentelemetry.io/otel/sdk/metric/processor/reducer" diff --git a/sdk/metric/processor/reducer/reducer.go b/sdk/metric/processor/reducer/reducer.go deleted file mode 100644 index d26fd55345e..00000000000 --- a/sdk/metric/processor/reducer/reducer.go +++ /dev/null @@ -1,66 +0,0 @@ -// 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 reducer // import "go.opentelemetry.io/otel/sdk/metric/processor/reducer" - -import ( - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type ( - // Processor implements "dimensionality reduction" by - // filtering keys from export label sets. - Processor struct { - export.Checkpointer - filterSelector LabelFilterSelector - } - - // LabelFilterSelector is the interface used to configure a - // specific Filter to an instrument. - LabelFilterSelector interface { - LabelFilterFor(descriptor *sdkapi.Descriptor) attribute.Filter - } -) - -var _ export.Processor = &Processor{} -var _ export.Checkpointer = &Processor{} - -// New returns a dimensionality-reducing Processor that passes data to -// the next stage in an export pipeline. -func New(filterSelector LabelFilterSelector, ckpter export.Checkpointer) *Processor { - return &Processor{ - Checkpointer: ckpter, - filterSelector: filterSelector, - } -} - -// Process implements export.Processor. -func (p *Processor) Process(accum export.Accumulation) error { - // Note: the removed labels are returned and ignored here. - // Conceivably these inputs could be useful to a sampler. - reduced, _ := accum.Labels().Filter( - p.filterSelector.LabelFilterFor( - accum.Descriptor(), - ), - ) - return p.Checkpointer.Process( - export.NewAccumulation( - accum.Descriptor(), - &reduced, - accum.Aggregator(), - ), - ) -} diff --git a/sdk/metric/processor/reducer/reducer_test.go b/sdk/metric/processor/reducer/reducer_test.go deleted file mode 100644 index 22fc774f17e..00000000000 --- a/sdk/metric/processor/reducer/reducer_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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 reducer_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/instrumentation" - metricsdk "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/export/aggregation" - "go.opentelemetry.io/otel/sdk/metric/processor/basic" - "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - processorTest "go.opentelemetry.io/otel/sdk/metric/processor/processortest" - "go.opentelemetry.io/otel/sdk/metric/processor/reducer" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/resource" -) - -var ( - kvs1 = []attribute.KeyValue{ - attribute.Int("A", 1), - attribute.Int("B", 2), - attribute.Int("C", 3), - } - kvs2 = []attribute.KeyValue{ - attribute.Int("A", 1), - attribute.Int("B", 0), - attribute.Int("C", 3), - } -) - -type testFilter struct{} - -func (testFilter) LabelFilterFor(_ *sdkapi.Descriptor) attribute.Filter { - return func(label attribute.KeyValue) bool { - return label.Key == "A" || label.Key == "C" - } -} - -func generateData(t *testing.T, impl sdkapi.MeterImpl) { - ctx := context.Background() - meter := sdkapi.WrapMeterImpl(impl) - - counter, err := meter.SyncFloat64().Counter("counter.sum") - require.NoError(t, err) - counter.Add(ctx, 100, kvs1...) - counter.Add(ctx, 100, kvs2...) - - counterObserver, err := meter.AsyncInt64().Counter("observer.sum") - require.NoError(t, err) - err = meter.RegisterCallback([]instrument.Asynchronous{counterObserver}, func(ctx context.Context) { - counterObserver.Observe(ctx, 10, kvs1...) - counterObserver.Observe(ctx, 10, kvs2...) - }) - require.NoError(t, err) -} - -func TestFilterProcessor(t *testing.T) { - testProc := processorTest.NewProcessor( - processorTest.AggregatorSelector(), - attribute.DefaultEncoder(), - ) - accum := metricsdk.NewAccumulator( - reducer.New(testFilter{}, processorTest.NewCheckpointer(testProc)), - ) - generateData(t, accum) - - accum.Collect(context.Background()) - - require.EqualValues(t, map[string]float64{ - "counter.sum/A=1,C=3/": 200, - "observer.sum/A=1,C=3/": 20, - }, testProc.Values()) -} - -// Test a filter with the ../basic Processor. -func TestFilterBasicProcessor(t *testing.T) { - basicProc := basic.New(processorTest.AggregatorSelector(), aggregation.CumulativeTemporalitySelector()) - accum := metricsdk.NewAccumulator( - reducer.New(testFilter{}, basicProc), - ) - exporter := processorTest.New(basicProc, attribute.DefaultEncoder()) - - generateData(t, accum) - - basicProc.StartCollection() - accum.Collect(context.Background()) - if err := basicProc.FinishCollection(); err != nil { - t.Error(err) - } - - res := resource.NewSchemaless(attribute.String("R", "V")) - require.NoError(t, exporter.Export(context.Background(), res, processortest.OneInstrumentationLibraryReader(instrumentation.Library{ - Name: "test", - }, basicProc.Reader()))) - - require.EqualValues(t, map[string]float64{ - "counter.sum/A=1,C=3/R=V": 200, - "observer.sum/A=1,C=3/R=V": 20, - }, exporter.Values()) -} diff --git a/sdk/metric/refcount_mapped.go b/sdk/metric/refcount_mapped.go deleted file mode 100644 index 9abfb9cca70..00000000000 --- a/sdk/metric/refcount_mapped.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 metric // import "go.opentelemetry.io/otel/sdk/metric" - -import ( - "sync/atomic" -) - -// refcountMapped atomically counts the number of references (usages) of an entry -// while also keeping a state of mapped/unmapped into a different data structure -// (an external map or list for example). -// -// refcountMapped uses an atomic value where the least significant bit is used to -// keep the state of mapping ('1' is used for unmapped and '0' is for mapped) and -// the rest of the bits are used for refcounting. -type refcountMapped struct { - // refcount has to be aligned for 64-bit atomic operations. - value int64 -} - -// ref returns true if the entry is still mapped and increases the -// reference usages, if unmapped returns false. -func (rm *refcountMapped) ref() bool { - // Check if this entry was marked as unmapped between the moment - // we got a reference to it (or will be removed very soon) and here. - return atomic.AddInt64(&rm.value, 2)&1 == 0 -} - -func (rm *refcountMapped) unref() { - atomic.AddInt64(&rm.value, -2) -} - -// tryUnmap flips the mapped bit to "unmapped" state and returns true if both of the -// following conditions are true upon entry to this function: -// * There are no active references; -// * The mapped bit is in "mapped" state. -// Otherwise no changes are done to mapped bit and false is returned. -func (rm *refcountMapped) tryUnmap() bool { - if atomic.LoadInt64(&rm.value) != 0 { - return false - } - return atomic.CompareAndSwapInt64( - &rm.value, - 0, - 1, - ) -} diff --git a/sdk/metric/registry/doc.go b/sdk/metric/registry/doc.go deleted file mode 100644 index b401408beef..00000000000 --- a/sdk/metric/registry/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -// 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 registry provides a non-standalone implementation of -MeterProvider that adds uniqueness checking for instrument descriptors -on top of other MeterProvider it wraps. - -This package is currently in a pre-GA phase. Backwards incompatible changes -may be introduced in subsequent minor version releases as we work to track the -evolving OpenTelemetry specification and user feedback. -*/ -package registry // import "go.opentelemetry.io/otel/sdk/metric/registry" diff --git a/sdk/metric/registry/registry.go b/sdk/metric/registry/registry.go deleted file mode 100644 index c2870e483d1..00000000000 --- a/sdk/metric/registry/registry.go +++ /dev/null @@ -1,138 +0,0 @@ -// 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 registry // import "go.opentelemetry.io/otel/sdk/metric/registry" - -import ( - "context" - "fmt" - "sync" - - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -// UniqueInstrumentMeterImpl implements the metric.MeterImpl interface, adding -// uniqueness checking for instrument descriptors. -type UniqueInstrumentMeterImpl struct { - lock sync.Mutex - impl sdkapi.MeterImpl - state map[string]sdkapi.InstrumentImpl -} - -var _ sdkapi.MeterImpl = (*UniqueInstrumentMeterImpl)(nil) - -// ErrMetricKindMismatch is the standard error for mismatched metric -// instrument definitions. -var ErrMetricKindMismatch = fmt.Errorf( - "a metric was already registered by this name with another kind or number type") - -// NewUniqueInstrumentMeterImpl returns a wrapped metric.MeterImpl -// with the addition of instrument name uniqueness checking. -func NewUniqueInstrumentMeterImpl(impl sdkapi.MeterImpl) *UniqueInstrumentMeterImpl { - return &UniqueInstrumentMeterImpl{ - impl: impl, - state: map[string]sdkapi.InstrumentImpl{}, - } -} - -// MeterImpl gives the caller access to the underlying MeterImpl -// used by this UniqueInstrumentMeterImpl. -func (u *UniqueInstrumentMeterImpl) MeterImpl() sdkapi.MeterImpl { - return u.impl -} - -// NewMetricKindMismatchError formats an error that describes a -// mismatched metric instrument definition. -func NewMetricKindMismatchError(desc sdkapi.Descriptor) error { - return fmt.Errorf("metric %s registered as %s %s: %w", - desc.Name(), - desc.NumberKind(), - desc.InstrumentKind(), - ErrMetricKindMismatch) -} - -// Compatible determines whether two sdkapi.Descriptors are considered -// the same for the purpose of uniqueness checking. -func Compatible(candidate, existing sdkapi.Descriptor) bool { - return candidate.InstrumentKind() == existing.InstrumentKind() && - candidate.NumberKind() == existing.NumberKind() -} - -// checkUniqueness returns an ErrMetricKindMismatch error if there is -// a conflict between a descriptor that was already registered and the -// `descriptor` argument. If there is an existing compatible -// registration, this returns the already-registered instrument. If -// there is no conflict and no prior registration, returns (nil, nil). -func (u *UniqueInstrumentMeterImpl) checkUniqueness(descriptor sdkapi.Descriptor) (sdkapi.InstrumentImpl, error) { - impl, ok := u.state[descriptor.Name()] - if !ok { - return nil, nil - } - - if !Compatible(descriptor, impl.Descriptor()) { - return nil, NewMetricKindMismatchError(impl.Descriptor()) - } - - return impl, nil -} - -// NewSyncInstrument implements sdkapi.MeterImpl. -func (u *UniqueInstrumentMeterImpl) NewSyncInstrument(descriptor sdkapi.Descriptor) (sdkapi.SyncImpl, error) { - u.lock.Lock() - defer u.lock.Unlock() - - impl, err := u.checkUniqueness(descriptor) - - if err != nil { - return nil, err - } else if impl != nil { - return impl.(sdkapi.SyncImpl), nil - } - - syncInst, err := u.impl.NewSyncInstrument(descriptor) - if err != nil { - return nil, err - } - u.state[descriptor.Name()] = syncInst - return syncInst, nil -} - -// NewAsyncInstrument implements sdkapi.MeterImpl. -func (u *UniqueInstrumentMeterImpl) NewAsyncInstrument(descriptor sdkapi.Descriptor) (sdkapi.AsyncImpl, error) { - u.lock.Lock() - defer u.lock.Unlock() - - impl, err := u.checkUniqueness(descriptor) - - if err != nil { - return nil, err - } else if impl != nil { - return impl.(sdkapi.AsyncImpl), nil - } - - asyncInst, err := u.impl.NewAsyncInstrument(descriptor) - if err != nil { - return nil, err - } - u.state[descriptor.Name()] = asyncInst - return asyncInst, nil -} - -func (u *UniqueInstrumentMeterImpl) RegisterCallback(insts []instrument.Asynchronous, callback func(context.Context)) error { - u.lock.Lock() - defer u.lock.Unlock() - - return u.impl.RegisterCallback(insts, callback) -} diff --git a/sdk/metric/registry/registry_test.go b/sdk/metric/registry/registry_test.go deleted file mode 100644 index 5d2bc9b108f..00000000000 --- a/sdk/metric/registry/registry_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// 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 registry_test - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/metric" - metricsdk "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/registry" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type ( - newFunc func(m metric.Meter, name string) (sdkapi.InstrumentImpl, error) -) - -var ( - allNew = map[string]newFunc{ - "counter.int64": func(m metric.Meter, name string) (sdkapi.InstrumentImpl, error) { - return unwrap(m.SyncInt64().Counter(name)) - }, - "counter.float64": func(m metric.Meter, name string) (sdkapi.InstrumentImpl, error) { - return unwrap(m.SyncFloat64().Counter(name)) - }, - "histogram.int64": func(m metric.Meter, name string) (sdkapi.InstrumentImpl, error) { - return unwrap(m.SyncInt64().Histogram(name)) - }, - "histogram.float64": func(m metric.Meter, name string) (sdkapi.InstrumentImpl, error) { - return unwrap(m.SyncFloat64().Histogram(name)) - }, - "gaugeobserver.int64": func(m metric.Meter, name string) (sdkapi.InstrumentImpl, error) { - return unwrap(m.AsyncInt64().Gauge(name)) - }, - "gaugeobserver.float64": func(m metric.Meter, name string) (sdkapi.InstrumentImpl, error) { - return unwrap(m.AsyncFloat64().Gauge(name)) - }, - } -) - -func unwrap(impl interface{}, err error) (sdkapi.InstrumentImpl, error) { - if impl == nil { - return nil, err - } - if s, ok := impl.(interface { - SyncImpl() sdkapi.SyncImpl - }); ok { - return s.SyncImpl(), err - } - if a, ok := impl.(interface { - AsyncImpl() sdkapi.AsyncImpl - }); ok { - return a.AsyncImpl(), err - } - return nil, err -} - -// TODO Replace with controller -func testMeterWithRegistry(name string) metric.Meter { - return sdkapi.WrapMeterImpl( - registry.NewUniqueInstrumentMeterImpl( - metricsdk.NewAccumulator(nil), - ), - ) -} - -func TestRegistrySameInstruments(t *testing.T) { - for _, nf := range allNew { - meter := testMeterWithRegistry("meter") - inst1, err1 := nf(meter, "this") - inst2, err2 := nf(meter, "this") - - require.NoError(t, err1) - require.NoError(t, err2) - require.Equal(t, inst1, inst2) - } -} - -func TestRegistryDiffInstruments(t *testing.T) { - for origName, origf := range allNew { - meter := testMeterWithRegistry("meter") - - _, err := origf(meter, "this") - require.NoError(t, err) - - for newName, nf := range allNew { - if newName == origName { - continue - } - - other, err := nf(meter, "this") - require.Error(t, err) - require.Nil(t, other) - require.True(t, errors.Is(err, registry.ErrMetricKindMismatch)) - } - } -} diff --git a/sdk/metric/sdk.go b/sdk/metric/sdk.go deleted file mode 100644 index db3ad330213..00000000000 --- a/sdk/metric/sdk.go +++ /dev/null @@ -1,424 +0,0 @@ -// 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 metric // import "go.opentelemetry.io/otel/sdk/metric" - -import ( - "context" - "fmt" - "runtime" - "sync" - "sync/atomic" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type ( - // Accumulator implements the OpenTelemetry Meter API. The - // Accumulator is bound to a single export.Processor in - // `NewAccumulator()`. - // - // The Accumulator supports a Collect() API to gather and export - // current data. Collect() should be arranged according to - // the processor model. Push-based processors will setup a - // timer to call Collect() periodically. Pull-based processors - // will call Collect() when a pull request arrives. - Accumulator struct { - // current maps `mapkey` to *record. - current sync.Map - - callbackLock sync.Mutex - callbacks map[*callback]struct{} - - // currentEpoch is the current epoch number. It is - // incremented in `Collect()`. - currentEpoch int64 - - // processor is the configured processor+configuration. - processor export.Processor - - // collectLock prevents simultaneous calls to Collect(). - collectLock sync.Mutex - } - - callback struct { - insts map[*asyncInstrument]struct{} - f func(context.Context) - } - - asyncContextKey struct{} - - asyncInstrument struct { - baseInstrument - instrument.Asynchronous - } - - syncInstrument struct { - baseInstrument - instrument.Synchronous - } - - // mapkey uniquely describes a metric instrument in terms of - // its InstrumentID and the encoded form of its labels. - mapkey struct { - descriptor *sdkapi.Descriptor - ordered attribute.Distinct - } - - // record maintains the state of one metric instrument. Due - // the use of lock-free algorithms, there may be more than one - // `record` in existence at a time, although at most one can - // be referenced from the `Accumulator.current` map. - record struct { - // refMapped keeps track of refcounts and the mapping state to the - // Accumulator.current map. - refMapped refcountMapped - - // updateCount is incremented on every Update. - updateCount int64 - - // collectedCount is set to updateCount on collection, - // supports checking for no updates during a round. - collectedCount int64 - - // labels is the stored label set for this record, - // except in cases where a label set is shared due to - // batch recording. - labels attribute.Set - - // sortSlice has a single purpose - as a temporary - // place for sorting during labels creation to avoid - // allocation. - sortSlice attribute.Sortable - - // inst is a pointer to the corresponding instrument. - inst *baseInstrument - - // current implements the actual RecordOne() API, - // depending on the type of aggregation. If nil, the - // metric was disabled by the exporter. - current aggregator.Aggregator - checkpoint aggregator.Aggregator - } - - baseInstrument struct { - meter *Accumulator - descriptor sdkapi.Descriptor - } -) - -var ( - _ sdkapi.MeterImpl = &Accumulator{} - - // ErrUninitializedInstrument is returned when an instrument is used when uninitialized. - ErrUninitializedInstrument = fmt.Errorf("use of an uninitialized instrument") - - ErrBadInstrument = fmt.Errorf("use of a instrument from another SDK") -) - -func (b *baseInstrument) Descriptor() sdkapi.Descriptor { - return b.descriptor -} - -func (a *asyncInstrument) Implementation() interface{} { - return a -} - -func (s *syncInstrument) Implementation() interface{} { - return s -} - -// acquireHandle gets or creates a `*record` corresponding to `kvs`, -// the input labels. -func (b *baseInstrument) acquireHandle(kvs []attribute.KeyValue) *record { - - // This memory allocation may not be used, but it's - // needed for the `sortSlice` field, to avoid an - // allocation while sorting. - rec := &record{} - rec.labels = attribute.NewSetWithSortable(kvs, &rec.sortSlice) - - // Create lookup key for sync.Map (one allocation, as this - // passes through an interface{}) - mk := mapkey{ - descriptor: &b.descriptor, - ordered: rec.labels.Equivalent(), - } - - if actual, ok := b.meter.current.Load(mk); ok { - // Existing record case. - existingRec := actual.(*record) - if existingRec.refMapped.ref() { - // At this moment it is guaranteed that the entry is in - // the map and will not be removed. - return existingRec - } - // This entry is no longer mapped, try to add a new entry. - } - - rec.refMapped = refcountMapped{value: 2} - rec.inst = b - - b.meter.processor.AggregatorFor(&b.descriptor, &rec.current, &rec.checkpoint) - - for { - // Load/Store: there's a memory allocation to place `mk` into - // an interface here. - if actual, loaded := b.meter.current.LoadOrStore(mk, rec); loaded { - // Existing record case. Cannot change rec here because if fail - // will try to add rec again to avoid new allocations. - oldRec := actual.(*record) - if oldRec.refMapped.ref() { - // At this moment it is guaranteed that the entry is in - // the map and will not be removed. - return oldRec - } - // This loaded entry is marked as unmapped (so Collect will remove - // it from the map immediately), try again - this is a busy waiting - // strategy to wait until Collect() removes this entry from the map. - // - // This can be improved by having a list of "Unmapped" entries for - // one time only usages, OR we can make this a blocking path and use - // a Mutex that protects the delete operation (delete only if the old - // record is associated with the key). - - // Let collector get work done to remove the entry from the map. - runtime.Gosched() - continue - } - // The new entry was added to the map, good to go. - return rec - } -} - -// RecordOne captures a single synchronous metric event. -// -// The order of the input array `kvs` may be sorted after the function is called. -func (s *syncInstrument) RecordOne(ctx context.Context, num number.Number, kvs []attribute.KeyValue) { - h := s.acquireHandle(kvs) - defer h.unbind() - h.captureOne(ctx, num) -} - -// ObserveOne captures a single asynchronous metric event. - -// The order of the input array `kvs` may be sorted after the function is called. -func (a *asyncInstrument) ObserveOne(ctx context.Context, num number.Number, attrs []attribute.KeyValue) { - h := a.acquireHandle(attrs) - defer h.unbind() - h.captureOne(ctx, num) -} - -// NewAccumulator constructs a new Accumulator for the given -// processor. This Accumulator supports only a single processor. -// -// The Accumulator does not start any background process to collect itself -// periodically, this responsibility lies with the processor, typically, -// depending on the type of export. For example, a pull-based -// processor will call Collect() when it receives a request to scrape -// current metric values. A push-based processor should configure its -// own periodic collection. -func NewAccumulator(processor export.Processor) *Accumulator { - return &Accumulator{ - processor: processor, - callbacks: map[*callback]struct{}{}, - } -} - -var _ sdkapi.MeterImpl = &Accumulator{} - -// NewSyncInstrument implements sdkapi.MetricImpl. -func (m *Accumulator) NewSyncInstrument(descriptor sdkapi.Descriptor) (sdkapi.SyncImpl, error) { - return &syncInstrument{ - baseInstrument: baseInstrument{ - descriptor: descriptor, - meter: m, - }, - }, nil -} - -// NewAsyncInstrument implements sdkapi.MetricImpl. -func (m *Accumulator) NewAsyncInstrument(descriptor sdkapi.Descriptor) (sdkapi.AsyncImpl, error) { - a := &asyncInstrument{ - baseInstrument: baseInstrument{ - descriptor: descriptor, - meter: m, - }, - } - return a, nil -} - -func (m *Accumulator) RegisterCallback(insts []instrument.Asynchronous, f func(context.Context)) error { - cb := &callback{ - insts: map[*asyncInstrument]struct{}{}, - f: f, - } - for _, inst := range insts { - impl, ok := inst.(sdkapi.AsyncImpl) - if !ok { - return ErrBadInstrument - } - - ai, err := m.fromAsync(impl) - if err != nil { - return err - } - cb.insts[ai] = struct{}{} - } - - m.callbackLock.Lock() - defer m.callbackLock.Unlock() - m.callbacks[cb] = struct{}{} - return nil -} - -// Collect traverses the list of active records and observers and -// exports data for each active instrument. Collect() may not be -// called concurrently. -// -// During the collection pass, the export.Processor will receive -// one Export() call per current aggregation. -// -// Returns the number of records that were checkpointed. -func (m *Accumulator) Collect(ctx context.Context) int { - m.collectLock.Lock() - defer m.collectLock.Unlock() - - m.runAsyncCallbacks(ctx) - checkpointed := m.collectInstruments() - m.currentEpoch++ - - return checkpointed -} - -func (m *Accumulator) collectInstruments() int { - checkpointed := 0 - - m.current.Range(func(key interface{}, value interface{}) bool { - // Note: always continue to iterate over the entire - // map by returning `true` in this function. - inuse := value.(*record) - - mods := atomic.LoadInt64(&inuse.updateCount) - coll := inuse.collectedCount - - if mods != coll { - // Updates happened in this interval, - // checkpoint and continue. - checkpointed += m.checkpointRecord(inuse) - inuse.collectedCount = mods - return true - } - - // Having no updates since last collection, try to unmap: - if unmapped := inuse.refMapped.tryUnmap(); !unmapped { - // The record is referenced by a binding, continue. - return true - } - - // If any other goroutines are now trying to re-insert this - // entry in the map, they are busy calling Gosched() awaiting - // this deletion: - m.current.Delete(inuse.mapkey()) - - // There's a potential race between `LoadInt64` and - // `tryUnmap` in this function. Since this is the - // last we'll see of this record, checkpoint - mods = atomic.LoadInt64(&inuse.updateCount) - if mods != coll { - checkpointed += m.checkpointRecord(inuse) - } - return true - }) - - return checkpointed -} - -func (m *Accumulator) runAsyncCallbacks(ctx context.Context) { - m.callbackLock.Lock() - defer m.callbackLock.Unlock() - - ctx = context.WithValue(ctx, asyncContextKey{}, m) - - for cb := range m.callbacks { - cb.f(ctx) - } -} - -func (m *Accumulator) checkpointRecord(r *record) int { - if r.current == nil { - return 0 - } - err := r.current.SynchronizedMove(r.checkpoint, &r.inst.descriptor) - if err != nil { - otel.Handle(err) - return 0 - } - - a := export.NewAccumulation(&r.inst.descriptor, &r.labels, r.checkpoint) - err = m.processor.Process(a) - if err != nil { - otel.Handle(err) - } - return 1 -} - -func (r *record) captureOne(ctx context.Context, num number.Number) { - if r.current == nil { - // The instrument is disabled according to the AggregatorSelector. - return - } - if err := aggregator.RangeTest(num, &r.inst.descriptor); err != nil { - otel.Handle(err) - return - } - if err := r.current.Update(ctx, num, &r.inst.descriptor); err != nil { - otel.Handle(err) - return - } - // Record was modified, inform the Collect() that things need - // to be collected while the record is still mapped. - atomic.AddInt64(&r.updateCount, 1) -} - -func (r *record) unbind() { - r.refMapped.unref() -} - -func (r *record) mapkey() mapkey { - return mapkey{ - descriptor: &r.inst.descriptor, - ordered: r.labels.Equivalent(), - } -} - -// fromSync gets an async implementation object, checking for -// uninitialized instruments and instruments created by another SDK. -func (m *Accumulator) fromAsync(async sdkapi.AsyncImpl) (*asyncInstrument, error) { - if async == nil { - return nil, ErrUninitializedInstrument - } - inst, ok := async.Implementation().(*asyncInstrument) - if !ok { - return nil, ErrBadInstrument - } - return inst, nil - -} diff --git a/sdk/metric/sdkapi/descriptor.go b/sdk/metric/sdkapi/descriptor.go deleted file mode 100644 index f86e4473459..00000000000 --- a/sdk/metric/sdkapi/descriptor.go +++ /dev/null @@ -1,70 +0,0 @@ -// 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 sdkapi // import "go.opentelemetry.io/otel/sdk/metric/sdkapi" - -import ( - "go.opentelemetry.io/otel/metric/unit" - "go.opentelemetry.io/otel/sdk/metric/number" -) - -// Descriptor contains all the settings that describe an instrument, -// including its name, metric kind, number kind, and the configurable -// options. -type Descriptor struct { - name string - instrumentKind InstrumentKind - numberKind number.Kind - description string - unit unit.Unit -} - -// NewDescriptor returns a Descriptor with the given contents. -func NewDescriptor(name string, ikind InstrumentKind, nkind number.Kind, description string, unit unit.Unit) Descriptor { - return Descriptor{ - name: name, - instrumentKind: ikind, - numberKind: nkind, - description: description, - unit: unit, - } -} - -// Name returns the metric instrument's name. -func (d Descriptor) Name() string { - return d.name -} - -// InstrumentKind returns the specific kind of instrument. -func (d Descriptor) InstrumentKind() InstrumentKind { - return d.instrumentKind -} - -// Description provides a human-readable description of the metric -// instrument. -func (d Descriptor) Description() string { - return d.description -} - -// Unit describes the units of the metric instrument. Unitless -// metrics return the empty string. -func (d Descriptor) Unit() unit.Unit { - return d.unit -} - -// NumberKind returns whether this instrument is declared over int64, -// float64, or uint64 values. -func (d Descriptor) NumberKind() number.Kind { - return d.numberKind -} diff --git a/sdk/metric/sdkapi/descriptor_test.go b/sdk/metric/sdkapi/descriptor_test.go deleted file mode 100644 index 1f084472535..00000000000 --- a/sdk/metric/sdkapi/descriptor_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// 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 sdkapi - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/metric/unit" - "go.opentelemetry.io/otel/sdk/metric/number" -) - -func TestDescriptorGetters(t *testing.T) { - d := NewDescriptor("name", HistogramInstrumentKind, number.Int64Kind, "my description", "my unit") - require.Equal(t, "name", d.Name()) - require.Equal(t, HistogramInstrumentKind, d.InstrumentKind()) - require.Equal(t, number.Int64Kind, d.NumberKind()) - require.Equal(t, "my description", d.Description()) - require.Equal(t, unit.Unit("my unit"), d.Unit()) -} diff --git a/sdk/metric/sdkapi/instrumentkind.go b/sdk/metric/sdkapi/instrumentkind.go deleted file mode 100644 index c7406a3e49a..00000000000 --- a/sdk/metric/sdkapi/instrumentkind.go +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -//go:generate stringer -type=InstrumentKind - -package sdkapi // import "go.opentelemetry.io/otel/sdk/metric/sdkapi" - -// InstrumentKind describes the kind of instrument. -type InstrumentKind int8 - -const ( - // HistogramInstrumentKind indicates a Histogram instrument. - HistogramInstrumentKind InstrumentKind = iota - // GaugeObserverInstrumentKind indicates an GaugeObserver instrument. - GaugeObserverInstrumentKind - - // CounterInstrumentKind indicates a Counter instrument. - CounterInstrumentKind - // UpDownCounterInstrumentKind indicates a UpDownCounter instrument. - UpDownCounterInstrumentKind - - // CounterObserverInstrumentKind indicates a CounterObserver instrument. - CounterObserverInstrumentKind - // UpDownCounterObserverInstrumentKind indicates a UpDownCounterObserver - // instrument. - UpDownCounterObserverInstrumentKind -) - -// Synchronous returns whether this is a synchronous kind of instrument. -func (k InstrumentKind) Synchronous() bool { - switch k { - case CounterInstrumentKind, UpDownCounterInstrumentKind, HistogramInstrumentKind: - return true - } - return false -} - -// Asynchronous returns whether this is an asynchronous kind of instrument. -func (k InstrumentKind) Asynchronous() bool { - return !k.Synchronous() -} - -// Adding returns whether this kind of instrument adds its inputs (as opposed to Grouping). -func (k InstrumentKind) Adding() bool { - switch k { - case CounterInstrumentKind, UpDownCounterInstrumentKind, CounterObserverInstrumentKind, UpDownCounterObserverInstrumentKind: - return true - } - return false -} - -// Grouping returns whether this kind of instrument groups its inputs (as opposed to Adding). -func (k InstrumentKind) Grouping() bool { - return !k.Adding() -} - -// Monotonic returns whether this kind of instrument exposes a non-decreasing sum. -func (k InstrumentKind) Monotonic() bool { - switch k { - case CounterInstrumentKind, CounterObserverInstrumentKind: - return true - } - return false -} - -// PrecomputedSum returns whether this kind of instrument receives precomputed sums. -func (k InstrumentKind) PrecomputedSum() bool { - return k.Adding() && k.Asynchronous() -} diff --git a/sdk/metric/sdkapi/instrumentkind_string.go b/sdk/metric/sdkapi/instrumentkind_string.go deleted file mode 100644 index 3a2e79d823e..00000000000 --- a/sdk/metric/sdkapi/instrumentkind_string.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by "stringer -type=InstrumentKind"; DO NOT EDIT. - -package sdkapi - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[HistogramInstrumentKind-0] - _ = x[GaugeObserverInstrumentKind-1] - _ = x[CounterInstrumentKind-2] - _ = x[UpDownCounterInstrumentKind-3] - _ = x[CounterObserverInstrumentKind-4] - _ = x[UpDownCounterObserverInstrumentKind-5] -} - -const _InstrumentKind_name = "HistogramInstrumentKindGaugeObserverInstrumentKindCounterInstrumentKindUpDownCounterInstrumentKindCounterObserverInstrumentKindUpDownCounterObserverInstrumentKind" - -var _InstrumentKind_index = [...]uint8{0, 23, 50, 71, 98, 127, 162} - -func (i InstrumentKind) String() string { - if i < 0 || i >= InstrumentKind(len(_InstrumentKind_index)-1) { - return "InstrumentKind(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _InstrumentKind_name[_InstrumentKind_index[i]:_InstrumentKind_index[i+1]] -} diff --git a/sdk/metric/sdkapi/instrumentkind_test.go b/sdk/metric/sdkapi/instrumentkind_test.go deleted file mode 100644 index cd1db02a898..00000000000 --- a/sdk/metric/sdkapi/instrumentkind_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// 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 sdkapi_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -func TestInstrumentKinds(t *testing.T) { - require.Equal(t, sdkapi.HistogramInstrumentKind.String(), "HistogramInstrumentKind") - require.Equal(t, sdkapi.GaugeObserverInstrumentKind.String(), "GaugeObserverInstrumentKind") - require.Equal(t, sdkapi.CounterInstrumentKind.String(), "CounterInstrumentKind") - require.Equal(t, sdkapi.UpDownCounterInstrumentKind.String(), "UpDownCounterInstrumentKind") - require.Equal(t, sdkapi.CounterObserverInstrumentKind.String(), "CounterObserverInstrumentKind") - require.Equal(t, sdkapi.UpDownCounterObserverInstrumentKind.String(), "UpDownCounterObserverInstrumentKind") -} diff --git a/sdk/metric/sdkapi/noop.go b/sdk/metric/sdkapi/noop.go deleted file mode 100644 index 6b2374b68a3..00000000000 --- a/sdk/metric/sdkapi/noop.go +++ /dev/null @@ -1,83 +0,0 @@ -// 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 sdkapi // import "go.opentelemetry.io/otel/sdk/metric/sdkapi" - -import ( - "context" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/metric/number" -) // import ( -// "context" - -// "go.opentelemetry.io/otel/attribute" -// "go.opentelemetry.io/otel/sdk/metric/number" -// ) - -type noopInstrument struct { - descriptor Descriptor -} -type noopSyncInstrument struct { - noopInstrument - - instrument.Synchronous -} -type noopAsyncInstrument struct { - noopInstrument - - instrument.Asynchronous -} - -var _ SyncImpl = noopSyncInstrument{} -var _ AsyncImpl = noopAsyncInstrument{} - -// NewNoopSyncInstrument returns a No-op implementation of the -// synchronous instrument interface. -func NewNoopSyncInstrument() SyncImpl { - return noopSyncInstrument{ - noopInstrument: noopInstrument{ - descriptor: Descriptor{ - instrumentKind: CounterInstrumentKind, - }, - }, - } -} - -// NewNoopAsyncInstrument returns a No-op implementation of the -// asynchronous instrument interface. -func NewNoopAsyncInstrument() AsyncImpl { - return noopAsyncInstrument{ - noopInstrument: noopInstrument{ - descriptor: Descriptor{ - instrumentKind: CounterObserverInstrumentKind, - }, - }, - } -} - -func (noopInstrument) Implementation() interface{} { - return nil -} - -func (n noopInstrument) Descriptor() Descriptor { - return n.descriptor -} - -func (noopSyncInstrument) RecordOne(context.Context, number.Number, []attribute.KeyValue) { -} - -func (noopAsyncInstrument) ObserveOne(ctx context.Context, number number.Number, labels []attribute.KeyValue) { -} diff --git a/sdk/metric/sdkapi/sdkapi.go b/sdk/metric/sdkapi/sdkapi.go deleted file mode 100644 index 4345358ff3e..00000000000 --- a/sdk/metric/sdkapi/sdkapi.go +++ /dev/null @@ -1,162 +0,0 @@ -// 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 sdkapi // import "go.opentelemetry.io/otel/sdk/metric/sdkapi" - -import ( - "context" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/sdk/metric/number" -) - -// MeterImpl is the interface an SDK must implement to supply a Meter -// implementation. -type MeterImpl interface { - // NewSyncInstrument returns a newly constructed - // synchronous instrument implementation or an error, should - // one occur. - NewSyncInstrument(descriptor Descriptor) (SyncImpl, error) - - // NewAsyncInstrument returns a newly constructed - // asynchronous instrument implementation or an error, should - // one occur. - NewAsyncInstrument(descriptor Descriptor) (AsyncImpl, error) - - // Etc. - RegisterCallback(insts []instrument.Asynchronous, callback func(context.Context)) error -} - -// InstrumentImpl is a common interface for synchronous and -// asynchronous instruments. -type InstrumentImpl interface { - // Implementation returns the underlying implementation of the - // instrument, which allows the implementation to gain access - // to its own representation especially from a `Measurement`. - Implementation() interface{} - - // Descriptor returns a copy of the instrument's Descriptor. - Descriptor() Descriptor -} - -// SyncImpl is the implementation-level interface to a generic -// synchronous instrument (e.g., Histogram and Counter instruments). -type SyncImpl interface { - InstrumentImpl - instrument.Synchronous - - // RecordOne captures a single synchronous metric event. - RecordOne(ctx context.Context, number number.Number, labels []attribute.KeyValue) -} - -// AsyncImpl is an implementation-level interface to an -// asynchronous instrument (e.g., Observer instruments). -type AsyncImpl interface { - InstrumentImpl - instrument.Asynchronous - - // ObserveOne captures a single synchronous metric event. - ObserveOne(ctx context.Context, number number.Number, labels []attribute.KeyValue) -} - -// AsyncRunner is expected to convert into an AsyncSingleRunner or an -// AsyncBatchRunner. SDKs will encounter an error if the AsyncRunner -// does not satisfy one of these interfaces. -type AsyncRunner interface { - // AnyRunner is a non-exported method with no functional use - // other than to make this a non-empty interface. - AnyRunner() -} - -// AsyncSingleRunner is an interface implemented by single-observer -// callbacks. -type AsyncSingleRunner interface { - // Run accepts a single instrument and function for capturing - // observations of that instrument. Each call to the function - // receives one captured observation. (The function accepts - // multiple observations so the same implementation can be - // used for batch runners.) - Run(ctx context.Context, single AsyncImpl, capture func([]attribute.KeyValue, ...Observation)) - - AsyncRunner -} - -// AsyncBatchRunner is an interface implemented by batch-observer -// callbacks. -type AsyncBatchRunner interface { - // Run accepts a function for capturing observations of - // multiple instruments. - Run(ctx context.Context, capture func([]attribute.KeyValue, ...Observation)) - - AsyncRunner -} - -// NewMeasurement constructs a single observation, a binding between -// an asynchronous instrument and a number. -func NewMeasurement(instrument SyncImpl, number number.Number) Measurement { - return Measurement{ - instrument: instrument, - number: number, - } -} - -// Measurement is a low-level type used with synchronous instruments -// as a direct interface to the SDK via `RecordBatch`. -type Measurement struct { - // number needs to be aligned for 64-bit atomic operations. - number number.Number - instrument SyncImpl -} - -// SyncImpl returns the instrument that created this measurement. -// This returns an implementation-level object for use by the SDK, -// users should not refer to this. -func (m Measurement) SyncImpl() SyncImpl { - return m.instrument -} - -// Number returns a number recorded in this measurement. -func (m Measurement) Number() number.Number { - return m.number -} - -// NewObservation constructs a single observation, a binding between -// an asynchronous instrument and a number. -func NewObservation(instrument AsyncImpl, number number.Number) Observation { - return Observation{ - instrument: instrument, - number: number, - } -} - -// Observation is a low-level type used with asynchronous instruments -// as a direct interface to the SDK via `BatchObserver`. -type Observation struct { - // number needs to be aligned for 64-bit atomic operations. - number number.Number - instrument AsyncImpl -} - -// AsyncImpl returns the instrument that created this observation. -// This returns an implementation-level object for use by the SDK, -// users should not refer to this. -func (m Observation) AsyncImpl() AsyncImpl { - return m.instrument -} - -// Number returns a number recorded in this observation. -func (m Observation) Number() number.Number { - return m.number -} diff --git a/sdk/metric/sdkapi/sdkapi_test.go b/sdk/metric/sdkapi/sdkapi_test.go deleted file mode 100644 index 69fec0fe692..00000000000 --- a/sdk/metric/sdkapi/sdkapi_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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 sdkapi - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/sdk/metric/number" -) - -func TestMeasurementGetters(t *testing.T) { - num := number.NewFloat64Number(1.5) - si := NewNoopSyncInstrument() - meas := NewMeasurement(si, num) - - require.Equal(t, si, meas.SyncImpl()) - require.Equal(t, num, meas.Number()) -} - -func TestObservationGetters(t *testing.T) { - num := number.NewFloat64Number(1.5) - ai := NewNoopAsyncInstrument() - obs := NewObservation(ai, num) - - require.Equal(t, ai, obs.AsyncImpl()) - require.Equal(t, num, obs.Number()) -} diff --git a/sdk/metric/sdkapi/wrap.go b/sdk/metric/sdkapi/wrap.go deleted file mode 100644 index 9a4d5b0de14..00000000000 --- a/sdk/metric/sdkapi/wrap.go +++ /dev/null @@ -1,181 +0,0 @@ -// 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 sdkapi // import "go.opentelemetry.io/otel/sdk/metric/sdkapi" - -import ( - "context" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/instrument" - "go.opentelemetry.io/otel/metric/instrument/asyncfloat64" - "go.opentelemetry.io/otel/metric/instrument/asyncint64" - "go.opentelemetry.io/otel/metric/instrument/syncfloat64" - "go.opentelemetry.io/otel/metric/instrument/syncint64" - "go.opentelemetry.io/otel/sdk/metric/number" -) - -type ( - meter struct{ MeterImpl } - sfMeter struct{ meter } - siMeter struct{ meter } - afMeter struct{ meter } - aiMeter struct{ meter } - - iAdder struct{ SyncImpl } - fAdder struct{ SyncImpl } - iRecorder struct{ SyncImpl } - fRecorder struct{ SyncImpl } - iObserver struct{ AsyncImpl } - fObserver struct{ AsyncImpl } -) - -func WrapMeterImpl(impl MeterImpl) metric.Meter { - return meter{impl} -} - -func UnwrapMeterImpl(m metric.Meter) MeterImpl { - mm, ok := m.(meter) - if !ok { - return nil - } - return mm.MeterImpl -} - -func (m meter) AsyncFloat64() asyncfloat64.InstrumentProvider { - return afMeter{m} -} - -func (m meter) AsyncInt64() asyncint64.InstrumentProvider { - return aiMeter{m} -} - -func (m meter) SyncFloat64() syncfloat64.InstrumentProvider { - return sfMeter{m} -} - -func (m meter) SyncInt64() syncint64.InstrumentProvider { - return siMeter{m} -} - -func (m meter) RegisterCallback(insts []instrument.Asynchronous, cb func(ctx context.Context)) error { - return m.MeterImpl.RegisterCallback(insts, cb) -} - -func (m meter) newSync(name string, ikind InstrumentKind, nkind number.Kind, opts []instrument.Option) (SyncImpl, error) { - cfg := instrument.NewConfig(opts...) - return m.NewSyncInstrument(NewDescriptor(name, ikind, nkind, cfg.Description(), cfg.Unit())) -} - -func (m meter) newAsync(name string, ikind InstrumentKind, nkind number.Kind, opts []instrument.Option) (AsyncImpl, error) { - cfg := instrument.NewConfig(opts...) - return m.NewAsyncInstrument(NewDescriptor(name, ikind, nkind, cfg.Description(), cfg.Unit())) -} - -func (m afMeter) Counter(name string, opts ...instrument.Option) (asyncfloat64.Counter, error) { - inst, err := m.newAsync(name, CounterObserverInstrumentKind, number.Float64Kind, opts) - return fObserver{inst}, err -} - -func (m afMeter) UpDownCounter(name string, opts ...instrument.Option) (asyncfloat64.UpDownCounter, error) { - inst, err := m.newAsync(name, UpDownCounterObserverInstrumentKind, number.Float64Kind, opts) - return fObserver{inst}, err -} - -func (m afMeter) Gauge(name string, opts ...instrument.Option) (asyncfloat64.Gauge, error) { - inst, err := m.newAsync(name, GaugeObserverInstrumentKind, number.Float64Kind, opts) - return fObserver{inst}, err -} - -func (m aiMeter) Counter(name string, opts ...instrument.Option) (asyncint64.Counter, error) { - inst, err := m.newAsync(name, CounterObserverInstrumentKind, number.Int64Kind, opts) - return iObserver{inst}, err -} - -func (m aiMeter) UpDownCounter(name string, opts ...instrument.Option) (asyncint64.UpDownCounter, error) { - inst, err := m.newAsync(name, UpDownCounterObserverInstrumentKind, number.Int64Kind, opts) - return iObserver{inst}, err -} - -func (m aiMeter) Gauge(name string, opts ...instrument.Option) (asyncint64.Gauge, error) { - inst, err := m.newAsync(name, GaugeObserverInstrumentKind, number.Int64Kind, opts) - return iObserver{inst}, err -} - -func (m sfMeter) Counter(name string, opts ...instrument.Option) (syncfloat64.Counter, error) { - inst, err := m.newSync(name, CounterInstrumentKind, number.Float64Kind, opts) - return fAdder{inst}, err -} - -func (m sfMeter) UpDownCounter(name string, opts ...instrument.Option) (syncfloat64.UpDownCounter, error) { - inst, err := m.newSync(name, UpDownCounterInstrumentKind, number.Float64Kind, opts) - return fAdder{inst}, err -} - -func (m sfMeter) Histogram(name string, opts ...instrument.Option) (syncfloat64.Histogram, error) { - inst, err := m.newSync(name, HistogramInstrumentKind, number.Float64Kind, opts) - return fRecorder{inst}, err -} - -func (m siMeter) Counter(name string, opts ...instrument.Option) (syncint64.Counter, error) { - inst, err := m.newSync(name, CounterInstrumentKind, number.Int64Kind, opts) - return iAdder{inst}, err -} - -func (m siMeter) UpDownCounter(name string, opts ...instrument.Option) (syncint64.UpDownCounter, error) { - inst, err := m.newSync(name, UpDownCounterInstrumentKind, number.Int64Kind, opts) - return iAdder{inst}, err -} - -func (m siMeter) Histogram(name string, opts ...instrument.Option) (syncint64.Histogram, error) { - inst, err := m.newSync(name, HistogramInstrumentKind, number.Int64Kind, opts) - return iRecorder{inst}, err -} - -func (a fAdder) Add(ctx context.Context, value float64, attrs ...attribute.KeyValue) { - if a.SyncImpl != nil { - a.SyncImpl.RecordOne(ctx, number.NewFloat64Number(value), attrs) - } -} - -func (a iAdder) Add(ctx context.Context, value int64, attrs ...attribute.KeyValue) { - if a.SyncImpl != nil { - a.SyncImpl.RecordOne(ctx, number.NewInt64Number(value), attrs) - } -} - -func (a fRecorder) Record(ctx context.Context, value float64, attrs ...attribute.KeyValue) { - if a.SyncImpl != nil { - a.SyncImpl.RecordOne(ctx, number.NewFloat64Number(value), attrs) - } -} - -func (a iRecorder) Record(ctx context.Context, value int64, attrs ...attribute.KeyValue) { - if a.SyncImpl != nil { - a.SyncImpl.RecordOne(ctx, number.NewInt64Number(value), attrs) - } -} - -func (a fObserver) Observe(ctx context.Context, value float64, attrs ...attribute.KeyValue) { - if a.AsyncImpl != nil { - a.AsyncImpl.ObserveOne(ctx, number.NewFloat64Number(value), attrs) - } -} - -func (a iObserver) Observe(ctx context.Context, value int64, attrs ...attribute.KeyValue) { - if a.AsyncImpl != nil { - a.AsyncImpl.ObserveOne(ctx, number.NewInt64Number(value), attrs) - } -} diff --git a/sdk/metric/selector/simple/simple.go b/sdk/metric/selector/simple/simple.go deleted file mode 100644 index 5451072f607..00000000000 --- a/sdk/metric/selector/simple/simple.go +++ /dev/null @@ -1,94 +0,0 @@ -// 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 simple // import "go.opentelemetry.io/otel/sdk/metric/selector/simple" - -import ( - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" - "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" -) - -type ( - selectorInexpensive struct{} - selectorHistogram struct { - options []histogram.Option - } -) - -var ( - _ export.AggregatorSelector = selectorInexpensive{} - _ export.AggregatorSelector = selectorHistogram{} -) - -// NewWithInexpensiveDistribution returns a simple aggregator selector -// that uses minmaxsumcount aggregators for `Histogram` -// instruments. This selector is faster and uses less memory than the -// others in this package because minmaxsumcount aggregators maintain -// the least information about the distribution among these choices. -func NewWithInexpensiveDistribution() export.AggregatorSelector { - return selectorInexpensive{} -} - -// NewWithHistogramDistribution returns a simple aggregator selector -// that uses histogram aggregators for `Histogram` instruments. -// This selector is a good default choice for most metric exporters. -func NewWithHistogramDistribution(options ...histogram.Option) export.AggregatorSelector { - return selectorHistogram{options: options} -} - -func sumAggs(aggPtrs []*aggregator.Aggregator) { - aggs := sum.New(len(aggPtrs)) - for i := range aggPtrs { - *aggPtrs[i] = &aggs[i] - } -} - -func lastValueAggs(aggPtrs []*aggregator.Aggregator) { - aggs := lastvalue.New(len(aggPtrs)) - for i := range aggPtrs { - *aggPtrs[i] = &aggs[i] - } -} - -func (selectorInexpensive) AggregatorFor(descriptor *sdkapi.Descriptor, aggPtrs ...*aggregator.Aggregator) { - switch descriptor.InstrumentKind() { - case sdkapi.GaugeObserverInstrumentKind: - lastValueAggs(aggPtrs) - case sdkapi.HistogramInstrumentKind: - aggs := sum.New(len(aggPtrs)) - for i := range aggPtrs { - *aggPtrs[i] = &aggs[i] - } - default: - sumAggs(aggPtrs) - } -} - -func (s selectorHistogram) AggregatorFor(descriptor *sdkapi.Descriptor, aggPtrs ...*aggregator.Aggregator) { - switch descriptor.InstrumentKind() { - case sdkapi.GaugeObserverInstrumentKind: - lastValueAggs(aggPtrs) - case sdkapi.HistogramInstrumentKind: - aggs := histogram.New(len(aggPtrs), descriptor, s.options...) - for i := range aggPtrs { - *aggPtrs[i] = &aggs[i] - } - default: - sumAggs(aggPtrs) - } -} diff --git a/sdk/metric/selector/simple/simple_test.go b/sdk/metric/selector/simple/simple_test.go deleted file mode 100644 index 9e946864e53..00000000000 --- a/sdk/metric/selector/simple/simple_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// 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 simple_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "go.opentelemetry.io/otel/sdk/metric/aggregator" - "go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" - "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" - "go.opentelemetry.io/otel/sdk/metric/aggregator/sum" - "go.opentelemetry.io/otel/sdk/metric/export" - "go.opentelemetry.io/otel/sdk/metric/metrictest" - "go.opentelemetry.io/otel/sdk/metric/number" - "go.opentelemetry.io/otel/sdk/metric/sdkapi" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" -) - -var ( - testCounterDesc = metrictest.NewDescriptor("counter", sdkapi.CounterInstrumentKind, number.Int64Kind) - testUpDownCounterDesc = metrictest.NewDescriptor("updowncounter", sdkapi.UpDownCounterInstrumentKind, number.Int64Kind) - testCounterObserverDesc = metrictest.NewDescriptor("counterobserver", sdkapi.CounterObserverInstrumentKind, number.Int64Kind) - testUpDownCounterObserverDesc = metrictest.NewDescriptor("updowncounterobserver", sdkapi.UpDownCounterObserverInstrumentKind, number.Int64Kind) - testHistogramDesc = metrictest.NewDescriptor("histogram", sdkapi.HistogramInstrumentKind, number.Int64Kind) - testGaugeObserverDesc = metrictest.NewDescriptor("gauge", sdkapi.GaugeObserverInstrumentKind, number.Int64Kind) -) - -func oneAgg(sel export.AggregatorSelector, desc *sdkapi.Descriptor) aggregator.Aggregator { - var agg aggregator.Aggregator - sel.AggregatorFor(desc, &agg) - return agg -} - -func testFixedSelectors(t *testing.T, sel export.AggregatorSelector) { - require.IsType(t, (*lastvalue.Aggregator)(nil), oneAgg(sel, &testGaugeObserverDesc)) - require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testCounterDesc)) - require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testUpDownCounterDesc)) - require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testCounterObserverDesc)) - require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testUpDownCounterObserverDesc)) -} - -func TestInexpensiveDistribution(t *testing.T) { - inex := simple.NewWithInexpensiveDistribution() - require.IsType(t, (*sum.Aggregator)(nil), oneAgg(inex, &testHistogramDesc)) - testFixedSelectors(t, inex) -} - -func TestHistogramDistribution(t *testing.T) { - hist := simple.NewWithHistogramDistribution() - require.IsType(t, (*histogram.Aggregator)(nil), oneAgg(hist, &testHistogramDesc)) - testFixedSelectors(t, hist) -}