Prechádzať zdrojové kódy

vendor: go.opencensus.io v0.23.0

un-pinning the dependency

full diff: https://github.com/census-instrumentation/opencensus-go/compare/v0.22.3...v0.23.0

- replace gofmt with goimports
- Allow creating additional View universes
- Safely reject invalid-length span and trace ids
    - fix Panic when x-b3-spanid exceeds 16 characters
- Reduce allocations
- Remove call to time.Now() on worker thread when handling record reqs
- Delete views from measure ref when unregistering
- Allow custom view.Meters to export metrics for other Resources
- Initialize View Start Time During View Registration
- Record a Start Time Per Time Series within a View
- Made public traceparent/tracestate marshal/unmarshal
- Fix const labels with derived metrics
- Defer IDGenerator initialization until first use
- Allow replacing trace SDK
- Provide accessor to the span implementation
- Lock only when needed, remove duplicate code
- Update dependencies
- fix memory leak cause by the spanStore.(census-instrumentation/opencensus-go)
- Adds an exported function to flush interval reader
- Adding GC stats to runmetrics plugin

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 3 rokov pred
rodič
commit
f0647f33f5

+ 0 - 1
vendor.mod

@@ -174,7 +174,6 @@ replace (
 	github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.1
 	github.com/prometheus/client_golang => github.com/prometheus/client_golang v1.6.0
 	github.com/prometheus/procfs => github.com/prometheus/procfs v0.0.11
-	go.opencensus.io => go.opencensus.io v0.22.3
 )
 
 // Removes etcd dependency

+ 9 - 1
vendor.sum

@@ -527,6 +527,7 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -1027,8 +1028,14 @@ go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVd
 go.etcd.io/etcd/server/v3 v3.5.2 h1:B6ytJvS4Fmt8nkjzS2/8POf4tuPhFMluE0lWd4dx/7U=
 go.etcd.io/etcd/server/v3 v3.5.2/go.mod h1:mlG8znIEz4N/28GABrohZCBM11FqgGVQcpbcyJgh0j0=
 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
-go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
+go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
+go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w=
@@ -1149,6 +1156,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=

+ 0 - 17
vendor/go.opencensus.io/.travis.yml

@@ -1,17 +0,0 @@
-language: go
-
-go_import_path: go.opencensus.io
-
-go:
-  - 1.11.x
-
-env:
-  global:
-    GO111MODULE=on
-
-before_script:
-  - make install-tools
-
-script:
-  - make travis-ci
-  - go run internal/check/version.go # TODO move this to makefile

+ 14 - 13
vendor/go.opencensus.io/Makefile

@@ -8,7 +8,7 @@ ALL_PKGS := $(shell go list $(sort $(dir $(ALL_SRC))))
 GOTEST_OPT?=-v -race -timeout 30s
 GOTEST_OPT_WITH_COVERAGE = $(GOTEST_OPT) -coverprofile=coverage.txt -covermode=atomic
 GOTEST=go test
-GOFMT=gofmt
+GOIMPORTS=goimports
 GOLINT=golint
 GOVET=go vet
 EMBEDMD=embedmd
@@ -17,14 +17,14 @@ TRACE_ID_LINT_EXCEPTION="type name will be used as trace.TraceID by other packag
 TRACE_OPTION_LINT_EXCEPTION="type name will be used as trace.TraceOptions by other packages"
 README_FILES := $(shell find . -name '*README.md' | sort | tr '\n' ' ')
 
-.DEFAULT_GOAL := fmt-lint-vet-embedmd-test
+.DEFAULT_GOAL := imports-lint-vet-embedmd-test
 
-.PHONY: fmt-lint-vet-embedmd-test
-fmt-lint-vet-embedmd-test: fmt lint vet embedmd test
+.PHONY: imports-lint-vet-embedmd-test
+imports-lint-vet-embedmd-test: imports lint vet embedmd test
 
 # TODO enable test-with-coverage in tavis
 .PHONY: travis-ci
-travis-ci: fmt lint vet embedmd test test-386
+travis-ci: imports lint vet embedmd test test-386
 
 all-pkgs:
 	@echo $(ALL_PKGS) | tr ' ' '\n' | sort
@@ -44,15 +44,15 @@ test-386:
 test-with-coverage:
 	$(GOTEST) $(GOTEST_OPT_WITH_COVERAGE) $(ALL_PKGS)
 
-.PHONY: fmt
-fmt:
-	@FMTOUT=`$(GOFMT) -s -l $(ALL_SRC) 2>&1`; \
-	if [ "$$FMTOUT" ]; then \
-		echo "$(GOFMT) FAILED => gofmt the following files:\n"; \
-		echo "$$FMTOUT\n"; \
+.PHONY: imports
+imports:
+	@IMPORTSOUT=`$(GOIMPORTS) -l $(ALL_SRC) 2>&1`; \
+	if [ "$$IMPORTSOUT" ]; then \
+		echo "$(GOIMPORTS) FAILED => goimports the following files:\n"; \
+		echo "$$IMPORTSOUT\n"; \
 		exit 1; \
 	else \
-	    echo "Fmt finished successfully"; \
+	    echo "Imports finished successfully"; \
 	fi
 
 .PHONY: lint
@@ -91,6 +91,7 @@ embedmd:
 
 .PHONY: install-tools
 install-tools:
-	go get -u golang.org/x/tools/cmd/cover
 	go get -u golang.org/x/lint/golint
+	go get -u golang.org/x/tools/cmd/cover
+	go get -u golang.org/x/tools/cmd/goimports
 	go get -u github.com/rakyll/embedmd

+ 1 - 1
vendor/go.opencensus.io/plugin/ocgrpc/client.go

@@ -16,8 +16,8 @@ package ocgrpc
 
 import (
 	"context"
-	"go.opencensus.io/trace"
 
+	"go.opencensus.io/trace"
 	"google.golang.org/grpc/stats"
 )
 

+ 2 - 0
vendor/go.opencensus.io/plugin/ocgrpc/client_metrics.go

@@ -60,6 +60,8 @@ var (
 		Aggregation: DefaultMillisecondsDistribution,
 	}
 
+	// Purposely reuses the count from `ClientRoundtripLatency`, tagging
+	// with method and status to result in ClientCompletedRpcs.
 	ClientCompletedRPCsView = &view.View{
 		Measure:     ClientRoundtripLatency,
 		Name:        "grpc.io/client/completed_rpcs",

+ 2 - 1
vendor/go.opencensus.io/plugin/ocgrpc/server.go

@@ -16,9 +16,10 @@ package ocgrpc
 
 import (
 	"context"
-	"go.opencensus.io/trace"
 
 	"google.golang.org/grpc/stats"
+
+	"go.opencensus.io/trace"
 )
 
 // ServerHandler implements gRPC stats.Handler recording OpenCensus stats and

+ 2 - 0
vendor/go.opencensus.io/plugin/ocgrpc/server_metrics.go

@@ -63,6 +63,8 @@ var (
 		Aggregation: DefaultMillisecondsDistribution,
 	}
 
+	// Purposely reuses the count from `ServerLatency`, tagging
+	// with method and status to result in ServerCompletedRpcs.
 	ServerCompletedRPCsView = &view.View{
 		Name:        "grpc.io/server/completed_rpcs",
 		Description: "Count of RPCs by method and status.",

+ 4 - 4
vendor/go.opencensus.io/plugin/ocgrpc/trace_common.go

@@ -15,16 +15,16 @@
 package ocgrpc
 
 import (
+	"context"
 	"strings"
 
 	"google.golang.org/grpc/codes"
-
-	"context"
-	"go.opencensus.io/trace"
-	"go.opencensus.io/trace/propagation"
 	"google.golang.org/grpc/metadata"
 	"google.golang.org/grpc/stats"
 	"google.golang.org/grpc/status"
+
+	"go.opencensus.io/trace"
+	"go.opencensus.io/trace/propagation"
 )
 
 const traceContextKey = "grpc-trace-bin"

+ 20 - 0
vendor/go.opencensus.io/stats/record.go

@@ -31,10 +31,19 @@ func init() {
 	}
 }
 
+// Recorder provides an interface for exporting measurement information from
+// the static Record method by using the WithRecorder option.
+type Recorder interface {
+	// Record records a set of measurements associated with the given tags and attachments.
+	// The second argument is a `[]Measurement`.
+	Record(*tag.Map, interface{}, map[string]interface{})
+}
+
 type recordOptions struct {
 	attachments  metricdata.Attachments
 	mutators     []tag.Mutator
 	measurements []Measurement
+	recorder     Recorder
 }
 
 // WithAttachments applies provided exemplar attachments.
@@ -58,6 +67,14 @@ func WithMeasurements(measurements ...Measurement) Options {
 	}
 }
 
+// WithRecorder records the measurements to the specified `Recorder`, rather
+// than to the global metrics recorder.
+func WithRecorder(meter Recorder) Options {
+	return func(ro *recordOptions) {
+		ro.recorder = meter
+	}
+}
+
 // Options apply changes to recordOptions.
 type Options func(*recordOptions)
 
@@ -93,6 +110,9 @@ func RecordWithOptions(ctx context.Context, ros ...Options) error {
 		return nil
 	}
 	recorder := internal.DefaultRecorder
+	if o.recorder != nil {
+		recorder = o.recorder.Record
+	}
 	if recorder == nil {
 		return nil
 	}

+ 10 - 8
vendor/go.opencensus.io/stats/view/aggregation.go

@@ -15,6 +15,8 @@
 
 package view
 
+import "time"
+
 // AggType represents the type of aggregation function used on a View.
 type AggType int
 
@@ -45,20 +47,20 @@ type Aggregation struct {
 	Type    AggType   // Type is the AggType of this Aggregation.
 	Buckets []float64 // Buckets are the bucket endpoints if this Aggregation represents a distribution, see Distribution.
 
-	newData func() AggregationData
+	newData func(time.Time) AggregationData
 }
 
 var (
 	aggCount = &Aggregation{
 		Type: AggTypeCount,
-		newData: func() AggregationData {
-			return &CountData{}
+		newData: func(t time.Time) AggregationData {
+			return &CountData{Start: t}
 		},
 	}
 	aggSum = &Aggregation{
 		Type: AggTypeSum,
-		newData: func() AggregationData {
-			return &SumData{}
+		newData: func(t time.Time) AggregationData {
+			return &SumData{Start: t}
 		},
 	}
 )
@@ -103,8 +105,8 @@ func Distribution(bounds ...float64) *Aggregation {
 		Type:    AggTypeDistribution,
 		Buckets: bounds,
 	}
-	agg.newData = func() AggregationData {
-		return newDistributionData(agg)
+	agg.newData = func(t time.Time) AggregationData {
+		return newDistributionData(agg, t)
 	}
 	return agg
 }
@@ -114,7 +116,7 @@ func Distribution(bounds ...float64) *Aggregation {
 func LastValue() *Aggregation {
 	return &Aggregation{
 		Type: AggTypeLastValue,
-		newData: func() AggregationData {
+		newData: func(_ time.Time) AggregationData {
 			return &LastValueData{}
 		},
 	}

+ 49 - 6
vendor/go.opencensus.io/stats/view/aggregation_data.go

@@ -31,6 +31,7 @@ type AggregationData interface {
 	clone() AggregationData
 	equal(other AggregationData) bool
 	toPoint(t metricdata.Type, time time.Time) metricdata.Point
+	StartTime() time.Time
 }
 
 const epsilon = 1e-9
@@ -40,6 +41,7 @@ const epsilon = 1e-9
 //
 // Most users won't directly access count data.
 type CountData struct {
+	Start time.Time
 	Value int64
 }
 
@@ -50,7 +52,7 @@ func (a *CountData) addSample(_ float64, _ map[string]interface{}, _ time.Time)
 }
 
 func (a *CountData) clone() AggregationData {
-	return &CountData{Value: a.Value}
+	return &CountData{Value: a.Value, Start: a.Start}
 }
 
 func (a *CountData) equal(other AggregationData) bool {
@@ -59,7 +61,7 @@ func (a *CountData) equal(other AggregationData) bool {
 		return false
 	}
 
-	return a.Value == a2.Value
+	return a.Start.Equal(a2.Start) && a.Value == a2.Value
 }
 
 func (a *CountData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point {
@@ -71,11 +73,17 @@ func (a *CountData) toPoint(metricType metricdata.Type, t time.Time) metricdata.
 	}
 }
 
+// StartTime returns the start time of the data being aggregated by CountData.
+func (a *CountData) StartTime() time.Time {
+	return a.Start
+}
+
 // SumData is the aggregated data for the Sum aggregation.
 // A sum aggregation processes data and sums up the recordings.
 //
 // Most users won't directly access sum data.
 type SumData struct {
+	Start time.Time
 	Value float64
 }
 
@@ -86,7 +94,7 @@ func (a *SumData) addSample(v float64, _ map[string]interface{}, _ time.Time) {
 }
 
 func (a *SumData) clone() AggregationData {
-	return &SumData{Value: a.Value}
+	return &SumData{Value: a.Value, Start: a.Start}
 }
 
 func (a *SumData) equal(other AggregationData) bool {
@@ -94,7 +102,7 @@ func (a *SumData) equal(other AggregationData) bool {
 	if !ok {
 		return false
 	}
-	return math.Pow(a.Value-a2.Value, 2) < epsilon
+	return a.Start.Equal(a2.Start) && math.Pow(a.Value-a2.Value, 2) < epsilon
 }
 
 func (a *SumData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point {
@@ -108,6 +116,11 @@ func (a *SumData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Po
 	}
 }
 
+// StartTime returns the start time of the data being aggregated by SumData.
+func (a *SumData) StartTime() time.Time {
+	return a.Start
+}
+
 // DistributionData is the aggregated data for the
 // Distribution aggregation.
 //
@@ -126,9 +139,10 @@ type DistributionData struct {
 	// an exemplar for the associated bucket, or nil.
 	ExemplarsPerBucket []*metricdata.Exemplar
 	bounds             []float64 // histogram distribution of the values
+	Start              time.Time
 }
 
-func newDistributionData(agg *Aggregation) *DistributionData {
+func newDistributionData(agg *Aggregation, t time.Time) *DistributionData {
 	bucketCount := len(agg.Buckets) + 1
 	return &DistributionData{
 		CountPerBucket:     make([]int64, bucketCount),
@@ -136,6 +150,7 @@ func newDistributionData(agg *Aggregation) *DistributionData {
 		bounds:             agg.Buckets,
 		Min:                math.MaxFloat64,
 		Max:                math.SmallestNonzeroFloat64,
+		Start:              t,
 	}
 }
 
@@ -226,7 +241,11 @@ func (a *DistributionData) equal(other AggregationData) bool {
 			return false
 		}
 	}
-	return a.Count == a2.Count && a.Min == a2.Min && a.Max == a2.Max && math.Pow(a.Mean-a2.Mean, 2) < epsilon && math.Pow(a.variance()-a2.variance(), 2) < epsilon
+	return a.Start.Equal(a2.Start) &&
+		a.Count == a2.Count &&
+		a.Min == a2.Min &&
+		a.Max == a2.Max &&
+		math.Pow(a.Mean-a2.Mean, 2) < epsilon && math.Pow(a.variance()-a2.variance(), 2) < epsilon
 }
 
 func (a *DistributionData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point {
@@ -256,6 +275,11 @@ func (a *DistributionData) toPoint(metricType metricdata.Type, t time.Time) metr
 	}
 }
 
+// StartTime returns the start time of the data being aggregated by DistributionData.
+func (a *DistributionData) StartTime() time.Time {
+	return a.Start
+}
+
 // LastValueData returns the last value recorded for LastValue aggregation.
 type LastValueData struct {
 	Value float64
@@ -291,3 +315,22 @@ func (l *LastValueData) toPoint(metricType metricdata.Type, t time.Time) metricd
 		panic("unsupported metricdata.Type")
 	}
 }
+
+// StartTime returns an empty time value as start time is not recorded when using last value
+// aggregation.
+func (l *LastValueData) StartTime() time.Time {
+	return time.Time{}
+}
+
+// ClearStart clears the Start field from data if present. Useful for testing in cases where the
+// start time will be nondeterministic.
+func ClearStart(data AggregationData) {
+	switch data := data.(type) {
+	case *CountData:
+		data.Start = time.Time{}
+	case *SumData:
+		data.Start = time.Time{}
+	case *DistributionData:
+		data.Start = time.Time{}
+	}
+}

+ 1 - 1
vendor/go.opencensus.io/stats/view/collector.go

@@ -35,7 +35,7 @@ type collector struct {
 func (c *collector) addSample(s string, v float64, attachments map[string]interface{}, t time.Time) {
 	aggregator, ok := c.signatures[s]
 	if !ok {
-		aggregator = c.a.newData()
+		aggregator = c.a.newData(t)
 		c.signatures[s] = aggregator
 	}
 	aggregator.addSample(v, attachments, t)

+ 2 - 15
vendor/go.opencensus.io/stats/view/export.go

@@ -14,13 +14,6 @@
 
 package view
 
-import "sync"
-
-var (
-	exportersMu sync.RWMutex // guards exporters
-	exporters   = make(map[Exporter]struct{})
-)
-
 // Exporter exports the collected records as view data.
 //
 // The ExportView method should return quickly; if an
@@ -43,16 +36,10 @@ type Exporter interface {
 //
 // Binaries can register exporters, libraries shouldn't register exporters.
 func RegisterExporter(e Exporter) {
-	exportersMu.Lock()
-	defer exportersMu.Unlock()
-
-	exporters[e] = struct{}{}
+	defaultWorker.RegisterExporter(e)
 }
 
 // UnregisterExporter unregisters an exporter.
 func UnregisterExporter(e Exporter) {
-	exportersMu.Lock()
-	defer exportersMu.Unlock()
-
-	delete(exporters, e)
+	defaultWorker.UnregisterExporter(e)
 }

+ 7 - 9
vendor/go.opencensus.io/stats/view/view_to_metric.go

@@ -18,6 +18,8 @@ package view
 import (
 	"time"
 
+	"go.opencensus.io/resource"
+
 	"go.opencensus.io/metric/metricdata"
 	"go.opencensus.io/stats"
 )
@@ -117,20 +119,15 @@ func toLabelValues(row *Row, expectedKeys []metricdata.LabelKey) []metricdata.La
 	return labelValues
 }
 
-func rowToTimeseries(v *viewInternal, row *Row, now time.Time, startTime time.Time) *metricdata.TimeSeries {
+func rowToTimeseries(v *viewInternal, row *Row, now time.Time) *metricdata.TimeSeries {
 	return &metricdata.TimeSeries{
 		Points:      []metricdata.Point{row.Data.toPoint(v.metricDescriptor.Type, now)},
 		LabelValues: toLabelValues(row, v.metricDescriptor.LabelKeys),
-		StartTime:   startTime,
+		StartTime:   row.Data.StartTime(),
 	}
 }
 
-func viewToMetric(v *viewInternal, now time.Time, startTime time.Time) *metricdata.Metric {
-	if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 ||
-		v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 {
-		startTime = time.Time{}
-	}
-
+func viewToMetric(v *viewInternal, r *resource.Resource, now time.Time) *metricdata.Metric {
 	rows := v.collectedRows()
 	if len(rows) == 0 {
 		return nil
@@ -138,12 +135,13 @@ func viewToMetric(v *viewInternal, now time.Time, startTime time.Time) *metricda
 
 	ts := []*metricdata.TimeSeries{}
 	for _, row := range rows {
-		ts = append(ts, rowToTimeseries(v, row, now, startTime))
+		ts = append(ts, rowToTimeseries(v, row, now))
 	}
 
 	m := &metricdata.Metric{
 		Descriptor: *v.metricDescriptor,
 		TimeSeries: ts,
+		Resource:   r,
 	}
 	return m
 }

+ 171 - 47
vendor/go.opencensus.io/stats/view/worker.go

@@ -20,6 +20,8 @@ import (
 	"sync"
 	"time"
 
+	"go.opencensus.io/resource"
+
 	"go.opencensus.io/metric/metricdata"
 	"go.opencensus.io/metric/metricproducer"
 	"go.opencensus.io/stats"
@@ -28,7 +30,7 @@ import (
 )
 
 func init() {
-	defaultWorker = newWorker()
+	defaultWorker = NewMeter().(*worker)
 	go defaultWorker.start()
 	internal.DefaultRecorder = record
 }
@@ -39,16 +41,77 @@ type measureRef struct {
 }
 
 type worker struct {
-	measures   map[string]*measureRef
-	views      map[string]*viewInternal
-	startTimes map[*viewInternal]time.Time
+	measures       map[string]*measureRef
+	views          map[string]*viewInternal
+	viewStartTimes map[*viewInternal]time.Time
 
 	timer      *time.Ticker
 	c          chan command
 	quit, done chan bool
 	mu         sync.RWMutex
+	r          *resource.Resource
+
+	exportersMu sync.RWMutex
+	exporters   map[Exporter]struct{}
+}
+
+// Meter defines an interface which allows a single process to maintain
+// multiple sets of metrics exports (intended for the advanced case where a
+// single process wants to report metrics about multiple objects, such as
+// multiple databases or HTTP services).
+//
+// Note that this is an advanced use case, and the static functions in this
+// module should cover the common use cases.
+type Meter interface {
+	stats.Recorder
+	// Find returns a registered view associated with this name.
+	// If no registered view is found, nil is returned.
+	Find(name string) *View
+	// Register begins collecting data for the given views.
+	// Once a view is registered, it reports data to the registered exporters.
+	Register(views ...*View) error
+	// Unregister the given views. Data will not longer be exported for these views
+	// after Unregister returns.
+	// It is not necessary to unregister from views you expect to collect for the
+	// duration of your program execution.
+	Unregister(views ...*View)
+	// SetReportingPeriod sets the interval between reporting aggregated views in
+	// the program. If duration is less than or equal to zero, it enables the
+	// default behavior.
+	//
+	// Note: each exporter makes different promises about what the lowest supported
+	// duration is. For example, the Stackdriver exporter recommends a value no
+	// lower than 1 minute. Consult each exporter per your needs.
+	SetReportingPeriod(time.Duration)
+
+	// RegisterExporter registers an exporter.
+	// Collected data will be reported via all the
+	// registered exporters. Once you no longer
+	// want data to be exported, invoke UnregisterExporter
+	// with the previously registered exporter.
+	//
+	// Binaries can register exporters, libraries shouldn't register exporters.
+	RegisterExporter(Exporter)
+	// UnregisterExporter unregisters an exporter.
+	UnregisterExporter(Exporter)
+	// SetResource may be used to set the Resource associated with this registry.
+	// This is intended to be used in cases where a single process exports metrics
+	// for multiple Resources, typically in a multi-tenant situation.
+	SetResource(*resource.Resource)
+
+	// Start causes the Meter to start processing Record calls and aggregating
+	// statistics as well as exporting data.
+	Start()
+	// Stop causes the Meter to stop processing calls and terminate data export.
+	Stop()
+
+	// RetrieveData gets a snapshot of the data collected for the the view registered
+	// with the given name. It is intended for testing only.
+	RetrieveData(viewName string) ([]*Row, error)
 }
 
+var _ Meter = (*worker)(nil)
+
 var defaultWorker *worker
 
 var defaultReportingDuration = 10 * time.Second
@@ -56,11 +119,17 @@ var defaultReportingDuration = 10 * time.Second
 // Find returns a registered view associated with this name.
 // If no registered view is found, nil is returned.
 func Find(name string) (v *View) {
+	return defaultWorker.Find(name)
+}
+
+// Find returns a registered view associated with this name.
+// If no registered view is found, nil is returned.
+func (w *worker) Find(name string) (v *View) {
 	req := &getViewByNameReq{
 		name: name,
 		c:    make(chan *getViewByNameResp),
 	}
-	defaultWorker.c <- req
+	w.c <- req
 	resp := <-req.c
 	return resp.v
 }
@@ -68,11 +137,17 @@ func Find(name string) (v *View) {
 // Register begins collecting data for the given views.
 // Once a view is registered, it reports data to the registered exporters.
 func Register(views ...*View) error {
+	return defaultWorker.Register(views...)
+}
+
+// Register begins collecting data for the given views.
+// Once a view is registered, it reports data to the registered exporters.
+func (w *worker) Register(views ...*View) error {
 	req := &registerViewReq{
 		views: views,
 		err:   make(chan error),
 	}
-	defaultWorker.c <- req
+	w.c <- req
 	return <-req.err
 }
 
@@ -81,6 +156,14 @@ func Register(views ...*View) error {
 // It is not necessary to unregister from views you expect to collect for the
 // duration of your program execution.
 func Unregister(views ...*View) {
+	defaultWorker.Unregister(views...)
+}
+
+// Unregister the given views. Data will not longer be exported for these views
+// after Unregister returns.
+// It is not necessary to unregister from views you expect to collect for the
+// duration of your program execution.
+func (w *worker) Unregister(views ...*View) {
 	names := make([]string, len(views))
 	for i := range views {
 		names[i] = views[i].Name
@@ -89,31 +172,42 @@ func Unregister(views ...*View) {
 		views: names,
 		done:  make(chan struct{}),
 	}
-	defaultWorker.c <- req
+	w.c <- req
 	<-req.done
 }
 
 // RetrieveData gets a snapshot of the data collected for the the view registered
 // with the given name. It is intended for testing only.
 func RetrieveData(viewName string) ([]*Row, error) {
+	return defaultWorker.RetrieveData(viewName)
+}
+
+// RetrieveData gets a snapshot of the data collected for the the view registered
+// with the given name. It is intended for testing only.
+func (w *worker) RetrieveData(viewName string) ([]*Row, error) {
 	req := &retrieveDataReq{
 		now: time.Now(),
 		v:   viewName,
 		c:   make(chan *retrieveDataResp),
 	}
-	defaultWorker.c <- req
+	w.c <- req
 	resp := <-req.c
 	return resp.rows, resp.err
 }
 
 func record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
+	defaultWorker.Record(tags, ms, attachments)
+}
+
+// Record records a set of measurements ms associated with the given tags and attachments.
+func (w *worker) Record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
 	req := &recordReq{
 		tm:          tags,
 		ms:          ms.([]stats.Measurement),
 		attachments: attachments,
 		t:           time.Now(),
 	}
-	defaultWorker.c <- req
+	w.c <- req
 }
 
 // SetReportingPeriod sets the interval between reporting aggregated views in
@@ -124,28 +218,56 @@ func record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
 // duration is. For example, the Stackdriver exporter recommends a value no
 // lower than 1 minute. Consult each exporter per your needs.
 func SetReportingPeriod(d time.Duration) {
+	defaultWorker.SetReportingPeriod(d)
+}
+
+// SetReportingPeriod sets the interval between reporting aggregated views in
+// the program. If duration is less than or equal to zero, it enables the
+// default behavior.
+//
+// Note: each exporter makes different promises about what the lowest supported
+// duration is. For example, the Stackdriver exporter recommends a value no
+// lower than 1 minute. Consult each exporter per your needs.
+func (w *worker) SetReportingPeriod(d time.Duration) {
 	// TODO(acetechnologist): ensure that the duration d is more than a certain
 	// value. e.g. 1s
 	req := &setReportingPeriodReq{
 		d: d,
 		c: make(chan bool),
 	}
-	defaultWorker.c <- req
+	w.c <- req
 	<-req.c // don't return until the timer is set to the new duration.
 }
 
-func newWorker() *worker {
+// NewMeter constructs a Meter instance. You should only need to use this if
+// you need to separate out Measurement recordings and View aggregations within
+// a single process.
+func NewMeter() Meter {
 	return &worker{
-		measures:   make(map[string]*measureRef),
-		views:      make(map[string]*viewInternal),
-		startTimes: make(map[*viewInternal]time.Time),
-		timer:      time.NewTicker(defaultReportingDuration),
-		c:          make(chan command, 1024),
-		quit:       make(chan bool),
-		done:       make(chan bool),
+		measures:       make(map[string]*measureRef),
+		views:          make(map[string]*viewInternal),
+		viewStartTimes: make(map[*viewInternal]time.Time),
+		timer:          time.NewTicker(defaultReportingDuration),
+		c:              make(chan command, 1024),
+		quit:           make(chan bool),
+		done:           make(chan bool),
+
+		exporters: make(map[Exporter]struct{}),
 	}
 }
 
+// SetResource associates all data collected by this Meter with the specified
+// resource. This resource is reported when using metricexport.ReadAndExport;
+// it is not provided when used with ExportView/RegisterExporter, because that
+// interface does not provide a means for reporting the Resource.
+func (w *worker) SetResource(r *resource.Resource) {
+	w.r = r
+}
+
+func (w *worker) Start() {
+	go w.start()
+}
+
 func (w *worker) start() {
 	prodMgr := metricproducer.GlobalManager()
 	prodMgr.AddProducer(w)
@@ -155,7 +277,7 @@ func (w *worker) start() {
 		case cmd := <-w.c:
 			cmd.handleCommand(w)
 		case <-w.timer.C:
-			w.reportUsage(time.Now())
+			w.reportUsage()
 		case <-w.quit:
 			w.timer.Stop()
 			close(w.c)
@@ -165,7 +287,7 @@ func (w *worker) start() {
 	}
 }
 
-func (w *worker) stop() {
+func (w *worker) Stop() {
 	prodMgr := metricproducer.GlobalManager()
 	prodMgr.DeleteProducer(w)
 
@@ -202,44 +324,45 @@ func (w *worker) tryRegisterView(v *View) (*viewInternal, error) {
 		return x, nil
 	}
 	w.views[vi.view.Name] = vi
+	w.viewStartTimes[vi] = time.Now()
 	ref := w.getMeasureRef(vi.view.Measure.Name())
 	ref.views[vi] = struct{}{}
 	return vi, nil
 }
 
-func (w *worker) unregisterView(viewName string) {
+func (w *worker) unregisterView(v *viewInternal) {
 	w.mu.Lock()
 	defer w.mu.Unlock()
-	delete(w.views, viewName)
+	delete(w.views, v.view.Name)
+	delete(w.viewStartTimes, v)
+	if measure := w.measures[v.view.Measure.Name()]; measure != nil {
+		delete(measure.views, v)
+	}
 }
 
-func (w *worker) reportView(v *viewInternal, now time.Time) {
+func (w *worker) reportView(v *viewInternal) {
 	if !v.isSubscribed() {
 		return
 	}
 	rows := v.collectedRows()
-	_, ok := w.startTimes[v]
-	if !ok {
-		w.startTimes[v] = now
-	}
 	viewData := &Data{
 		View:  v.view,
-		Start: w.startTimes[v],
+		Start: w.viewStartTimes[v],
 		End:   time.Now(),
 		Rows:  rows,
 	}
-	exportersMu.Lock()
-	for e := range exporters {
+	w.exportersMu.Lock()
+	defer w.exportersMu.Unlock()
+	for e := range w.exporters {
 		e.ExportView(viewData)
 	}
-	exportersMu.Unlock()
 }
 
-func (w *worker) reportUsage(now time.Time) {
+func (w *worker) reportUsage() {
 	w.mu.Lock()
 	defer w.mu.Unlock()
 	for _, v := range w.views {
-		w.reportView(v, now)
+		w.reportView(v)
 	}
 }
 
@@ -248,20 +371,7 @@ func (w *worker) toMetric(v *viewInternal, now time.Time) *metricdata.Metric {
 		return nil
 	}
 
-	_, ok := w.startTimes[v]
-	if !ok {
-		w.startTimes[v] = now
-	}
-
-	var startTime time.Time
-	if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 ||
-		v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 {
-		startTime = time.Time{}
-	} else {
-		startTime = w.startTimes[v]
-	}
-
-	return viewToMetric(v, now, startTime)
+	return viewToMetric(v, w.r, now)
 }
 
 // Read reads all view data and returns them as metrics.
@@ -279,3 +389,17 @@ func (w *worker) Read() []*metricdata.Metric {
 	}
 	return metrics
 }
+
+func (w *worker) RegisterExporter(e Exporter) {
+	w.exportersMu.Lock()
+	defer w.exportersMu.Unlock()
+
+	w.exporters[e] = struct{}{}
+}
+
+func (w *worker) UnregisterExporter(e Exporter) {
+	w.exportersMu.Lock()
+	defer w.exportersMu.Unlock()
+
+	delete(w.exporters, e)
+}

+ 3 - 3
vendor/go.opencensus.io/stats/view/worker_commands.go

@@ -95,7 +95,7 @@ func (cmd *unregisterFromViewReq) handleCommand(w *worker) {
 		}
 
 		// Report pending data for this view before removing it.
-		w.reportView(vi, time.Now())
+		w.reportView(vi)
 
 		vi.unsubscribe()
 		if !vi.isSubscribed() {
@@ -103,7 +103,7 @@ func (cmd *unregisterFromViewReq) handleCommand(w *worker) {
 			// The collected data can be cleared.
 			vi.clearRows()
 		}
-		w.unregisterView(name)
+		w.unregisterView(vi)
 	}
 	cmd.done <- struct{}{}
 }
@@ -163,7 +163,7 @@ func (cmd *recordReq) handleCommand(w *worker) {
 		}
 		ref := w.getMeasureRef(m.Measure().Name())
 		for v := range ref.views {
-			v.addSample(cmd.tm, m.Value(), cmd.attachments, time.Now())
+			v.addSample(cmd.tm, m.Value(), cmd.attachments, cmd.t)
 		}
 	}
 }

+ 10 - 0
vendor/go.opencensus.io/trace/basetypes.go

@@ -49,6 +49,16 @@ type Attribute struct {
 	value interface{}
 }
 
+// Key returns the attribute's key
+func (a *Attribute) Key() string {
+	return a.key
+}
+
+// Value returns the attribute's value
+func (a *Attribute) Value() interface{} {
+	return a.value
+}
+
 // BoolAttribute returns a bool-valued attribute.
 func BoolAttribute(key string, value bool) Attribute {
 	return Attribute{key: key, value: value}

+ 1 - 1
vendor/go.opencensus.io/trace/lrumap.go

@@ -44,7 +44,7 @@ func (lm lruMap) len() int {
 }
 
 func (lm lruMap) keys() []interface{} {
-	keys := []interface{}{}
+	keys := make([]interface{}, len(lm.cacheKeys))
 	for k := range lm.cacheKeys {
 		keys = append(keys, k)
 	}

+ 8 - 6
vendor/go.opencensus.io/trace/spanstore.go

@@ -48,8 +48,10 @@ func (i internalOnly) ReportActiveSpans(name string) []*SpanData {
 	var out []*SpanData
 	s.mu.Lock()
 	defer s.mu.Unlock()
-	for span := range s.active {
-		out = append(out, span.makeSpanData())
+	for activeSpan := range s.active {
+		if s, ok := activeSpan.(*span); ok {
+			out = append(out, s.makeSpanData())
+		}
 	}
 	return out
 }
@@ -185,7 +187,7 @@ func (i internalOnly) ReportSpansByLatency(name string, minLatency, maxLatency t
 // bucketed by latency.
 type spanStore struct {
 	mu                     sync.Mutex // protects everything below.
-	active                 map[*Span]struct{}
+	active                 map[SpanInterface]struct{}
 	errors                 map[int32]*bucket
 	latency                []bucket
 	maxSpansPerErrorBucket int
@@ -194,7 +196,7 @@ type spanStore struct {
 // newSpanStore creates a span store.
 func newSpanStore(name string, latencyBucketSize int, errorBucketSize int) *spanStore {
 	s := &spanStore{
-		active:                 make(map[*Span]struct{}),
+		active:                 make(map[SpanInterface]struct{}),
 		latency:                make([]bucket, len(defaultLatencies)+1),
 		maxSpansPerErrorBucket: errorBucketSize,
 	}
@@ -271,7 +273,7 @@ func (s *spanStore) resize(latencyBucketSize int, errorBucketSize int) {
 }
 
 // add adds a span to the active bucket of the spanStore.
-func (s *spanStore) add(span *Span) {
+func (s *spanStore) add(span SpanInterface) {
 	s.mu.Lock()
 	s.active[span] = struct{}{}
 	s.mu.Unlock()
@@ -279,7 +281,7 @@ func (s *spanStore) add(span *Span) {
 
 // finished removes a span from the active set, and adds a corresponding
 // SpanData to a latency or error bucket.
-func (s *spanStore) finished(span *Span, sd *SpanData) {
+func (s *spanStore) finished(span SpanInterface, sd *SpanData) {
 	latency := sd.EndTime.Sub(sd.StartTime)
 	if latency < 0 {
 		latency = 0

+ 92 - 95
vendor/go.opencensus.io/trace/trace.go

@@ -28,12 +28,16 @@ import (
 	"go.opencensus.io/trace/tracestate"
 )
 
+type tracer struct{}
+
+var _ Tracer = &tracer{}
+
 // Span represents a span of a trace.  It has an associated SpanContext, and
 // stores data accumulated while the span is active.
 //
 // Ideally users should interact with Spans by calling the functions in this
 // package that take a Context parameter.
-type Span struct {
+type span struct {
 	// data contains information recorded about the span.
 	//
 	// It will be non-nil if we are exporting the span or recording events for it.
@@ -66,7 +70,7 @@ type Span struct {
 // IsRecordingEvents returns true if events are being recorded for this span.
 // Use this check to avoid computing expensive annotations when they will never
 // be used.
-func (s *Span) IsRecordingEvents() bool {
+func (s *span) IsRecordingEvents() bool {
 	if s == nil {
 		return false
 	}
@@ -109,13 +113,13 @@ type SpanContext struct {
 type contextKey struct{}
 
 // FromContext returns the Span stored in a context, or nil if there isn't one.
-func FromContext(ctx context.Context) *Span {
+func (t *tracer) FromContext(ctx context.Context) *Span {
 	s, _ := ctx.Value(contextKey{}).(*Span)
 	return s
 }
 
 // NewContext returns a new context with the given Span attached.
-func NewContext(parent context.Context, s *Span) context.Context {
+func (t *tracer) NewContext(parent context.Context, s *Span) context.Context {
 	return context.WithValue(parent, contextKey{}, s)
 }
 
@@ -166,12 +170,14 @@ func WithSampler(sampler Sampler) StartOption {
 //
 // Returned context contains the newly created span. You can use it to
 // propagate the returned span in process.
-func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
+func (t *tracer) StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
 	var opts StartOptions
 	var parent SpanContext
-	if p := FromContext(ctx); p != nil {
-		p.addChild()
-		parent = p.spanContext
+	if p := t.FromContext(ctx); p != nil {
+		if ps, ok := p.internal.(*span); ok {
+			ps.addChild()
+		}
+		parent = p.SpanContext()
 	}
 	for _, op := range o {
 		op(&opts)
@@ -180,7 +186,8 @@ func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Cont
 
 	ctx, end := startExecutionTracerTask(ctx, name)
 	span.executionTracerTaskEnd = end
-	return NewContext(ctx, span), span
+	extSpan := NewSpan(span)
+	return t.NewContext(ctx, extSpan), extSpan
 }
 
 // StartSpanWithRemoteParent starts a new child span of the span from the given parent.
@@ -190,7 +197,7 @@ func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Cont
 //
 // Returned context contains the newly created span. You can use it to
 // propagate the returned span in process.
-func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
+func (t *tracer) StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
 	var opts StartOptions
 	for _, op := range o {
 		op(&opts)
@@ -198,19 +205,24 @@ func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanCont
 	span := startSpanInternal(name, parent != SpanContext{}, parent, true, opts)
 	ctx, end := startExecutionTracerTask(ctx, name)
 	span.executionTracerTaskEnd = end
-	return NewContext(ctx, span), span
+	extSpan := NewSpan(span)
+	return t.NewContext(ctx, extSpan), extSpan
 }
 
-func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *Span {
-	span := &Span{}
-	span.spanContext = parent
+func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *span {
+	s := &span{}
+	s.spanContext = parent
 
 	cfg := config.Load().(*Config)
+	if gen, ok := cfg.IDGenerator.(*defaultIDGenerator); ok {
+		// lazy initialization
+		gen.init()
+	}
 
 	if !hasParent {
-		span.spanContext.TraceID = cfg.IDGenerator.NewTraceID()
+		s.spanContext.TraceID = cfg.IDGenerator.NewTraceID()
 	}
-	span.spanContext.SpanID = cfg.IDGenerator.NewSpanID()
+	s.spanContext.SpanID = cfg.IDGenerator.NewSpanID()
 	sampler := cfg.DefaultSampler
 
 	if !hasParent || remoteParent || o.Sampler != nil {
@@ -222,47 +234,47 @@ func startSpanInternal(name string, hasParent bool, parent SpanContext, remotePa
 		if o.Sampler != nil {
 			sampler = o.Sampler
 		}
-		span.spanContext.setIsSampled(sampler(SamplingParameters{
+		s.spanContext.setIsSampled(sampler(SamplingParameters{
 			ParentContext:   parent,
-			TraceID:         span.spanContext.TraceID,
-			SpanID:          span.spanContext.SpanID,
+			TraceID:         s.spanContext.TraceID,
+			SpanID:          s.spanContext.SpanID,
 			Name:            name,
 			HasRemoteParent: remoteParent}).Sample)
 	}
 
-	if !internal.LocalSpanStoreEnabled && !span.spanContext.IsSampled() {
-		return span
+	if !internal.LocalSpanStoreEnabled && !s.spanContext.IsSampled() {
+		return s
 	}
 
-	span.data = &SpanData{
-		SpanContext:     span.spanContext,
+	s.data = &SpanData{
+		SpanContext:     s.spanContext,
 		StartTime:       time.Now(),
 		SpanKind:        o.SpanKind,
 		Name:            name,
 		HasRemoteParent: remoteParent,
 	}
-	span.lruAttributes = newLruMap(cfg.MaxAttributesPerSpan)
-	span.annotations = newEvictedQueue(cfg.MaxAnnotationEventsPerSpan)
-	span.messageEvents = newEvictedQueue(cfg.MaxMessageEventsPerSpan)
-	span.links = newEvictedQueue(cfg.MaxLinksPerSpan)
+	s.lruAttributes = newLruMap(cfg.MaxAttributesPerSpan)
+	s.annotations = newEvictedQueue(cfg.MaxAnnotationEventsPerSpan)
+	s.messageEvents = newEvictedQueue(cfg.MaxMessageEventsPerSpan)
+	s.links = newEvictedQueue(cfg.MaxLinksPerSpan)
 
 	if hasParent {
-		span.data.ParentSpanID = parent.SpanID
+		s.data.ParentSpanID = parent.SpanID
 	}
 	if internal.LocalSpanStoreEnabled {
 		var ss *spanStore
 		ss = spanStoreForNameCreateIfNew(name)
 		if ss != nil {
-			span.spanStore = ss
-			ss.add(span)
+			s.spanStore = ss
+			ss.add(s)
 		}
 	}
 
-	return span
+	return s
 }
 
 // End ends the span.
-func (s *Span) End() {
+func (s *span) End() {
 	if s == nil {
 		return
 	}
@@ -292,7 +304,7 @@ func (s *Span) End() {
 
 // makeSpanData produces a SpanData representing the current state of the Span.
 // It requires that s.data is non-nil.
-func (s *Span) makeSpanData() *SpanData {
+func (s *span) makeSpanData() *SpanData {
 	var sd SpanData
 	s.mu.Lock()
 	sd = *s.data
@@ -317,7 +329,7 @@ func (s *Span) makeSpanData() *SpanData {
 }
 
 // SpanContext returns the SpanContext of the span.
-func (s *Span) SpanContext() SpanContext {
+func (s *span) SpanContext() SpanContext {
 	if s == nil {
 		return SpanContext{}
 	}
@@ -325,7 +337,7 @@ func (s *Span) SpanContext() SpanContext {
 }
 
 // SetName sets the name of the span, if it is recording events.
-func (s *Span) SetName(name string) {
+func (s *span) SetName(name string) {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -335,7 +347,7 @@ func (s *Span) SetName(name string) {
 }
 
 // SetStatus sets the status of the span, if it is recording events.
-func (s *Span) SetStatus(status Status) {
+func (s *span) SetStatus(status Status) {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -344,32 +356,32 @@ func (s *Span) SetStatus(status Status) {
 	s.mu.Unlock()
 }
 
-func (s *Span) interfaceArrayToLinksArray() []Link {
-	linksArr := make([]Link, 0)
+func (s *span) interfaceArrayToLinksArray() []Link {
+	linksArr := make([]Link, 0, len(s.links.queue))
 	for _, value := range s.links.queue {
 		linksArr = append(linksArr, value.(Link))
 	}
 	return linksArr
 }
 
-func (s *Span) interfaceArrayToMessageEventArray() []MessageEvent {
-	messageEventArr := make([]MessageEvent, 0)
+func (s *span) interfaceArrayToMessageEventArray() []MessageEvent {
+	messageEventArr := make([]MessageEvent, 0, len(s.messageEvents.queue))
 	for _, value := range s.messageEvents.queue {
 		messageEventArr = append(messageEventArr, value.(MessageEvent))
 	}
 	return messageEventArr
 }
 
-func (s *Span) interfaceArrayToAnnotationArray() []Annotation {
-	annotationArr := make([]Annotation, 0)
+func (s *span) interfaceArrayToAnnotationArray() []Annotation {
+	annotationArr := make([]Annotation, 0, len(s.annotations.queue))
 	for _, value := range s.annotations.queue {
 		annotationArr = append(annotationArr, value.(Annotation))
 	}
 	return annotationArr
 }
 
-func (s *Span) lruAttributesToAttributeMap() map[string]interface{} {
-	attributes := make(map[string]interface{})
+func (s *span) lruAttributesToAttributeMap() map[string]interface{} {
+	attributes := make(map[string]interface{}, s.lruAttributes.len())
 	for _, key := range s.lruAttributes.keys() {
 		value, ok := s.lruAttributes.get(key)
 		if ok {
@@ -380,13 +392,13 @@ func (s *Span) lruAttributesToAttributeMap() map[string]interface{} {
 	return attributes
 }
 
-func (s *Span) copyToCappedAttributes(attributes []Attribute) {
+func (s *span) copyToCappedAttributes(attributes []Attribute) {
 	for _, a := range attributes {
 		s.lruAttributes.add(a.key, a.value)
 	}
 }
 
-func (s *Span) addChild() {
+func (s *span) addChild() {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -398,7 +410,7 @@ func (s *Span) addChild() {
 // AddAttributes sets attributes in the span.
 //
 // Existing attributes whose keys appear in the attributes parameter are overwritten.
-func (s *Span) AddAttributes(attributes ...Attribute) {
+func (s *span) AddAttributes(attributes ...Attribute) {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -407,49 +419,27 @@ func (s *Span) AddAttributes(attributes ...Attribute) {
 	s.mu.Unlock()
 }
 
-// copyAttributes copies a slice of Attributes into a map.
-func copyAttributes(m map[string]interface{}, attributes []Attribute) {
-	for _, a := range attributes {
-		m[a.key] = a.value
-	}
-}
-
-func (s *Span) lazyPrintfInternal(attributes []Attribute, format string, a ...interface{}) {
+func (s *span) printStringInternal(attributes []Attribute, str string) {
 	now := time.Now()
-	msg := fmt.Sprintf(format, a...)
-	var m map[string]interface{}
-	s.mu.Lock()
+	var am map[string]interface{}
 	if len(attributes) != 0 {
-		m = make(map[string]interface{})
-		copyAttributes(m, attributes)
+		am = make(map[string]interface{}, len(attributes))
+		for _, attr := range attributes {
+			am[attr.key] = attr.value
+		}
 	}
-	s.annotations.add(Annotation{
-		Time:       now,
-		Message:    msg,
-		Attributes: m,
-	})
-	s.mu.Unlock()
-}
-
-func (s *Span) printStringInternal(attributes []Attribute, str string) {
-	now := time.Now()
-	var a map[string]interface{}
 	s.mu.Lock()
-	if len(attributes) != 0 {
-		a = make(map[string]interface{})
-		copyAttributes(a, attributes)
-	}
 	s.annotations.add(Annotation{
 		Time:       now,
 		Message:    str,
-		Attributes: a,
+		Attributes: am,
 	})
 	s.mu.Unlock()
 }
 
 // Annotate adds an annotation with attributes.
 // Attributes can be nil.
-func (s *Span) Annotate(attributes []Attribute, str string) {
+func (s *span) Annotate(attributes []Attribute, str string) {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -457,11 +447,11 @@ func (s *Span) Annotate(attributes []Attribute, str string) {
 }
 
 // Annotatef adds an annotation with attributes.
-func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
+func (s *span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
 	if !s.IsRecordingEvents() {
 		return
 	}
-	s.lazyPrintfInternal(attributes, format, a...)
+	s.printStringInternal(attributes, fmt.Sprintf(format, a...))
 }
 
 // AddMessageSendEvent adds a message send event to the span.
@@ -470,7 +460,7 @@ func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}
 // unique in this span and the same between the send event and the receive
 // event (this allows to identify a message between the sender and receiver).
 // For example, this could be a sequence id.
-func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
+func (s *span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -492,7 +482,7 @@ func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedBy
 // unique in this span and the same between the send event and the receive
 // event (this allows to identify a message between the sender and receiver).
 // For example, this could be a sequence id.
-func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
+func (s *span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -509,7 +499,7 @@ func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compresse
 }
 
 // AddLink adds a link to the span.
-func (s *Span) AddLink(l Link) {
+func (s *span) AddLink(l Link) {
 	if !s.IsRecordingEvents() {
 		return
 	}
@@ -518,7 +508,7 @@ func (s *Span) AddLink(l Link) {
 	s.mu.Unlock()
 }
 
-func (s *Span) String() string {
+func (s *span) String() string {
 	if s == nil {
 		return "<nil>"
 	}
@@ -534,20 +524,9 @@ func (s *Span) String() string {
 var config atomic.Value // access atomically
 
 func init() {
-	gen := &defaultIDGenerator{}
-	// initialize traceID and spanID generators.
-	var rngSeed int64
-	for _, p := range []interface{}{
-		&rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc,
-	} {
-		binary.Read(crand.Reader, binary.LittleEndian, p)
-	}
-	gen.traceIDRand = rand.New(rand.NewSource(rngSeed))
-	gen.spanIDInc |= 1
-
 	config.Store(&Config{
 		DefaultSampler:             ProbabilitySampler(defaultSamplingProbability),
-		IDGenerator:                gen,
+		IDGenerator:                &defaultIDGenerator{},
 		MaxAttributesPerSpan:       DefaultMaxAttributesPerSpan,
 		MaxAnnotationEventsPerSpan: DefaultMaxAnnotationEventsPerSpan,
 		MaxMessageEventsPerSpan:    DefaultMaxMessageEventsPerSpan,
@@ -571,6 +550,24 @@ type defaultIDGenerator struct {
 
 	traceIDAdd  [2]uint64
 	traceIDRand *rand.Rand
+
+	initOnce sync.Once
+}
+
+// init initializes the generator on the first call to avoid consuming entropy
+// unnecessarily.
+func (gen *defaultIDGenerator) init() {
+	gen.initOnce.Do(func() {
+		// initialize traceID and spanID generators.
+		var rngSeed int64
+		for _, p := range []interface{}{
+			&rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc,
+		} {
+			binary.Read(crand.Reader, binary.LittleEndian, p)
+		}
+		gen.traceIDRand = rand.New(rand.NewSource(rngSeed))
+		gen.spanIDInc |= 1
+	})
 }
 
 // NewSpanID returns a non-zero span ID from a randomly-chosen sequence.

+ 265 - 0
vendor/go.opencensus.io/trace/trace_api.go

@@ -0,0 +1,265 @@
+// Copyright 2020, OpenCensus 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 trace
+
+import (
+	"context"
+)
+
+// DefaultTracer is the tracer used when package-level exported functions are invoked.
+var DefaultTracer Tracer = &tracer{}
+
+// Tracer can start spans and access context functions.
+type Tracer interface {
+
+	// StartSpan starts a new child span of the current span in the context. If
+	// there is no span in the context, creates a new trace and span.
+	//
+	// Returned context contains the newly created span. You can use it to
+	// propagate the returned span in process.
+	StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span)
+
+	// StartSpanWithRemoteParent starts a new child span of the span from the given parent.
+	//
+	// If the incoming context contains a parent, it ignores. StartSpanWithRemoteParent is
+	// preferred for cases where the parent is propagated via an incoming request.
+	//
+	// Returned context contains the newly created span. You can use it to
+	// propagate the returned span in process.
+	StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span)
+
+	// FromContext returns the Span stored in a context, or nil if there isn't one.
+	FromContext(ctx context.Context) *Span
+
+	// NewContext returns a new context with the given Span attached.
+	NewContext(parent context.Context, s *Span) context.Context
+}
+
+// StartSpan starts a new child span of the current span in the context. If
+// there is no span in the context, creates a new trace and span.
+//
+// Returned context contains the newly created span. You can use it to
+// propagate the returned span in process.
+func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
+	return DefaultTracer.StartSpan(ctx, name, o...)
+}
+
+// StartSpanWithRemoteParent starts a new child span of the span from the given parent.
+//
+// If the incoming context contains a parent, it ignores. StartSpanWithRemoteParent is
+// preferred for cases where the parent is propagated via an incoming request.
+//
+// Returned context contains the newly created span. You can use it to
+// propagate the returned span in process.
+func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
+	return DefaultTracer.StartSpanWithRemoteParent(ctx, name, parent, o...)
+}
+
+// FromContext returns the Span stored in a context, or a Span that is not
+// recording events if there isn't one.
+func FromContext(ctx context.Context) *Span {
+	return DefaultTracer.FromContext(ctx)
+}
+
+// NewContext returns a new context with the given Span attached.
+func NewContext(parent context.Context, s *Span) context.Context {
+	return DefaultTracer.NewContext(parent, s)
+}
+
+// SpanInterface represents a span of a trace.  It has an associated SpanContext, and
+// stores data accumulated while the span is active.
+//
+// Ideally users should interact with Spans by calling the functions in this
+// package that take a Context parameter.
+type SpanInterface interface {
+
+	// IsRecordingEvents returns true if events are being recorded for this span.
+	// Use this check to avoid computing expensive annotations when they will never
+	// be used.
+	IsRecordingEvents() bool
+
+	// End ends the span.
+	End()
+
+	// SpanContext returns the SpanContext of the span.
+	SpanContext() SpanContext
+
+	// SetName sets the name of the span, if it is recording events.
+	SetName(name string)
+
+	// SetStatus sets the status of the span, if it is recording events.
+	SetStatus(status Status)
+
+	// AddAttributes sets attributes in the span.
+	//
+	// Existing attributes whose keys appear in the attributes parameter are overwritten.
+	AddAttributes(attributes ...Attribute)
+
+	// Annotate adds an annotation with attributes.
+	// Attributes can be nil.
+	Annotate(attributes []Attribute, str string)
+
+	// Annotatef adds an annotation with attributes.
+	Annotatef(attributes []Attribute, format string, a ...interface{})
+
+	// AddMessageSendEvent adds a message send event to the span.
+	//
+	// messageID is an identifier for the message, which is recommended to be
+	// unique in this span and the same between the send event and the receive
+	// event (this allows to identify a message between the sender and receiver).
+	// For example, this could be a sequence id.
+	AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64)
+
+	// AddMessageReceiveEvent adds a message receive event to the span.
+	//
+	// messageID is an identifier for the message, which is recommended to be
+	// unique in this span and the same between the send event and the receive
+	// event (this allows to identify a message between the sender and receiver).
+	// For example, this could be a sequence id.
+	AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64)
+
+	// AddLink adds a link to the span.
+	AddLink(l Link)
+
+	// String prints a string representation of a span.
+	String() string
+}
+
+// NewSpan is a convenience function for creating a *Span out of a *span
+func NewSpan(s SpanInterface) *Span {
+	return &Span{internal: s}
+}
+
+// Span is a struct wrapper around the SpanInt interface, which allows correctly handling
+// nil spans, while also allowing the SpanInterface implementation to be swapped out.
+type Span struct {
+	internal SpanInterface
+}
+
+// Internal returns the underlying implementation of the Span
+func (s *Span) Internal() SpanInterface {
+	return s.internal
+}
+
+// IsRecordingEvents returns true if events are being recorded for this span.
+// Use this check to avoid computing expensive annotations when they will never
+// be used.
+func (s *Span) IsRecordingEvents() bool {
+	if s == nil {
+		return false
+	}
+	return s.internal.IsRecordingEvents()
+}
+
+// End ends the span.
+func (s *Span) End() {
+	if s == nil {
+		return
+	}
+	s.internal.End()
+}
+
+// SpanContext returns the SpanContext of the span.
+func (s *Span) SpanContext() SpanContext {
+	if s == nil {
+		return SpanContext{}
+	}
+	return s.internal.SpanContext()
+}
+
+// SetName sets the name of the span, if it is recording events.
+func (s *Span) SetName(name string) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.SetName(name)
+}
+
+// SetStatus sets the status of the span, if it is recording events.
+func (s *Span) SetStatus(status Status) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.SetStatus(status)
+}
+
+// AddAttributes sets attributes in the span.
+//
+// Existing attributes whose keys appear in the attributes parameter are overwritten.
+func (s *Span) AddAttributes(attributes ...Attribute) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.AddAttributes(attributes...)
+}
+
+// Annotate adds an annotation with attributes.
+// Attributes can be nil.
+func (s *Span) Annotate(attributes []Attribute, str string) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.Annotate(attributes, str)
+}
+
+// Annotatef adds an annotation with attributes.
+func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.Annotatef(attributes, format, a...)
+}
+
+// AddMessageSendEvent adds a message send event to the span.
+//
+// messageID is an identifier for the message, which is recommended to be
+// unique in this span and the same between the send event and the receive
+// event (this allows to identify a message between the sender and receiver).
+// For example, this could be a sequence id.
+func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize)
+}
+
+// AddMessageReceiveEvent adds a message receive event to the span.
+//
+// messageID is an identifier for the message, which is recommended to be
+// unique in this span and the same between the send event and the receive
+// event (this allows to identify a message between the sender and receiver).
+// For example, this could be a sequence id.
+func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize)
+}
+
+// AddLink adds a link to the span.
+func (s *Span) AddLink(l Link) {
+	if !s.IsRecordingEvents() {
+		return
+	}
+	s.internal.AddLink(l)
+}
+
+// String prints a string representation of a span.
+func (s *Span) String() string {
+	if s == nil {
+		return "<nil>"
+	}
+	return s.internal.String()
+}

+ 1 - 2
vendor/modules.txt

@@ -802,7 +802,7 @@ go.etcd.io/etcd/server/v3/etcdserver/api/snap
 go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb
 go.etcd.io/etcd/server/v3/wal
 go.etcd.io/etcd/server/v3/wal/walpb
-# go.opencensus.io v0.23.0 => go.opencensus.io v0.22.3
+# go.opencensus.io v0.23.0
 ## explicit; go 1.13
 go.opencensus.io
 go.opencensus.io/internal
@@ -1123,6 +1123,5 @@ gotest.tools/v3/skip
 # github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.1
 # github.com/prometheus/client_golang => github.com/prometheus/client_golang v1.6.0
 # github.com/prometheus/procfs => github.com/prometheus/procfs v0.0.11
-# go.opencensus.io => go.opencensus.io v0.22.3
 # github.com/rexray/gocsi => github.com/dperny/gocsi v1.2.3-pre
 # github.com/google/certificate-transparency-go => github.com/google/certificate-transparency-go v1.0.20