From c38abde14b8cf04b7129fa0a2547f7a9bcce971a Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 21 May 2020 09:45:24 -0700 Subject: [PATCH 01/11] Proof of concept --- exporters/otlp/go.mod | 1 + exporters/otlp/go.sum | 2 + exporters/otlp/options.go | 45 +++++++ exporters/otlp/otlp.go | 11 +- exporters/otlp/otlp_integration_test.go | 30 ++++- exporters/otlp/testing/collector_suite.go | 144 ++++++++++++++++++++++ exporters/otlp/testing/server.go | 134 ++++++++++++++++++++ 7 files changed, 363 insertions(+), 4 deletions(-) create mode 100644 exporters/otlp/testing/collector_suite.go create mode 100644 exporters/otlp/testing/server.go diff --git a/exporters/otlp/go.mod b/exporters/otlp/go.mod index f16ea562d8f..eab7d4e7721 100644 --- a/exporters/otlp/go.mod +++ b/exporters/otlp/go.mod @@ -10,6 +10,7 @@ require ( github.com/open-telemetry/opentelemetry-proto v0.3.0 github.com/stretchr/testify v1.4.0 go.opentelemetry.io/otel v0.5.0 + golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect golang.org/x/text v0.3.2 // indirect google.golang.org/grpc v1.27.1 ) diff --git a/exporters/otlp/go.sum b/exporters/otlp/go.sum index 9efdf481db6..0e2260fee8f 100644 --- a/exporters/otlp/go.sum +++ b/exporters/otlp/go.sum @@ -71,6 +71,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= diff --git a/exporters/otlp/options.go b/exporters/otlp/options.go index d809ec0a209..76648f9b51c 100644 --- a/exporters/otlp/options.go +++ b/exporters/otlp/options.go @@ -25,6 +25,43 @@ const ( DefaultCollectorPort uint16 = 55680 DefaultCollectorHost string = "localhost" DefaultNumWorkers uint = 1 + + // For more info on gRPC service configs: + // https://github.com/grpc/proposal/blob/master/A6-client-retries.md + // + // For more info on the RetryableStatusCodes we allow here: + // https://github.com/open-telemetry/oteps/blob/be2a3fcbaa417ebbf5845cd485d34fdf0ab4a2a4/text/0035-opentelemetry-protocol.md#export-response + DefaultGRPCServiceConfig = `{ + "methodConfig":[ + { + "name":[ + { + "service":"opentelemetry.proto.collector.metrics.v1.MetricsService" + }, + { + "service":"opentelemetry.proto.collector.trace.v1.TraceService" + } + ], + "waitForReady": true, + "retryPolicy":{ + "MaxAttempts":4, + "InitialBackoff":".01s", + "MaxBackoff":"1.0s", + "BackoffMultiplier":1.0, + "RetryableStatusCodes":[ + "UNAVAILABLE", + "CANCELLED", + "DEADLINE_EXCEEDED", + "RESOURCE_EXHAUSTED", + "ABORTED", + "OUT_OF_RANGE", + "UNAVAILABLE", + "DATA_LOSS" + ] + } + } + ] +}` ) type ExporterOption func(*Config) @@ -34,6 +71,7 @@ type Config struct { collectorAddr string compressor string reconnectionPeriod time.Duration + grpcServiceConfig string grpcDialOptions []grpc.DialOption headers map[string]string clientCredentials credentials.TransportCredentials @@ -106,6 +144,13 @@ func WithTLSCredentials(creds credentials.TransportCredentials) ExporterOption { } } +// WithGRPCServiceConfig defines the default gRPC service config used. +func WithGRPCServiceConfig(serviceConfig string) ExporterOption { + return func(cfg *Config) { + cfg.grpcServiceConfig = serviceConfig + } +} + // WithGRPCDialOption opens support to any grpc.DialOption to be used. If it conflicts // with some other configuration the GRPC specified via the collector the ones here will // take preference since they are set last. diff --git a/exporters/otlp/otlp.go b/exporters/otlp/otlp.go index d0e83f94475..0c4d9a30a68 100644 --- a/exporters/otlp/otlp.go +++ b/exporters/otlp/otlp.go @@ -72,7 +72,10 @@ func NewExporter(opts ...ExporterOption) (*Exporter, error) { func NewUnstartedExporter(opts ...ExporterOption) *Exporter { e := new(Exporter) - e.c = Config{numWorkers: DefaultNumWorkers} + e.c = Config{ + numWorkers: DefaultNumWorkers, + grpcServiceConfig: DefaultGRPCServiceConfig, + } configureOptions(&e.c, opts...) // TODO (rghetia): add resources @@ -157,7 +160,11 @@ func (e *Exporter) enableConnections(cc *grpc.ClientConn) error { func (e *Exporter) dialToCollector() (*grpc.ClientConn, error) { addr := e.prepareCollectorAddress() - var dialOpts []grpc.DialOption + + dialOpts := []grpc.DialOption{} + if e.c.grpcServiceConfig != "" { + dialOpts = append(dialOpts, grpc.WithDefaultServiceConfig(e.c.grpcServiceConfig)) + } if e.c.clientCredentials != nil { dialOpts = append(dialOpts, grpc.WithTransportCredentials(e.c.clientCredentials)) } else if e.c.canDialInsecure { diff --git a/exporters/otlp/otlp_integration_test.go b/exporters/otlp/otlp_integration_test.go index 081437c71a3..c0ddb85c5d2 100644 --- a/exporters/otlp/otlp_integration_test.go +++ b/exporters/otlp/otlp_integration_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" @@ -30,6 +31,7 @@ import ( "go.opentelemetry.io/otel/api/metric" metricapi "go.opentelemetry.io/otel/api/metric" "go.opentelemetry.io/otel/exporters/otlp" + otlp_testing "go.opentelemetry.io/otel/exporters/otlp/testing" exporttrace "go.opentelemetry.io/otel/sdk/export/trace" "go.opentelemetry.io/otel/sdk/metric/controller/push" integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple" @@ -37,6 +39,28 @@ import ( sdktrace "go.opentelemetry.io/otel/sdk/trace" ) +func TestIntegrationTestSuite(t *testing.T) { + s := &IntegrationTestSuite{ + CollectorTestSuite: &otlp_testing.CollectorTestSuite{}, + } + suite.Run(t, s) +} + +type IntegrationTestSuite struct { + *otlp_testing.CollectorTestSuite +} + +func (s *IntegrationTestSuite) TestSpanExport() { + tracer := s.TraceProvider.Tracer("test") + _, span := tracer.Start(context.Background(), "test/span") + span.End() + s.Len(s.TraceService.GetResourceSpans(), 1) + /* TODO: + * Maybe do a TraceSuite and a MetricSuite (embeed a generic suite). + * Have a failure server that can fail on a modulo of calls: https://github.com/grpc/grpc-go/blob/master/examples/features/retry/server/main.go + */ +} + func TestNewExporter_endToEnd(t *testing.T) { tests := []struct { name string @@ -55,7 +79,7 @@ func TestNewExporter_endToEnd(t *testing.T) { } func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption) { - mc := runMockColAtAddr(t, "localhost:56561") + mc := runMockColAtAddr(t, "127.0.0.1:56561") defer func() { _ = mc.stop() @@ -304,7 +328,9 @@ func TestNewExporter_collectorConnectionDiesThenReconnects(t *testing.T) { reconnectionPeriod := 20 * time.Millisecond exp, err := otlp.NewExporter(otlp.WithInsecure(), otlp.WithAddress(mc.address), - otlp.WithReconnectionPeriod(reconnectionPeriod)) + otlp.WithReconnectionPeriod(reconnectionPeriod), + otlp.WithGRPCServiceConfig(""), + ) if err != nil { t.Fatalf("Unexpected error: %v", err) } diff --git a/exporters/otlp/testing/collector_suite.go b/exporters/otlp/testing/collector_suite.go new file mode 100644 index 00000000000..b6581c19bd2 --- /dev/null +++ b/exporters/otlp/testing/collector_suite.go @@ -0,0 +1,144 @@ +// 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 otlp_testing + +import ( + "net" + "time" + + colmetricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1" + coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" + tracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "go.opentelemetry.io/otel/api/metric" + "go.opentelemetry.io/otel/exporters/otlp" + "go.opentelemetry.io/otel/sdk/metric/controller/push" + integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple" + "go.opentelemetry.io/otel/sdk/metric/selector/simple" + "go.opentelemetry.io/otel/sdk/trace" + "google.golang.org/grpc" +) + +// Let the system define the port +const defaultServerAddr = "127.0.0.1:0" + +type CollectorTestSuite struct { + suite.Suite + + TraceService *TraceService + MetricService *MetricService + + ServerOpts []grpc.ServerOption + serverAddr string + ServerListener net.Listener + Server *grpc.Server + + ExporterOpts []otlp.ExporterOption + Exporter *otlp.Exporter + + TraceProvider *trace.Provider + MetricProvider metric.Provider + metricController *push.Controller +} + +func (s *CollectorTestSuite) SetupSuite() { + s.serverAddr = defaultServerAddr + + var err error + s.ServerListener, err = net.Listen("tcp", s.serverAddr) + s.serverAddr = s.ServerListener.Addr().String() + require.NoError(s.T(), err, "failed to allocate a port for server") + + s.Server = grpc.NewServer(s.ServerOpts...) + + if s.TraceService == nil { + s.TraceService = &TraceService{ + T: s.T(), + rsm: map[string]*tracepb.ResourceSpans{}, + } + } + coltracepb.RegisterTraceServiceServer(s.Server, s.TraceService) + + if s.MetricService == nil { + s.MetricService = &MetricService{T: s.T()} + } + colmetricpb.RegisterMetricsServiceServer(s.Server, s.MetricService) + + go func() { + s.Server.Serve(s.ServerListener) + }() + + if s.Exporter == nil { + s.Exporter = s.NewExporter() + } + + if s.TraceProvider == nil { + s.TraceProvider = s.NewTraceProvider(s.Exporter, nil) + } + + if s.MetricProvider == nil { + s.metricController = s.NewPushController(s.Exporter, nil) + s.metricController.SetErrorHandler(func(err error) { + s.T().Errorf("testing push controller: %w", err) + }) + s.metricController.Start() + s.MetricProvider = s.metricController.Provider() + } +} + +func (s *CollectorTestSuite) ServerAddr() string { + return s.serverAddr +} + +func (s *CollectorTestSuite) NewExporter() *otlp.Exporter { + opts := []otlp.ExporterOption{ + otlp.WithInsecure(), + otlp.WithAddress(s.serverAddr), + otlp.WithReconnectionPeriod(10 * time.Millisecond), + } + exp, err := otlp.NewExporter(append(opts, s.ExporterOpts...)...) + require.NoError(s.T(), err, "failed to create exporter") + return exp +} + +func (s *CollectorTestSuite) NewTraceProvider(exp *otlp.Exporter, opts []trace.ProviderOption) *trace.Provider { + defaultOpts := []trace.ProviderOption{ + trace.WithConfig( + trace.Config{ + DefaultSampler: trace.AlwaysSample(), + }, + ), + trace.WithSyncer(exp), + } + p, err := trace.NewProvider(append(defaultOpts, opts...)...) + require.NoError(s.T(), err, "failed to create trace provider") + return p +} + +func (s *CollectorTestSuite) NewPushController(exp *otlp.Exporter, opts []push.Option) *push.Controller { + integrator := integrator.New(simple.NewWithExactDistribution(), true) + pusher := push.New(integrator, exp, opts...) + return pusher +} + +func (s *CollectorTestSuite) TearDownSuite() { + s.metricController.Stop() + if s.ServerListener != nil { + s.Server.GracefulStop() + s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr()) + } + s.Exporter.Stop() +} diff --git a/exporters/otlp/testing/server.go b/exporters/otlp/testing/server.go new file mode 100644 index 00000000000..b329d27be10 --- /dev/null +++ b/exporters/otlp/testing/server.go @@ -0,0 +1,134 @@ +// 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 otlp_testing + +import ( + "context" + "fmt" + "sort" + "sync" + "testing" + + colmetricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1" + coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" + commonpb "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" + metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" + resourcepb "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" + tracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" +) + +var _ coltracepb.TraceServiceServer = (*TraceService)(nil) +var _ colmetricpb.MetricsServiceServer = (*MetricService)(nil) + +var errAlreadyStopped = fmt.Errorf("already stopped") + +type TraceService struct { + T *testing.T + + mu sync.RWMutex + rsm map[string]*tracepb.ResourceSpans +} + +func (ts *TraceService) GetSpans() []*tracepb.Span { + ts.mu.RLock() + defer ts.mu.RUnlock() + spans := []*tracepb.Span{} + for _, rs := range ts.rsm { + spans = append(spans, rs.InstrumentationLibrarySpans[0].Spans...) + } + return spans +} + +func (ts *TraceService) GetResourceSpans() []*tracepb.ResourceSpans { + ts.mu.RLock() + defer ts.mu.RUnlock() + rss := make([]*tracepb.ResourceSpans, 0, len(ts.rsm)) + for _, rs := range ts.rsm { + rss = append(rss, rs) + } + return rss +} + +func (ts *TraceService) Export(ctx context.Context, exp *coltracepb.ExportTraceServiceRequest) (*coltracepb.ExportTraceServiceResponse, error) { + ts.mu.Lock() + defer ts.mu.Unlock() + rss := exp.GetResourceSpans() + for _, rs := range rss { + rstr := resourceString(rs.Resource) + existingRs, ok := ts.rsm[rstr] + if !ok { + ts.rsm[rstr] = rs + // TODO (rghetia): Add support for library Info. + if len(rs.InstrumentationLibrarySpans) == 0 { + rs.InstrumentationLibrarySpans = []*tracepb.InstrumentationLibrarySpans{ + { + Spans: []*tracepb.Span{}, + }, + } + } + } else { + if len(rs.InstrumentationLibrarySpans) > 0 { + existingRs.InstrumentationLibrarySpans[0].Spans = + append(existingRs.InstrumentationLibrarySpans[0].Spans, + rs.InstrumentationLibrarySpans[0].GetSpans()...) + } + } + } + return &coltracepb.ExportTraceServiceResponse{}, nil +} + +func resourceString(res *resourcepb.Resource) string { + sAttrs := sortedAttributes(res.GetAttributes()) + rstr := "" + for _, attr := range sAttrs { + rstr = rstr + attr.String() + + } + return rstr +} + +func sortedAttributes(attrs []*commonpb.AttributeKeyValue) []*commonpb.AttributeKeyValue { + sort.Slice(attrs[:], func(i, j int) bool { + return attrs[i].Key < attrs[j].Key + }) + return attrs +} + +type MetricService struct { + T *testing.T + + mu sync.RWMutex + metrics []*metricpb.Metric +} + +func (ms *MetricService) GetMetrics() []*metricpb.Metric { + // copy in order to not change. + m := make([]*metricpb.Metric, 0, len(ms.metrics)) + ms.mu.RLock() + defer ms.mu.RUnlock() + return append(m, ms.metrics...) +} + +func (ms *MetricService) Export(ctx context.Context, exp *colmetricpb.ExportMetricsServiceRequest) (*colmetricpb.ExportMetricsServiceResponse, error) { + ms.mu.Lock() + for _, rm := range exp.GetResourceMetrics() { + // TODO (rghetia) handle multiple resource and library info. + if len(rm.InstrumentationLibraryMetrics) > 0 { + ms.metrics = append(ms.metrics, rm.InstrumentationLibraryMetrics[0].Metrics...) + } + } + ms.mu.Unlock() + return &colmetricpb.ExportMetricsServiceResponse{}, nil +} From 4bb182a91c54e21dce67c1325b7d5cf076915844 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 21 May 2020 10:31:57 -0700 Subject: [PATCH 02/11] Break up to trace and metric suite --- exporters/otlp/otlp_integration_test.go | 12 +- exporters/otlp/testing/collector_suite.go | 210 +++++++++++++++++----- exporters/otlp/testing/server.go | 134 -------------- 3 files changed, 170 insertions(+), 186 deletions(-) delete mode 100644 exporters/otlp/testing/server.go diff --git a/exporters/otlp/otlp_integration_test.go b/exporters/otlp/otlp_integration_test.go index c0ddb85c5d2..3da3ad323d3 100644 --- a/exporters/otlp/otlp_integration_test.go +++ b/exporters/otlp/otlp_integration_test.go @@ -40,21 +40,21 @@ import ( ) func TestIntegrationTestSuite(t *testing.T) { - s := &IntegrationTestSuite{ - CollectorTestSuite: &otlp_testing.CollectorTestSuite{}, + s := &TraceIntegrationTestSuite{ + TraceSuite: &otlp_testing.TraceSuite{}, } suite.Run(t, s) } -type IntegrationTestSuite struct { - *otlp_testing.CollectorTestSuite +type TraceIntegrationTestSuite struct { + *otlp_testing.TraceSuite } -func (s *IntegrationTestSuite) TestSpanExport() { +func (s *TraceIntegrationTestSuite) TestSpanExport() { tracer := s.TraceProvider.Tracer("test") _, span := tracer.Start(context.Background(), "test/span") span.End() - s.Len(s.TraceService.GetResourceSpans(), 1) + s.Len(s.GetResourceSpans(), 1) /* TODO: * Maybe do a TraceSuite and a MetricSuite (embeed a generic suite). * Have a failure server that can fail on a modulo of calls: https://github.com/grpc/grpc-go/blob/master/examples/features/retry/server/main.go diff --git a/exporters/otlp/testing/collector_suite.go b/exporters/otlp/testing/collector_suite.go index b6581c19bd2..604f3b61d7d 100644 --- a/exporters/otlp/testing/collector_suite.go +++ b/exporters/otlp/testing/collector_suite.go @@ -15,11 +15,17 @@ package otlp_testing import ( + "context" "net" + "sort" + "sync" "time" colmetricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1" coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" + commonpb "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" + metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" + resourcepb "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" tracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -35,12 +41,9 @@ import ( // Let the system define the port const defaultServerAddr = "127.0.0.1:0" -type CollectorTestSuite struct { +type ServerSuite struct { suite.Suite - TraceService *TraceService - MetricService *MetricService - ServerOpts []grpc.ServerOption serverAddr string ServerListener net.Listener @@ -48,13 +51,9 @@ type CollectorTestSuite struct { ExporterOpts []otlp.ExporterOption Exporter *otlp.Exporter - - TraceProvider *trace.Provider - MetricProvider metric.Provider - metricController *push.Controller } -func (s *CollectorTestSuite) SetupSuite() { +func (s *ServerSuite) SetupSuite() { s.serverAddr = defaultServerAddr var err error @@ -63,20 +62,9 @@ func (s *CollectorTestSuite) SetupSuite() { require.NoError(s.T(), err, "failed to allocate a port for server") s.Server = grpc.NewServer(s.ServerOpts...) +} - if s.TraceService == nil { - s.TraceService = &TraceService{ - T: s.T(), - rsm: map[string]*tracepb.ResourceSpans{}, - } - } - coltracepb.RegisterTraceServiceServer(s.Server, s.TraceService) - - if s.MetricService == nil { - s.MetricService = &MetricService{T: s.T()} - } - colmetricpb.RegisterMetricsServiceServer(s.Server, s.MetricService) - +func (s *ServerSuite) StartServer() { go func() { s.Server.Serve(s.ServerListener) }() @@ -84,26 +72,13 @@ func (s *CollectorTestSuite) SetupSuite() { if s.Exporter == nil { s.Exporter = s.NewExporter() } - - if s.TraceProvider == nil { - s.TraceProvider = s.NewTraceProvider(s.Exporter, nil) - } - - if s.MetricProvider == nil { - s.metricController = s.NewPushController(s.Exporter, nil) - s.metricController.SetErrorHandler(func(err error) { - s.T().Errorf("testing push controller: %w", err) - }) - s.metricController.Start() - s.MetricProvider = s.metricController.Provider() - } } -func (s *CollectorTestSuite) ServerAddr() string { +func (s *ServerSuite) ServerAddr() string { return s.serverAddr } -func (s *CollectorTestSuite) NewExporter() *otlp.Exporter { +func (s *ServerSuite) NewExporter() *otlp.Exporter { opts := []otlp.ExporterOption{ otlp.WithInsecure(), otlp.WithAddress(s.serverAddr), @@ -114,7 +89,37 @@ func (s *CollectorTestSuite) NewExporter() *otlp.Exporter { return exp } -func (s *CollectorTestSuite) NewTraceProvider(exp *otlp.Exporter, opts []trace.ProviderOption) *trace.Provider { +func (s *ServerSuite) TearDownSuite() { + if s.ServerListener != nil { + s.Server.GracefulStop() + s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr()) + } + s.Exporter.Stop() +} + +type TraceSuite struct { + ServerSuite + + TraceProvider *trace.Provider + + mu sync.RWMutex + resourceSpanMap map[string]*tracepb.ResourceSpans +} + +func (ts *TraceSuite) SetupSuite() { + ts.ServerSuite.SetupSuite() + + ts.Reset() + coltracepb.RegisterTraceServiceServer(ts.Server, ts) + + ts.ServerSuite.StartServer() + + if ts.TraceProvider == nil { + ts.TraceProvider = ts.NewTraceProvider(ts.Exporter, nil) + } +} + +func (ts *TraceSuite) NewTraceProvider(exp *otlp.Exporter, opts []trace.ProviderOption) *trace.Provider { defaultOpts := []trace.ProviderOption{ trace.WithConfig( trace.Config{ @@ -124,21 +129,134 @@ func (s *CollectorTestSuite) NewTraceProvider(exp *otlp.Exporter, opts []trace.P trace.WithSyncer(exp), } p, err := trace.NewProvider(append(defaultOpts, opts...)...) - require.NoError(s.T(), err, "failed to create trace provider") + require.NoError(ts.T(), err, "failed to create trace provider") return p } -func (s *CollectorTestSuite) NewPushController(exp *otlp.Exporter, opts []push.Option) *push.Controller { +func (ts *TraceSuite) Reset() { + ts.resourceSpanMap = map[string]*tracepb.ResourceSpans{} +} + +func (ts *TraceSuite) GetSpans() []*tracepb.Span { + ts.mu.RLock() + defer ts.mu.RUnlock() + spans := []*tracepb.Span{} + for _, rs := range ts.resourceSpanMap { + for _, ils := range rs.InstrumentationLibrarySpans { + spans = append(spans, ils.Spans...) + } + } + return spans +} + +func (ts *TraceSuite) GetResourceSpans() []*tracepb.ResourceSpans { + ts.mu.RLock() + defer ts.mu.RUnlock() + rss := make([]*tracepb.ResourceSpans, 0, len(ts.resourceSpanMap)) + for _, rs := range ts.resourceSpanMap { + rss = append(rss, rs) + } + return rss +} + +func (ts *TraceSuite) Export(ctx context.Context, req *coltracepb.ExportTraceServiceRequest) (*coltracepb.ExportTraceServiceResponse, error) { + ts.mu.Lock() + defer ts.mu.Unlock() + rss := req.GetResourceSpans() + for _, rs := range rss { + rstr := resourceString(rs.Resource) + existingRs, ok := ts.resourceSpanMap[rstr] + if !ok { + ts.resourceSpanMap[rstr] = rs + // TODO (rghetia): Add support for library Info. + if len(rs.InstrumentationLibrarySpans) == 0 { + rs.InstrumentationLibrarySpans = []*tracepb.InstrumentationLibrarySpans{ + { + Spans: []*tracepb.Span{}, + }, + } + } + } else { + if len(rs.InstrumentationLibrarySpans) > 0 { + existingRs.InstrumentationLibrarySpans[0].Spans = + append(existingRs.InstrumentationLibrarySpans[0].Spans, + rs.InstrumentationLibrarySpans[0].GetSpans()...) + } + } + } + return &coltracepb.ExportTraceServiceResponse{}, nil +} + +func resourceString(res *resourcepb.Resource) string { + sAttrs := sortedAttributes(res.GetAttributes()) + rstr := "" + for _, attr := range sAttrs { + rstr = rstr + attr.String() + + } + return rstr +} + +func sortedAttributes(attrs []*commonpb.AttributeKeyValue) []*commonpb.AttributeKeyValue { + sort.Slice(attrs[:], func(i, j int) bool { + return attrs[i].Key < attrs[j].Key + }) + return attrs +} + +type MetricSuite struct { + ServerSuite + + MetricProvider metric.Provider + metricController *push.Controller + + mu sync.RWMutex + metrics []*metricpb.Metric +} + +func (ms *MetricSuite) SetupSuite() { + ms.ServerSuite.SetupSuite() + + colmetricpb.RegisterMetricsServiceServer(ms.Server, ms) + + ms.ServerSuite.StartServer() + + if ms.MetricProvider == nil { + ms.metricController = ms.NewPushController(ms.Exporter, nil) + ms.metricController.SetErrorHandler(func(err error) { + ms.T().Errorf("testing push controller: %w", err) + }) + ms.metricController.Start() + ms.MetricProvider = ms.metricController.Provider() + } +} + +func (ms *MetricSuite) NewPushController(exp *otlp.Exporter, opts []push.Option) *push.Controller { integrator := integrator.New(simple.NewWithExactDistribution(), true) pusher := push.New(integrator, exp, opts...) return pusher } -func (s *CollectorTestSuite) TearDownSuite() { - s.metricController.Stop() - if s.ServerListener != nil { - s.Server.GracefulStop() - s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr()) +func (ms *MetricSuite) GetMetrics() []*metricpb.Metric { + // copy in order to not change. + m := make([]*metricpb.Metric, 0, len(ms.metrics)) + ms.mu.RLock() + defer ms.mu.RUnlock() + return append(m, ms.metrics...) +} + +func (ms *MetricSuite) Export(ctx context.Context, exp *colmetricpb.ExportMetricsServiceRequest) (*colmetricpb.ExportMetricsServiceResponse, error) { + ms.mu.Lock() + for _, rm := range exp.GetResourceMetrics() { + // TODO (rghetia) handle multiple resource and library info. + if len(rm.InstrumentationLibraryMetrics) > 0 { + ms.metrics = append(ms.metrics, rm.InstrumentationLibraryMetrics[0].Metrics...) + } } - s.Exporter.Stop() + ms.mu.Unlock() + return &colmetricpb.ExportMetricsServiceResponse{}, nil +} +func (ms *MetricSuite) TearDownSuite() { + ms.metricController.Stop() + ms.ServerSuite.TearDownSuite() } diff --git a/exporters/otlp/testing/server.go b/exporters/otlp/testing/server.go deleted file mode 100644 index b329d27be10..00000000000 --- a/exporters/otlp/testing/server.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 otlp_testing - -import ( - "context" - "fmt" - "sort" - "sync" - "testing" - - colmetricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1" - coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" - commonpb "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" - metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" - resourcepb "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" - tracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" -) - -var _ coltracepb.TraceServiceServer = (*TraceService)(nil) -var _ colmetricpb.MetricsServiceServer = (*MetricService)(nil) - -var errAlreadyStopped = fmt.Errorf("already stopped") - -type TraceService struct { - T *testing.T - - mu sync.RWMutex - rsm map[string]*tracepb.ResourceSpans -} - -func (ts *TraceService) GetSpans() []*tracepb.Span { - ts.mu.RLock() - defer ts.mu.RUnlock() - spans := []*tracepb.Span{} - for _, rs := range ts.rsm { - spans = append(spans, rs.InstrumentationLibrarySpans[0].Spans...) - } - return spans -} - -func (ts *TraceService) GetResourceSpans() []*tracepb.ResourceSpans { - ts.mu.RLock() - defer ts.mu.RUnlock() - rss := make([]*tracepb.ResourceSpans, 0, len(ts.rsm)) - for _, rs := range ts.rsm { - rss = append(rss, rs) - } - return rss -} - -func (ts *TraceService) Export(ctx context.Context, exp *coltracepb.ExportTraceServiceRequest) (*coltracepb.ExportTraceServiceResponse, error) { - ts.mu.Lock() - defer ts.mu.Unlock() - rss := exp.GetResourceSpans() - for _, rs := range rss { - rstr := resourceString(rs.Resource) - existingRs, ok := ts.rsm[rstr] - if !ok { - ts.rsm[rstr] = rs - // TODO (rghetia): Add support for library Info. - if len(rs.InstrumentationLibrarySpans) == 0 { - rs.InstrumentationLibrarySpans = []*tracepb.InstrumentationLibrarySpans{ - { - Spans: []*tracepb.Span{}, - }, - } - } - } else { - if len(rs.InstrumentationLibrarySpans) > 0 { - existingRs.InstrumentationLibrarySpans[0].Spans = - append(existingRs.InstrumentationLibrarySpans[0].Spans, - rs.InstrumentationLibrarySpans[0].GetSpans()...) - } - } - } - return &coltracepb.ExportTraceServiceResponse{}, nil -} - -func resourceString(res *resourcepb.Resource) string { - sAttrs := sortedAttributes(res.GetAttributes()) - rstr := "" - for _, attr := range sAttrs { - rstr = rstr + attr.String() - - } - return rstr -} - -func sortedAttributes(attrs []*commonpb.AttributeKeyValue) []*commonpb.AttributeKeyValue { - sort.Slice(attrs[:], func(i, j int) bool { - return attrs[i].Key < attrs[j].Key - }) - return attrs -} - -type MetricService struct { - T *testing.T - - mu sync.RWMutex - metrics []*metricpb.Metric -} - -func (ms *MetricService) GetMetrics() []*metricpb.Metric { - // copy in order to not change. - m := make([]*metricpb.Metric, 0, len(ms.metrics)) - ms.mu.RLock() - defer ms.mu.RUnlock() - return append(m, ms.metrics...) -} - -func (ms *MetricService) Export(ctx context.Context, exp *colmetricpb.ExportMetricsServiceRequest) (*colmetricpb.ExportMetricsServiceResponse, error) { - ms.mu.Lock() - for _, rm := range exp.GetResourceMetrics() { - // TODO (rghetia) handle multiple resource and library info. - if len(rm.InstrumentationLibraryMetrics) > 0 { - ms.metrics = append(ms.metrics, rm.InstrumentationLibraryMetrics[0].Metrics...) - } - } - ms.mu.Unlock() - return &colmetricpb.ExportMetricsServiceResponse{}, nil -} From 40324a744abaf2a413c6f2de009c06993d7f5185 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 21 May 2020 10:44:46 -0700 Subject: [PATCH 03/11] Split into different files --- exporters/otlp/testing/metric.go | 85 ++++++++++++ exporters/otlp/testing/server.go | 84 ++++++++++++ .../testing/{collector_suite.go => trace.go} | 126 ------------------ 3 files changed, 169 insertions(+), 126 deletions(-) create mode 100644 exporters/otlp/testing/metric.go create mode 100644 exporters/otlp/testing/server.go rename exporters/otlp/testing/{collector_suite.go => trace.go} (52%) diff --git a/exporters/otlp/testing/metric.go b/exporters/otlp/testing/metric.go new file mode 100644 index 00000000000..dc3ca448176 --- /dev/null +++ b/exporters/otlp/testing/metric.go @@ -0,0 +1,85 @@ +// 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 otlp_testing + +import ( + "context" + "sync" + + colmetricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1" + metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" + "go.opentelemetry.io/otel/api/metric" + "go.opentelemetry.io/otel/exporters/otlp" + "go.opentelemetry.io/otel/sdk/metric/controller/push" + integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple" + "go.opentelemetry.io/otel/sdk/metric/selector/simple" +) + +type MetricSuite struct { + ServerSuite + + MetricProvider metric.Provider + metricController *push.Controller + + mu sync.RWMutex + metrics []*metricpb.Metric +} + +func (ms *MetricSuite) SetupSuite() { + ms.ServerSuite.SetupSuite() + + colmetricpb.RegisterMetricsServiceServer(ms.Server, ms) + + ms.ServerSuite.StartServer() + + if ms.MetricProvider == nil { + ms.metricController = ms.NewPushController(ms.Exporter, nil) + ms.metricController.SetErrorHandler(func(err error) { + ms.T().Errorf("testing push controller: %w", err) + }) + ms.metricController.Start() + ms.MetricProvider = ms.metricController.Provider() + } +} + +func (ms *MetricSuite) NewPushController(exp *otlp.Exporter, opts []push.Option) *push.Controller { + integrator := integrator.New(simple.NewWithExactDistribution(), true) + pusher := push.New(integrator, exp, opts...) + return pusher +} + +func (ms *MetricSuite) GetMetrics() []*metricpb.Metric { + // copy in order to not change. + m := make([]*metricpb.Metric, 0, len(ms.metrics)) + ms.mu.RLock() + defer ms.mu.RUnlock() + return append(m, ms.metrics...) +} + +func (ms *MetricSuite) Export(ctx context.Context, exp *colmetricpb.ExportMetricsServiceRequest) (*colmetricpb.ExportMetricsServiceResponse, error) { + ms.mu.Lock() + for _, rm := range exp.GetResourceMetrics() { + // TODO (rghetia) handle multiple resource and library info. + if len(rm.InstrumentationLibraryMetrics) > 0 { + ms.metrics = append(ms.metrics, rm.InstrumentationLibraryMetrics[0].Metrics...) + } + } + ms.mu.Unlock() + return &colmetricpb.ExportMetricsServiceResponse{}, nil +} +func (ms *MetricSuite) TearDownSuite() { + ms.metricController.Stop() + ms.ServerSuite.TearDownSuite() +} diff --git a/exporters/otlp/testing/server.go b/exporters/otlp/testing/server.go new file mode 100644 index 00000000000..c3fa5d25b7d --- /dev/null +++ b/exporters/otlp/testing/server.go @@ -0,0 +1,84 @@ +// 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 otlp_testing + +import ( + "net" + "time" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "go.opentelemetry.io/otel/exporters/otlp" + "google.golang.org/grpc" +) + +// Let the system define the port +const defaultServerAddr = "127.0.0.1:0" + +type ServerSuite struct { + suite.Suite + + ServerOpts []grpc.ServerOption + serverAddr string + ServerListener net.Listener + Server *grpc.Server + + ExporterOpts []otlp.ExporterOption + Exporter *otlp.Exporter +} + +func (s *ServerSuite) SetupSuite() { + s.serverAddr = defaultServerAddr + + var err error + s.ServerListener, err = net.Listen("tcp", s.serverAddr) + s.serverAddr = s.ServerListener.Addr().String() + require.NoError(s.T(), err, "failed to allocate a port for server") + + s.Server = grpc.NewServer(s.ServerOpts...) +} + +func (s *ServerSuite) StartServer() { + go func() { + s.Server.Serve(s.ServerListener) + }() + + if s.Exporter == nil { + s.Exporter = s.NewExporter() + } +} + +func (s *ServerSuite) ServerAddr() string { + return s.serverAddr +} + +func (s *ServerSuite) NewExporter() *otlp.Exporter { + opts := []otlp.ExporterOption{ + otlp.WithInsecure(), + otlp.WithAddress(s.serverAddr), + otlp.WithReconnectionPeriod(10 * time.Millisecond), + } + exp, err := otlp.NewExporter(append(opts, s.ExporterOpts...)...) + require.NoError(s.T(), err, "failed to create exporter") + return exp +} + +func (s *ServerSuite) TearDownSuite() { + if s.ServerListener != nil { + s.Server.GracefulStop() + s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr()) + } + s.Exporter.Stop() +} diff --git a/exporters/otlp/testing/collector_suite.go b/exporters/otlp/testing/trace.go similarity index 52% rename from exporters/otlp/testing/collector_suite.go rename to exporters/otlp/testing/trace.go index 604f3b61d7d..f92c401b8e5 100644 --- a/exporters/otlp/testing/collector_suite.go +++ b/exporters/otlp/testing/trace.go @@ -16,87 +16,18 @@ package otlp_testing import ( "context" - "net" "sort" "sync" - "time" - colmetricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1" coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" commonpb "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" - metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" resourcepb "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" tracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "go.opentelemetry.io/otel/api/metric" "go.opentelemetry.io/otel/exporters/otlp" - "go.opentelemetry.io/otel/sdk/metric/controller/push" - integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" "go.opentelemetry.io/otel/sdk/trace" - "google.golang.org/grpc" ) -// Let the system define the port -const defaultServerAddr = "127.0.0.1:0" - -type ServerSuite struct { - suite.Suite - - ServerOpts []grpc.ServerOption - serverAddr string - ServerListener net.Listener - Server *grpc.Server - - ExporterOpts []otlp.ExporterOption - Exporter *otlp.Exporter -} - -func (s *ServerSuite) SetupSuite() { - s.serverAddr = defaultServerAddr - - var err error - s.ServerListener, err = net.Listen("tcp", s.serverAddr) - s.serverAddr = s.ServerListener.Addr().String() - require.NoError(s.T(), err, "failed to allocate a port for server") - - s.Server = grpc.NewServer(s.ServerOpts...) -} - -func (s *ServerSuite) StartServer() { - go func() { - s.Server.Serve(s.ServerListener) - }() - - if s.Exporter == nil { - s.Exporter = s.NewExporter() - } -} - -func (s *ServerSuite) ServerAddr() string { - return s.serverAddr -} - -func (s *ServerSuite) NewExporter() *otlp.Exporter { - opts := []otlp.ExporterOption{ - otlp.WithInsecure(), - otlp.WithAddress(s.serverAddr), - otlp.WithReconnectionPeriod(10 * time.Millisecond), - } - exp, err := otlp.NewExporter(append(opts, s.ExporterOpts...)...) - require.NoError(s.T(), err, "failed to create exporter") - return exp -} - -func (s *ServerSuite) TearDownSuite() { - if s.ServerListener != nil { - s.Server.GracefulStop() - s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr()) - } - s.Exporter.Stop() -} - type TraceSuite struct { ServerSuite @@ -203,60 +134,3 @@ func sortedAttributes(attrs []*commonpb.AttributeKeyValue) []*commonpb.Attribute }) return attrs } - -type MetricSuite struct { - ServerSuite - - MetricProvider metric.Provider - metricController *push.Controller - - mu sync.RWMutex - metrics []*metricpb.Metric -} - -func (ms *MetricSuite) SetupSuite() { - ms.ServerSuite.SetupSuite() - - colmetricpb.RegisterMetricsServiceServer(ms.Server, ms) - - ms.ServerSuite.StartServer() - - if ms.MetricProvider == nil { - ms.metricController = ms.NewPushController(ms.Exporter, nil) - ms.metricController.SetErrorHandler(func(err error) { - ms.T().Errorf("testing push controller: %w", err) - }) - ms.metricController.Start() - ms.MetricProvider = ms.metricController.Provider() - } -} - -func (ms *MetricSuite) NewPushController(exp *otlp.Exporter, opts []push.Option) *push.Controller { - integrator := integrator.New(simple.NewWithExactDistribution(), true) - pusher := push.New(integrator, exp, opts...) - return pusher -} - -func (ms *MetricSuite) GetMetrics() []*metricpb.Metric { - // copy in order to not change. - m := make([]*metricpb.Metric, 0, len(ms.metrics)) - ms.mu.RLock() - defer ms.mu.RUnlock() - return append(m, ms.metrics...) -} - -func (ms *MetricSuite) Export(ctx context.Context, exp *colmetricpb.ExportMetricsServiceRequest) (*colmetricpb.ExportMetricsServiceResponse, error) { - ms.mu.Lock() - for _, rm := range exp.GetResourceMetrics() { - // TODO (rghetia) handle multiple resource and library info. - if len(rm.InstrumentationLibraryMetrics) > 0 { - ms.metrics = append(ms.metrics, rm.InstrumentationLibraryMetrics[0].Metrics...) - } - } - ms.mu.Unlock() - return &colmetricpb.ExportMetricsServiceResponse{}, nil -} -func (ms *MetricSuite) TearDownSuite() { - ms.metricController.Stop() - ms.ServerSuite.TearDownSuite() -} From e0256f9e94f8861b1348794e3224f8a6c7946908 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 21 May 2020 12:05:59 -0700 Subject: [PATCH 04/11] First try at a failing suite --- exporters/otlp/otlp_integration_test.go | 49 +++++++++++++++++++++++-- exporters/otlp/testing/server.go | 1 + 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/exporters/otlp/otlp_integration_test.go b/exporters/otlp/otlp_integration_test.go index 3da3ad323d3..4d1d0fce6aa 100644 --- a/exporters/otlp/otlp_integration_test.go +++ b/exporters/otlp/otlp_integration_test.go @@ -24,7 +24,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" "go.opentelemetry.io/otel/api/kv" @@ -40,14 +43,17 @@ import ( ) func TestIntegrationTestSuite(t *testing.T) { - s := &TraceIntegrationTestSuite{ - TraceSuite: &otlp_testing.TraceSuite{}, + ts := &TraceIntegrationTestSuite{} + suite.Run(t, ts) + + fts := &FailingTraceIntegrationTestSuite{ + reqModulo: 14, } - suite.Run(t, s) + suite.Run(t, fts) } type TraceIntegrationTestSuite struct { - *otlp_testing.TraceSuite + otlp_testing.TraceSuite } func (s *TraceIntegrationTestSuite) TestSpanExport() { @@ -61,6 +67,41 @@ func (s *TraceIntegrationTestSuite) TestSpanExport() { */ } +type FailingTraceIntegrationTestSuite struct { + otlp_testing.TraceSuite + + reqCounter uint + reqModulo uint +} + +// FIXME: doesn't get used! the embedded is registered not this. +// probaly need to move this lower in the stack. +func (s *FailingTraceIntegrationTestSuite) Export(ctx context.Context, req *coltracepb.ExportTraceServiceRequest) (*coltracepb.ExportTraceServiceResponse, error) { + + s.T().Logf("deciding: count %d, modulo %d", s.reqCounter, s.reqModulo) + s.reqCounter++ + if (s.reqModulo > 0) && (s.reqCounter%s.reqModulo == 0) { + return s.TraceSuite.Export(ctx, req) + } + + s.T().Logf("failing: count %d, modulo %d", s.reqCounter, s.reqModulo) + + // TODO: make the return code configuable. + return &coltracepb.ExportTraceServiceResponse{}, status.Errorf( + codes.Unavailable, + "FailingTraceIntegrationTestSuite: count %d, modulo %d", + s.reqCounter, s.reqModulo, + ) +} + +func (s *FailingTraceIntegrationTestSuite) TestSpanExport() { + tracer := s.TraceProvider.Tracer("test") + _, span := tracer.Start(context.Background(), "test/span") + span.End() + s.Len(s.GetResourceSpans(), 1) + s.Fail("here") +} + func TestNewExporter_endToEnd(t *testing.T) { tests := []struct { name string diff --git a/exporters/otlp/testing/server.go b/exporters/otlp/testing/server.go index c3fa5d25b7d..1d20a6d2011 100644 --- a/exporters/otlp/testing/server.go +++ b/exporters/otlp/testing/server.go @@ -54,6 +54,7 @@ func (s *ServerSuite) StartServer() { go func() { s.Server.Serve(s.ServerListener) }() + s.T().Logf("started grpc.Server at: %v", s.ServerAddr()) if s.Exporter == nil { s.Exporter = s.NewExporter() From 7cf20c3af9ccbcc1c8807a2dbafa30affb522ef3 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Fri, 29 May 2020 10:13:00 -0700 Subject: [PATCH 05/11] Update README Add information about setup, options, and retries. --- exporters/otlp/README.md | 141 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 4 deletions(-) diff --git a/exporters/otlp/README.md b/exporters/otlp/README.md index 65346556589..7310ea93dc8 100644 --- a/exporters/otlp/README.md +++ b/exporters/otlp/README.md @@ -3,13 +3,146 @@ [![GoDoc](https://godoc.org/go.opentelemetry.io/otel?status.svg)](https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp) -This exporter converts OpenTelemetry [SpanData](https://github.com/open-telemetry/opentelemetry-go/blob/6769330394f78192df01cb59299e9e0f2e5e977b/sdk/export/trace/trace.go#L49) -to OpenTelemetry Protocol [Span](https://github.com/open-telemetry/opentelemetry-proto/blob/c20698d5bb483cf05de1a7c0e134b7c57e359674/opentelemetry/proto/trace/v1/trace.proto#L46) -and exports them to OpenTelemetry Collector. +This exporter exports OpenTelemetry spans and metrics to the OpenTelemetry Collector. -## Installation +## Installation and Setup + +The exporter can be installed using standard `go` functionality. ```bash $ go get -u go.opentelemetry.io/otel/exporters/otlp ``` + +A new exporter can be created using the `NewExporter` function. + +```golang +package main + +import ( + "log" + + "go.opentelemetry.io/otel/exporters/otlp" + "go.opentelemetry.io/otel/sdk/metric/controller/push" + "go.opentelemetry.io/otel/sdk/metric/selector/simple" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +func main() { + exporter, err := otlp.NewExporter() // Configure as needed. + if err != nil { + log.Fatalf("failed to create exporter: %v", err) + } + defer func() { + err := exporter.Stop() + if err != nil { + log.Fatalf("failed to stop exporter: %v", err) + } + }() + + // Note: The exporter can also be used as a Batcher. + traceProvider, err := sdktrace.NewProvider(sdktrace.WithSyncer(exporter)) + if err != nil { + log.Fatal("failed to create trace provider: %v", err) + } + + pusher := push.New(simple.NewWithExactDistribution(), exporter) + pusher.Start() + metricProvider := pusher.Provider() + + // Your code here ... +} +``` + +## Configuration + +Configuratin options can be specified when creating a new exporter (`NewExporter`). + +### `WorkerCount(n uint)` + +Sets the number of Goroutines to use when processing telemetry. + + +### `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. +By default, client security is required unless `WithInsecure` is used. + +### `WithAddress(addr string)` + +Sets the address that the exporter will connect to the collector on. +The default address the exporter connects to is `localhost:55680`. + +### `WithReconnectionPeriod(rp time.Duration)` + +Set the delay between connection attempts after failing to connect with the collector. + +### `WithCompressor(compressor string)` + +Set the compressor for the gRPC client to use when sending requests. +The compressor used needs to have been registered with `google.golang.org/grpc/encoding` prior to using here. +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"`. + +### `WithHeaders(headers map[string]string)` + +Headers to send when the gRPC stream connection is instantiated. + +### `WithTLSCredentials(creds "google.golang.org/grpc/credentials".TransportCredentials)` + +TLS credentials to use when talking to the server. + +### `WithGRPCServiceConfig(serviceConfig string)` + +The default gRPC service config used when . + +By default, the exporter is configured to support [retries](#retries). + +```json +{ + "methodConfig":[{ + "name":[ + { "service":"opentelemetry.proto.collector.metrics.v1.MetricsService" }, + { "service":"opentelemetry.proto.collector.trace.v1.TraceService" } + ], + "waitForReady": true, + "retryPolicy":{ + "MaxAttempts":5, + "InitialBackoff":"0.3s", + "MaxBackoff":"5s", + "BackoffMultiplier":2, + "RetryableStatusCodes":[ + "UNAVAILABLE", + "CANCELLED", + "DEADLINE_EXCEEDED", + "RESOURCE_EXHAUSTED", + "ABORTED", + "OUT_OF_RANGE", + "UNAVAILABLE", + "DATA_LOSS" + ] + } + }] +} +``` + +### `WithGRPCDialOption(opts ..."google.golang.org/grpc".DialOption)` + +Additional `grpc.DialOption` to be used. + +These options take precedence over any other set by other parts of the configuration. + +## Retries + +The exporter will not, by default, retry failed requests to the collector. +However, it is configured in a way that it can easily be enable. + +To enable retries, the `GRPC_GO_RETRY` environment variable needs to be set to `on`. For example, + +``` +GRPC_GO_RETRY=on go run . +``` + +The [default service config](https://github.com/grpc/proposal/blob/master/A6-client-retries.md) used by default is defined to retry failed requests with exponential backoff (`0.3seconds * (2)^retry`) with [a max of `5` retries](https://github.com/open-telemetry/oteps/blob/be2a3fcbaa417ebbf5845cd485d34fdf0ab4a2a4/text/0035-opentelemetry-protocol.md#export-response)). + +These retries are only attempted for reponses that are [deemed "retry-able" by the collector](https://github.com/grpc/proposal/blob/master/A6-client-retries.md#validation-of-retrypolicy). From 07ccb274d2d31383fdcbd12ed925da9515b4779f Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Fri, 29 May 2020 10:17:57 -0700 Subject: [PATCH 06/11] Update options --- exporters/otlp/options.go | 56 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/exporters/otlp/options.go b/exporters/otlp/options.go index 76648f9b51c..a8d8b364ae8 100644 --- a/exporters/otlp/options.go +++ b/exporters/otlp/options.go @@ -31,36 +31,34 @@ const ( // // For more info on the RetryableStatusCodes we allow here: // https://github.com/open-telemetry/oteps/blob/be2a3fcbaa417ebbf5845cd485d34fdf0ab4a2a4/text/0035-opentelemetry-protocol.md#export-response + // + // Note: MaxAttempts > 5 are treated as 5. See + // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#validation-of-retrypolicy + // for more details. DefaultGRPCServiceConfig = `{ - "methodConfig":[ - { - "name":[ - { - "service":"opentelemetry.proto.collector.metrics.v1.MetricsService" - }, - { - "service":"opentelemetry.proto.collector.trace.v1.TraceService" - } - ], - "waitForReady": true, - "retryPolicy":{ - "MaxAttempts":4, - "InitialBackoff":".01s", - "MaxBackoff":"1.0s", - "BackoffMultiplier":1.0, - "RetryableStatusCodes":[ - "UNAVAILABLE", - "CANCELLED", - "DEADLINE_EXCEEDED", - "RESOURCE_EXHAUSTED", - "ABORTED", - "OUT_OF_RANGE", - "UNAVAILABLE", - "DATA_LOSS" - ] - } - } - ] + "methodConfig":[{ + "name":[ + { "service":"opentelemetry.proto.collector.metrics.v1.MetricsService" }, + { "service":"opentelemetry.proto.collector.trace.v1.TraceService" } + ], + "waitForReady": true, + "retryPolicy":{ + "MaxAttempts":5, + "InitialBackoff":"0.3s", + "MaxBackoff":"5s", + "BackoffMultiplier":2, + "RetryableStatusCodes":[ + "UNAVAILABLE", + "CANCELLED", + "DEADLINE_EXCEEDED", + "RESOURCE_EXHAUSTED", + "ABORTED", + "OUT_OF_RANGE", + "UNAVAILABLE", + "DATA_LOSS" + ] + } + }] }` ) From 45a679730d6ff9b836d29ae0e6bed2d77c74dbc1 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Fri, 29 May 2020 10:18:36 -0700 Subject: [PATCH 07/11] "Working" tests with failure Needs to be run `GRPC_GO_RETRY=on go test .` to not fail the failing tests because retries are not enabled by default, nor can they be enabled programmatically. --- exporters/otlp/go.mod | 11 +++-- exporters/otlp/go.sum | 21 +++++++-- exporters/otlp/otlp_integration_test.go | 61 ++++++------------------- exporters/otlp/testing/server.go | 43 +++++++++++++++++ exporters/otlp/testing/trace.go | 4 ++ 5 files changed, 84 insertions(+), 56 deletions(-) diff --git a/exporters/otlp/go.mod b/exporters/otlp/go.mod index eab7d4e7721..f9f1eb25e2c 100644 --- a/exporters/otlp/go.mod +++ b/exporters/otlp/go.mod @@ -4,15 +4,18 @@ replace go.opentelemetry.io/otel => ../.. require ( github.com/gogo/protobuf v1.3.1 - github.com/golang/protobuf v1.3.4 // indirect + github.com/golang/protobuf v1.3.5 // indirect github.com/google/go-cmp v0.4.0 github.com/grpc-ecosystem/grpc-gateway v1.14.3 // indirect + github.com/kr/pretty v0.2.0 // indirect github.com/open-telemetry/opentelemetry-proto v0.3.0 github.com/stretchr/testify v1.4.0 - go.opentelemetry.io/otel v0.5.0 - golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect + go.opentelemetry.io/otel v0.6.0 + golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect + golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 // indirect golang.org/x/text v0.3.2 // indirect - google.golang.org/grpc v1.27.1 + google.golang.org/grpc v1.29.1 + gopkg.in/yaml.v2 v2.2.8 // indirect ) go 1.13 diff --git a/exporters/otlp/go.sum b/exporters/otlp/go.sum index 0e2260fee8f..8013bf03756 100644 --- a/exporters/otlp/go.sum +++ b/exporters/otlp/go.sum @@ -8,10 +8,13 @@ github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiU github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= 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/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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= @@ -23,8 +26,9 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= @@ -37,6 +41,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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= @@ -62,6 +68,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJV golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/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 h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -71,8 +79,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= +golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -96,8 +104,11 @@ google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvx google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -105,5 +116,7 @@ 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.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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/exporters/otlp/otlp_integration_test.go b/exporters/otlp/otlp_integration_test.go index 4d1d0fce6aa..34140fbcfe6 100644 --- a/exporters/otlp/otlp_integration_test.go +++ b/exporters/otlp/otlp_integration_test.go @@ -24,10 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" "go.opentelemetry.io/otel/api/kv" @@ -43,13 +40,20 @@ import ( ) func TestIntegrationTestSuite(t *testing.T) { - ts := &TraceIntegrationTestSuite{} - suite.Run(t, ts) - - fts := &FailingTraceIntegrationTestSuite{ - reqModulo: 14, + /* + standard := &TraceIntegrationTestSuite{} + suite.Run(t, standard) + */ + + // Default retry policy should ensure these succeed. + retry := &TraceIntegrationTestSuite{ + TraceSuite: otlp_testing.TraceSuite{ + ServerSuite: otlp_testing.ServerSuite{ + FailureModulo: 5, + }, + }, } - suite.Run(t, fts) + suite.Run(t, retry) } type TraceIntegrationTestSuite struct { @@ -61,45 +65,6 @@ func (s *TraceIntegrationTestSuite) TestSpanExport() { _, span := tracer.Start(context.Background(), "test/span") span.End() s.Len(s.GetResourceSpans(), 1) - /* TODO: - * Maybe do a TraceSuite and a MetricSuite (embeed a generic suite). - * Have a failure server that can fail on a modulo of calls: https://github.com/grpc/grpc-go/blob/master/examples/features/retry/server/main.go - */ -} - -type FailingTraceIntegrationTestSuite struct { - otlp_testing.TraceSuite - - reqCounter uint - reqModulo uint -} - -// FIXME: doesn't get used! the embedded is registered not this. -// probaly need to move this lower in the stack. -func (s *FailingTraceIntegrationTestSuite) Export(ctx context.Context, req *coltracepb.ExportTraceServiceRequest) (*coltracepb.ExportTraceServiceResponse, error) { - - s.T().Logf("deciding: count %d, modulo %d", s.reqCounter, s.reqModulo) - s.reqCounter++ - if (s.reqModulo > 0) && (s.reqCounter%s.reqModulo == 0) { - return s.TraceSuite.Export(ctx, req) - } - - s.T().Logf("failing: count %d, modulo %d", s.reqCounter, s.reqModulo) - - // TODO: make the return code configuable. - return &coltracepb.ExportTraceServiceResponse{}, status.Errorf( - codes.Unavailable, - "FailingTraceIntegrationTestSuite: count %d, modulo %d", - s.reqCounter, s.reqModulo, - ) -} - -func (s *FailingTraceIntegrationTestSuite) TestSpanExport() { - tracer := s.TraceProvider.Tracer("test") - _, span := tracer.Start(context.Background(), "test/span") - span.End() - s.Len(s.GetResourceSpans(), 1) - s.Fail("here") } func TestNewExporter_endToEnd(t *testing.T) { diff --git a/exporters/otlp/testing/server.go b/exporters/otlp/testing/server.go index 1d20a6d2011..14bdd382577 100644 --- a/exporters/otlp/testing/server.go +++ b/exporters/otlp/testing/server.go @@ -16,12 +16,15 @@ package otlp_testing import ( "net" + "sync/atomic" "time" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "go.opentelemetry.io/otel/exporters/otlp" "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) // Let the system define the port @@ -35,6 +38,10 @@ type ServerSuite struct { ServerListener net.Listener Server *grpc.Server + requestCount uint64 + FailureModulo uint64 + FailureCodes []codes.Code + ExporterOpts []otlp.ExporterOption Exporter *otlp.Exporter } @@ -65,6 +72,42 @@ func (s *ServerSuite) ServerAddr() string { return s.serverAddr } +func (s *ServerSuite) RequestError() error { + if s.FailureModulo <= 0 { + return nil + } + + count := atomic.AddUint64(&s.requestCount, 1) + if count%s.FailureModulo == 0 { + return nil + } + + var c codes.Code + if n := len(s.FailureCodes); n > 0 { + /* Example to understand the indexing: + * - s.FailureModulo = 3 + * - len(s.Codes) 5 + * + * count - 1 | count / s.FailureModulo | index (mod 5) + * =================================================== + * 0 | 0 | 0 + * 1 | 0 | 1 + * 2 | 1 | n/a (2) + * 3 | 1 | 2 + * 4 | 1 | 3 + * 5 | 2 | n/a (3) + * 6 | 2 | 4 + * 7 | 2 | 0 + * 8 | 3 | n/a (0) + * 9 | 3 | 1 + */ + c = s.FailureCodes[(count-1-(count/s.FailureModulo))%uint64(n)] + } else { + c = codes.Unavailable + } + return status.Errorf(c, "artificial error: count %d, modulo %d", count, s.FailureModulo) +} + func (s *ServerSuite) NewExporter() *otlp.Exporter { opts := []otlp.ExporterOption{ otlp.WithInsecure(), diff --git a/exporters/otlp/testing/trace.go b/exporters/otlp/testing/trace.go index f92c401b8e5..9dda7d559ea 100644 --- a/exporters/otlp/testing/trace.go +++ b/exporters/otlp/testing/trace.go @@ -91,6 +91,10 @@ func (ts *TraceSuite) GetResourceSpans() []*tracepb.ResourceSpans { } func (ts *TraceSuite) Export(ctx context.Context, req *coltracepb.ExportTraceServiceRequest) (*coltracepb.ExportTraceServiceResponse, error) { + if err := ts.RequestError(); err != nil { + return nil, err + } + ts.mu.Lock() defer ts.mu.Unlock() rss := req.GetResourceSpans() From 2b1998f1b4d314384c76a50042a3dbacd7fcff67 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Fri, 29 May 2020 10:23:01 -0700 Subject: [PATCH 08/11] Remove tests The lack of programmatic enablement of retries means testing is going to be flaky or cumbersome. --- exporters/otlp/otlp_integration_test.go | 53 +++------ exporters/otlp/testing/metric.go | 85 -------------- exporters/otlp/testing/server.go | 128 ---------------------- exporters/otlp/testing/trace.go | 140 ------------------------ 4 files changed, 13 insertions(+), 393 deletions(-) delete mode 100644 exporters/otlp/testing/metric.go delete mode 100644 exporters/otlp/testing/server.go delete mode 100644 exporters/otlp/testing/trace.go diff --git a/exporters/otlp/otlp_integration_test.go b/exporters/otlp/otlp_integration_test.go index 34140fbcfe6..0f01eeace1b 100644 --- a/exporters/otlp/otlp_integration_test.go +++ b/exporters/otlp/otlp_integration_test.go @@ -23,7 +23,6 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" @@ -31,42 +30,14 @@ import ( "go.opentelemetry.io/otel/api/metric" metricapi "go.opentelemetry.io/otel/api/metric" "go.opentelemetry.io/otel/exporters/otlp" - otlp_testing "go.opentelemetry.io/otel/exporters/otlp/testing" exporttrace "go.opentelemetry.io/otel/sdk/export/trace" "go.opentelemetry.io/otel/sdk/metric/controller/push" integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple" "go.opentelemetry.io/otel/sdk/metric/selector/simple" + "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) -func TestIntegrationTestSuite(t *testing.T) { - /* - standard := &TraceIntegrationTestSuite{} - suite.Run(t, standard) - */ - - // Default retry policy should ensure these succeed. - retry := &TraceIntegrationTestSuite{ - TraceSuite: otlp_testing.TraceSuite{ - ServerSuite: otlp_testing.ServerSuite{ - FailureModulo: 5, - }, - }, - } - suite.Run(t, retry) -} - -type TraceIntegrationTestSuite struct { - otlp_testing.TraceSuite -} - -func (s *TraceIntegrationTestSuite) TestSpanExport() { - tracer := s.TraceProvider.Tracer("test") - _, span := tracer.Start(context.Background(), "test/span") - span.End() - s.Len(s.GetResourceSpans(), 1) -} - func TestNewExporter_endToEnd(t *testing.T) { tests := []struct { name string @@ -85,7 +56,7 @@ func TestNewExporter_endToEnd(t *testing.T) { } func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption) { - mc := runMockColAtAddr(t, "127.0.0.1:56561") + mc := runMockColAtAddr(t, "localhost:56561") defer func() { _ = mc.stop() @@ -116,13 +87,17 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption) ), } tp1, err := sdktrace.NewProvider(append(pOpts, - sdktrace.WithResourceAttributes(kv.String("rk1", "rv11)"), - kv.Int64("rk2", 5)))...) + sdktrace.WithResource(resource.New( + kv.String("rk1", "rv11)"), + kv.Int64("rk2", 5), + )))...) assert.NoError(t, err) tp2, err := sdktrace.NewProvider(append(pOpts, - sdktrace.WithResourceAttributes(kv.String("rk1", "rv12)"), - kv.Float32("rk3", 6.5)))...) + sdktrace.WithResource(resource.New( + kv.String("rk1", "rv12)"), + kv.Float32("rk3", 6.5), + )))...) assert.NoError(t, err) tr1 := tp1.Tracer("test-tracer1") @@ -187,12 +162,12 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption) callback := func(v int64) metricapi.Int64ObserverCallback { return metricapi.Int64ObserverCallback(func(_ context.Context, result metricapi.Int64ObserverResult) { result.Observe(v, labels...) }) }(data.val) - metricapi.Must(meter).RegisterInt64ValueObserver(name, callback) + metricapi.Must(meter).NewInt64ValueObserver(name, callback) case metricapi.Float64NumberKind: callback := func(v float64) metricapi.Float64ObserverCallback { return metricapi.Float64ObserverCallback(func(_ context.Context, result metricapi.Float64ObserverResult) { result.Observe(v, labels...) }) }(float64(data.val)) - metricapi.Must(meter).RegisterFloat64ValueObserver(name, callback) + metricapi.Must(meter).NewFloat64ValueObserver(name, callback) default: assert.Failf(t, "unsupported number testing kind", data.nKind.String()) } @@ -334,9 +309,7 @@ func TestNewExporter_collectorConnectionDiesThenReconnects(t *testing.T) { reconnectionPeriod := 20 * time.Millisecond exp, err := otlp.NewExporter(otlp.WithInsecure(), otlp.WithAddress(mc.address), - otlp.WithReconnectionPeriod(reconnectionPeriod), - otlp.WithGRPCServiceConfig(""), - ) + otlp.WithReconnectionPeriod(reconnectionPeriod)) if err != nil { t.Fatalf("Unexpected error: %v", err) } diff --git a/exporters/otlp/testing/metric.go b/exporters/otlp/testing/metric.go deleted file mode 100644 index dc3ca448176..00000000000 --- a/exporters/otlp/testing/metric.go +++ /dev/null @@ -1,85 +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 otlp_testing - -import ( - "context" - "sync" - - colmetricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1" - metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1" - "go.opentelemetry.io/otel/api/metric" - "go.opentelemetry.io/otel/exporters/otlp" - "go.opentelemetry.io/otel/sdk/metric/controller/push" - integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple" - "go.opentelemetry.io/otel/sdk/metric/selector/simple" -) - -type MetricSuite struct { - ServerSuite - - MetricProvider metric.Provider - metricController *push.Controller - - mu sync.RWMutex - metrics []*metricpb.Metric -} - -func (ms *MetricSuite) SetupSuite() { - ms.ServerSuite.SetupSuite() - - colmetricpb.RegisterMetricsServiceServer(ms.Server, ms) - - ms.ServerSuite.StartServer() - - if ms.MetricProvider == nil { - ms.metricController = ms.NewPushController(ms.Exporter, nil) - ms.metricController.SetErrorHandler(func(err error) { - ms.T().Errorf("testing push controller: %w", err) - }) - ms.metricController.Start() - ms.MetricProvider = ms.metricController.Provider() - } -} - -func (ms *MetricSuite) NewPushController(exp *otlp.Exporter, opts []push.Option) *push.Controller { - integrator := integrator.New(simple.NewWithExactDistribution(), true) - pusher := push.New(integrator, exp, opts...) - return pusher -} - -func (ms *MetricSuite) GetMetrics() []*metricpb.Metric { - // copy in order to not change. - m := make([]*metricpb.Metric, 0, len(ms.metrics)) - ms.mu.RLock() - defer ms.mu.RUnlock() - return append(m, ms.metrics...) -} - -func (ms *MetricSuite) Export(ctx context.Context, exp *colmetricpb.ExportMetricsServiceRequest) (*colmetricpb.ExportMetricsServiceResponse, error) { - ms.mu.Lock() - for _, rm := range exp.GetResourceMetrics() { - // TODO (rghetia) handle multiple resource and library info. - if len(rm.InstrumentationLibraryMetrics) > 0 { - ms.metrics = append(ms.metrics, rm.InstrumentationLibraryMetrics[0].Metrics...) - } - } - ms.mu.Unlock() - return &colmetricpb.ExportMetricsServiceResponse{}, nil -} -func (ms *MetricSuite) TearDownSuite() { - ms.metricController.Stop() - ms.ServerSuite.TearDownSuite() -} diff --git a/exporters/otlp/testing/server.go b/exporters/otlp/testing/server.go deleted file mode 100644 index 14bdd382577..00000000000 --- a/exporters/otlp/testing/server.go +++ /dev/null @@ -1,128 +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 otlp_testing - -import ( - "net" - "sync/atomic" - "time" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "go.opentelemetry.io/otel/exporters/otlp" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// Let the system define the port -const defaultServerAddr = "127.0.0.1:0" - -type ServerSuite struct { - suite.Suite - - ServerOpts []grpc.ServerOption - serverAddr string - ServerListener net.Listener - Server *grpc.Server - - requestCount uint64 - FailureModulo uint64 - FailureCodes []codes.Code - - ExporterOpts []otlp.ExporterOption - Exporter *otlp.Exporter -} - -func (s *ServerSuite) SetupSuite() { - s.serverAddr = defaultServerAddr - - var err error - s.ServerListener, err = net.Listen("tcp", s.serverAddr) - s.serverAddr = s.ServerListener.Addr().String() - require.NoError(s.T(), err, "failed to allocate a port for server") - - s.Server = grpc.NewServer(s.ServerOpts...) -} - -func (s *ServerSuite) StartServer() { - go func() { - s.Server.Serve(s.ServerListener) - }() - s.T().Logf("started grpc.Server at: %v", s.ServerAddr()) - - if s.Exporter == nil { - s.Exporter = s.NewExporter() - } -} - -func (s *ServerSuite) ServerAddr() string { - return s.serverAddr -} - -func (s *ServerSuite) RequestError() error { - if s.FailureModulo <= 0 { - return nil - } - - count := atomic.AddUint64(&s.requestCount, 1) - if count%s.FailureModulo == 0 { - return nil - } - - var c codes.Code - if n := len(s.FailureCodes); n > 0 { - /* Example to understand the indexing: - * - s.FailureModulo = 3 - * - len(s.Codes) 5 - * - * count - 1 | count / s.FailureModulo | index (mod 5) - * =================================================== - * 0 | 0 | 0 - * 1 | 0 | 1 - * 2 | 1 | n/a (2) - * 3 | 1 | 2 - * 4 | 1 | 3 - * 5 | 2 | n/a (3) - * 6 | 2 | 4 - * 7 | 2 | 0 - * 8 | 3 | n/a (0) - * 9 | 3 | 1 - */ - c = s.FailureCodes[(count-1-(count/s.FailureModulo))%uint64(n)] - } else { - c = codes.Unavailable - } - return status.Errorf(c, "artificial error: count %d, modulo %d", count, s.FailureModulo) -} - -func (s *ServerSuite) NewExporter() *otlp.Exporter { - opts := []otlp.ExporterOption{ - otlp.WithInsecure(), - otlp.WithAddress(s.serverAddr), - otlp.WithReconnectionPeriod(10 * time.Millisecond), - } - exp, err := otlp.NewExporter(append(opts, s.ExporterOpts...)...) - require.NoError(s.T(), err, "failed to create exporter") - return exp -} - -func (s *ServerSuite) TearDownSuite() { - if s.ServerListener != nil { - s.Server.GracefulStop() - s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr()) - } - s.Exporter.Stop() -} diff --git a/exporters/otlp/testing/trace.go b/exporters/otlp/testing/trace.go deleted file mode 100644 index 9dda7d559ea..00000000000 --- a/exporters/otlp/testing/trace.go +++ /dev/null @@ -1,140 +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 otlp_testing - -import ( - "context" - "sort" - "sync" - - coltracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/trace/v1" - commonpb "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1" - resourcepb "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1" - tracepb "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1" - "github.com/stretchr/testify/require" - "go.opentelemetry.io/otel/exporters/otlp" - "go.opentelemetry.io/otel/sdk/trace" -) - -type TraceSuite struct { - ServerSuite - - TraceProvider *trace.Provider - - mu sync.RWMutex - resourceSpanMap map[string]*tracepb.ResourceSpans -} - -func (ts *TraceSuite) SetupSuite() { - ts.ServerSuite.SetupSuite() - - ts.Reset() - coltracepb.RegisterTraceServiceServer(ts.Server, ts) - - ts.ServerSuite.StartServer() - - if ts.TraceProvider == nil { - ts.TraceProvider = ts.NewTraceProvider(ts.Exporter, nil) - } -} - -func (ts *TraceSuite) NewTraceProvider(exp *otlp.Exporter, opts []trace.ProviderOption) *trace.Provider { - defaultOpts := []trace.ProviderOption{ - trace.WithConfig( - trace.Config{ - DefaultSampler: trace.AlwaysSample(), - }, - ), - trace.WithSyncer(exp), - } - p, err := trace.NewProvider(append(defaultOpts, opts...)...) - require.NoError(ts.T(), err, "failed to create trace provider") - return p -} - -func (ts *TraceSuite) Reset() { - ts.resourceSpanMap = map[string]*tracepb.ResourceSpans{} -} - -func (ts *TraceSuite) GetSpans() []*tracepb.Span { - ts.mu.RLock() - defer ts.mu.RUnlock() - spans := []*tracepb.Span{} - for _, rs := range ts.resourceSpanMap { - for _, ils := range rs.InstrumentationLibrarySpans { - spans = append(spans, ils.Spans...) - } - } - return spans -} - -func (ts *TraceSuite) GetResourceSpans() []*tracepb.ResourceSpans { - ts.mu.RLock() - defer ts.mu.RUnlock() - rss := make([]*tracepb.ResourceSpans, 0, len(ts.resourceSpanMap)) - for _, rs := range ts.resourceSpanMap { - rss = append(rss, rs) - } - return rss -} - -func (ts *TraceSuite) Export(ctx context.Context, req *coltracepb.ExportTraceServiceRequest) (*coltracepb.ExportTraceServiceResponse, error) { - if err := ts.RequestError(); err != nil { - return nil, err - } - - ts.mu.Lock() - defer ts.mu.Unlock() - rss := req.GetResourceSpans() - for _, rs := range rss { - rstr := resourceString(rs.Resource) - existingRs, ok := ts.resourceSpanMap[rstr] - if !ok { - ts.resourceSpanMap[rstr] = rs - // TODO (rghetia): Add support for library Info. - if len(rs.InstrumentationLibrarySpans) == 0 { - rs.InstrumentationLibrarySpans = []*tracepb.InstrumentationLibrarySpans{ - { - Spans: []*tracepb.Span{}, - }, - } - } - } else { - if len(rs.InstrumentationLibrarySpans) > 0 { - existingRs.InstrumentationLibrarySpans[0].Spans = - append(existingRs.InstrumentationLibrarySpans[0].Spans, - rs.InstrumentationLibrarySpans[0].GetSpans()...) - } - } - } - return &coltracepb.ExportTraceServiceResponse{}, nil -} - -func resourceString(res *resourcepb.Resource) string { - sAttrs := sortedAttributes(res.GetAttributes()) - rstr := "" - for _, attr := range sAttrs { - rstr = rstr + attr.String() - - } - return rstr -} - -func sortedAttributes(attrs []*commonpb.AttributeKeyValue) []*commonpb.AttributeKeyValue { - sort.Slice(attrs[:], func(i, j int) bool { - return attrs[i].Key < attrs[j].Key - }) - return attrs -} From d917dd7d79300c2c932b4c3563617ab3ca7af368 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Fri, 29 May 2020 11:04:57 -0700 Subject: [PATCH 09/11] Lint --- example/otel-collector/go.sum | 1 - exporters/otlp/README.md | 2 +- exporters/otlp/options.go | 4 +++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/example/otel-collector/go.sum b/example/otel-collector/go.sum index 7f08f906d70..9df9798c799 100644 --- a/example/otel-collector/go.sum +++ b/example/otel-collector/go.sum @@ -414,7 +414,6 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y 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 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= diff --git a/exporters/otlp/README.md b/exporters/otlp/README.md index 7310ea93dc8..d9d86b52e20 100644 --- a/exporters/otlp/README.md +++ b/exporters/otlp/README.md @@ -56,7 +56,7 @@ func main() { ## Configuration -Configuratin options can be specified when creating a new exporter (`NewExporter`). +Configurations options can be specified when creating a new exporter (`NewExporter`). ### `WorkerCount(n uint)` diff --git a/exporters/otlp/options.go b/exporters/otlp/options.go index a8d8b364ae8..6f2702bed96 100644 --- a/exporters/otlp/options.go +++ b/exporters/otlp/options.go @@ -35,13 +35,15 @@ const ( // Note: MaxAttempts > 5 are treated as 5. See // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#validation-of-retrypolicy // for more details. + // + // The following is to ensure CANCELLED is not corrected to CANCELED. + // nolint DefaultGRPCServiceConfig = `{ "methodConfig":[{ "name":[ { "service":"opentelemetry.proto.collector.metrics.v1.MetricsService" }, { "service":"opentelemetry.proto.collector.trace.v1.TraceService" } ], - "waitForReady": true, "retryPolicy":{ "MaxAttempts":5, "InitialBackoff":"0.3s", From 5d9472beab75acb5215743b0cd57998ee0b9d4ff Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Fri, 29 May 2020 11:11:19 -0700 Subject: [PATCH 10/11] Remove nolint and update misspell to ignore cancelled --- .golangci.yml | 4 ++-- exporters/otlp/options.go | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index cef170f7c7f..2ef168198c2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -26,7 +26,7 @@ issues: linters-settings: misspell: locale: US - #ignore-words: - # - someword + ignore-words: + - cancelled goimports: local-prefixes: go.opentelemetry.io diff --git a/exporters/otlp/options.go b/exporters/otlp/options.go index 6f2702bed96..cf86a081c05 100644 --- a/exporters/otlp/options.go +++ b/exporters/otlp/options.go @@ -35,9 +35,6 @@ const ( // Note: MaxAttempts > 5 are treated as 5. See // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#validation-of-retrypolicy // for more details. - // - // The following is to ensure CANCELLED is not corrected to CANCELED. - // nolint DefaultGRPCServiceConfig = `{ "methodConfig":[{ "name":[ From 0c3127c27eeb14f7117a96ec0f85073f50a5480c Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 1 Jun 2020 09:09:26 -0700 Subject: [PATCH 11/11] Update README.md with batcher comment --- exporters/otlp/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/exporters/otlp/README.md b/exporters/otlp/README.md index d9d86b52e20..24da77069a2 100644 --- a/exporters/otlp/README.md +++ b/exporters/otlp/README.md @@ -40,7 +40,13 @@ func main() { } }() - // Note: The exporter can also be used as a Batcher. + // Note: The exporter can also be used as a Batcher. E.g. + // traceProvider, err := sdktrace.NewProvider( + // sdktrace.WithBatcher(exporter, + // sdktrace.WithBatchTimeout(time.Second*15), + // sdktrace.WithMaxExportBatchSize(100), + // ), + // ) traceProvider, err := sdktrace.NewProvider(sdktrace.WithSyncer(exporter)) if err != nil { log.Fatal("failed to create trace provider: %v", err)