aboutsummaryrefslogtreecommitdiff
path: root/vendor/go.opencensus.io
diff options
context:
space:
mode:
authorNiall Sheridan <nsheridan@gmail.com>2018-08-23 22:51:21 +0100
committerNiall Sheridan <nsheridan@gmail.com>2018-08-24 13:45:03 +0100
commitf8e3dea19012ccf05965d10255789eec33c2ebcf (patch)
tree8522ceada8bc7270648f29615b89550db910cb6c /vendor/go.opencensus.io
parent91f9bc722152146466523861162b85195f99875b (diff)
Update deps
Diffstat (limited to 'vendor/go.opencensus.io')
-rw-r--r--vendor/go.opencensus.io/CONTRIBUTING.md34
-rw-r--r--vendor/go.opencensus.io/Gopkg.lock185
-rw-r--r--vendor/go.opencensus.io/Gopkg.toml12
-rw-r--r--vendor/go.opencensus.io/README.md99
-rw-r--r--vendor/go.opencensus.io/go.mod20
-rw-r--r--vendor/go.opencensus.io/opencensus.go2
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/client.go27
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/server.go291
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/span_annotator.go160
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/stats.go10
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/trace.go39
-rw-r--r--vendor/go.opencensus.io/stats/measure.go28
-rw-r--r--vendor/go.opencensus.io/stats/measure_float64.go8
-rw-r--r--vendor/go.opencensus.io/stats/measure_int64.go8
-rw-r--r--vendor/go.opencensus.io/stats/view/collector.go5
-rw-r--r--vendor/go.opencensus.io/stats/view/export.go3
-rw-r--r--vendor/go.opencensus.io/stats/view/view.go6
-rw-r--r--vendor/go.opencensus.io/stats/view/worker.go62
-rw-r--r--vendor/go.opencensus.io/stats/view/worker_commands.go9
-rw-r--r--vendor/go.opencensus.io/tag/map_codec.go31
-rw-r--r--vendor/go.opencensus.io/trace/config.go9
-rw-r--r--vendor/go.opencensus.io/trace/doc.go2
-rw-r--r--vendor/go.opencensus.io/trace/export.go34
-rw-r--r--vendor/go.opencensus.io/trace/trace.go93
24 files changed, 865 insertions, 312 deletions
diff --git a/vendor/go.opencensus.io/CONTRIBUTING.md b/vendor/go.opencensus.io/CONTRIBUTING.md
index 6ec97c9..3f3aed3 100644
--- a/vendor/go.opencensus.io/CONTRIBUTING.md
+++ b/vendor/go.opencensus.io/CONTRIBUTING.md
@@ -21,4 +21,36 @@ All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult [GitHub Help] for more
information on using pull requests.
-[GitHub Help]: https://help.github.com/articles/about-pull-requests/ \ No newline at end of file
+[GitHub Help]: https://help.github.com/articles/about-pull-requests/
+
+## Instructions
+
+Fork the repo, checkout the upstream repo to your GOPATH by:
+
+```
+$ go get -d go.opencensus.io
+```
+
+Add your fork as an origin:
+
+```
+cd $(go env GOPATH)/src/go.opencensus.io
+git remote add fork git@github.com:YOUR_GITHUB_USERNAME/opencensus-go.git
+```
+
+Run tests:
+
+```
+$ go test ./...
+```
+
+Checkout a new branch, make modifications and push the branch to your fork:
+
+```
+$ git checkout -b feature
+# edit files
+$ git commit
+$ git push fork feature
+```
+
+Open a pull request against the main opencensus-go repo.
diff --git a/vendor/go.opencensus.io/Gopkg.lock b/vendor/go.opencensus.io/Gopkg.lock
index 026f013..3be12ac 100644
--- a/vendor/go.opencensus.io/Gopkg.lock
+++ b/vendor/go.opencensus.io/Gopkg.lock
@@ -2,57 +2,46 @@
[[projects]]
- name = "cloud.google.com/go"
- packages = [
- "compute/metadata",
- "internal/version",
- "monitoring/apiv3",
- "trace/apiv2"
- ]
- revision = "0fd7230b2a7505833d5f69b75cbd6c9582401479"
- version = "v0.23.0"
-
-[[projects]]
branch = "master"
+ digest = "1:eee9386329f4fcdf8d6c0def0c9771b634bdd5ba460d888aa98c17d59b37a76c"
name = "git.apache.org/thrift.git"
packages = ["lib/go/thrift"]
- revision = "88591e32e710a0524327153c8b629d5b461e35e0"
+ pruneopts = "UT"
+ revision = "6e67faa92827ece022380b211c2caaadd6145bf5"
source = "github.com/apache/thrift"
[[projects]]
branch = "master"
+ digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d"
name = "github.com/beorn7/perks"
packages = ["quantile"]
+ pruneopts = "UT"
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
[[projects]]
+ digest = "1:4c0989ca0bcd10799064318923b9bc2db6b4d6338dd75f3f2d86c3511aaaf5cf"
name = "github.com/golang/protobuf"
packages = [
"proto",
- "protoc-gen-go/descriptor",
"ptypes",
"ptypes/any",
"ptypes/duration",
- "ptypes/empty",
"ptypes/timestamp",
- "ptypes/wrappers"
]
- revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
- version = "v1.1.0"
-
-[[projects]]
- name = "github.com/googleapis/gax-go"
- packages = ["."]
- revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f"
- version = "v2.0.0"
+ pruneopts = "UT"
+ revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
+ version = "v1.2.0"
[[projects]]
+ digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"]
- revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
- version = "v1.0.0"
+ pruneopts = "UT"
+ revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
+ version = "v1.0.1"
[[projects]]
+ digest = "1:824c8f3aa4c5f23928fa84ebbd5ed2e9443b3f0cb958a40c1f2fbed5cf5e64b1"
name = "github.com/openzipkin/zipkin-go"
packages = [
".",
@@ -60,81 +49,90 @@
"model",
"propagation",
"reporter",
- "reporter/http"
+ "reporter/http",
]
- revision = "f197ec29e729f226d23370ea60f0e49b8f44ccf4"
- version = "v0.1.0"
+ pruneopts = "UT"
+ revision = "d455a5674050831c1e187644faa4046d653433c2"
+ version = "v0.1.1"
[[projects]]
+ digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb"
name = "github.com/prometheus/client_golang"
packages = [
"prometheus",
- "prometheus/promhttp"
+ "prometheus/promhttp",
]
+ pruneopts = "UT"
revision = "c5b7fccd204277076155f10851dad72b76a49317"
version = "v0.8.0"
[[projects]]
branch = "master"
+ digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
name = "github.com/prometheus/client_model"
packages = ["go"]
- revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
+ pruneopts = "UT"
+ revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f"
[[projects]]
branch = "master"
+ digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5"
name = "github.com/prometheus/common"
packages = [
"expfmt",
"internal/bitbucket.org/ww/goautoneg",
- "model"
+ "model",
]
- revision = "7600349dcfe1abd18d72d3a1770870d9800a7801"
+ pruneopts = "UT"
+ revision = "c7de2306084e37d54b8be01f3541a8464345e9a5"
[[projects]]
branch = "master"
+ digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290"
name = "github.com/prometheus/procfs"
packages = [
".",
"internal/util",
"nfs",
- "xfs"
+ "xfs",
]
- revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e"
+ pruneopts = "UT"
+ revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92"
[[projects]]
branch = "master"
+ digest = "1:deafe4ab271911fec7de5b693d7faae3f38796d9eb8622e2b9e7df42bb3dfea9"
name = "golang.org/x/net"
packages = [
"context",
- "context/ctxhttp",
"http/httpguts",
"http2",
"http2/hpack",
"idna",
"internal/timeseries",
- "trace"
+ "trace",
]
- revision = "9ef9f5bb98a1fdc41f8cf6c250a4404b4085e389"
-
-[[projects]]
- branch = "master"
- name = "golang.org/x/oauth2"
- packages = [
- ".",
- "google",
- "internal",
- "jws",
- "jwt"
- ]
- revision = "dd5f5d8e78ce062a4aa881dff95a94f2a0fd405a"
+ pruneopts = "UT"
+ revision = "922f4815f713f213882e8ef45e0d315b164d705c"
[[projects]]
branch = "master"
+ digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a"
name = "golang.org/x/sync"
packages = ["semaphore"]
+ pruneopts = "UT"
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
[[projects]]
+ branch = "master"
+ digest = "1:a3f00ac457c955fe86a41e1495e8f4c54cb5399d609374c5cc26aa7d72e542c8"
+ name = "golang.org/x/sys"
+ packages = ["unix"]
+ pruneopts = "UT"
+ revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec"
+
+[[projects]]
+ digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
name = "golang.org/x/text"
packages = [
"collate",
@@ -150,79 +148,48 @@
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
- "unicode/rangetable"
+ "unicode/rangetable",
]
+ pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
branch = "master"
+ digest = "1:c0c17c94fe8bc1ab34e7f586a4a8b788c5e1f4f9f750ff23395b8b2f5a523530"
name = "google.golang.org/api"
- packages = [
- "googleapi/transport",
- "internal",
- "iterator",
- "option",
- "support/bundler",
- "transport",
- "transport/grpc",
- "transport/http"
- ]
- revision = "4f7dd2b006a4ffd9fd683c1c734d2fe91ca0ea1c"
-
-[[projects]]
- name = "google.golang.org/appengine"
- packages = [
- ".",
- "internal",
- "internal/app_identity",
- "internal/base",
- "internal/datastore",
- "internal/log",
- "internal/modules",
- "internal/remote_api",
- "internal/socket",
- "internal/urlfetch",
- "socket",
- "urlfetch"
- ]
- revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
- version = "v1.0.0"
+ packages = ["support/bundler"]
+ pruneopts = "UT"
+ revision = "e21acd801f91da814261b938941d193bb036441a"
[[projects]]
branch = "master"
+ digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c"
name = "google.golang.org/genproto"
- packages = [
- "googleapis/api/annotations",
- "googleapis/api/distribution",
- "googleapis/api/label",
- "googleapis/api/metric",
- "googleapis/api/monitoredres",
- "googleapis/devtools/cloudtrace/v2",
- "googleapis/monitoring/v3",
- "googleapis/rpc/code",
- "googleapis/rpc/status",
- "protobuf/field_mask"
- ]
- revision = "11a468237815f3a3ddf9f7c6e8b6b3b382a24d15"
+ packages = ["googleapis/rpc/status"]
+ pruneopts = "UT"
+ revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4"
[[projects]]
+ digest = "1:3dd7996ce6bf52dec6a2f69fa43e7c4cefea1d4dfa3c8ab7a5f8a9f7434e239d"
name = "google.golang.org/grpc"
packages = [
".",
"balancer",
"balancer/base",
"balancer/roundrobin",
- "channelz",
"codes",
"connectivity",
"credentials",
- "credentials/oauth",
"encoding",
"encoding/proto",
- "grpclb/grpc_lb_v1/messages",
"grpclog",
"internal",
+ "internal/backoff",
+ "internal/channelz",
+ "internal/envconfig",
+ "internal/grpcrand",
+ "internal/transport",
"keepalive",
"metadata",
"naming",
@@ -233,14 +200,32 @@
"stats",
"status",
"tap",
- "transport"
]
- revision = "41344da2231b913fa3d983840a57a6b1b7b631a1"
- version = "v1.12.0"
+ pruneopts = "UT"
+ revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
+ version = "v1.14.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
- inputs-digest = "3fd3b357ae771c152cbc6b6d7b731c00c91c871cf2dbccb2f155ecc84ec80c4f"
+ input-imports = [
+ "git.apache.org/thrift.git/lib/go/thrift",
+ "github.com/golang/protobuf/proto",
+ "github.com/openzipkin/zipkin-go",
+ "github.com/openzipkin/zipkin-go/model",
+ "github.com/openzipkin/zipkin-go/reporter",
+ "github.com/openzipkin/zipkin-go/reporter/http",
+ "github.com/prometheus/client_golang/prometheus",
+ "github.com/prometheus/client_golang/prometheus/promhttp",
+ "golang.org/x/net/context",
+ "golang.org/x/net/http2",
+ "google.golang.org/api/support/bundler",
+ "google.golang.org/grpc",
+ "google.golang.org/grpc/codes",
+ "google.golang.org/grpc/grpclog",
+ "google.golang.org/grpc/metadata",
+ "google.golang.org/grpc/stats",
+ "google.golang.org/grpc/status",
+ ]
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/vendor/go.opencensus.io/Gopkg.toml b/vendor/go.opencensus.io/Gopkg.toml
index c3f8292..a9f3cd6 100644
--- a/vendor/go.opencensus.io/Gopkg.toml
+++ b/vendor/go.opencensus.io/Gopkg.toml
@@ -3,10 +3,6 @@
# able to find a satisfying dependency graph.
[[constraint]]
- name = "cloud.google.com/go"
- version = ">=0.21.0"
-
-[[constraint]]
branch = "master"
name = "git.apache.org/thrift.git"
source = "github.com/apache/thrift"
@@ -29,17 +25,9 @@
[[constraint]]
branch = "master"
- name = "golang.org/x/oauth2"
-
-[[constraint]]
- branch = "master"
name = "google.golang.org/api"
[[constraint]]
- branch = "master"
- name = "google.golang.org/genproto"
-
-[[constraint]]
name = "google.golang.org/grpc"
version = "1.11.3"
diff --git a/vendor/go.opencensus.io/README.md b/vendor/go.opencensus.io/README.md
index 1a4a58b..bc50ee4 100644
--- a/vendor/go.opencensus.io/README.md
+++ b/vendor/go.opencensus.io/README.md
@@ -22,17 +22,40 @@ The use of vendoring or a dependency management tool is recommended.
OpenCensus Go libraries require Go 1.8 or later.
+## Getting Started
+
+The easiest way to get started using OpenCensus in your application is to use an existing
+integration with your RPC framework:
+
+* [net/http](https://godoc.org/go.opencensus.io/plugin/ochttp)
+* [gRPC](https://godoc.org/go.opencensus.io/plugin/ocgrpc)
+* [database/sql](https://godoc.org/github.com/basvanbeek/ocsql)
+* [Go kit](https://godoc.org/github.com/go-kit/kit/tracing/opencensus)
+* [Groupcache](https://godoc.org/github.com/orijtech/groupcache)
+* [Caddy webserver](https://godoc.org/github.com/orijtech/caddy)
+* [MongoDB](https://godoc.org/github.com/orijtech/mongo-go-driver)
+* [Redis gomodule/redigo](https://godoc.org/github.com/orijtech/redigo)
+* [Redis goredis/redis](https://godoc.org/github.com/orijtech/redis)
+* [Memcache](https://godoc.org/github.com/orijtech/gomemcache)
+
+If you're a framework not listed here, you could either implement your own middleware for your
+framework or use [custom stats](#stats) and [spans](#spans) directly in your application.
+
## Exporters
-OpenCensus can export instrumentation data to various backends.
-Currently, OpenCensus supports:
+OpenCensus can export instrumentation data to various backends.
+OpenCensus has exporter implementations for the following, users
+can implement their own exporters by implementing the exporter interfaces
+([stats](https://godoc.org/go.opencensus.io/stats/view#Exporter),
+[trace](https://godoc.org/go.opencensus.io/trace#Exporter)):
* [Prometheus][exporter-prom] for stats
* [OpenZipkin][exporter-zipkin] for traces
-* Stackdriver [Monitoring][exporter-stackdriver] and [Trace][exporter-stackdriver]
+* [Stackdriver][exporter-stackdriver] Monitoring for stats and Trace for traces
* [Jaeger][exporter-jaeger] for traces
* [AWS X-Ray][exporter-xray] for traces
* [Datadog][exporter-datadog] for stats and traces
+
## Overview
![OpenCensus Overview](https://i.imgur.com/cf4ElHE.jpg)
@@ -42,13 +65,6 @@ multiple services until there is a response. OpenCensus allows
you to instrument your services and collect diagnostics data all
through your services end-to-end.
-Start with instrumenting HTTP and gRPC clients and servers,
-then add additional custom instrumentation if needed.
-
-* [HTTP guide](https://github.com/census-instrumentation/opencensus-go/tree/master/examples/http)
-* [gRPC guide](https://github.com/census-instrumentation/opencensus-go/tree/master/examples/grpc)
-
-
## Tags
Tags represent propagated key-value pairs. They are propagated using `context.Context`
@@ -115,26 +131,79 @@ Here we create a view with the DistributionAggregation over our measure.
[embedmd]:# (internal/readme/stats.go view)
```go
if err := view.Register(&view.View{
- Name: "my.org/video_size_distribution",
+ Name: "example.com/video_size_distribution",
Description: "distribution of processed video size over time",
Measure: videoSize,
Aggregation: view.Distribution(0, 1<<32, 2<<32, 3<<32),
}); err != nil {
- log.Fatalf("Failed to subscribe to view: %v", err)
+ log.Fatalf("Failed to register view: %v", err)
}
```
-Subscribe begins collecting data for the view. Subscribed views' data will be
+Register begins collecting data for the view. Registered views' data will be
exported via the registered exporters.
## Traces
+A distributed trace tracks the progression of a single user request as
+it is handled by the services and processes that make up an application.
+Each step is called a span in the trace. Spans include metadata about the step,
+including especially the time spent in the step, called the span’s latency.
+
+Below you see a trace and several spans underneath it.
+
+![Traces and spans](https://i.imgur.com/7hZwRVj.png)
+
+### Spans
+
+Span is the unit step in a trace. Each span has a name, latency, status and
+additional metadata.
+
+Below we are starting a span for a cache read and ending it
+when we are done:
+
[embedmd]:# (internal/readme/trace.go startend)
```go
-ctx, span := trace.StartSpan(ctx, "your choice of name")
+ctx, span := trace.StartSpan(ctx, "cache.Get")
defer span.End()
+
+// Do work to get from cache.
+```
+
+### Propagation
+
+Spans can have parents or can be root spans if they don't have any parents.
+The current span is propagated in-process and across the network to allow associating
+new child spans with the parent.
+
+In the same process, context.Context is used to propagate spans.
+trace.StartSpan creates a new span as a root if the current context
+doesn't contain a span. Or, it creates a child of the span that is
+already in current context. The returned context can be used to keep
+propagating the newly created span in the current context.
+
+[embedmd]:# (internal/readme/trace.go startend)
+```go
+ctx, span := trace.StartSpan(ctx, "cache.Get")
+defer span.End()
+
+// Do work to get from cache.
```
+Across the network, OpenCensus provides different propagation
+methods for different protocols.
+
+* gRPC integrations uses the OpenCensus' [binary propagation format](https://godoc.org/go.opencensus.io/trace/propagation).
+* HTTP integrations uses Zipkin's [B3](https://github.com/openzipkin/b3-propagation)
+ by default but can be configured to use a custom propagation method by setting another
+ [propagation.HTTPFormat](https://godoc.org/go.opencensus.io/trace/propagation#HTTPFormat).
+
+## Execution Tracer
+
+With Go 1.11, OpenCensus Go will support integration with the Go execution tracer.
+See [Debugging Latency in Go](https://medium.com/observability/debugging-latency-in-go-1-11-9f97a7910d68)
+for an example of their mutual use.
+
## Profiles
OpenCensus tags can be applied as profiler labels
@@ -166,7 +235,7 @@ Before version 1.0.0, the following deprecation policy will be observed:
No backwards-incompatible changes will be made except for the removal of symbols that have
been marked as *Deprecated* for at least one minor release (e.g. 0.9.0 to 0.10.0). A release
-removing the *Deprecated* functionality will be made no sooner than 28 days after the first
+removing the *Deprecated* functionality will be made no sooner than 28 days after the first
release in which the functionality was marked *Deprecated*.
[travis-image]: https://travis-ci.org/census-instrumentation/opencensus-go.svg?branch=master
diff --git a/vendor/go.opencensus.io/go.mod b/vendor/go.opencensus.io/go.mod
new file mode 100644
index 0000000..7a1ccc6
--- /dev/null
+++ b/vendor/go.opencensus.io/go.mod
@@ -0,0 +1,20 @@
+module go.opencensus.io
+
+require (
+ git.apache.org/thrift.git v0.0.0-20180807212849-6e67faa92827
+ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973
+ github.com/golang/protobuf v1.2.0
+ github.com/matttproud/golang_protobuf_extensions v1.0.1
+ github.com/openzipkin/zipkin-go v0.1.1
+ github.com/prometheus/client_golang v0.8.0
+ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910
+ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e
+ github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273
+ golang.org/x/net v0.0.0-20180821023952-922f4815f713
+ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
+ golang.org/x/sys v0.0.0-20180821140842-3b58ed4ad339
+ golang.org/x/text v0.3.0
+ google.golang.org/api v0.0.0-20180818000503-e21acd801f91
+ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
+ google.golang.org/grpc v1.14.0
+)
diff --git a/vendor/go.opencensus.io/opencensus.go b/vendor/go.opencensus.io/opencensus.go
index eb8e721..3b4e0c6 100644
--- a/vendor/go.opencensus.io/opencensus.go
+++ b/vendor/go.opencensus.io/opencensus.go
@@ -17,5 +17,5 @@ package opencensus // import "go.opencensus.io"
// Version is the current release version of OpenCensus in use.
func Version() string {
- return "0.14.0"
+ return "0.16.0"
}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/client.go b/vendor/go.opencensus.io/plugin/ochttp/client.go
index 37f42b3..68faf24 100644
--- a/vendor/go.opencensus.io/plugin/ochttp/client.go
+++ b/vendor/go.opencensus.io/plugin/ochttp/client.go
@@ -16,14 +16,18 @@ package ochttp
import (
"net/http"
+ "net/http/httptrace"
"go.opencensus.io/trace"
"go.opencensus.io/trace/propagation"
)
// Transport is an http.RoundTripper that instruments all outgoing requests with
-// stats and tracing. The zero value is intended to be a useful default, but for
-// now it's recommended that you explicitly set Propagation.
+// OpenCensus stats and tracing.
+//
+// The zero value is intended to be a useful default, but for
+// now it's recommended that you explicitly set Propagation, since the default
+// for this may change.
type Transport struct {
// Base may be set to wrap another http.RoundTripper that does the actual
// requests. By default http.DefaultTransport is used.
@@ -43,17 +47,34 @@ type Transport struct {
// for spans started by this transport.
StartOptions trace.StartOptions
+ // NameFromRequest holds the function to use for generating the span name
+ // from the information found in the outgoing HTTP Request. By default the
+ // name equals the URL Path.
+ FormatSpanName func(*http.Request) string
+
+ // NewClientTrace may be set to a function allowing the current *trace.Span
+ // to be annotated with HTTP request event information emitted by the
+ // httptrace package.
+ NewClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace
+
// TODO: Implement tag propagation for HTTP.
}
// RoundTrip implements http.RoundTripper, delegating to Base and recording stats and traces for the request.
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
rt := t.base()
+ if isHealthEndpoint(req.URL.Path) {
+ return rt.RoundTrip(req)
+ }
// TODO: remove excessive nesting of http.RoundTrippers here.
format := t.Propagation
if format == nil {
format = defaultFormat
}
+ spanNameFormatter := t.FormatSpanName
+ if spanNameFormatter == nil {
+ spanNameFormatter = spanNameFromURL
+ }
rt = &traceTransport{
base: rt,
format: format,
@@ -61,6 +82,8 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
Sampler: t.StartOptions.Sampler,
SpanKind: trace.SpanKindClient,
},
+ formatSpanName: spanNameFormatter,
+ newClientTrace: t.NewClientTrace,
}
rt = statsTransport{base: rt}
return rt.RoundTrip(req)
diff --git a/vendor/go.opencensus.io/plugin/ochttp/server.go b/vendor/go.opencensus.io/plugin/ochttp/server.go
index 4b3c855..72aa8c2 100644
--- a/vendor/go.opencensus.io/plugin/ochttp/server.go
+++ b/vendor/go.opencensus.io/plugin/ochttp/server.go
@@ -15,10 +15,8 @@
package ochttp
import (
- "bufio"
"context"
- "errors"
- "net"
+ "io"
"net/http"
"strconv"
"sync"
@@ -30,16 +28,19 @@ import (
"go.opencensus.io/trace/propagation"
)
-// Handler is a http.Handler that is aware of the incoming request's span.
+// Handler is an http.Handler wrapper to instrument your HTTP server with
+// OpenCensus. It supports both stats and tracing.
//
+// Tracing
+//
+// This handler is aware of the incoming request's span, reading it from request
+// headers as configured using the Propagation field.
// The extracted span can be accessed from the incoming request's
// context.
//
// span := trace.FromContext(r.Context())
//
// The server span will be automatically ended at the end of ServeHTTP.
-//
-// Incoming propagation mechanism is determined by the given HTTP propagators.
type Handler struct {
// Propagation defines how traces are propagated. If unspecified,
// B3 propagation will be used.
@@ -60,6 +61,11 @@ type Handler struct {
// be added as a linked trace instead of being added as a parent of the
// current trace.
IsPublicEndpoint bool
+
+ // FormatSpanName holds the function to use for generating the span name
+ // from the information found in the incoming HTTP Request. By default the
+ // name equals the URL Path.
+ FormatSpanName func(*http.Request) string
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -76,7 +82,15 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Request, func()) {
- name := spanNameFromURL(r.URL)
+ if isHealthEndpoint(r.URL.Path) {
+ return r, func() {}
+ }
+ var name string
+ if h.FormatSpanName == nil {
+ name = spanNameFromURL(r)
+ } else {
+ name = h.FormatSpanName(r)
+ }
ctx := r.Context()
var span *trace.Span
sc, ok := h.extractSpanContext(r)
@@ -126,7 +140,7 @@ func (h *Handler) startStats(w http.ResponseWriter, r *http.Request) (http.Respo
track.reqSize = r.ContentLength
}
stats.Record(ctx, ServerRequestCount.M(1))
- return track, track.end
+ return track.wrappedResponseWriter(), track.end
}
type trackingResponseWriter struct {
@@ -140,39 +154,9 @@ type trackingResponseWriter struct {
writer http.ResponseWriter
}
-// Compile time assertions for widely used net/http interfaces
-var _ http.CloseNotifier = (*trackingResponseWriter)(nil)
-var _ http.Flusher = (*trackingResponseWriter)(nil)
-var _ http.Hijacker = (*trackingResponseWriter)(nil)
-var _ http.Pusher = (*trackingResponseWriter)(nil)
+// Compile time assertion for ResponseWriter interface
var _ http.ResponseWriter = (*trackingResponseWriter)(nil)
-var errHijackerUnimplemented = errors.New("ResponseWriter does not implement http.Hijacker")
-
-func (t *trackingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
- hj, ok := t.writer.(http.Hijacker)
- if !ok {
- return nil, nil, errHijackerUnimplemented
- }
- return hj.Hijack()
-}
-
-func (t *trackingResponseWriter) CloseNotify() <-chan bool {
- cn, ok := t.writer.(http.CloseNotifier)
- if !ok {
- return nil
- }
- return cn.CloseNotify()
-}
-
-func (t *trackingResponseWriter) Push(target string, opts *http.PushOptions) error {
- pusher, ok := t.writer.(http.Pusher)
- if !ok {
- return http.ErrNotSupported
- }
- return pusher.Push(target, opts)
-}
-
func (t *trackingResponseWriter) end() {
t.endOnce.Do(func() {
if t.statusCode == 0 {
@@ -210,8 +194,231 @@ func (t *trackingResponseWriter) WriteHeader(statusCode int) {
t.statusLine = http.StatusText(t.statusCode)
}
-func (t *trackingResponseWriter) Flush() {
- if flusher, ok := t.writer.(http.Flusher); ok {
- flusher.Flush()
+// wrappedResponseWriter returns a wrapped version of the original
+// ResponseWriter and only implements the same combination of additional
+// interfaces as the original.
+// This implementation is based on https://github.com/felixge/httpsnoop.
+func (t *trackingResponseWriter) wrappedResponseWriter() http.ResponseWriter {
+ var (
+ hj, i0 = t.writer.(http.Hijacker)
+ cn, i1 = t.writer.(http.CloseNotifier)
+ pu, i2 = t.writer.(http.Pusher)
+ fl, i3 = t.writer.(http.Flusher)
+ rf, i4 = t.writer.(io.ReaderFrom)
+ )
+
+ switch {
+ case !i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ }{t}
+ case !i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ }{t, rf}
+ case !i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ }{t, fl}
+ case !i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ }{t, fl, rf}
+ case !i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ }{t, pu}
+ case !i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ io.ReaderFrom
+ }{t, pu, rf}
+ case !i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ http.Flusher
+ }{t, pu, fl}
+ case !i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, pu, fl, rf}
+ case !i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ }{t, cn}
+ case !i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ }{t, cn, rf}
+ case !i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Flusher
+ }{t, cn, fl}
+ case !i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Flusher
+ io.ReaderFrom
+ }{t, cn, fl, rf}
+ case !i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ }{t, cn, pu}
+ case !i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ io.ReaderFrom
+ }{t, cn, pu, rf}
+ case !i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ }{t, cn, pu, fl}
+ case !i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, cn, pu, fl, rf}
+ case i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ }{t, hj}
+ case i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ }{t, hj, rf}
+ case i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Flusher
+ }{t, hj, fl}
+ case i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, fl, rf}
+ case i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ }{t, hj, pu}
+ case i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ io.ReaderFrom
+ }{t, hj, pu, rf}
+ case i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ http.Flusher
+ }{t, hj, pu, fl}
+ case i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, pu, fl, rf}
+ case i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ }{t, hj, cn}
+ case i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ io.ReaderFrom
+ }{t, hj, cn, rf}
+ case i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Flusher
+ }{t, hj, cn, fl}
+ case i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, cn, fl, rf}
+ case i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ }{t, hj, cn, pu}
+ case i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ io.ReaderFrom
+ }{t, hj, cn, pu, rf}
+ case i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ }{t, hj, cn, pu, fl}
+ case i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, cn, pu, fl, rf}
+ default:
+ return struct {
+ http.ResponseWriter
+ }{t}
}
}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/span_annotator.go b/vendor/go.opencensus.io/plugin/ochttp/span_annotator.go
new file mode 100644
index 0000000..1282287
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/span_annotator.go
@@ -0,0 +1,160 @@
+// Copyright 2018, 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 ochttp
+
+import (
+ "crypto/tls"
+ "net/http"
+ "net/http/httptrace"
+ "strings"
+
+ "go.opencensus.io/trace"
+)
+
+type spanAnnotator struct {
+ sp *trace.Span
+}
+
+// NewSpanAnnotator returns a httptrace.ClientTrace which annotates all emitted
+// httptrace events on the provided Span.
+func NewSpanAnnotator(_ *http.Request, s *trace.Span) *httptrace.ClientTrace {
+ sa := spanAnnotator{sp: s}
+
+ return &httptrace.ClientTrace{
+ GetConn: sa.getConn,
+ GotConn: sa.gotConn,
+ PutIdleConn: sa.putIdleConn,
+ GotFirstResponseByte: sa.gotFirstResponseByte,
+ Got100Continue: sa.got100Continue,
+ DNSStart: sa.dnsStart,
+ DNSDone: sa.dnsDone,
+ ConnectStart: sa.connectStart,
+ ConnectDone: sa.connectDone,
+ TLSHandshakeStart: sa.tlsHandshakeStart,
+ TLSHandshakeDone: sa.tlsHandshakeDone,
+ WroteHeaders: sa.wroteHeaders,
+ Wait100Continue: sa.wait100Continue,
+ WroteRequest: sa.wroteRequest,
+ }
+}
+
+func (s spanAnnotator) getConn(hostPort string) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.get_connection.host_port", hostPort),
+ }
+ s.sp.Annotate(attrs, "GetConn")
+}
+
+func (s spanAnnotator) gotConn(info httptrace.GotConnInfo) {
+ attrs := []trace.Attribute{
+ trace.BoolAttribute("httptrace.got_connection.reused", info.Reused),
+ trace.BoolAttribute("httptrace.got_connection.was_idle", info.WasIdle),
+ }
+ if info.WasIdle {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.got_connection.idle_time", info.IdleTime.String()))
+ }
+ s.sp.Annotate(attrs, "GotConn")
+}
+
+// PutIdleConn implements a httptrace.ClientTrace hook
+func (s spanAnnotator) putIdleConn(err error) {
+ var attrs []trace.Attribute
+ if err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.put_idle_connection.error", err.Error()))
+ }
+ s.sp.Annotate(attrs, "PutIdleConn")
+}
+
+func (s spanAnnotator) gotFirstResponseByte() {
+ s.sp.Annotate(nil, "GotFirstResponseByte")
+}
+
+func (s spanAnnotator) got100Continue() {
+ s.sp.Annotate(nil, "Got100Continue")
+}
+
+func (s spanAnnotator) dnsStart(info httptrace.DNSStartInfo) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.dns_start.host", info.Host),
+ }
+ s.sp.Annotate(attrs, "DNSStart")
+}
+
+func (s spanAnnotator) dnsDone(info httptrace.DNSDoneInfo) {
+ var addrs []string
+ for _, addr := range info.Addrs {
+ addrs = append(addrs, addr.String())
+ }
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.dns_done.addrs", strings.Join(addrs, " , ")),
+ }
+ if info.Err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.dns_done.error", info.Err.Error()))
+ }
+ s.sp.Annotate(attrs, "DNSDone")
+}
+
+func (s spanAnnotator) connectStart(network, addr string) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.connect_start.network", network),
+ trace.StringAttribute("httptrace.connect_start.addr", addr),
+ }
+ s.sp.Annotate(attrs, "ConnectStart")
+}
+
+func (s spanAnnotator) connectDone(network, addr string, err error) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.connect_done.network", network),
+ trace.StringAttribute("httptrace.connect_done.addr", addr),
+ }
+ if err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.connect_done.error", err.Error()))
+ }
+ s.sp.Annotate(attrs, "ConnectDone")
+}
+
+func (s spanAnnotator) tlsHandshakeStart() {
+ s.sp.Annotate(nil, "TLSHandshakeStart")
+}
+
+func (s spanAnnotator) tlsHandshakeDone(_ tls.ConnectionState, err error) {
+ var attrs []trace.Attribute
+ if err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.tls_handshake_done.error", err.Error()))
+ }
+ s.sp.Annotate(attrs, "TLSHandshakeDone")
+}
+
+func (s spanAnnotator) wroteHeaders() {
+ s.sp.Annotate(nil, "WroteHeaders")
+}
+
+func (s spanAnnotator) wait100Continue() {
+ s.sp.Annotate(nil, "Wait100Continue")
+}
+
+func (s spanAnnotator) wroteRequest(info httptrace.WroteRequestInfo) {
+ var attrs []trace.Attribute
+ if info.Err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.wrote_request.error", info.Err.Error()))
+ }
+ s.sp.Annotate(attrs, "WroteRequest")
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/stats.go b/vendor/go.opencensus.io/plugin/ochttp/stats.go
index 2bd11f6..19a8825 100644
--- a/vendor/go.opencensus.io/plugin/ochttp/stats.go
+++ b/vendor/go.opencensus.io/plugin/ochttp/stats.go
@@ -41,6 +41,10 @@ var (
// ClientRequestCount or ServerRequestCount, since it is recorded before the status is known.
var (
// Host is the value of the HTTP Host header.
+ //
+ // The value of this tag can be controlled by the HTTP client, so you need
+ // to watch out for potentially generating high-cardinality labels in your
+ // metrics backend if you use this tag in views.
Host, _ = tag.NewKey("http.host")
// StatusCode is the numeric HTTP response status code,
@@ -48,6 +52,10 @@ var (
StatusCode, _ = tag.NewKey("http.status")
// Path is the URL path (not including query string) in the request.
+ //
+ // The value of this tag can be controlled by the HTTP client, so you need
+ // to watch out for potentially generating high-cardinality labels in your
+ // metrics backend if you use this tag in views.
Path, _ = tag.NewKey("http.path")
// Method is the HTTP method of the request, capitalized (GET, POST, etc.).
@@ -61,7 +69,7 @@ var (
)
// Package ochttp provides some convenience views.
-// You need to subscribe to the views for data to actually be collected.
+// You need to register the views for data to actually be collected.
var (
ClientRequestCountView = &view.View{
Name: "opencensus.io/http/client/request_count",
diff --git a/vendor/go.opencensus.io/plugin/ochttp/trace.go b/vendor/go.opencensus.io/plugin/ochttp/trace.go
index 79bbfd1..980b639 100644
--- a/vendor/go.opencensus.io/plugin/ochttp/trace.go
+++ b/vendor/go.opencensus.io/plugin/ochttp/trace.go
@@ -17,7 +17,7 @@ package ochttp
import (
"io"
"net/http"
- "net/url"
+ "net/http/httptrace"
"go.opencensus.io/plugin/ochttp/propagation/b3"
"go.opencensus.io/trace"
@@ -39,9 +39,11 @@ const (
)
type traceTransport struct {
- base http.RoundTripper
- startOptions trace.StartOptions
- format propagation.HTTPFormat
+ base http.RoundTripper
+ startOptions trace.StartOptions
+ format propagation.HTTPFormat
+ formatSpanName func(*http.Request) string
+ newClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace
}
// TODO(jbd): Add message events for request and response size.
@@ -50,14 +52,19 @@ type traceTransport struct {
// The created span can follow a parent span, if a parent is presented in
// the request's context.
func (t *traceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
- name := spanNameFromURL(req.URL)
+ name := t.formatSpanName(req)
// TODO(jbd): Discuss whether we want to prefix
// outgoing requests with Sent.
- _, span := trace.StartSpan(req.Context(), name,
+ ctx, span := trace.StartSpan(req.Context(), name,
trace.WithSampler(t.startOptions.Sampler),
trace.WithSpanKind(trace.SpanKindClient))
- req = req.WithContext(trace.WithSpan(req.Context(), span))
+ if t.newClientTrace != nil {
+ req = req.WithContext(httptrace.WithClientTrace(ctx, t.newClientTrace(req, span)))
+ } else {
+ req = req.WithContext(ctx)
+ }
+
if t.format != nil {
t.format.SpanContextToRequest(span.SpanContext(), req)
}
@@ -127,8 +134,8 @@ func (t *traceTransport) CancelRequest(req *http.Request) {
}
}
-func spanNameFromURL(u *url.URL) string {
- return u.Path
+func spanNameFromURL(req *http.Request) string {
+ return req.URL.Path
}
func requestAttrs(r *http.Request) []trace.Attribute {
@@ -146,7 +153,7 @@ func responseAttrs(resp *http.Response) []trace.Attribute {
}
}
-// TraceStatus converts the HTTP status code to a trace.Status that
+// TraceStatus is a utility to convert the HTTP status code to a trace.Status that
// represents the outcome as closely as possible.
func TraceStatus(httpStatusCode int, statusLine string) trace.Status {
var code int32
@@ -197,3 +204,15 @@ var codeToStr = map[int32]string{
trace.StatusCodeDataLoss: `"DATA_LOSS"`,
trace.StatusCodeUnauthenticated: `"UNAUTHENTICATED"`,
}
+
+func isHealthEndpoint(path string) bool {
+ // Health checking is pretty frequent and
+ // traces collected for health endpoints
+ // can be extremely noisy and expensive.
+ // Disable canonical health checking endpoints
+ // like /healthz and /_ah/health for now.
+ if path == "/healthz" || path == "/_ah/health" {
+ return true
+ }
+ return false
+}
diff --git a/vendor/go.opencensus.io/stats/measure.go b/vendor/go.opencensus.io/stats/measure.go
index aa555c2..7b4b49c 100644
--- a/vendor/go.opencensus.io/stats/measure.go
+++ b/vendor/go.opencensus.io/stats/measure.go
@@ -20,19 +20,31 @@ import (
"sync/atomic"
)
-// Measure represents a type of metric to be tracked and recorded.
-// For example, latency, request Mb/s, and response Mb/s are measures
+// Measure represents a single numeric value to be tracked and recorded.
+// For example, latency, request bytes, and response bytes could be measures
// to collect from a server.
//
-// Each measure needs to be registered before being used.
-// Measure constructors such as Int64 and
-// Float64 automatically registers the measure
-// by the given name.
-// Each registered measure needs to be unique by name.
-// Measures also have a description and a unit.
+// Measures by themselves have no outside effects. In order to be exported,
+// the measure needs to be used in a View. If no Views are defined over a
+// measure, there is very little cost in recording it.
type Measure interface {
+ // Name returns the name of this measure.
+ //
+ // Measure names are globally unique (among all libraries linked into your program).
+ // We recommend prefixing the measure name with a domain name relevant to your
+ // project or application.
+ //
+ // Measure names are never sent over the wire or exported to backends.
+ // They are only used to create Views.
Name() string
+
+ // Description returns the human-readable description of this measure.
Description() string
+
+ // Unit returns the units for the values this measure takes on.
+ //
+ // Units are encoded according to the case-sensitive abbreviations from the
+ // Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html
Unit() string
}
diff --git a/vendor/go.opencensus.io/stats/measure_float64.go b/vendor/go.opencensus.io/stats/measure_float64.go
index 8de6b52..da4b5a8 100644
--- a/vendor/go.opencensus.io/stats/measure_float64.go
+++ b/vendor/go.opencensus.io/stats/measure_float64.go
@@ -15,7 +15,7 @@
package stats
-// Float64Measure is a measure of type float64.
+// Float64Measure is a measure for float64 values.
type Float64Measure struct {
md *measureDescriptor
}
@@ -44,8 +44,10 @@ func (m *Float64Measure) M(v float64) Measurement {
return Measurement{m: m, v: v}
}
-// Float64 creates a new measure of type Float64Measure.
-// It never returns an error.
+// Float64 creates a new measure for float64 values.
+//
+// See the documentation for interface Measure for more guidance on the
+// parameters of this function.
func Float64(name, description, unit string) *Float64Measure {
mi := registerMeasureHandle(name, description, unit)
return &Float64Measure{mi}
diff --git a/vendor/go.opencensus.io/stats/measure_int64.go b/vendor/go.opencensus.io/stats/measure_int64.go
index b6fd25f..5fedaad 100644
--- a/vendor/go.opencensus.io/stats/measure_int64.go
+++ b/vendor/go.opencensus.io/stats/measure_int64.go
@@ -15,7 +15,7 @@
package stats
-// Int64Measure is a measure of type int64.
+// Int64Measure is a measure for int64 values.
type Int64Measure struct {
md *measureDescriptor
}
@@ -44,8 +44,10 @@ func (m *Int64Measure) M(v int64) Measurement {
return Measurement{m: m, v: float64(v)}
}
-// Int64 creates a new measure of type Int64Measure.
-// It never returns an error.
+// Int64 creates a new measure for int64 values.
+//
+// See the documentation for interface Measure for more guidance on the
+// parameters of this function.
func Int64(name, description, unit string) *Int64Measure {
mi := registerMeasureHandle(name, description, unit)
return &Int64Measure{mi}
diff --git a/vendor/go.opencensus.io/stats/view/collector.go b/vendor/go.opencensus.io/stats/view/collector.go
index 863a5b6..250395d 100644
--- a/vendor/go.opencensus.io/stats/view/collector.go
+++ b/vendor/go.opencensus.io/stats/view/collector.go
@@ -40,11 +40,12 @@ func (c *collector) addSample(s string, v float64) {
aggregator.addSample(v)
}
+// collectRows returns a snapshot of the collected Row values.
func (c *collector) collectedRows(keys []tag.Key) []*Row {
- var rows []*Row
+ rows := make([]*Row, 0, len(c.signatures))
for sig, aggregator := range c.signatures {
tags := decodeTags([]byte(sig), keys)
- row := &Row{tags, aggregator}
+ row := &Row{Tags: tags, Data: aggregator.clone()}
rows = append(rows, row)
}
return rows
diff --git a/vendor/go.opencensus.io/stats/view/export.go b/vendor/go.opencensus.io/stats/view/export.go
index ffd0d1a..7cb5971 100644
--- a/vendor/go.opencensus.io/stats/view/export.go
+++ b/vendor/go.opencensus.io/stats/view/export.go
@@ -27,6 +27,9 @@ var (
// Exporter takes a significant amount of time to
// process a Data, that work should be done on another goroutine.
//
+// It is safe to assume that ExportView will not be called concurrently from
+// multiple goroutines.
+//
// The Data should not be modified.
type Exporter interface {
ExportView(viewData *Data)
diff --git a/vendor/go.opencensus.io/stats/view/view.go b/vendor/go.opencensus.io/stats/view/view.go
index 87bf5d4..22323e2 100644
--- a/vendor/go.opencensus.io/stats/view/view.go
+++ b/vendor/go.opencensus.io/stats/view/view.go
@@ -29,7 +29,7 @@ import (
)
// View allows users to aggregate the recorded stats.Measurements.
-// Views need to be passed to the Subscribe function to be before data will be
+// Views need to be passed to the Register function to be before data will be
// collected and sent to Exporters.
type View struct {
Name string // Name of View. Must be unique. If unset, will default to the name of the Measure.
@@ -71,10 +71,10 @@ func (v *View) same(other *View) bool {
// defaults for Name and Description and sorting the TagKeys
func (v *View) canonicalize() error {
if v.Measure == nil {
- return fmt.Errorf("cannot subscribe view %q: measure not set", v.Name)
+ return fmt.Errorf("cannot register view %q: measure not set", v.Name)
}
if v.Aggregation == nil {
- return fmt.Errorf("cannot subscribe view %q: aggregation not set", v.Name)
+ return fmt.Errorf("cannot register view %q: aggregation not set", v.Name)
}
if v.Name == "" {
v.Name = v.Measure.Name()
diff --git a/vendor/go.opencensus.io/stats/view/worker.go b/vendor/go.opencensus.io/stats/view/worker.go
index ba9d7fc..fef7bf5 100644
--- a/vendor/go.opencensus.io/stats/view/worker.go
+++ b/vendor/go.opencensus.io/stats/view/worker.go
@@ -49,8 +49,8 @@ var defaultWorker *worker
var defaultReportingDuration = 10 * time.Second
-// Find returns a subscribed view associated with this name.
-// If no subscribed view is found, nil is returned.
+// Find returns a registered view associated with this name.
+// If no registered view is found, nil is returned.
func Find(name string) (v *View) {
req := &getViewByNameReq{
name: name,
@@ -62,7 +62,7 @@ func Find(name string) (v *View) {
}
// Register begins collecting data for the given views.
-// Once a view is subscribed, it reports data to the registered exporters.
+// Once a view is registered, it reports data to the registered exporters.
func Register(views ...*View) error {
for _, v := range views {
if err := v.canonicalize(); err != nil {
@@ -181,7 +181,7 @@ func (w *worker) tryRegisterView(v *View) (*viewInternal, error) {
}
if x, ok := w.views[vi.view.Name]; ok {
if !x.view.same(vi.view) {
- return nil, fmt.Errorf("cannot subscribe view %q; a different view with the same name is already subscribed", v.Name)
+ return nil, fmt.Errorf("cannot register view %q; a different view with the same name is already registered", v.Name)
}
// the view is already registered so there is nothing to do and the
@@ -194,40 +194,30 @@ func (w *worker) tryRegisterView(v *View) (*viewInternal, error) {
return vi, nil
}
-func (w *worker) reportUsage(now time.Time) {
- for _, v := range w.views {
- if !v.isSubscribed() {
- continue
- }
- rows := v.collectedRows()
- _, ok := w.startTimes[v]
- if !ok {
- w.startTimes[v] = now
- }
- // Make sure collector is never going
- // to mutate the exported data.
- rows = deepCopyRowData(rows)
- viewData := &Data{
- View: v.view,
- Start: w.startTimes[v],
- End: time.Now(),
- Rows: rows,
- }
- exportersMu.Lock()
- for e := range exporters {
- e.ExportView(viewData)
- }
- exportersMu.Unlock()
+func (w *worker) reportView(v *viewInternal, now time.Time) {
+ 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],
+ End: time.Now(),
+ Rows: rows,
+ }
+ exportersMu.Lock()
+ for e := range exporters {
+ e.ExportView(viewData)
+ }
+ exportersMu.Unlock()
}
-func deepCopyRowData(rows []*Row) []*Row {
- newRows := make([]*Row, 0, len(rows))
- for _, r := range rows {
- newRows = append(newRows, &Row{
- Data: r.Data.clone(),
- Tags: r.Tags,
- })
+func (w *worker) reportUsage(now time.Time) {
+ for _, v := range w.views {
+ w.reportView(v, now)
}
- return newRows
}
diff --git a/vendor/go.opencensus.io/stats/view/worker_commands.go b/vendor/go.opencensus.io/stats/view/worker_commands.go
index ef79ec3..06c3c54 100644
--- a/vendor/go.opencensus.io/stats/view/worker_commands.go
+++ b/vendor/go.opencensus.io/stats/view/worker_commands.go
@@ -73,7 +73,7 @@ func (cmd *registerViewReq) handleCommand(w *worker) {
}
}
-// unregisterFromViewReq is the command to unsubscribe to a view. Has no
+// unregisterFromViewReq is the command to unregister to a view. Has no
// impact on the data collection for client that are pulling data from the
// library.
type unregisterFromViewReq struct {
@@ -88,6 +88,9 @@ func (cmd *unregisterFromViewReq) handleCommand(w *worker) {
continue
}
+ // Report pending data for this view before removing it.
+ w.reportView(vi, time.Now())
+
vi.unsubscribe()
if !vi.isSubscribed() {
// this was the last subscription and view is not collecting anymore.
@@ -143,7 +146,7 @@ type recordReq struct {
func (cmd *recordReq) handleCommand(w *worker) {
for _, m := range cmd.ms {
- if (m == stats.Measurement{}) { // not subscribed
+ if (m == stats.Measurement{}) { // not registered
continue
}
ref := w.getMeasureRef(m.Measure().Name())
@@ -154,7 +157,7 @@ func (cmd *recordReq) handleCommand(w *worker) {
}
// setReportingPeriodReq is the command to modify the duration between
-// reporting the collected data to the subscribed clients.
+// reporting the collected data to the registered clients.
type setReportingPeriodReq struct {
d time.Duration
c chan bool
diff --git a/vendor/go.opencensus.io/tag/map_codec.go b/vendor/go.opencensus.io/tag/map_codec.go
index 33be1f0..3e99895 100644
--- a/vendor/go.opencensus.io/tag/map_codec.go
+++ b/vendor/go.opencensus.io/tag/map_codec.go
@@ -177,45 +177,58 @@ func Encode(m *Map) []byte {
// Decode decodes the given []byte into a tag map.
func Decode(bytes []byte) (*Map, error) {
ts := newMap()
+ err := DecodeEach(bytes, ts.upsert)
+ if err != nil {
+ // no partial failures
+ return nil, err
+ }
+ return ts, nil
+}
+// DecodeEach decodes the given serialized tag map, calling handler for each
+// tag key and value decoded.
+func DecodeEach(bytes []byte, fn func(key Key, val string)) error {
eg := &encoderGRPC{
buf: bytes,
}
if len(eg.buf) == 0 {
- return ts, nil
+ return nil
}
version := eg.readByte()
if version > tagsVersionID {
- return nil, fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID)
+ return fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID)
}
for !eg.readEnded() {
typ := keyType(eg.readByte())
if typ != keyTypeString {
- return nil, fmt.Errorf("cannot decode: invalid key type: %q", typ)
+ return fmt.Errorf("cannot decode: invalid key type: %q", typ)
}
k, err := eg.readBytesWithVarintLen()
if err != nil {
- return nil, err
+ return err
}
v, err := eg.readBytesWithVarintLen()
if err != nil {
- return nil, err
+ return err
}
key, err := NewKey(string(k))
if err != nil {
- return nil, err // no partial failures
+ return err
}
val := string(v)
if !checkValue(val) {
- return nil, errInvalidValue // no partial failures
+ return errInvalidValue
+ }
+ fn(key, val)
+ if err != nil {
+ return err
}
- ts.upsert(key, val)
}
- return ts, nil
+ return nil
}
diff --git a/vendor/go.opencensus.io/trace/config.go b/vendor/go.opencensus.io/trace/config.go
index d5473a7..e464671 100644
--- a/vendor/go.opencensus.io/trace/config.go
+++ b/vendor/go.opencensus.io/trace/config.go
@@ -14,7 +14,10 @@
package trace
-import "go.opencensus.io/trace/internal"
+import (
+ "go.opencensus.io/trace/internal"
+ "sync"
+)
// Config represents the global tracing configuration.
type Config struct {
@@ -25,10 +28,14 @@ type Config struct {
IDGenerator internal.IDGenerator
}
+var configWriteMu sync.Mutex
+
// ApplyConfig applies changes to the global tracing configuration.
//
// Fields not provided in the given config are going to be preserved.
func ApplyConfig(cfg Config) {
+ configWriteMu.Lock()
+ defer configWriteMu.Unlock()
c := *config.Load().(*Config)
if cfg.DefaultSampler != nil {
c.DefaultSampler = cfg.DefaultSampler
diff --git a/vendor/go.opencensus.io/trace/doc.go b/vendor/go.opencensus.io/trace/doc.go
index a2b54e5..db00044 100644
--- a/vendor/go.opencensus.io/trace/doc.go
+++ b/vendor/go.opencensus.io/trace/doc.go
@@ -42,7 +42,7 @@ It is common to want to capture all the activity of a function call in a span. F
this to work, the function must take a context.Context as a parameter. Add these two
lines to the top of the function:
- ctx, span := trace.StartSpan(ctx, "my.org/Run")
+ ctx, span := trace.StartSpan(ctx, "example.com/Run")
defer span.End()
StartSpan will create a new top-level span if the context
diff --git a/vendor/go.opencensus.io/trace/export.go b/vendor/go.opencensus.io/trace/export.go
index c522550..77a8c73 100644
--- a/vendor/go.opencensus.io/trace/export.go
+++ b/vendor/go.opencensus.io/trace/export.go
@@ -16,6 +16,7 @@ package trace
import (
"sync"
+ "sync/atomic"
"time"
)
@@ -30,9 +31,11 @@ type Exporter interface {
ExportSpan(s *SpanData)
}
+type exportersMap map[Exporter]struct{}
+
var (
- exportersMu sync.Mutex
- exporters map[Exporter]struct{}
+ exporterMu sync.Mutex
+ exporters atomic.Value
)
// RegisterExporter adds to the list of Exporters that will receive sampled
@@ -40,20 +43,31 @@ var (
//
// Binaries can register exporters, libraries shouldn't register exporters.
func RegisterExporter(e Exporter) {
- exportersMu.Lock()
- if exporters == nil {
- exporters = make(map[Exporter]struct{})
+ exporterMu.Lock()
+ new := make(exportersMap)
+ if old, ok := exporters.Load().(exportersMap); ok {
+ for k, v := range old {
+ new[k] = v
+ }
}
- exporters[e] = struct{}{}
- exportersMu.Unlock()
+ new[e] = struct{}{}
+ exporters.Store(new)
+ exporterMu.Unlock()
}
// UnregisterExporter removes from the list of Exporters the Exporter that was
// registered with the given name.
func UnregisterExporter(e Exporter) {
- exportersMu.Lock()
- delete(exporters, e)
- exportersMu.Unlock()
+ exporterMu.Lock()
+ new := make(exportersMap)
+ if old, ok := exporters.Load().(exportersMap); ok {
+ for k, v := range old {
+ new[k] = v
+ }
+ }
+ delete(new, e)
+ exporters.Store(new)
+ exporterMu.Unlock()
}
// SpanData contains all the information collected by a Span.
diff --git a/vendor/go.opencensus.io/trace/trace.go b/vendor/go.opencensus.io/trace/trace.go
index 19c6930..887e90b 100644
--- a/vendor/go.opencensus.io/trace/trace.go
+++ b/vendor/go.opencensus.io/trace/trace.go
@@ -98,13 +98,6 @@ func FromContext(ctx context.Context) *Span {
return s
}
-// WithSpan returns a new context with the given Span attached.
-//
-// Deprecated: Use NewContext.
-func WithSpan(parent context.Context, s *Span) context.Context {
- return NewContext(parent, s)
-}
-
// NewContext returns a new context with the given Span attached.
func NewContext(parent context.Context, s *Span) context.Context {
return context.WithValue(parent, contextKey{}, s)
@@ -154,6 +147,9 @@ func WithSampler(sampler Sampler) StartOption {
// 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) {
var opts StartOptions
var parent SpanContext
@@ -174,6 +170,9 @@ func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Cont
//
// 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) {
var opts StartOptions
for _, op := range o {
@@ -185,26 +184,6 @@ func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanCont
return NewContext(ctx, span), span
}
-// NewSpan returns a new span.
-//
-// If parent is not nil, created span will be a child of the parent.
-//
-// Deprecated: Use StartSpan.
-func NewSpan(name string, parent *Span, o StartOptions) *Span {
- var parentSpanContext SpanContext
- if parent != nil {
- parentSpanContext = parent.SpanContext()
- }
- return startSpanInternal(name, parent != nil, parentSpanContext, false, o)
-}
-
-// NewSpanWithRemoteParent returns a new span with the given parent SpanContext.
-//
-// Deprecated: Use StartSpanWithRemoteParent.
-func NewSpanWithRemoteParent(name string, parent SpanContext, o StartOptions) *Span {
- return startSpanInternal(name, true, parent, true, o)
-}
-
func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *Span {
span := &Span{}
span.spanContext = parent
@@ -269,19 +248,19 @@ func (s *Span) End() {
if s.executionTracerTaskEnd != nil {
s.executionTracerTaskEnd()
}
- // TODO: optimize to avoid this call if sd won't be used.
- sd := s.makeSpanData()
- sd.EndTime = internal.MonotonicEndTime(sd.StartTime)
- if s.spanStore != nil {
- s.spanStore.finished(s, sd)
- }
- if s.spanContext.IsSampled() {
- // TODO: consider holding exportersMu for less time.
- exportersMu.Lock()
- for e := range exporters {
- e.ExportSpan(sd)
+ exp, _ := exporters.Load().(exportersMap)
+ mustExport := s.spanContext.IsSampled() && len(exp) > 0
+ if s.spanStore != nil || mustExport {
+ sd := s.makeSpanData()
+ sd.EndTime = internal.MonotonicEndTime(sd.StartTime)
+ if s.spanStore != nil {
+ s.spanStore.finished(s, sd)
+ }
+ if mustExport {
+ for e := range exp {
+ e.ExportSpan(sd)
+ }
}
- exportersMu.Unlock()
}
})
}
@@ -310,6 +289,16 @@ func (s *Span) SpanContext() SpanContext {
return s.spanContext
}
+// SetName sets the name of the span, if it is recording events.
+func (s *Span) SetName(name string) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.mu.Lock()
+ s.data.Name = name
+ s.mu.Unlock()
+}
+
// SetStatus sets the status of the span, if it is recording events.
func (s *Span) SetStatus(status Status) {
if !s.IsRecordingEvents() {
@@ -481,22 +470,28 @@ func init() {
type defaultIDGenerator struct {
sync.Mutex
- traceIDRand *rand.Rand
+
+ // Please keep these as the first fields
+ // so that these 8 byte fields will be aligned on addresses
+ // divisible by 8, on both 32-bit and 64-bit machines when
+ // performing atomic increments and accesses.
+ // See:
+ // * https://github.com/census-instrumentation/opencensus-go/issues/587
+ // * https://github.com/census-instrumentation/opencensus-go/issues/865
+ // * https://golang.org/pkg/sync/atomic/#pkg-note-BUG
+ nextSpanID uint64
+ spanIDInc uint64
+
traceIDAdd [2]uint64
- nextSpanID uint64
- spanIDInc uint64
+ traceIDRand *rand.Rand
}
// NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
-// mu should be held while this function is called.
func (gen *defaultIDGenerator) NewSpanID() [8]byte {
- gen.Lock()
- id := gen.nextSpanID
- gen.nextSpanID += gen.spanIDInc
- if gen.nextSpanID == 0 {
- gen.nextSpanID += gen.spanIDInc
+ var id uint64
+ for id == 0 {
+ id = atomic.AddUint64(&gen.nextSpanID, gen.spanIDInc)
}
- gen.Unlock()
var sid [8]byte
binary.LittleEndian.PutUint64(sid[:], id)
return sid