Skip to content
This repository was archived by the owner on Oct 3, 2023. It is now read-only.

Commit 2b93072

Browse files
knyarRamon Nogueira
authored andcommitted
Allow users to provide context. (#28)
Users can now provide a custom context that will be used instead of context.Background(). This fixes #27.
1 parent 81c8a51 commit 2b93072

File tree

4 files changed

+79
-7
lines changed

4 files changed

+79
-7
lines changed

stackdriver.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,15 @@ type Options struct {
168168
// default "opencensus_task" label. You should only do this if you know that
169169
// the Resource you set uniquely identifies this Go process.
170170
DefaultMonitoringLabels *Labels
171+
172+
// Context allows users to provide a custom context for API calls.
173+
//
174+
// This context will be used several times: first, to create Stackdriver
175+
// trace and metric clients, and then every time a new batch of traces or
176+
// stats needs to be uploaded.
177+
//
178+
// If unset, context.Background() will be used.
179+
Context context.Context
171180
}
172181

173182
// Exporter is a stats.Exporter and trace.Exporter
@@ -180,8 +189,11 @@ type Exporter struct {
180189
// NewExporter creates a new Exporter that implements both stats.Exporter and
181190
// trace.Exporter.
182191
func NewExporter(o Options) (*Exporter, error) {
192+
if o.Context == nil {
193+
o.Context = context.Background()
194+
}
183195
if o.ProjectID == "" {
184-
creds, err := google.FindDefaultCredentials(context.Background(), traceapi.DefaultAuthScopes()...)
196+
creds, err := google.FindDefaultCredentials(o.Context, traceapi.DefaultAuthScopes()...)
185197
if err != nil {
186198
return nil, fmt.Errorf("stackdriver: %v", err)
187199
}

stats.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func newStatsExporter(o Options, enforceProjectUniqueness bool) (*statsExporter,
7878
}
7979

8080
opts := append(o.MonitoringClientOptions, option.WithUserAgent(userAgent))
81-
client, err := monitoring.NewMetricClient(context.Background(), opts...)
81+
client, err := monitoring.NewMetricClient(o.Context, opts...)
8282
if err != nil {
8383
return nil, err
8484
}
@@ -150,7 +150,7 @@ func (e *statsExporter) Flush() {
150150

151151
func (e *statsExporter) uploadStats(vds []*view.Data) error {
152152
ctx, span := trace.StartSpan(
153-
context.Background(),
153+
e.o.Context,
154154
"contrib.go.opencensus.io/exporter/stackdriver.uploadStats",
155155
trace.WithSampler(trace.NeverSample()),
156156
)
@@ -163,7 +163,7 @@ func (e *statsExporter) uploadStats(vds []*view.Data) error {
163163
}
164164
}
165165
for _, req := range e.makeReq(vds, maxTimeSeriesPerUpload) {
166-
if err := e.c.CreateTimeSeries(ctx, req); err != nil {
166+
if err := createTimeSeries(ctx, e.c, req); err != nil {
167167
span.SetStatus(trace.Status{Code: 2, Message: err.Error()})
168168
// TODO(jbd): Don't fail fast here, batch errors?
169169
return err
@@ -465,3 +465,7 @@ var createMetricDescriptor = func(ctx context.Context, c *monitoring.MetricClien
465465
var getMetricDescriptor = func(ctx context.Context, c *monitoring.MetricClient, mdr *monitoringpb.GetMetricDescriptorRequest) (*metric.MetricDescriptor, error) {
466466
return c.GetMetricDescriptor(ctx, mdr)
467467
}
468+
469+
var createTimeSeries = func(ctx context.Context, c *monitoring.MetricClient, ts *monitoringpb.CreateTimeSeriesRequest) error {
470+
return c.CreateTimeSeries(ctx, ts)
471+
}

stats_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package stackdriver
1616

1717
import (
1818
"context"
19+
"fmt"
1920
"reflect"
2021
"testing"
2122
"time"
@@ -1014,6 +1015,62 @@ func TestExporter_makeReq_withCustomMonitoredResource(t *testing.T) {
10141015
}
10151016
}
10161017

1018+
func TestExporter_customContext(t *testing.T) {
1019+
oldCreateMetricDescriptor := createMetricDescriptor
1020+
oldCreateTimeSeries := createTimeSeries
1021+
1022+
defer func() {
1023+
createMetricDescriptor = oldCreateMetricDescriptor
1024+
createTimeSeries = oldCreateTimeSeries
1025+
}()
1026+
1027+
var timedOut = 0
1028+
createMetricDescriptor = func(ctx context.Context, c *monitoring.MetricClient, mdr *monitoringpb.CreateMetricDescriptorRequest) (*metric.MetricDescriptor, error) {
1029+
select {
1030+
case <-time.After(15 * time.Millisecond):
1031+
fmt.Println("createMetricDescriptor did not time out")
1032+
case <-ctx.Done():
1033+
timedOut++
1034+
}
1035+
return &metric.MetricDescriptor{}, nil
1036+
}
1037+
createTimeSeries = func(ctx context.Context, c *monitoring.MetricClient, ts *monitoringpb.CreateTimeSeriesRequest) error {
1038+
select {
1039+
case <-time.After(15 * time.Millisecond):
1040+
fmt.Println("createTimeSeries did not time out")
1041+
case <-ctx.Done():
1042+
timedOut++
1043+
}
1044+
return nil
1045+
}
1046+
1047+
v := &view.View{
1048+
Name: "test_view_count",
1049+
Description: "view_description",
1050+
Measure: stats.Float64("test-measure/TestExporter_createMeasure", "measure desc", stats.UnitMilliseconds),
1051+
Aggregation: view.Count(),
1052+
}
1053+
1054+
data := &view.CountData{Value: 0}
1055+
vd := newTestViewData(v, time.Now(), time.Now(), data, data)
1056+
1057+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
1058+
defer cancel()
1059+
e := &statsExporter{
1060+
createdViews: make(map[string]*metricpb.MetricDescriptor),
1061+
o: Options{ProjectID: "test_project", Context: ctx},
1062+
}
1063+
if err := e.uploadStats([]*view.Data{vd}); err != nil {
1064+
t.Errorf("Exporter.uploadStats() error = %v", err)
1065+
}
1066+
if ctx.Err() != context.DeadlineExceeded {
1067+
t.Errorf("expected context to time out; got %v", ctx.Err())
1068+
}
1069+
if timedOut != 2 {
1070+
t.Errorf("expected two functions to time out; got %d", timedOut)
1071+
}
1072+
}
1073+
10171074
func newTestViewData(v *view.View, start, end time.Time, data1, data2 view.AggregationData) *view.Data {
10181075
key, _ := tag.NewKey("test-key")
10191076
tag1 := tag.Tag{Key: key, Value: "test-value-1"}

trace.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package stackdriver
1616

1717
import (
18-
"context"
1918
"fmt"
2019
"log"
2120
"sync"
@@ -43,7 +42,7 @@ type traceExporter struct {
4342
var _ trace.Exporter = (*traceExporter)(nil)
4443

4544
func newTraceExporter(o Options) (*traceExporter, error) {
46-
client, err := tracingclient.NewClient(context.Background(), o.TraceClientOptions...)
45+
client, err := tracingclient.NewClient(o.Context, o.TraceClientOptions...)
4746
if err != nil {
4847
return nil, fmt.Errorf("stackdriver: couldn't initialize trace client: %v", err)
4948
}
@@ -118,7 +117,7 @@ func (e *traceExporter) uploadSpans(spans []*trace.SpanData) {
118117
}
119118
// Create a never-sampled span to prevent traces associated with exporter.
120119
ctx, span := trace.StartSpan( // TODO: add timeouts
121-
context.Background(),
120+
e.o.Context,
122121
"contrib.go.opencensus.io/exporter/stackdriver.uploadSpans",
123122
trace.WithSampler(trace.NeverSample()),
124123
)

0 commit comments

Comments
 (0)