From a228bafec5356329b7daf8ef008c2907a4a437fb Mon Sep 17 00:00:00 2001 From: Cheng-Lung Sung Date: Fri, 15 Nov 2019 01:45:17 +0800 Subject: [PATCH] exporter(stackdriver): fix ExportSpans when ctx is not nil (#294) * exporter(stackdriver): fix ExportSpans when ctx is not nil - problem: if ctx is not, calling cancel() will panic - nil Context already handled in newContextWithTimeout - add with test * update go.sum * mock traceserver for traceclient * make precommit * - respect option.Context when get google cred and traceclient * Revise with timeout, context - rename blackbox tests package to stackdriver_test - remove context is nil checking, add to initialization - add tests for timeout --- example/http-stackdriver/go.sum | 7 + exporter/trace/stackdriver/go.mod | 1 + exporter/trace/stackdriver/go.sum | 7 + exporter/trace/stackdriver/stackdriver.go | 18 +- .../trace/stackdriver/stackdriver_test.go | 159 ++++++++++++++++++ exporter/trace/stackdriver/trace.go | 18 +- 6 files changed, 188 insertions(+), 22 deletions(-) create mode 100644 exporter/trace/stackdriver/stackdriver_test.go diff --git a/example/http-stackdriver/go.sum b/example/http-stackdriver/go.sum index 5ed9e6b7ade..d2f1699701d 100644 --- a/example/http-stackdriver/go.sum +++ b/example/http-stackdriver/go.sum @@ -36,6 +36,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -135,9 +136,11 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo 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.2/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/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= @@ -164,6 +167,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.5.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= 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/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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -205,6 +209,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -367,6 +372,7 @@ google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRn 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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -375,6 +381,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/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-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/exporter/trace/stackdriver/go.mod b/exporter/trace/stackdriver/go.mod index e1e330bce6c..5cfbe90dacc 100644 --- a/exporter/trace/stackdriver/go.mod +++ b/exporter/trace/stackdriver/go.mod @@ -7,6 +7,7 @@ replace go.opentelemetry.io/otel => ../../.. require ( cloud.google.com/go v0.47.0 github.com/golang/protobuf v1.3.2 + github.com/stretchr/testify v1.4.0 go.opentelemetry.io/otel v0.0.0-20191104130340-9f82c642f5d2 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 google.golang.org/api v0.11.0 diff --git a/exporter/trace/stackdriver/go.sum b/exporter/trace/stackdriver/go.sum index d4a9495302b..08e99865184 100644 --- a/exporter/trace/stackdriver/go.sum +++ b/exporter/trace/stackdriver/go.sum @@ -35,6 +35,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -134,9 +135,11 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo 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.2/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/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= @@ -163,6 +166,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.5.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= 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/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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -204,6 +208,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -363,6 +368,7 @@ google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRn 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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -371,6 +377,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/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-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/exporter/trace/stackdriver/stackdriver.go b/exporter/trace/stackdriver/stackdriver.go index f4cc53fc5ca..7d43abb863c 100644 --- a/exporter/trace/stackdriver/stackdriver.go +++ b/exporter/trace/stackdriver/stackdriver.go @@ -144,6 +144,13 @@ func WithContext(ctx context.Context) func(o *options) { } } +// WithTimeout sets the timeout for trace exporter and metric exporter +func WithTimeout(t time.Duration) func(o *options) { + return func(o *options) { + o.Timeout = t + } +} + func (o *options) handleError(err error) { if o.OnError != nil { o.OnError(err) @@ -168,16 +175,12 @@ type Exporter struct { // TODO(yoshifumi): add a metrics exporter one the spec definition // process and the sampler implementation are done. func NewExporter(opts ...Option) (*Exporter, error) { - o := options{} + o := options{Context: context.Background()} for _, opt := range opts { opt(&o) } if o.ProjectID == "" { - ctx := o.Context - if ctx == nil { - ctx = context.Background() - } - creds, err := google.FindDefaultCredentials(ctx, traceapi.DefaultAuthScopes()...) + creds, err := google.FindDefaultCredentials(o.Context, traceapi.DefaultAuthScopes()...) if err != nil { return nil, fmt.Errorf("Stackdriver: %v", err) } @@ -197,9 +200,6 @@ func NewExporter(opts ...Option) (*Exporter, error) { } func newContextWithTimeout(ctx context.Context, timeout time.Duration) (context.Context, func()) { - if ctx == nil { - ctx = context.Background() - } if timeout <= 0 { timeout = defaultTimeout } diff --git a/exporter/trace/stackdriver/stackdriver_test.go b/exporter/trace/stackdriver/stackdriver_test.go new file mode 100644 index 00000000000..8dd93e76e60 --- /dev/null +++ b/exporter/trace/stackdriver/stackdriver_test.go @@ -0,0 +1,159 @@ +// Copyright 2019, 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 stackdriver_test + +import ( + "context" + "flag" + "log" + "net" + "os" + "sync" + "testing" + "time" + + emptypb "github.com/golang/protobuf/ptypes/empty" + "github.com/stretchr/testify/assert" + "google.golang.org/api/option" + tracepb "google.golang.org/genproto/googleapis/devtools/cloudtrace/v2" + "google.golang.org/grpc" + + "go.opentelemetry.io/otel/exporter/trace/stackdriver" + "go.opentelemetry.io/otel/global" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +type mockTraceServer struct { + tracepb.TraceServiceServer + mu sync.Mutex + spansUploaded []*tracepb.Span + delay time.Duration +} + +func (s *mockTraceServer) BatchWriteSpans(ctx context.Context, req *tracepb.BatchWriteSpansRequest) (*emptypb.Empty, error) { + var err error + s.mu.Lock() + select { + case <-ctx.Done(): + err = ctx.Err() + case <-time.After(s.delay): + s.spansUploaded = append(s.spansUploaded, req.Spans...) + } + s.mu.Unlock() + return &emptypb.Empty{}, err +} + +func (s *mockTraceServer) len() int { + s.mu.Lock() + defer s.mu.Unlock() + return len(s.spansUploaded) +} + +// clientOpt is the option tests should use to connect to the test server. +// It is initialized by TestMain. +var clientOpt []option.ClientOption + +var ( + mockTrace mockTraceServer +) + +func TestMain(m *testing.M) { + flag.Parse() + + serv := grpc.NewServer() + tracepb.RegisterTraceServiceServer(serv, &mockTrace) + + lis, err := net.Listen("tcp", "localhost:0") + if err != nil { + log.Fatal(err) + } + go func() { + _ = serv.Serve(lis) + }() + + conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure()) + if err != nil { + log.Fatal(err) + } + clientOpt = []option.ClientOption{option.WithGRPCConn(conn)} + + os.Exit(m.Run()) +} + +func TestExporter_ExportSpans(t *testing.T) { + // Initial test precondition + mockTrace.spansUploaded = nil + mockTrace.delay = 0 + + // Create StackDriver Exporter + exp, err := stackdriver.NewExporter( + stackdriver.WithProjectID("PROJECT_ID_NOT_REAL"), + stackdriver.WithTraceClientOptions(clientOpt), + ) + assert.NoError(t, err) + + tp, err := sdktrace.NewProvider( + sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}), + sdktrace.WithBatcher(exp, // add following two options to ensure flush + sdktrace.WithScheduleDelayMillis(1), + sdktrace.WithMaxExportBatchSize(1), + )) + assert.NoError(t, err) + + global.SetTraceProvider(tp) + _, span := global.TraceProvider().GetTracer("test-tracer").Start(context.Background(), "test-span") + span.End() + assert.True(t, span.SpanContext().IsValid()) + + // wait exporter to flush + time.Sleep(20 * time.Millisecond) + assert.EqualValues(t, 1, mockTrace.len()) +} + +func TestExporter_Timeout(t *testing.T) { + // Initial test precondition + mockTrace.spansUploaded = nil + mockTrace.delay = 20 * time.Millisecond + var exportErrors []error + + // Create StackDriver Exporter + exp, err := stackdriver.NewExporter( + stackdriver.WithProjectID("PROJECT_ID_NOT_REAL"), + stackdriver.WithTraceClientOptions(clientOpt), + stackdriver.WithTimeout(1*time.Millisecond), + stackdriver.WithOnError(func(err error) { + exportErrors = append(exportErrors, err) + }), + ) + assert.NoError(t, err) + + tp, err := sdktrace.NewProvider( + sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}), + sdktrace.WithSyncer(exp)) + assert.NoError(t, err) + + global.SetTraceProvider(tp) + _, span := global.TraceProvider().GetTracer("test-tracer").Start(context.Background(), "test-span") + span.End() + assert.True(t, span.SpanContext().IsValid()) + + assert.EqualValues(t, 0, mockTrace.len()) + if got, want := len(exportErrors), 1; got != want { + t.Fatalf("len(exportErrors) = %q; want %q", got, want) + } + if got, want := exportErrors[0].Error(), "rpc error: code = DeadlineExceeded desc = context deadline exceeded"; got != want { + t.Fatalf("err.Error() = %q; want %q", got, want) + } +} diff --git a/exporter/trace/stackdriver/trace.go b/exporter/trace/stackdriver/trace.go index ab265caf2fa..114a2bc66dc 100644 --- a/exporter/trace/stackdriver/trace.go +++ b/exporter/trace/stackdriver/trace.go @@ -35,11 +35,7 @@ type traceExporter struct { } func newTraceExporter(o *options) (*traceExporter, error) { - ctx := o.Context - if ctx == nil { - ctx = context.Background() - } - client, err := traceclient.NewClient(ctx, o.TraceClientOptions...) + client, err := traceclient.NewClient(o.Context, o.TraceClientOptions...) if err != nil { return nil, fmt.Errorf("Stackdriver: couldn't initiate trace client: %v", err) } @@ -55,9 +51,6 @@ func newTraceExporter(o *options) (*traceExporter, error) { // ExportSpan exports a SpanData to Stackdriver Trace. func (e *traceExporter) ExportSpan(ctx context.Context, sd *export.SpanData) { protoSpan := protoFromSpanData(sd, e.projectID) - if ctx == nil { - ctx = context.Background() - } e.uploadFn(ctx, []*tracepb.Span{protoSpan}) } @@ -67,11 +60,6 @@ func (e *traceExporter) ExportSpans(ctx context.Context, sds []*export.SpanData) for i, sd := range sds { pbSpans[i] = protoFromSpanData(sd, e.projectID) } - var cancel func() - if ctx == nil { - ctx, cancel = newContextWithTimeout(e.o.Context, e.o.Timeout) - } - defer cancel() e.uploadFn(ctx, pbSpans) } @@ -82,6 +70,10 @@ func (e *traceExporter) uploadSpans(ctx context.Context, spans []*tracepb.Span) Spans: spans, } + var cancel func() + ctx, cancel = newContextWithTimeout(ctx, e.o.Timeout) + defer cancel() + // TODO(ymotongpoo): add this part after OTel support NeverSampler // for tracer.Start() initialization. //