diff options
Diffstat (limited to 'vendor/go.opencensus.io')
65 files changed, 6748 insertions, 0 deletions
diff --git a/vendor/go.opencensus.io/.gitignore b/vendor/go.opencensus.io/.gitignore new file mode 100644 index 0000000..74a6db4 --- /dev/null +++ b/vendor/go.opencensus.io/.gitignore | |||
@@ -0,0 +1,9 @@ | |||
1 | /.idea/ | ||
2 | |||
3 | # go.opencensus.io/exporter/aws | ||
4 | /exporter/aws/ | ||
5 | |||
6 | # Exclude vendor, use dep ensure after checkout: | ||
7 | /vendor/github.com/ | ||
8 | /vendor/golang.org/ | ||
9 | /vendor/google.golang.org/ | ||
diff --git a/vendor/go.opencensus.io/.travis.yml b/vendor/go.opencensus.io/.travis.yml new file mode 100644 index 0000000..73c8571 --- /dev/null +++ b/vendor/go.opencensus.io/.travis.yml | |||
@@ -0,0 +1,27 @@ | |||
1 | language: go | ||
2 | |||
3 | go: | ||
4 | # 1.8 is tested by AppVeyor | ||
5 | - 1.11.x | ||
6 | |||
7 | go_import_path: go.opencensus.io | ||
8 | |||
9 | # Don't email me the results of the test runs. | ||
10 | notifications: | ||
11 | email: false | ||
12 | |||
13 | before_script: | ||
14 | - GO_FILES=$(find . -iname '*.go' | grep -v /vendor/) # All the .go files, excluding vendor/ if any | ||
15 | - PKGS=$(go list ./... | grep -v /vendor/) # All the import paths, excluding vendor/ if any | ||
16 | - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh # Install latest dep release | ||
17 | - go get github.com/rakyll/embedmd | ||
18 | |||
19 | script: | ||
20 | - embedmd -d README.md # Ensure embedded code is up-to-date | ||
21 | - go build ./... # Ensure dependency updates don't break build | ||
22 | - if [ -n "$(gofmt -s -l $GO_FILES)" ]; then echo "gofmt the following files:"; gofmt -s -l $GO_FILES; exit 1; fi | ||
23 | - go vet ./... | ||
24 | - go test -v -race $PKGS # Run all the tests with the race detector enabled | ||
25 | - GOARCH=386 go test -v $PKGS # Run all tests against a 386 architecture | ||
26 | - 'if [[ $TRAVIS_GO_VERSION = 1.8* ]]; then ! golint ./... | grep -vE "(_mock|_string|\.pb)\.go:"; fi' | ||
27 | - go run internal/check/version.go | ||
diff --git a/vendor/go.opencensus.io/AUTHORS b/vendor/go.opencensus.io/AUTHORS new file mode 100644 index 0000000..e491a9e --- /dev/null +++ b/vendor/go.opencensus.io/AUTHORS | |||
@@ -0,0 +1 @@ | |||
Google Inc. | |||
diff --git a/vendor/go.opencensus.io/CONTRIBUTING.md b/vendor/go.opencensus.io/CONTRIBUTING.md new file mode 100644 index 0000000..3f3aed3 --- /dev/null +++ b/vendor/go.opencensus.io/CONTRIBUTING.md | |||
@@ -0,0 +1,56 @@ | |||
1 | # How to contribute | ||
2 | |||
3 | We'd love to accept your patches and contributions to this project. There are | ||
4 | just a few small guidelines you need to follow. | ||
5 | |||
6 | ## Contributor License Agreement | ||
7 | |||
8 | Contributions to this project must be accompanied by a Contributor License | ||
9 | Agreement. You (or your employer) retain the copyright to your contribution, | ||
10 | this simply gives us permission to use and redistribute your contributions as | ||
11 | part of the project. Head over to <https://cla.developers.google.com/> to see | ||
12 | your current agreements on file or to sign a new one. | ||
13 | |||
14 | You generally only need to submit a CLA once, so if you've already submitted one | ||
15 | (even if it was for a different project), you probably don't need to do it | ||
16 | again. | ||
17 | |||
18 | ## Code reviews | ||
19 | |||
20 | All submissions, including submissions by project members, require review. We | ||
21 | use GitHub pull requests for this purpose. Consult [GitHub Help] for more | ||
22 | information on using pull requests. | ||
23 | |||
24 | [GitHub Help]: https://help.github.com/articles/about-pull-requests/ | ||
25 | |||
26 | ## Instructions | ||
27 | |||
28 | Fork the repo, checkout the upstream repo to your GOPATH by: | ||
29 | |||
30 | ``` | ||
31 | $ go get -d go.opencensus.io | ||
32 | ``` | ||
33 | |||
34 | Add your fork as an origin: | ||
35 | |||
36 | ``` | ||
37 | cd $(go env GOPATH)/src/go.opencensus.io | ||
38 | git remote add fork git@github.com:YOUR_GITHUB_USERNAME/opencensus-go.git | ||
39 | ``` | ||
40 | |||
41 | Run tests: | ||
42 | |||
43 | ``` | ||
44 | $ go test ./... | ||
45 | ``` | ||
46 | |||
47 | Checkout a new branch, make modifications and push the branch to your fork: | ||
48 | |||
49 | ``` | ||
50 | $ git checkout -b feature | ||
51 | # edit files | ||
52 | $ git commit | ||
53 | $ git push fork feature | ||
54 | ``` | ||
55 | |||
56 | 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 new file mode 100644 index 0000000..3be12ac --- /dev/null +++ b/vendor/go.opencensus.io/Gopkg.lock | |||
@@ -0,0 +1,231 @@ | |||
1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. | ||
2 | |||
3 | |||
4 | [[projects]] | ||
5 | branch = "master" | ||
6 | digest = "1:eee9386329f4fcdf8d6c0def0c9771b634bdd5ba460d888aa98c17d59b37a76c" | ||
7 | name = "git.apache.org/thrift.git" | ||
8 | packages = ["lib/go/thrift"] | ||
9 | pruneopts = "UT" | ||
10 | revision = "6e67faa92827ece022380b211c2caaadd6145bf5" | ||
11 | source = "github.com/apache/thrift" | ||
12 | |||
13 | [[projects]] | ||
14 | branch = "master" | ||
15 | digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" | ||
16 | name = "github.com/beorn7/perks" | ||
17 | packages = ["quantile"] | ||
18 | pruneopts = "UT" | ||
19 | revision = "3a771d992973f24aa725d07868b467d1ddfceafb" | ||
20 | |||
21 | [[projects]] | ||
22 | digest = "1:4c0989ca0bcd10799064318923b9bc2db6b4d6338dd75f3f2d86c3511aaaf5cf" | ||
23 | name = "github.com/golang/protobuf" | ||
24 | packages = [ | ||
25 | "proto", | ||
26 | "ptypes", | ||
27 | "ptypes/any", | ||
28 | "ptypes/duration", | ||
29 | "ptypes/timestamp", | ||
30 | ] | ||
31 | pruneopts = "UT" | ||
32 | revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" | ||
33 | version = "v1.2.0" | ||
34 | |||
35 | [[projects]] | ||
36 | digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc" | ||
37 | name = "github.com/matttproud/golang_protobuf_extensions" | ||
38 | packages = ["pbutil"] | ||
39 | pruneopts = "UT" | ||
40 | revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" | ||
41 | version = "v1.0.1" | ||
42 | |||
43 | [[projects]] | ||
44 | digest = "1:824c8f3aa4c5f23928fa84ebbd5ed2e9443b3f0cb958a40c1f2fbed5cf5e64b1" | ||
45 | name = "github.com/openzipkin/zipkin-go" | ||
46 | packages = [ | ||
47 | ".", | ||
48 | "idgenerator", | ||
49 | "model", | ||
50 | "propagation", | ||
51 | "reporter", | ||
52 | "reporter/http", | ||
53 | ] | ||
54 | pruneopts = "UT" | ||
55 | revision = "d455a5674050831c1e187644faa4046d653433c2" | ||
56 | version = "v0.1.1" | ||
57 | |||
58 | [[projects]] | ||
59 | digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb" | ||
60 | name = "github.com/prometheus/client_golang" | ||
61 | packages = [ | ||
62 | "prometheus", | ||
63 | "prometheus/promhttp", | ||
64 | ] | ||
65 | pruneopts = "UT" | ||
66 | revision = "c5b7fccd204277076155f10851dad72b76a49317" | ||
67 | version = "v0.8.0" | ||
68 | |||
69 | [[projects]] | ||
70 | branch = "master" | ||
71 | digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" | ||
72 | name = "github.com/prometheus/client_model" | ||
73 | packages = ["go"] | ||
74 | pruneopts = "UT" | ||
75 | revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" | ||
76 | |||
77 | [[projects]] | ||
78 | branch = "master" | ||
79 | digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" | ||
80 | name = "github.com/prometheus/common" | ||
81 | packages = [ | ||
82 | "expfmt", | ||
83 | "internal/bitbucket.org/ww/goautoneg", | ||
84 | "model", | ||
85 | ] | ||
86 | pruneopts = "UT" | ||
87 | revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" | ||
88 | |||
89 | [[projects]] | ||
90 | branch = "master" | ||
91 | digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" | ||
92 | name = "github.com/prometheus/procfs" | ||
93 | packages = [ | ||
94 | ".", | ||
95 | "internal/util", | ||
96 | "nfs", | ||
97 | "xfs", | ||
98 | ] | ||
99 | pruneopts = "UT" | ||
100 | revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" | ||
101 | |||
102 | [[projects]] | ||
103 | branch = "master" | ||
104 | digest = "1:deafe4ab271911fec7de5b693d7faae3f38796d9eb8622e2b9e7df42bb3dfea9" | ||
105 | name = "golang.org/x/net" | ||
106 | packages = [ | ||
107 | "context", | ||
108 | "http/httpguts", | ||
109 | "http2", | ||
110 | "http2/hpack", | ||
111 | "idna", | ||
112 | "internal/timeseries", | ||
113 | "trace", | ||
114 | ] | ||
115 | pruneopts = "UT" | ||
116 | revision = "922f4815f713f213882e8ef45e0d315b164d705c" | ||
117 | |||
118 | [[projects]] | ||
119 | branch = "master" | ||
120 | digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a" | ||
121 | name = "golang.org/x/sync" | ||
122 | packages = ["semaphore"] | ||
123 | pruneopts = "UT" | ||
124 | revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" | ||
125 | |||
126 | [[projects]] | ||
127 | branch = "master" | ||
128 | digest = "1:a3f00ac457c955fe86a41e1495e8f4c54cb5399d609374c5cc26aa7d72e542c8" | ||
129 | name = "golang.org/x/sys" | ||
130 | packages = ["unix"] | ||
131 | pruneopts = "UT" | ||
132 | revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" | ||
133 | |||
134 | [[projects]] | ||
135 | digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" | ||
136 | name = "golang.org/x/text" | ||
137 | packages = [ | ||
138 | "collate", | ||
139 | "collate/build", | ||
140 | "internal/colltab", | ||
141 | "internal/gen", | ||
142 | "internal/tag", | ||
143 | "internal/triegen", | ||
144 | "internal/ucd", | ||
145 | "language", | ||
146 | "secure/bidirule", | ||
147 | "transform", | ||
148 | "unicode/bidi", | ||
149 | "unicode/cldr", | ||
150 | "unicode/norm", | ||
151 | "unicode/rangetable", | ||
152 | ] | ||
153 | pruneopts = "UT" | ||
154 | revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" | ||
155 | version = "v0.3.0" | ||
156 | |||
157 | [[projects]] | ||
158 | branch = "master" | ||
159 | digest = "1:c0c17c94fe8bc1ab34e7f586a4a8b788c5e1f4f9f750ff23395b8b2f5a523530" | ||
160 | name = "google.golang.org/api" | ||
161 | packages = ["support/bundler"] | ||
162 | pruneopts = "UT" | ||
163 | revision = "e21acd801f91da814261b938941d193bb036441a" | ||
164 | |||
165 | [[projects]] | ||
166 | branch = "master" | ||
167 | digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" | ||
168 | name = "google.golang.org/genproto" | ||
169 | packages = ["googleapis/rpc/status"] | ||
170 | pruneopts = "UT" | ||
171 | revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" | ||
172 | |||
173 | [[projects]] | ||
174 | digest = "1:3dd7996ce6bf52dec6a2f69fa43e7c4cefea1d4dfa3c8ab7a5f8a9f7434e239d" | ||
175 | name = "google.golang.org/grpc" | ||
176 | packages = [ | ||
177 | ".", | ||
178 | "balancer", | ||
179 | "balancer/base", | ||
180 | "balancer/roundrobin", | ||
181 | "codes", | ||
182 | "connectivity", | ||
183 | "credentials", | ||
184 | "encoding", | ||
185 | "encoding/proto", | ||
186 | "grpclog", | ||
187 | "internal", | ||
188 | "internal/backoff", | ||
189 | "internal/channelz", | ||
190 | "internal/envconfig", | ||
191 | "internal/grpcrand", | ||
192 | "internal/transport", | ||
193 | "keepalive", | ||
194 | "metadata", | ||
195 | "naming", | ||
196 | "peer", | ||
197 | "resolver", | ||
198 | "resolver/dns", | ||
199 | "resolver/passthrough", | ||
200 | "stats", | ||
201 | "status", | ||
202 | "tap", | ||
203 | ] | ||
204 | pruneopts = "UT" | ||
205 | revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" | ||
206 | version = "v1.14.0" | ||
207 | |||
208 | [solve-meta] | ||
209 | analyzer-name = "dep" | ||
210 | analyzer-version = 1 | ||
211 | input-imports = [ | ||
212 | "git.apache.org/thrift.git/lib/go/thrift", | ||
213 | "github.com/golang/protobuf/proto", | ||
214 | "github.com/openzipkin/zipkin-go", | ||
215 | "github.com/openzipkin/zipkin-go/model", | ||
216 | "github.com/openzipkin/zipkin-go/reporter", | ||
217 | "github.com/openzipkin/zipkin-go/reporter/http", | ||
218 | "github.com/prometheus/client_golang/prometheus", | ||
219 | "github.com/prometheus/client_golang/prometheus/promhttp", | ||
220 | "golang.org/x/net/context", | ||
221 | "golang.org/x/net/http2", | ||
222 | "google.golang.org/api/support/bundler", | ||
223 | "google.golang.org/grpc", | ||
224 | "google.golang.org/grpc/codes", | ||
225 | "google.golang.org/grpc/grpclog", | ||
226 | "google.golang.org/grpc/metadata", | ||
227 | "google.golang.org/grpc/stats", | ||
228 | "google.golang.org/grpc/status", | ||
229 | ] | ||
230 | solver-name = "gps-cdcl" | ||
231 | solver-version = 1 | ||
diff --git a/vendor/go.opencensus.io/Gopkg.toml b/vendor/go.opencensus.io/Gopkg.toml new file mode 100644 index 0000000..a9f3cd6 --- /dev/null +++ b/vendor/go.opencensus.io/Gopkg.toml | |||
@@ -0,0 +1,36 @@ | |||
1 | # For v0.x.y dependencies, prefer adding a constraints of the form: version=">= 0.x.y" | ||
2 | # to avoid locking to a particular minor version which can cause dep to not be | ||
3 | # able to find a satisfying dependency graph. | ||
4 | |||
5 | [[constraint]] | ||
6 | branch = "master" | ||
7 | name = "git.apache.org/thrift.git" | ||
8 | source = "github.com/apache/thrift" | ||
9 | |||
10 | [[constraint]] | ||
11 | name = "github.com/golang/protobuf" | ||
12 | version = "1.0.0" | ||
13 | |||
14 | [[constraint]] | ||
15 | name = "github.com/openzipkin/zipkin-go" | ||
16 | version = ">=0.1.0" | ||
17 | |||
18 | [[constraint]] | ||
19 | name = "github.com/prometheus/client_golang" | ||
20 | version = ">=0.8.0" | ||
21 | |||
22 | [[constraint]] | ||
23 | branch = "master" | ||
24 | name = "golang.org/x/net" | ||
25 | |||
26 | [[constraint]] | ||
27 | branch = "master" | ||
28 | name = "google.golang.org/api" | ||
29 | |||
30 | [[constraint]] | ||
31 | name = "google.golang.org/grpc" | ||
32 | version = "1.11.3" | ||
33 | |||
34 | [prune] | ||
35 | go-tests = true | ||
36 | unused-packages = true | ||
diff --git a/vendor/go.opencensus.io/LICENSE b/vendor/go.opencensus.io/LICENSE new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/vendor/go.opencensus.io/LICENSE | |||
@@ -0,0 +1,202 @@ | |||
1 | |||
2 | Apache License | ||
3 | Version 2.0, January 2004 | ||
4 | http://www.apache.org/licenses/ | ||
5 | |||
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||
7 | |||
8 | 1. Definitions. | ||
9 | |||
10 | "License" shall mean the terms and conditions for use, reproduction, | ||
11 | and distribution as defined by Sections 1 through 9 of this document. | ||
12 | |||
13 | "Licensor" shall mean the copyright owner or entity authorized by | ||
14 | the copyright owner that is granting the License. | ||
15 | |||
16 | "Legal Entity" shall mean the union of the acting entity and all | ||
17 | other entities that control, are controlled by, or are under common | ||
18 | control with that entity. For the purposes of this definition, | ||
19 | "control" means (i) the power, direct or indirect, to cause the | ||
20 | direction or management of such entity, whether by contract or | ||
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||
22 | outstanding shares, or (iii) beneficial ownership of such entity. | ||
23 | |||
24 | "You" (or "Your") shall mean an individual or Legal Entity | ||
25 | exercising permissions granted by this License. | ||
26 | |||
27 | "Source" form shall mean the preferred form for making modifications, | ||
28 | including but not limited to software source code, documentation | ||
29 | source, and configuration files. | ||
30 | |||
31 | "Object" form shall mean any form resulting from mechanical | ||
32 | transformation or translation of a Source form, including but | ||
33 | not limited to compiled object code, generated documentation, | ||
34 | and conversions to other media types. | ||
35 | |||
36 | "Work" shall mean the work of authorship, whether in Source or | ||
37 | Object form, made available under the License, as indicated by a | ||
38 | copyright notice that is included in or attached to the work | ||
39 | (an example is provided in the Appendix below). | ||
40 | |||
41 | "Derivative Works" shall mean any work, whether in Source or Object | ||
42 | form, that is based on (or derived from) the Work and for which the | ||
43 | editorial revisions, annotations, elaborations, or other modifications | ||
44 | represent, as a whole, an original work of authorship. For the purposes | ||
45 | of this License, Derivative Works shall not include works that remain | ||
46 | separable from, or merely link (or bind by name) to the interfaces of, | ||
47 | the Work and Derivative Works thereof. | ||
48 | |||
49 | "Contribution" shall mean any work of authorship, including | ||
50 | the original version of the Work and any modifications or additions | ||
51 | to that Work or Derivative Works thereof, that is intentionally | ||
52 | submitted to Licensor for inclusion in the Work by the copyright owner | ||
53 | or by an individual or Legal Entity authorized to submit on behalf of | ||
54 | the copyright owner. For the purposes of this definition, "submitted" | ||
55 | means any form of electronic, verbal, or written communication sent | ||
56 | to the Licensor or its representatives, including but not limited to | ||
57 | communication on electronic mailing lists, source code control systems, | ||
58 | and issue tracking systems that are managed by, or on behalf of, the | ||
59 | Licensor for the purpose of discussing and improving the Work, but | ||
60 | excluding communication that is conspicuously marked or otherwise | ||
61 | designated in writing by the copyright owner as "Not a Contribution." | ||
62 | |||
63 | "Contributor" shall mean Licensor and any individual or Legal Entity | ||
64 | on behalf of whom a Contribution has been received by Licensor and | ||
65 | subsequently incorporated within the Work. | ||
66 | |||
67 | 2. Grant of Copyright License. Subject to the terms and conditions of | ||
68 | this License, each Contributor hereby grants to You a perpetual, | ||
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
70 | copyright license to reproduce, prepare Derivative Works of, | ||
71 | publicly display, publicly perform, sublicense, and distribute the | ||
72 | Work and such Derivative Works in Source or Object form. | ||
73 | |||
74 | 3. Grant of Patent License. Subject to the terms and conditions of | ||
75 | this License, each Contributor hereby grants to You a perpetual, | ||
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
77 | (except as stated in this section) patent license to make, have made, | ||
78 | use, offer to sell, sell, import, and otherwise transfer the Work, | ||
79 | where such license applies only to those patent claims licensable | ||
80 | by such Contributor that are necessarily infringed by their | ||
81 | Contribution(s) alone or by combination of their Contribution(s) | ||
82 | with the Work to which such Contribution(s) was submitted. If You | ||
83 | institute patent litigation against any entity (including a | ||
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work | ||
85 | or a Contribution incorporated within the Work constitutes direct | ||
86 | or contributory patent infringement, then any patent licenses | ||
87 | granted to You under this License for that Work shall terminate | ||
88 | as of the date such litigation is filed. | ||
89 | |||
90 | 4. Redistribution. You may reproduce and distribute copies of the | ||
91 | Work or Derivative Works thereof in any medium, with or without | ||
92 | modifications, and in Source or Object form, provided that You | ||
93 | meet the following conditions: | ||
94 | |||
95 | (a) You must give any other recipients of the Work or | ||
96 | Derivative Works a copy of this License; and | ||
97 | |||
98 | (b) You must cause any modified files to carry prominent notices | ||
99 | stating that You changed the files; and | ||
100 | |||
101 | (c) You must retain, in the Source form of any Derivative Works | ||
102 | that You distribute, all copyright, patent, trademark, and | ||
103 | attribution notices from the Source form of the Work, | ||
104 | excluding those notices that do not pertain to any part of | ||
105 | the Derivative Works; and | ||
106 | |||
107 | (d) If the Work includes a "NOTICE" text file as part of its | ||
108 | distribution, then any Derivative Works that You distribute must | ||
109 | include a readable copy of the attribution notices contained | ||
110 | within such NOTICE file, excluding those notices that do not | ||
111 | pertain to any part of the Derivative Works, in at least one | ||
112 | of the following places: within a NOTICE text file distributed | ||
113 | as part of the Derivative Works; within the Source form or | ||
114 | documentation, if provided along with the Derivative Works; or, | ||
115 | within a display generated by the Derivative Works, if and | ||
116 | wherever such third-party notices normally appear. The contents | ||
117 | of the NOTICE file are for informational purposes only and | ||
118 | do not modify the License. You may add Your own attribution | ||
119 | notices within Derivative Works that You distribute, alongside | ||
120 | or as an addendum to the NOTICE text from the Work, provided | ||
121 | that such additional attribution notices cannot be construed | ||
122 | as modifying the License. | ||
123 | |||
124 | You may add Your own copyright statement to Your modifications and | ||
125 | may provide additional or different license terms and conditions | ||
126 | for use, reproduction, or distribution of Your modifications, or | ||
127 | for any such Derivative Works as a whole, provided Your use, | ||
128 | reproduction, and distribution of the Work otherwise complies with | ||
129 | the conditions stated in this License. | ||
130 | |||
131 | 5. Submission of Contributions. Unless You explicitly state otherwise, | ||
132 | any Contribution intentionally submitted for inclusion in the Work | ||
133 | by You to the Licensor shall be under the terms and conditions of | ||
134 | this License, without any additional terms or conditions. | ||
135 | Notwithstanding the above, nothing herein shall supersede or modify | ||
136 | the terms of any separate license agreement you may have executed | ||
137 | with Licensor regarding such Contributions. | ||
138 | |||
139 | 6. Trademarks. This License does not grant permission to use the trade | ||
140 | names, trademarks, service marks, or product names of the Licensor, | ||
141 | except as required for reasonable and customary use in describing the | ||
142 | origin of the Work and reproducing the content of the NOTICE file. | ||
143 | |||
144 | 7. Disclaimer of Warranty. Unless required by applicable law or | ||
145 | agreed to in writing, Licensor provides the Work (and each | ||
146 | Contributor provides its Contributions) on an "AS IS" BASIS, | ||
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
148 | implied, including, without limitation, any warranties or conditions | ||
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||
150 | PARTICULAR PURPOSE. You are solely responsible for determining the | ||
151 | appropriateness of using or redistributing the Work and assume any | ||
152 | risks associated with Your exercise of permissions under this License. | ||
153 | |||
154 | 8. Limitation of Liability. In no event and under no legal theory, | ||
155 | whether in tort (including negligence), contract, or otherwise, | ||
156 | unless required by applicable law (such as deliberate and grossly | ||
157 | negligent acts) or agreed to in writing, shall any Contributor be | ||
158 | liable to You for damages, including any direct, indirect, special, | ||
159 | incidental, or consequential damages of any character arising as a | ||
160 | result of this License or out of the use or inability to use the | ||
161 | Work (including but not limited to damages for loss of goodwill, | ||
162 | work stoppage, computer failure or malfunction, or any and all | ||
163 | other commercial damages or losses), even if such Contributor | ||
164 | has been advised of the possibility of such damages. | ||
165 | |||
166 | 9. Accepting Warranty or Additional Liability. While redistributing | ||
167 | the Work or Derivative Works thereof, You may choose to offer, | ||
168 | and charge a fee for, acceptance of support, warranty, indemnity, | ||
169 | or other liability obligations and/or rights consistent with this | ||
170 | License. However, in accepting such obligations, You may act only | ||
171 | on Your own behalf and on Your sole responsibility, not on behalf | ||
172 | of any other Contributor, and only if You agree to indemnify, | ||
173 | defend, and hold each Contributor harmless for any liability | ||
174 | incurred by, or claims asserted against, such Contributor by reason | ||
175 | of your accepting any such warranty or additional liability. | ||
176 | |||
177 | END OF TERMS AND CONDITIONS | ||
178 | |||
179 | APPENDIX: How to apply the Apache License to your work. | ||
180 | |||
181 | To apply the Apache License to your work, attach the following | ||
182 | boilerplate notice, with the fields enclosed by brackets "[]" | ||
183 | replaced with your own identifying information. (Don't include | ||
184 | the brackets!) The text should be enclosed in the appropriate | ||
185 | comment syntax for the file format. We also recommend that a | ||
186 | file or class name and description of purpose be included on the | ||
187 | same "printed page" as the copyright notice for easier | ||
188 | identification within third-party archives. | ||
189 | |||
190 | Copyright [yyyy] [name of copyright owner] | ||
191 | |||
192 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
193 | you may not use this file except in compliance with the License. | ||
194 | You may obtain a copy of the License at | ||
195 | |||
196 | http://www.apache.org/licenses/LICENSE-2.0 | ||
197 | |||
198 | Unless required by applicable law or agreed to in writing, software | ||
199 | distributed under the License is distributed on an "AS IS" BASIS, | ||
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
201 | See the License for the specific language governing permissions and | ||
202 | limitations under the License. \ No newline at end of file | ||
diff --git a/vendor/go.opencensus.io/README.md b/vendor/go.opencensus.io/README.md new file mode 100644 index 0000000..97d6698 --- /dev/null +++ b/vendor/go.opencensus.io/README.md | |||
@@ -0,0 +1,263 @@ | |||
1 | # OpenCensus Libraries for Go | ||
2 | |||
3 | [![Build Status][travis-image]][travis-url] | ||
4 | [![Windows Build Status][appveyor-image]][appveyor-url] | ||
5 | [![GoDoc][godoc-image]][godoc-url] | ||
6 | [![Gitter chat][gitter-image]][gitter-url] | ||
7 | |||
8 | OpenCensus Go is a Go implementation of OpenCensus, a toolkit for | ||
9 | collecting application performance and behavior monitoring data. | ||
10 | Currently it consists of three major components: tags, stats and tracing. | ||
11 | |||
12 | ## Installation | ||
13 | |||
14 | ``` | ||
15 | $ go get -u go.opencensus.io | ||
16 | ``` | ||
17 | |||
18 | The API of this project is still evolving, see: [Deprecation Policy](#deprecation-policy). | ||
19 | The use of vendoring or a dependency management tool is recommended. | ||
20 | |||
21 | ## Prerequisites | ||
22 | |||
23 | OpenCensus Go libraries require Go 1.8 or later. | ||
24 | |||
25 | ## Getting Started | ||
26 | |||
27 | The easiest way to get started using OpenCensus in your application is to use an existing | ||
28 | integration with your RPC framework: | ||
29 | |||
30 | * [net/http](https://godoc.org/go.opencensus.io/plugin/ochttp) | ||
31 | * [gRPC](https://godoc.org/go.opencensus.io/plugin/ocgrpc) | ||
32 | * [database/sql](https://godoc.org/github.com/basvanbeek/ocsql) | ||
33 | * [Go kit](https://godoc.org/github.com/go-kit/kit/tracing/opencensus) | ||
34 | * [Groupcache](https://godoc.org/github.com/orijtech/groupcache) | ||
35 | * [Caddy webserver](https://godoc.org/github.com/orijtech/caddy) | ||
36 | * [MongoDB](https://godoc.org/github.com/orijtech/mongo-go-driver) | ||
37 | * [Redis gomodule/redigo](https://godoc.org/github.com/orijtech/redigo) | ||
38 | * [Redis goredis/redis](https://godoc.org/github.com/orijtech/redis) | ||
39 | * [Memcache](https://godoc.org/github.com/orijtech/gomemcache) | ||
40 | |||
41 | If you're using a framework not listed here, you could either implement your own middleware for your | ||
42 | framework or use [custom stats](#stats) and [spans](#spans) directly in your application. | ||
43 | |||
44 | ## Exporters | ||
45 | |||
46 | OpenCensus can export instrumentation data to various backends. | ||
47 | OpenCensus has exporter implementations for the following, users | ||
48 | can implement their own exporters by implementing the exporter interfaces | ||
49 | ([stats](https://godoc.org/go.opencensus.io/stats/view#Exporter), | ||
50 | [trace](https://godoc.org/go.opencensus.io/trace#Exporter)): | ||
51 | |||
52 | * [Prometheus][exporter-prom] for stats | ||
53 | * [OpenZipkin][exporter-zipkin] for traces | ||
54 | * [Stackdriver][exporter-stackdriver] Monitoring for stats and Trace for traces | ||
55 | * [Jaeger][exporter-jaeger] for traces | ||
56 | * [AWS X-Ray][exporter-xray] for traces | ||
57 | * [Datadog][exporter-datadog] for stats and traces | ||
58 | * [Graphite][exporter-graphite] for stats | ||
59 | * [Honeycomb][exporter-honeycomb] for traces | ||
60 | |||
61 | ## Overview | ||
62 | |||
63 | ![OpenCensus Overview](https://i.imgur.com/cf4ElHE.jpg) | ||
64 | |||
65 | In a microservices environment, a user request may go through | ||
66 | multiple services until there is a response. OpenCensus allows | ||
67 | you to instrument your services and collect diagnostics data all | ||
68 | through your services end-to-end. | ||
69 | |||
70 | ## Tags | ||
71 | |||
72 | Tags represent propagated key-value pairs. They are propagated using `context.Context` | ||
73 | in the same process or can be encoded to be transmitted on the wire. Usually, this will | ||
74 | be handled by an integration plugin, e.g. `ocgrpc.ServerHandler` and `ocgrpc.ClientHandler` | ||
75 | for gRPC. | ||
76 | |||
77 | Package `tag` allows adding or modifying tags in the current context. | ||
78 | |||
79 | [embedmd]:# (internal/readme/tags.go new) | ||
80 | ```go | ||
81 | ctx, err = tag.New(ctx, | ||
82 | tag.Insert(osKey, "macOS-10.12.5"), | ||
83 | tag.Upsert(userIDKey, "cde36753ed"), | ||
84 | ) | ||
85 | if err != nil { | ||
86 | log.Fatal(err) | ||
87 | } | ||
88 | ``` | ||
89 | |||
90 | ## Stats | ||
91 | |||
92 | OpenCensus is a low-overhead framework even if instrumentation is always enabled. | ||
93 | In order to be so, it is optimized to make recording of data points fast | ||
94 | and separate from the data aggregation. | ||
95 | |||
96 | OpenCensus stats collection happens in two stages: | ||
97 | |||
98 | * Definition of measures and recording of data points | ||
99 | * Definition of views and aggregation of the recorded data | ||
100 | |||
101 | ### Recording | ||
102 | |||
103 | Measurements are data points associated with a measure. | ||
104 | Recording implicitly tags the set of Measurements with the tags from the | ||
105 | provided context: | ||
106 | |||
107 | [embedmd]:# (internal/readme/stats.go record) | ||
108 | ```go | ||
109 | stats.Record(ctx, videoSize.M(102478)) | ||
110 | ``` | ||
111 | |||
112 | ### Views | ||
113 | |||
114 | Views are how Measures are aggregated. You can think of them as queries over the | ||
115 | set of recorded data points (measurements). | ||
116 | |||
117 | Views have two parts: the tags to group by and the aggregation type used. | ||
118 | |||
119 | Currently three types of aggregations are supported: | ||
120 | * CountAggregation is used to count the number of times a sample was recorded. | ||
121 | * DistributionAggregation is used to provide a histogram of the values of the samples. | ||
122 | * SumAggregation is used to sum up all sample values. | ||
123 | |||
124 | [embedmd]:# (internal/readme/stats.go aggs) | ||
125 | ```go | ||
126 | distAgg := view.Distribution(0, 1<<32, 2<<32, 3<<32) | ||
127 | countAgg := view.Count() | ||
128 | sumAgg := view.Sum() | ||
129 | ``` | ||
130 | |||
131 | Here we create a view with the DistributionAggregation over our measure. | ||
132 | |||
133 | [embedmd]:# (internal/readme/stats.go view) | ||
134 | ```go | ||
135 | if err := view.Register(&view.View{ | ||
136 | Name: "example.com/video_size_distribution", | ||
137 | Description: "distribution of processed video size over time", | ||
138 | Measure: videoSize, | ||
139 | Aggregation: view.Distribution(0, 1<<32, 2<<32, 3<<32), | ||
140 | }); err != nil { | ||
141 | log.Fatalf("Failed to register view: %v", err) | ||
142 | } | ||
143 | ``` | ||
144 | |||
145 | Register begins collecting data for the view. Registered views' data will be | ||
146 | exported via the registered exporters. | ||
147 | |||
148 | ## Traces | ||
149 | |||
150 | A distributed trace tracks the progression of a single user request as | ||
151 | it is handled by the services and processes that make up an application. | ||
152 | Each step is called a span in the trace. Spans include metadata about the step, | ||
153 | including especially the time spent in the step, called the span’s latency. | ||
154 | |||
155 | Below you see a trace and several spans underneath it. | ||
156 | |||
157 | ![Traces and spans](https://i.imgur.com/7hZwRVj.png) | ||
158 | |||
159 | ### Spans | ||
160 | |||
161 | Span is the unit step in a trace. Each span has a name, latency, status and | ||
162 | additional metadata. | ||
163 | |||
164 | Below we are starting a span for a cache read and ending it | ||
165 | when we are done: | ||
166 | |||
167 | [embedmd]:# (internal/readme/trace.go startend) | ||
168 | ```go | ||
169 | ctx, span := trace.StartSpan(ctx, "cache.Get") | ||
170 | defer span.End() | ||
171 | |||
172 | // Do work to get from cache. | ||
173 | ``` | ||
174 | |||
175 | ### Propagation | ||
176 | |||
177 | Spans can have parents or can be root spans if they don't have any parents. | ||
178 | The current span is propagated in-process and across the network to allow associating | ||
179 | new child spans with the parent. | ||
180 | |||
181 | In the same process, `context.Context` is used to propagate spans. | ||
182 | `trace.StartSpan` creates a new span as a root if the current context | ||
183 | doesn't contain a span. Or, it creates a child of the span that is | ||
184 | already in current context. The returned context can be used to keep | ||
185 | propagating the newly created span in the current context. | ||
186 | |||
187 | [embedmd]:# (internal/readme/trace.go startend) | ||
188 | ```go | ||
189 | ctx, span := trace.StartSpan(ctx, "cache.Get") | ||
190 | defer span.End() | ||
191 | |||
192 | // Do work to get from cache. | ||
193 | ``` | ||
194 | |||
195 | Across the network, OpenCensus provides different propagation | ||
196 | methods for different protocols. | ||
197 | |||
198 | * gRPC integrations use the OpenCensus' [binary propagation format](https://godoc.org/go.opencensus.io/trace/propagation). | ||
199 | * HTTP integrations use Zipkin's [B3](https://github.com/openzipkin/b3-propagation) | ||
200 | by default but can be configured to use a custom propagation method by setting another | ||
201 | [propagation.HTTPFormat](https://godoc.org/go.opencensus.io/trace/propagation#HTTPFormat). | ||
202 | |||
203 | ## Execution Tracer | ||
204 | |||
205 | With Go 1.11, OpenCensus Go will support integration with the Go execution tracer. | ||
206 | See [Debugging Latency in Go](https://medium.com/observability/debugging-latency-in-go-1-11-9f97a7910d68) | ||
207 | for an example of their mutual use. | ||
208 | |||
209 | ## Profiles | ||
210 | |||
211 | OpenCensus tags can be applied as profiler labels | ||
212 | for users who are on Go 1.9 and above. | ||
213 | |||
214 | [embedmd]:# (internal/readme/tags.go profiler) | ||
215 | ```go | ||
216 | ctx, err = tag.New(ctx, | ||
217 | tag.Insert(osKey, "macOS-10.12.5"), | ||
218 | tag.Insert(userIDKey, "fff0989878"), | ||
219 | ) | ||
220 | if err != nil { | ||
221 | log.Fatal(err) | ||
222 | } | ||
223 | tag.Do(ctx, func(ctx context.Context) { | ||
224 | // Do work. | ||
225 | // When profiling is on, samples will be | ||
226 | // recorded with the key/values from the tag map. | ||
227 | }) | ||
228 | ``` | ||
229 | |||
230 | A screenshot of the CPU profile from the program above: | ||
231 | |||
232 | ![CPU profile](https://i.imgur.com/jBKjlkw.png) | ||
233 | |||
234 | ## Deprecation Policy | ||
235 | |||
236 | Before version 1.0.0, the following deprecation policy will be observed: | ||
237 | |||
238 | No backwards-incompatible changes will be made except for the removal of symbols that have | ||
239 | been marked as *Deprecated* for at least one minor release (e.g. 0.9.0 to 0.10.0). A release | ||
240 | removing the *Deprecated* functionality will be made no sooner than 28 days after the first | ||
241 | release in which the functionality was marked *Deprecated*. | ||
242 | |||
243 | [travis-image]: https://travis-ci.org/census-instrumentation/opencensus-go.svg?branch=master | ||
244 | [travis-url]: https://travis-ci.org/census-instrumentation/opencensus-go | ||
245 | [appveyor-image]: https://ci.appveyor.com/api/projects/status/vgtt29ps1783ig38?svg=true | ||
246 | [appveyor-url]: https://ci.appveyor.com/project/opencensusgoteam/opencensus-go/branch/master | ||
247 | [godoc-image]: https://godoc.org/go.opencensus.io?status.svg | ||
248 | [godoc-url]: https://godoc.org/go.opencensus.io | ||
249 | [gitter-image]: https://badges.gitter.im/census-instrumentation/lobby.svg | ||
250 | [gitter-url]: https://gitter.im/census-instrumentation/lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge | ||
251 | |||
252 | |||
253 | [new-ex]: https://godoc.org/go.opencensus.io/tag#example-NewMap | ||
254 | [new-replace-ex]: https://godoc.org/go.opencensus.io/tag#example-NewMap--Replace | ||
255 | |||
256 | [exporter-prom]: https://godoc.org/go.opencensus.io/exporter/prometheus | ||
257 | [exporter-stackdriver]: https://godoc.org/contrib.go.opencensus.io/exporter/stackdriver | ||
258 | [exporter-zipkin]: https://godoc.org/go.opencensus.io/exporter/zipkin | ||
259 | [exporter-jaeger]: https://godoc.org/go.opencensus.io/exporter/jaeger | ||
260 | [exporter-xray]: https://github.com/census-ecosystem/opencensus-go-exporter-aws | ||
261 | [exporter-datadog]: https://github.com/DataDog/opencensus-go-exporter-datadog | ||
262 | [exporter-graphite]: https://github.com/census-ecosystem/opencensus-go-exporter-graphite | ||
263 | [exporter-honeycomb]: https://github.com/honeycombio/opencensus-exporter | ||
diff --git a/vendor/go.opencensus.io/appveyor.yml b/vendor/go.opencensus.io/appveyor.yml new file mode 100644 index 0000000..9805788 --- /dev/null +++ b/vendor/go.opencensus.io/appveyor.yml | |||
@@ -0,0 +1,24 @@ | |||
1 | version: "{build}" | ||
2 | |||
3 | platform: x64 | ||
4 | |||
5 | clone_folder: c:\gopath\src\go.opencensus.io | ||
6 | |||
7 | environment: | ||
8 | GOPATH: 'c:\gopath' | ||
9 | GOVERSION: '1.11' | ||
10 | GO111MODULE: 'on' | ||
11 | CGO_ENABLED: '0' # See: https://github.com/appveyor/ci/issues/2613 | ||
12 | |||
13 | install: | ||
14 | - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% | ||
15 | - go version | ||
16 | - go env | ||
17 | |||
18 | build: false | ||
19 | deploy: false | ||
20 | |||
21 | test_script: | ||
22 | - cd %APPVEYOR_BUILD_FOLDER% | ||
23 | - go build -v .\... | ||
24 | - go test -v .\... # No -race because cgo is disabled | ||
diff --git a/vendor/go.opencensus.io/exemplar/exemplar.go b/vendor/go.opencensus.io/exemplar/exemplar.go new file mode 100644 index 0000000..e676df8 --- /dev/null +++ b/vendor/go.opencensus.io/exemplar/exemplar.go | |||
@@ -0,0 +1,78 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // Package exemplar implements support for exemplars. Exemplars are additional | ||
16 | // data associated with each measurement. | ||
17 | // | ||
18 | // Their purpose it to provide an example of the kind of thing | ||
19 | // (request, RPC, trace span, etc.) that resulted in that measurement. | ||
20 | package exemplar | ||
21 | |||
22 | import ( | ||
23 | "context" | ||
24 | "time" | ||
25 | ) | ||
26 | |||
27 | const ( | ||
28 | KeyTraceID = "trace_id" | ||
29 | KeySpanID = "span_id" | ||
30 | KeyPrefixTag = "tag:" | ||
31 | ) | ||
32 | |||
33 | // Exemplar is an example data point associated with each bucket of a | ||
34 | // distribution type aggregation. | ||
35 | type Exemplar struct { | ||
36 | Value float64 // the value that was recorded | ||
37 | Timestamp time.Time // the time the value was recorded | ||
38 | Attachments Attachments // attachments (if any) | ||
39 | } | ||
40 | |||
41 | // Attachments is a map of extra values associated with a recorded data point. | ||
42 | // The map should only be mutated from AttachmentExtractor functions. | ||
43 | type Attachments map[string]string | ||
44 | |||
45 | // AttachmentExtractor is a function capable of extracting exemplar attachments | ||
46 | // from the context used to record measurements. | ||
47 | // The map passed to the function should be mutated and returned. It will | ||
48 | // initially be nil: the first AttachmentExtractor that would like to add keys to the | ||
49 | // map is responsible for initializing it. | ||
50 | type AttachmentExtractor func(ctx context.Context, a Attachments) Attachments | ||
51 | |||
52 | var extractors []AttachmentExtractor | ||
53 | |||
54 | // RegisterAttachmentExtractor registers the given extractor associated with the exemplar | ||
55 | // type name. | ||
56 | // | ||
57 | // Extractors will be used to attempt to extract exemplars from the context | ||
58 | // associated with each recorded measurement. | ||
59 | // | ||
60 | // Packages that support exemplars should register their extractor functions on | ||
61 | // initialization. | ||
62 | // | ||
63 | // RegisterAttachmentExtractor should not be called after any measurements have | ||
64 | // been recorded. | ||
65 | func RegisterAttachmentExtractor(e AttachmentExtractor) { | ||
66 | extractors = append(extractors, e) | ||
67 | } | ||
68 | |||
69 | // NewFromContext extracts exemplars from the given context. | ||
70 | // Each registered AttachmentExtractor (see RegisterAttachmentExtractor) is called in an | ||
71 | // unspecified order to add attachments to the exemplar. | ||
72 | func AttachmentsFromContext(ctx context.Context) Attachments { | ||
73 | var a Attachments | ||
74 | for _, extractor := range extractors { | ||
75 | a = extractor(ctx, a) | ||
76 | } | ||
77 | return a | ||
78 | } | ||
diff --git a/vendor/go.opencensus.io/go.mod b/vendor/go.opencensus.io/go.mod new file mode 100644 index 0000000..1236f4c --- /dev/null +++ b/vendor/go.opencensus.io/go.mod | |||
@@ -0,0 +1,25 @@ | |||
1 | module go.opencensus.io | ||
2 | |||
3 | require ( | ||
4 | git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 | ||
5 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 | ||
6 | github.com/ghodss/yaml v1.0.0 // indirect | ||
7 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect | ||
8 | github.com/golang/protobuf v1.2.0 | ||
9 | github.com/google/go-cmp v0.2.0 | ||
10 | github.com/grpc-ecosystem/grpc-gateway v1.5.0 // indirect | ||
11 | github.com/matttproud/golang_protobuf_extensions v1.0.1 | ||
12 | github.com/openzipkin/zipkin-go v0.1.1 | ||
13 | github.com/prometheus/client_golang v0.8.0 | ||
14 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 | ||
15 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e | ||
16 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 | ||
17 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd | ||
18 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f | ||
19 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e | ||
20 | golang.org/x/text v0.3.0 | ||
21 | google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf | ||
22 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b | ||
23 | google.golang.org/grpc v1.14.0 | ||
24 | gopkg.in/yaml.v2 v2.2.1 // indirect | ||
25 | ) | ||
diff --git a/vendor/go.opencensus.io/go.sum b/vendor/go.opencensus.io/go.sum new file mode 100644 index 0000000..3e0bab8 --- /dev/null +++ b/vendor/go.opencensus.io/go.sum | |||
@@ -0,0 +1,48 @@ | |||
1 | git.apache.org/thrift.git v0.0.0-20180807212849-6e67faa92827/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= | ||
2 | git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 h1:sihTnRgTOUSCQz0iS0pjZuFQy/z7GXCJgSBg3+rZKHw= | ||
3 | git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= | ||
4 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= | ||
5 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= | ||
6 | github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= | ||
7 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | ||
8 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= | ||
9 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | ||
10 | github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= | ||
11 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||
12 | github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= | ||
13 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | ||
14 | github.com/grpc-ecosystem/grpc-gateway v1.5.0 h1:WcmKMm43DR7RdtlkEXQJyo5ws8iTp98CyhCCbOHMvNI= | ||
15 | github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= | ||
16 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= | ||
17 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||
18 | github.com/openzipkin/zipkin-go v0.1.1 h1:A/ADD6HaPnAKj3yS7HjGHRK77qi41Hi0DirOOIQAeIw= | ||
19 | github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= | ||
20 | github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8= | ||
21 | github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= | ||
22 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= | ||
23 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | ||
24 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e h1:n/3MEhJQjQxrOUCzh1Y3Re6aJUUWRp2M9+Oc3eVn/54= | ||
25 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= | ||
26 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0= | ||
27 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | ||
28 | golang.org/x/net v0.0.0-20180821023952-922f4815f713/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
29 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= | ||
30 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
31 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= | ||
32 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
33 | golang.org/x/sys v0.0.0-20180821140842-3b58ed4ad339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
34 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= | ||
35 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
36 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||
37 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
38 | google.golang.org/api v0.0.0-20180818000503-e21acd801f91/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= | ||
39 | google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf h1:rjxqQmxjyqerRKEj+tZW+MCm4LgpFXu18bsEoCMgDsk= | ||
40 | google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= | ||
41 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | ||
42 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= | ||
43 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | ||
44 | google.golang.org/grpc v1.14.0 h1:ArxJuB1NWfPY6r9Gp9gqwplT0Ge7nqv9msgu03lHLmo= | ||
45 | google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= | ||
46 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
47 | gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= | ||
48 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
diff --git a/vendor/go.opencensus.io/internal/internal.go b/vendor/go.opencensus.io/internal/internal.go new file mode 100644 index 0000000..e1d1238 --- /dev/null +++ b/vendor/go.opencensus.io/internal/internal.go | |||
@@ -0,0 +1,37 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package internal // import "go.opencensus.io/internal" | ||
16 | |||
17 | import ( | ||
18 | "fmt" | ||
19 | "time" | ||
20 | |||
21 | "go.opencensus.io" | ||
22 | ) | ||
23 | |||
24 | // UserAgent is the user agent to be added to the outgoing | ||
25 | // requests from the exporters. | ||
26 | var UserAgent = fmt.Sprintf("opencensus-go [%s]", opencensus.Version()) | ||
27 | |||
28 | // MonotonicEndTime returns the end time at present | ||
29 | // but offset from start, monotonically. | ||
30 | // | ||
31 | // The monotonic clock is used in subtractions hence | ||
32 | // the duration since start added back to start gives | ||
33 | // end as a monotonic time. | ||
34 | // See https://golang.org/pkg/time/#hdr-Monotonic_Clocks | ||
35 | func MonotonicEndTime(start time.Time) time.Time { | ||
36 | return start.Add(time.Now().Sub(start)) | ||
37 | } | ||
diff --git a/vendor/go.opencensus.io/internal/sanitize.go b/vendor/go.opencensus.io/internal/sanitize.go new file mode 100644 index 0000000..de8ccf2 --- /dev/null +++ b/vendor/go.opencensus.io/internal/sanitize.go | |||
@@ -0,0 +1,50 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package internal | ||
16 | |||
17 | import ( | ||
18 | "strings" | ||
19 | "unicode" | ||
20 | ) | ||
21 | |||
22 | const labelKeySizeLimit = 100 | ||
23 | |||
24 | // Sanitize returns a string that is trunacated to 100 characters if it's too | ||
25 | // long, and replaces non-alphanumeric characters to underscores. | ||
26 | func Sanitize(s string) string { | ||
27 | if len(s) == 0 { | ||
28 | return s | ||
29 | } | ||
30 | if len(s) > labelKeySizeLimit { | ||
31 | s = s[:labelKeySizeLimit] | ||
32 | } | ||
33 | s = strings.Map(sanitizeRune, s) | ||
34 | if unicode.IsDigit(rune(s[0])) { | ||
35 | s = "key_" + s | ||
36 | } | ||
37 | if s[0] == '_' { | ||
38 | s = "key" + s | ||
39 | } | ||
40 | return s | ||
41 | } | ||
42 | |||
43 | // converts anything that is not a letter or digit to an underscore | ||
44 | func sanitizeRune(r rune) rune { | ||
45 | if unicode.IsLetter(r) || unicode.IsDigit(r) { | ||
46 | return r | ||
47 | } | ||
48 | // Everything else turns into an underscore | ||
49 | return '_' | ||
50 | } | ||
diff --git a/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go b/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go new file mode 100644 index 0000000..3b1af8b --- /dev/null +++ b/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go | |||
@@ -0,0 +1,72 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | // Package tagencoding contains the tag encoding | ||
17 | // used interally by the stats collector. | ||
18 | package tagencoding // import "go.opencensus.io/internal/tagencoding" | ||
19 | |||
20 | type Values struct { | ||
21 | Buffer []byte | ||
22 | WriteIndex int | ||
23 | ReadIndex int | ||
24 | } | ||
25 | |||
26 | func (vb *Values) growIfRequired(expected int) { | ||
27 | if len(vb.Buffer)-vb.WriteIndex < expected { | ||
28 | tmp := make([]byte, 2*(len(vb.Buffer)+1)+expected) | ||
29 | copy(tmp, vb.Buffer) | ||
30 | vb.Buffer = tmp | ||
31 | } | ||
32 | } | ||
33 | |||
34 | func (vb *Values) WriteValue(v []byte) { | ||
35 | length := len(v) & 0xff | ||
36 | vb.growIfRequired(1 + length) | ||
37 | |||
38 | // writing length of v | ||
39 | vb.Buffer[vb.WriteIndex] = byte(length) | ||
40 | vb.WriteIndex++ | ||
41 | |||
42 | if length == 0 { | ||
43 | // No value was encoded for this key | ||
44 | return | ||
45 | } | ||
46 | |||
47 | // writing v | ||
48 | copy(vb.Buffer[vb.WriteIndex:], v[:length]) | ||
49 | vb.WriteIndex += length | ||
50 | } | ||
51 | |||
52 | // ReadValue is the helper method to read the values when decoding valuesBytes to a map[Key][]byte. | ||
53 | func (vb *Values) ReadValue() []byte { | ||
54 | // read length of v | ||
55 | length := int(vb.Buffer[vb.ReadIndex]) | ||
56 | vb.ReadIndex++ | ||
57 | if length == 0 { | ||
58 | // No value was encoded for this key | ||
59 | return nil | ||
60 | } | ||
61 | |||
62 | // read value of v | ||
63 | v := make([]byte, length) | ||
64 | endIdx := vb.ReadIndex + length | ||
65 | copy(v, vb.Buffer[vb.ReadIndex:endIdx]) | ||
66 | vb.ReadIndex = endIdx | ||
67 | return v | ||
68 | } | ||
69 | |||
70 | func (vb *Values) Bytes() []byte { | ||
71 | return vb.Buffer[:vb.WriteIndex] | ||
72 | } | ||
diff --git a/vendor/go.opencensus.io/internal/traceinternals.go b/vendor/go.opencensus.io/internal/traceinternals.go new file mode 100644 index 0000000..553ca68 --- /dev/null +++ b/vendor/go.opencensus.io/internal/traceinternals.go | |||
@@ -0,0 +1,52 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package internal | ||
16 | |||
17 | import ( | ||
18 | "time" | ||
19 | ) | ||
20 | |||
21 | // Trace allows internal access to some trace functionality. | ||
22 | // TODO(#412): remove this | ||
23 | var Trace interface{} | ||
24 | |||
25 | var LocalSpanStoreEnabled bool | ||
26 | |||
27 | // BucketConfiguration stores the number of samples to store for span buckets | ||
28 | // for successful and failed spans for a particular span name. | ||
29 | type BucketConfiguration struct { | ||
30 | Name string | ||
31 | MaxRequestsSucceeded int | ||
32 | MaxRequestsErrors int | ||
33 | } | ||
34 | |||
35 | // PerMethodSummary is a summary of the spans stored for a single span name. | ||
36 | type PerMethodSummary struct { | ||
37 | Active int | ||
38 | LatencyBuckets []LatencyBucketSummary | ||
39 | ErrorBuckets []ErrorBucketSummary | ||
40 | } | ||
41 | |||
42 | // LatencyBucketSummary is a summary of a latency bucket. | ||
43 | type LatencyBucketSummary struct { | ||
44 | MinLatency, MaxLatency time.Duration | ||
45 | Size int | ||
46 | } | ||
47 | |||
48 | // ErrorBucketSummary is a summary of an error bucket. | ||
49 | type ErrorBucketSummary struct { | ||
50 | ErrorCode int32 | ||
51 | Size int | ||
52 | } | ||
diff --git a/vendor/go.opencensus.io/opencensus.go b/vendor/go.opencensus.io/opencensus.go new file mode 100644 index 0000000..62f0348 --- /dev/null +++ b/vendor/go.opencensus.io/opencensus.go | |||
@@ -0,0 +1,21 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // Package opencensus contains Go support for OpenCensus. | ||
16 | package opencensus // import "go.opencensus.io" | ||
17 | |||
18 | // Version is the current release version of OpenCensus in use. | ||
19 | func Version() string { | ||
20 | return "0.18.0" | ||
21 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/client.go b/vendor/go.opencensus.io/plugin/ochttp/client.go new file mode 100644 index 0000000..da815b2 --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/client.go | |||
@@ -0,0 +1,117 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package ochttp | ||
16 | |||
17 | import ( | ||
18 | "net/http" | ||
19 | "net/http/httptrace" | ||
20 | |||
21 | "go.opencensus.io/trace" | ||
22 | "go.opencensus.io/trace/propagation" | ||
23 | ) | ||
24 | |||
25 | // Transport is an http.RoundTripper that instruments all outgoing requests with | ||
26 | // OpenCensus stats and tracing. | ||
27 | // | ||
28 | // The zero value is intended to be a useful default, but for | ||
29 | // now it's recommended that you explicitly set Propagation, since the default | ||
30 | // for this may change. | ||
31 | type Transport struct { | ||
32 | // Base may be set to wrap another http.RoundTripper that does the actual | ||
33 | // requests. By default http.DefaultTransport is used. | ||
34 | // | ||
35 | // If base HTTP roundtripper implements CancelRequest, | ||
36 | // the returned round tripper will be cancelable. | ||
37 | Base http.RoundTripper | ||
38 | |||
39 | // Propagation defines how traces are propagated. If unspecified, a default | ||
40 | // (currently B3 format) will be used. | ||
41 | Propagation propagation.HTTPFormat | ||
42 | |||
43 | // StartOptions are applied to the span started by this Transport around each | ||
44 | // request. | ||
45 | // | ||
46 | // StartOptions.SpanKind will always be set to trace.SpanKindClient | ||
47 | // for spans started by this transport. | ||
48 | StartOptions trace.StartOptions | ||
49 | |||
50 | // GetStartOptions allows to set start options per request. If set, | ||
51 | // StartOptions is going to be ignored. | ||
52 | GetStartOptions func(*http.Request) trace.StartOptions | ||
53 | |||
54 | // NameFromRequest holds the function to use for generating the span name | ||
55 | // from the information found in the outgoing HTTP Request. By default the | ||
56 | // name equals the URL Path. | ||
57 | FormatSpanName func(*http.Request) string | ||
58 | |||
59 | // NewClientTrace may be set to a function allowing the current *trace.Span | ||
60 | // to be annotated with HTTP request event information emitted by the | ||
61 | // httptrace package. | ||
62 | NewClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace | ||
63 | |||
64 | // TODO: Implement tag propagation for HTTP. | ||
65 | } | ||
66 | |||
67 | // RoundTrip implements http.RoundTripper, delegating to Base and recording stats and traces for the request. | ||
68 | func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { | ||
69 | rt := t.base() | ||
70 | if isHealthEndpoint(req.URL.Path) { | ||
71 | return rt.RoundTrip(req) | ||
72 | } | ||
73 | // TODO: remove excessive nesting of http.RoundTrippers here. | ||
74 | format := t.Propagation | ||
75 | if format == nil { | ||
76 | format = defaultFormat | ||
77 | } | ||
78 | spanNameFormatter := t.FormatSpanName | ||
79 | if spanNameFormatter == nil { | ||
80 | spanNameFormatter = spanNameFromURL | ||
81 | } | ||
82 | |||
83 | startOpts := t.StartOptions | ||
84 | if t.GetStartOptions != nil { | ||
85 | startOpts = t.GetStartOptions(req) | ||
86 | } | ||
87 | |||
88 | rt = &traceTransport{ | ||
89 | base: rt, | ||
90 | format: format, | ||
91 | startOptions: trace.StartOptions{ | ||
92 | Sampler: startOpts.Sampler, | ||
93 | SpanKind: trace.SpanKindClient, | ||
94 | }, | ||
95 | formatSpanName: spanNameFormatter, | ||
96 | newClientTrace: t.NewClientTrace, | ||
97 | } | ||
98 | rt = statsTransport{base: rt} | ||
99 | return rt.RoundTrip(req) | ||
100 | } | ||
101 | |||
102 | func (t *Transport) base() http.RoundTripper { | ||
103 | if t.Base != nil { | ||
104 | return t.Base | ||
105 | } | ||
106 | return http.DefaultTransport | ||
107 | } | ||
108 | |||
109 | // CancelRequest cancels an in-flight request by closing its connection. | ||
110 | func (t *Transport) CancelRequest(req *http.Request) { | ||
111 | type canceler interface { | ||
112 | CancelRequest(*http.Request) | ||
113 | } | ||
114 | if cr, ok := t.base().(canceler); ok { | ||
115 | cr.CancelRequest(req) | ||
116 | } | ||
117 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/client_stats.go b/vendor/go.opencensus.io/plugin/ochttp/client_stats.go new file mode 100644 index 0000000..066ebb8 --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/client_stats.go | |||
@@ -0,0 +1,135 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package ochttp | ||
16 | |||
17 | import ( | ||
18 | "context" | ||
19 | "io" | ||
20 | "net/http" | ||
21 | "strconv" | ||
22 | "sync" | ||
23 | "time" | ||
24 | |||
25 | "go.opencensus.io/stats" | ||
26 | "go.opencensus.io/tag" | ||
27 | ) | ||
28 | |||
29 | // statsTransport is an http.RoundTripper that collects stats for the outgoing requests. | ||
30 | type statsTransport struct { | ||
31 | base http.RoundTripper | ||
32 | } | ||
33 | |||
34 | // RoundTrip implements http.RoundTripper, delegating to Base and recording stats for the request. | ||
35 | func (t statsTransport) RoundTrip(req *http.Request) (*http.Response, error) { | ||
36 | ctx, _ := tag.New(req.Context(), | ||
37 | tag.Upsert(KeyClientHost, req.URL.Host), | ||
38 | tag.Upsert(Host, req.URL.Host), | ||
39 | tag.Upsert(KeyClientPath, req.URL.Path), | ||
40 | tag.Upsert(Path, req.URL.Path), | ||
41 | tag.Upsert(KeyClientMethod, req.Method), | ||
42 | tag.Upsert(Method, req.Method)) | ||
43 | req = req.WithContext(ctx) | ||
44 | track := &tracker{ | ||
45 | start: time.Now(), | ||
46 | ctx: ctx, | ||
47 | } | ||
48 | if req.Body == nil { | ||
49 | // TODO: Handle cases where ContentLength is not set. | ||
50 | track.reqSize = -1 | ||
51 | } else if req.ContentLength > 0 { | ||
52 | track.reqSize = req.ContentLength | ||
53 | } | ||
54 | stats.Record(ctx, ClientRequestCount.M(1)) | ||
55 | |||
56 | // Perform request. | ||
57 | resp, err := t.base.RoundTrip(req) | ||
58 | |||
59 | if err != nil { | ||
60 | track.statusCode = http.StatusInternalServerError | ||
61 | track.end() | ||
62 | } else { | ||
63 | track.statusCode = resp.StatusCode | ||
64 | if resp.Body == nil { | ||
65 | track.end() | ||
66 | } else { | ||
67 | track.body = resp.Body | ||
68 | resp.Body = track | ||
69 | } | ||
70 | } | ||
71 | return resp, err | ||
72 | } | ||
73 | |||
74 | // CancelRequest cancels an in-flight request by closing its connection. | ||
75 | func (t statsTransport) CancelRequest(req *http.Request) { | ||
76 | type canceler interface { | ||
77 | CancelRequest(*http.Request) | ||
78 | } | ||
79 | if cr, ok := t.base.(canceler); ok { | ||
80 | cr.CancelRequest(req) | ||
81 | } | ||
82 | } | ||
83 | |||
84 | type tracker struct { | ||
85 | ctx context.Context | ||
86 | respSize int64 | ||
87 | reqSize int64 | ||
88 | start time.Time | ||
89 | body io.ReadCloser | ||
90 | statusCode int | ||
91 | endOnce sync.Once | ||
92 | } | ||
93 | |||
94 | var _ io.ReadCloser = (*tracker)(nil) | ||
95 | |||
96 | func (t *tracker) end() { | ||
97 | t.endOnce.Do(func() { | ||
98 | latencyMs := float64(time.Since(t.start)) / float64(time.Millisecond) | ||
99 | m := []stats.Measurement{ | ||
100 | ClientSentBytes.M(t.reqSize), | ||
101 | ClientReceivedBytes.M(t.respSize), | ||
102 | ClientRoundtripLatency.M(latencyMs), | ||
103 | ClientLatency.M(latencyMs), | ||
104 | ClientResponseBytes.M(t.respSize), | ||
105 | } | ||
106 | if t.reqSize >= 0 { | ||
107 | m = append(m, ClientRequestBytes.M(t.reqSize)) | ||
108 | } | ||
109 | |||
110 | stats.RecordWithTags(t.ctx, []tag.Mutator{ | ||
111 | tag.Upsert(StatusCode, strconv.Itoa(t.statusCode)), | ||
112 | tag.Upsert(KeyClientStatus, strconv.Itoa(t.statusCode)), | ||
113 | }, m...) | ||
114 | }) | ||
115 | } | ||
116 | |||
117 | func (t *tracker) Read(b []byte) (int, error) { | ||
118 | n, err := t.body.Read(b) | ||
119 | switch err { | ||
120 | case nil: | ||
121 | t.respSize += int64(n) | ||
122 | return n, nil | ||
123 | case io.EOF: | ||
124 | t.end() | ||
125 | } | ||
126 | return n, err | ||
127 | } | ||
128 | |||
129 | func (t *tracker) Close() error { | ||
130 | // Invoking endSpan on Close will help catch the cases | ||
131 | // in which a read returned a non-nil error, we set the | ||
132 | // span status but didn't end the span. | ||
133 | t.end() | ||
134 | return t.body.Close() | ||
135 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/doc.go b/vendor/go.opencensus.io/plugin/ochttp/doc.go new file mode 100644 index 0000000..10e626b --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/doc.go | |||
@@ -0,0 +1,19 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // Package ochttp provides OpenCensus instrumentation for net/http package. | ||
16 | // | ||
17 | // For server instrumentation, see Handler. For client-side instrumentation, | ||
18 | // see Transport. | ||
19 | package ochttp // import "go.opencensus.io/plugin/ochttp" | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go b/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go new file mode 100644 index 0000000..f777772 --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go | |||
@@ -0,0 +1,123 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // Package b3 contains a propagation.HTTPFormat implementation | ||
16 | // for B3 propagation. See https://github.com/openzipkin/b3-propagation | ||
17 | // for more details. | ||
18 | package b3 // import "go.opencensus.io/plugin/ochttp/propagation/b3" | ||
19 | |||
20 | import ( | ||
21 | "encoding/hex" | ||
22 | "net/http" | ||
23 | |||
24 | "go.opencensus.io/trace" | ||
25 | "go.opencensus.io/trace/propagation" | ||
26 | ) | ||
27 | |||
28 | // B3 headers that OpenCensus understands. | ||
29 | const ( | ||
30 | TraceIDHeader = "X-B3-TraceId" | ||
31 | SpanIDHeader = "X-B3-SpanId" | ||
32 | SampledHeader = "X-B3-Sampled" | ||
33 | ) | ||
34 | |||
35 | // HTTPFormat implements propagation.HTTPFormat to propagate | ||
36 | // traces in HTTP headers in B3 propagation format. | ||
37 | // HTTPFormat skips the X-B3-ParentId and X-B3-Flags headers | ||
38 | // because there are additional fields not represented in the | ||
39 | // OpenCensus span context. Spans created from the incoming | ||
40 | // header will be the direct children of the client-side span. | ||
41 | // Similarly, reciever of the outgoing spans should use client-side | ||
42 | // span created by OpenCensus as the parent. | ||
43 | type HTTPFormat struct{} | ||
44 | |||
45 | var _ propagation.HTTPFormat = (*HTTPFormat)(nil) | ||
46 | |||
47 | // SpanContextFromRequest extracts a B3 span context from incoming requests. | ||
48 | func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) { | ||
49 | tid, ok := ParseTraceID(req.Header.Get(TraceIDHeader)) | ||
50 | if !ok { | ||
51 | return trace.SpanContext{}, false | ||
52 | } | ||
53 | sid, ok := ParseSpanID(req.Header.Get(SpanIDHeader)) | ||
54 | if !ok { | ||
55 | return trace.SpanContext{}, false | ||
56 | } | ||
57 | sampled, _ := ParseSampled(req.Header.Get(SampledHeader)) | ||
58 | return trace.SpanContext{ | ||
59 | TraceID: tid, | ||
60 | SpanID: sid, | ||
61 | TraceOptions: sampled, | ||
62 | }, true | ||
63 | } | ||
64 | |||
65 | // ParseTraceID parses the value of the X-B3-TraceId header. | ||
66 | func ParseTraceID(tid string) (trace.TraceID, bool) { | ||
67 | if tid == "" { | ||
68 | return trace.TraceID{}, false | ||
69 | } | ||
70 | b, err := hex.DecodeString(tid) | ||
71 | if err != nil { | ||
72 | return trace.TraceID{}, false | ||
73 | } | ||
74 | var traceID trace.TraceID | ||
75 | if len(b) <= 8 { | ||
76 | // The lower 64-bits. | ||
77 | start := 8 + (8 - len(b)) | ||
78 | copy(traceID[start:], b) | ||
79 | } else { | ||
80 | start := 16 - len(b) | ||
81 | copy(traceID[start:], b) | ||
82 | } | ||
83 | |||
84 | return traceID, true | ||
85 | } | ||
86 | |||
87 | // ParseSpanID parses the value of the X-B3-SpanId or X-B3-ParentSpanId headers. | ||
88 | func ParseSpanID(sid string) (spanID trace.SpanID, ok bool) { | ||
89 | if sid == "" { | ||
90 | return trace.SpanID{}, false | ||
91 | } | ||
92 | b, err := hex.DecodeString(sid) | ||
93 | if err != nil { | ||
94 | return trace.SpanID{}, false | ||
95 | } | ||
96 | start := 8 - len(b) | ||
97 | copy(spanID[start:], b) | ||
98 | return spanID, true | ||
99 | } | ||
100 | |||
101 | // ParseSampled parses the value of the X-B3-Sampled header. | ||
102 | func ParseSampled(sampled string) (trace.TraceOptions, bool) { | ||
103 | switch sampled { | ||
104 | case "true", "1": | ||
105 | return trace.TraceOptions(1), true | ||
106 | default: | ||
107 | return trace.TraceOptions(0), false | ||
108 | } | ||
109 | } | ||
110 | |||
111 | // SpanContextToRequest modifies the given request to include B3 headers. | ||
112 | func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) { | ||
113 | req.Header.Set(TraceIDHeader, hex.EncodeToString(sc.TraceID[:])) | ||
114 | req.Header.Set(SpanIDHeader, hex.EncodeToString(sc.SpanID[:])) | ||
115 | |||
116 | var sampled string | ||
117 | if sc.IsSampled() { | ||
118 | sampled = "1" | ||
119 | } else { | ||
120 | sampled = "0" | ||
121 | } | ||
122 | req.Header.Set(SampledHeader, sampled) | ||
123 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/route.go b/vendor/go.opencensus.io/plugin/ochttp/route.go new file mode 100644 index 0000000..dbe22d5 --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/route.go | |||
@@ -0,0 +1,51 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package ochttp | ||
16 | |||
17 | import ( | ||
18 | "net/http" | ||
19 | |||
20 | "go.opencensus.io/tag" | ||
21 | ) | ||
22 | |||
23 | // WithRouteTag returns an http.Handler that records stats with the | ||
24 | // http_server_route tag set to the given value. | ||
25 | func WithRouteTag(handler http.Handler, route string) http.Handler { | ||
26 | return taggedHandlerFunc(func(w http.ResponseWriter, r *http.Request) []tag.Mutator { | ||
27 | addRoute := []tag.Mutator{tag.Upsert(KeyServerRoute, route)} | ||
28 | ctx, _ := tag.New(r.Context(), addRoute...) | ||
29 | r = r.WithContext(ctx) | ||
30 | handler.ServeHTTP(w, r) | ||
31 | return addRoute | ||
32 | }) | ||
33 | } | ||
34 | |||
35 | // taggedHandlerFunc is a http.Handler that returns tags describing the | ||
36 | // processing of the request. These tags will be recorded along with the | ||
37 | // measures in this package at the end of the request. | ||
38 | type taggedHandlerFunc func(w http.ResponseWriter, r *http.Request) []tag.Mutator | ||
39 | |||
40 | func (h taggedHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||
41 | tags := h(w, r) | ||
42 | if a, ok := r.Context().Value(addedTagsKey{}).(*addedTags); ok { | ||
43 | a.t = append(a.t, tags...) | ||
44 | } | ||
45 | } | ||
46 | |||
47 | type addedTagsKey struct{} | ||
48 | |||
49 | type addedTags struct { | ||
50 | t []tag.Mutator | ||
51 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/server.go b/vendor/go.opencensus.io/plugin/ochttp/server.go new file mode 100644 index 0000000..ff72de9 --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/server.go | |||
@@ -0,0 +1,440 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package ochttp | ||
16 | |||
17 | import ( | ||
18 | "context" | ||
19 | "io" | ||
20 | "net/http" | ||
21 | "strconv" | ||
22 | "sync" | ||
23 | "time" | ||
24 | |||
25 | "go.opencensus.io/stats" | ||
26 | "go.opencensus.io/tag" | ||
27 | "go.opencensus.io/trace" | ||
28 | "go.opencensus.io/trace/propagation" | ||
29 | ) | ||
30 | |||
31 | // Handler is an http.Handler wrapper to instrument your HTTP server with | ||
32 | // OpenCensus. It supports both stats and tracing. | ||
33 | // | ||
34 | // Tracing | ||
35 | // | ||
36 | // This handler is aware of the incoming request's span, reading it from request | ||
37 | // headers as configured using the Propagation field. | ||
38 | // The extracted span can be accessed from the incoming request's | ||
39 | // context. | ||
40 | // | ||
41 | // span := trace.FromContext(r.Context()) | ||
42 | // | ||
43 | // The server span will be automatically ended at the end of ServeHTTP. | ||
44 | type Handler struct { | ||
45 | // Propagation defines how traces are propagated. If unspecified, | ||
46 | // B3 propagation will be used. | ||
47 | Propagation propagation.HTTPFormat | ||
48 | |||
49 | // Handler is the handler used to handle the incoming request. | ||
50 | Handler http.Handler | ||
51 | |||
52 | // StartOptions are applied to the span started by this Handler around each | ||
53 | // request. | ||
54 | // | ||
55 | // StartOptions.SpanKind will always be set to trace.SpanKindServer | ||
56 | // for spans started by this transport. | ||
57 | StartOptions trace.StartOptions | ||
58 | |||
59 | // GetStartOptions allows to set start options per request. If set, | ||
60 | // StartOptions is going to be ignored. | ||
61 | GetStartOptions func(*http.Request) trace.StartOptions | ||
62 | |||
63 | // IsPublicEndpoint should be set to true for publicly accessible HTTP(S) | ||
64 | // servers. If true, any trace metadata set on the incoming request will | ||
65 | // be added as a linked trace instead of being added as a parent of the | ||
66 | // current trace. | ||
67 | IsPublicEndpoint bool | ||
68 | |||
69 | // FormatSpanName holds the function to use for generating the span name | ||
70 | // from the information found in the incoming HTTP Request. By default the | ||
71 | // name equals the URL Path. | ||
72 | FormatSpanName func(*http.Request) string | ||
73 | } | ||
74 | |||
75 | func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||
76 | var tags addedTags | ||
77 | r, traceEnd := h.startTrace(w, r) | ||
78 | defer traceEnd() | ||
79 | w, statsEnd := h.startStats(w, r) | ||
80 | defer statsEnd(&tags) | ||
81 | handler := h.Handler | ||
82 | if handler == nil { | ||
83 | handler = http.DefaultServeMux | ||
84 | } | ||
85 | r = r.WithContext(context.WithValue(r.Context(), addedTagsKey{}, &tags)) | ||
86 | handler.ServeHTTP(w, r) | ||
87 | } | ||
88 | |||
89 | func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Request, func()) { | ||
90 | if isHealthEndpoint(r.URL.Path) { | ||
91 | return r, func() {} | ||
92 | } | ||
93 | var name string | ||
94 | if h.FormatSpanName == nil { | ||
95 | name = spanNameFromURL(r) | ||
96 | } else { | ||
97 | name = h.FormatSpanName(r) | ||
98 | } | ||
99 | ctx := r.Context() | ||
100 | |||
101 | startOpts := h.StartOptions | ||
102 | if h.GetStartOptions != nil { | ||
103 | startOpts = h.GetStartOptions(r) | ||
104 | } | ||
105 | |||
106 | var span *trace.Span | ||
107 | sc, ok := h.extractSpanContext(r) | ||
108 | if ok && !h.IsPublicEndpoint { | ||
109 | ctx, span = trace.StartSpanWithRemoteParent(ctx, name, sc, | ||
110 | trace.WithSampler(startOpts.Sampler), | ||
111 | trace.WithSpanKind(trace.SpanKindServer)) | ||
112 | } else { | ||
113 | ctx, span = trace.StartSpan(ctx, name, | ||
114 | trace.WithSampler(startOpts.Sampler), | ||
115 | trace.WithSpanKind(trace.SpanKindServer), | ||
116 | ) | ||
117 | if ok { | ||
118 | span.AddLink(trace.Link{ | ||
119 | TraceID: sc.TraceID, | ||
120 | SpanID: sc.SpanID, | ||
121 | Type: trace.LinkTypeChild, | ||
122 | Attributes: nil, | ||
123 | }) | ||
124 | } | ||
125 | } | ||
126 | span.AddAttributes(requestAttrs(r)...) | ||
127 | return r.WithContext(ctx), span.End | ||
128 | } | ||
129 | |||
130 | func (h *Handler) extractSpanContext(r *http.Request) (trace.SpanContext, bool) { | ||
131 | if h.Propagation == nil { | ||
132 | return defaultFormat.SpanContextFromRequest(r) | ||
133 | } | ||
134 | return h.Propagation.SpanContextFromRequest(r) | ||
135 | } | ||
136 | |||
137 | func (h *Handler) startStats(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, func(tags *addedTags)) { | ||
138 | ctx, _ := tag.New(r.Context(), | ||
139 | tag.Upsert(Host, r.URL.Host), | ||
140 | tag.Upsert(Path, r.URL.Path), | ||
141 | tag.Upsert(Method, r.Method)) | ||
142 | track := &trackingResponseWriter{ | ||
143 | start: time.Now(), | ||
144 | ctx: ctx, | ||
145 | writer: w, | ||
146 | } | ||
147 | if r.Body == nil { | ||
148 | // TODO: Handle cases where ContentLength is not set. | ||
149 | track.reqSize = -1 | ||
150 | } else if r.ContentLength > 0 { | ||
151 | track.reqSize = r.ContentLength | ||
152 | } | ||
153 | stats.Record(ctx, ServerRequestCount.M(1)) | ||
154 | return track.wrappedResponseWriter(), track.end | ||
155 | } | ||
156 | |||
157 | type trackingResponseWriter struct { | ||
158 | ctx context.Context | ||
159 | reqSize int64 | ||
160 | respSize int64 | ||
161 | start time.Time | ||
162 | statusCode int | ||
163 | statusLine string | ||
164 | endOnce sync.Once | ||
165 | writer http.ResponseWriter | ||
166 | } | ||
167 | |||
168 | // Compile time assertion for ResponseWriter interface | ||
169 | var _ http.ResponseWriter = (*trackingResponseWriter)(nil) | ||
170 | |||
171 | var logTagsErrorOnce sync.Once | ||
172 | |||
173 | func (t *trackingResponseWriter) end(tags *addedTags) { | ||
174 | t.endOnce.Do(func() { | ||
175 | if t.statusCode == 0 { | ||
176 | t.statusCode = 200 | ||
177 | } | ||
178 | |||
179 | span := trace.FromContext(t.ctx) | ||
180 | span.SetStatus(TraceStatus(t.statusCode, t.statusLine)) | ||
181 | span.AddAttributes(trace.Int64Attribute(StatusCodeAttribute, int64(t.statusCode))) | ||
182 | |||
183 | m := []stats.Measurement{ | ||
184 | ServerLatency.M(float64(time.Since(t.start)) / float64(time.Millisecond)), | ||
185 | ServerResponseBytes.M(t.respSize), | ||
186 | } | ||
187 | if t.reqSize >= 0 { | ||
188 | m = append(m, ServerRequestBytes.M(t.reqSize)) | ||
189 | } | ||
190 | allTags := make([]tag.Mutator, len(tags.t)+1) | ||
191 | allTags[0] = tag.Upsert(StatusCode, strconv.Itoa(t.statusCode)) | ||
192 | copy(allTags[1:], tags.t) | ||
193 | stats.RecordWithTags(t.ctx, allTags, m...) | ||
194 | }) | ||
195 | } | ||
196 | |||
197 | func (t *trackingResponseWriter) Header() http.Header { | ||
198 | return t.writer.Header() | ||
199 | } | ||
200 | |||
201 | func (t *trackingResponseWriter) Write(data []byte) (int, error) { | ||
202 | n, err := t.writer.Write(data) | ||
203 | t.respSize += int64(n) | ||
204 | return n, err | ||
205 | } | ||
206 | |||
207 | func (t *trackingResponseWriter) WriteHeader(statusCode int) { | ||
208 | t.writer.WriteHeader(statusCode) | ||
209 | t.statusCode = statusCode | ||
210 | t.statusLine = http.StatusText(t.statusCode) | ||
211 | } | ||
212 | |||
213 | // wrappedResponseWriter returns a wrapped version of the original | ||
214 | // ResponseWriter and only implements the same combination of additional | ||
215 | // interfaces as the original. | ||
216 | // This implementation is based on https://github.com/felixge/httpsnoop. | ||
217 | func (t *trackingResponseWriter) wrappedResponseWriter() http.ResponseWriter { | ||
218 | var ( | ||
219 | hj, i0 = t.writer.(http.Hijacker) | ||
220 | cn, i1 = t.writer.(http.CloseNotifier) | ||
221 | pu, i2 = t.writer.(http.Pusher) | ||
222 | fl, i3 = t.writer.(http.Flusher) | ||
223 | rf, i4 = t.writer.(io.ReaderFrom) | ||
224 | ) | ||
225 | |||
226 | switch { | ||
227 | case !i0 && !i1 && !i2 && !i3 && !i4: | ||
228 | return struct { | ||
229 | http.ResponseWriter | ||
230 | }{t} | ||
231 | case !i0 && !i1 && !i2 && !i3 && i4: | ||
232 | return struct { | ||
233 | http.ResponseWriter | ||
234 | io.ReaderFrom | ||
235 | }{t, rf} | ||
236 | case !i0 && !i1 && !i2 && i3 && !i4: | ||
237 | return struct { | ||
238 | http.ResponseWriter | ||
239 | http.Flusher | ||
240 | }{t, fl} | ||
241 | case !i0 && !i1 && !i2 && i3 && i4: | ||
242 | return struct { | ||
243 | http.ResponseWriter | ||
244 | http.Flusher | ||
245 | io.ReaderFrom | ||
246 | }{t, fl, rf} | ||
247 | case !i0 && !i1 && i2 && !i3 && !i4: | ||
248 | return struct { | ||
249 | http.ResponseWriter | ||
250 | http.Pusher | ||
251 | }{t, pu} | ||
252 | case !i0 && !i1 && i2 && !i3 && i4: | ||
253 | return struct { | ||
254 | http.ResponseWriter | ||
255 | http.Pusher | ||
256 | io.ReaderFrom | ||
257 | }{t, pu, rf} | ||
258 | case !i0 && !i1 && i2 && i3 && !i4: | ||
259 | return struct { | ||
260 | http.ResponseWriter | ||
261 | http.Pusher | ||
262 | http.Flusher | ||
263 | }{t, pu, fl} | ||
264 | case !i0 && !i1 && i2 && i3 && i4: | ||
265 | return struct { | ||
266 | http.ResponseWriter | ||
267 | http.Pusher | ||
268 | http.Flusher | ||
269 | io.ReaderFrom | ||
270 | }{t, pu, fl, rf} | ||
271 | case !i0 && i1 && !i2 && !i3 && !i4: | ||
272 | return struct { | ||
273 | http.ResponseWriter | ||
274 | http.CloseNotifier | ||
275 | }{t, cn} | ||
276 | case !i0 && i1 && !i2 && !i3 && i4: | ||
277 | return struct { | ||
278 | http.ResponseWriter | ||
279 | http.CloseNotifier | ||
280 | io.ReaderFrom | ||
281 | }{t, cn, rf} | ||
282 | case !i0 && i1 && !i2 && i3 && !i4: | ||
283 | return struct { | ||
284 | http.ResponseWriter | ||
285 | http.CloseNotifier | ||
286 | http.Flusher | ||
287 | }{t, cn, fl} | ||
288 | case !i0 && i1 && !i2 && i3 && i4: | ||
289 | return struct { | ||
290 | http.ResponseWriter | ||
291 | http.CloseNotifier | ||
292 | http.Flusher | ||
293 | io.ReaderFrom | ||
294 | }{t, cn, fl, rf} | ||
295 | case !i0 && i1 && i2 && !i3 && !i4: | ||
296 | return struct { | ||
297 | http.ResponseWriter | ||
298 | http.CloseNotifier | ||
299 | http.Pusher | ||
300 | }{t, cn, pu} | ||
301 | case !i0 && i1 && i2 && !i3 && i4: | ||
302 | return struct { | ||
303 | http.ResponseWriter | ||
304 | http.CloseNotifier | ||
305 | http.Pusher | ||
306 | io.ReaderFrom | ||
307 | }{t, cn, pu, rf} | ||
308 | case !i0 && i1 && i2 && i3 && !i4: | ||
309 | return struct { | ||
310 | http.ResponseWriter | ||
311 | http.CloseNotifier | ||
312 | http.Pusher | ||
313 | http.Flusher | ||
314 | }{t, cn, pu, fl} | ||
315 | case !i0 && i1 && i2 && i3 && i4: | ||
316 | return struct { | ||
317 | http.ResponseWriter | ||
318 | http.CloseNotifier | ||
319 | http.Pusher | ||
320 | http.Flusher | ||
321 | io.ReaderFrom | ||
322 | }{t, cn, pu, fl, rf} | ||
323 | case i0 && !i1 && !i2 && !i3 && !i4: | ||
324 | return struct { | ||
325 | http.ResponseWriter | ||
326 | http.Hijacker | ||
327 | }{t, hj} | ||
328 | case i0 && !i1 && !i2 && !i3 && i4: | ||
329 | return struct { | ||
330 | http.ResponseWriter | ||
331 | http.Hijacker | ||
332 | io.ReaderFrom | ||
333 | }{t, hj, rf} | ||
334 | case i0 && !i1 && !i2 && i3 && !i4: | ||
335 | return struct { | ||
336 | http.ResponseWriter | ||
337 | http.Hijacker | ||
338 | http.Flusher | ||
339 | }{t, hj, fl} | ||
340 | case i0 && !i1 && !i2 && i3 && i4: | ||
341 | return struct { | ||
342 | http.ResponseWriter | ||
343 | http.Hijacker | ||
344 | http.Flusher | ||
345 | io.ReaderFrom | ||
346 | }{t, hj, fl, rf} | ||
347 | case i0 && !i1 && i2 && !i3 && !i4: | ||
348 | return struct { | ||
349 | http.ResponseWriter | ||
350 | http.Hijacker | ||
351 | http.Pusher | ||
352 | }{t, hj, pu} | ||
353 | case i0 && !i1 && i2 && !i3 && i4: | ||
354 | return struct { | ||
355 | http.ResponseWriter | ||
356 | http.Hijacker | ||
357 | http.Pusher | ||
358 | io.ReaderFrom | ||
359 | }{t, hj, pu, rf} | ||
360 | case i0 && !i1 && i2 && i3 && !i4: | ||
361 | return struct { | ||
362 | http.ResponseWriter | ||
363 | http.Hijacker | ||
364 | http.Pusher | ||
365 | http.Flusher | ||
366 | }{t, hj, pu, fl} | ||
367 | case i0 && !i1 && i2 && i3 && i4: | ||
368 | return struct { | ||
369 | http.ResponseWriter | ||
370 | http.Hijacker | ||
371 | http.Pusher | ||
372 | http.Flusher | ||
373 | io.ReaderFrom | ||
374 | }{t, hj, pu, fl, rf} | ||
375 | case i0 && i1 && !i2 && !i3 && !i4: | ||
376 | return struct { | ||
377 | http.ResponseWriter | ||
378 | http.Hijacker | ||
379 | http.CloseNotifier | ||
380 | }{t, hj, cn} | ||
381 | case i0 && i1 && !i2 && !i3 && i4: | ||
382 | return struct { | ||
383 | http.ResponseWriter | ||
384 | http.Hijacker | ||
385 | http.CloseNotifier | ||
386 | io.ReaderFrom | ||
387 | }{t, hj, cn, rf} | ||
388 | case i0 && i1 && !i2 && i3 && !i4: | ||
389 | return struct { | ||
390 | http.ResponseWriter | ||
391 | http.Hijacker | ||
392 | http.CloseNotifier | ||
393 | http.Flusher | ||
394 | }{t, hj, cn, fl} | ||
395 | case i0 && i1 && !i2 && i3 && i4: | ||
396 | return struct { | ||
397 | http.ResponseWriter | ||
398 | http.Hijacker | ||
399 | http.CloseNotifier | ||
400 | http.Flusher | ||
401 | io.ReaderFrom | ||
402 | }{t, hj, cn, fl, rf} | ||
403 | case i0 && i1 && i2 && !i3 && !i4: | ||
404 | return struct { | ||
405 | http.ResponseWriter | ||
406 | http.Hijacker | ||
407 | http.CloseNotifier | ||
408 | http.Pusher | ||
409 | }{t, hj, cn, pu} | ||
410 | case i0 && i1 && i2 && !i3 && i4: | ||
411 | return struct { | ||
412 | http.ResponseWriter | ||
413 | http.Hijacker | ||
414 | http.CloseNotifier | ||
415 | http.Pusher | ||
416 | io.ReaderFrom | ||
417 | }{t, hj, cn, pu, rf} | ||
418 | case i0 && i1 && i2 && i3 && !i4: | ||
419 | return struct { | ||
420 | http.ResponseWriter | ||
421 | http.Hijacker | ||
422 | http.CloseNotifier | ||
423 | http.Pusher | ||
424 | http.Flusher | ||
425 | }{t, hj, cn, pu, fl} | ||
426 | case i0 && i1 && i2 && i3 && i4: | ||
427 | return struct { | ||
428 | http.ResponseWriter | ||
429 | http.Hijacker | ||
430 | http.CloseNotifier | ||
431 | http.Pusher | ||
432 | http.Flusher | ||
433 | io.ReaderFrom | ||
434 | }{t, hj, cn, pu, fl, rf} | ||
435 | default: | ||
436 | return struct { | ||
437 | http.ResponseWriter | ||
438 | }{t} | ||
439 | } | ||
440 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace.go b/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace.go new file mode 100644 index 0000000..05c6c56 --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace.go | |||
@@ -0,0 +1,169 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package ochttp | ||
16 | |||
17 | import ( | ||
18 | "crypto/tls" | ||
19 | "net/http" | ||
20 | "net/http/httptrace" | ||
21 | "strings" | ||
22 | |||
23 | "go.opencensus.io/trace" | ||
24 | ) | ||
25 | |||
26 | type spanAnnotator struct { | ||
27 | sp *trace.Span | ||
28 | } | ||
29 | |||
30 | // TODO: Remove NewSpanAnnotator at the next release. | ||
31 | |||
32 | // NewSpanAnnotator returns a httptrace.ClientTrace which annotates | ||
33 | // all emitted httptrace events on the provided Span. | ||
34 | // Deprecated: Use NewSpanAnnotatingClientTrace instead | ||
35 | func NewSpanAnnotator(r *http.Request, s *trace.Span) *httptrace.ClientTrace { | ||
36 | return NewSpanAnnotatingClientTrace(r, s) | ||
37 | } | ||
38 | |||
39 | // NewSpanAnnotatingClientTrace returns a httptrace.ClientTrace which annotates | ||
40 | // all emitted httptrace events on the provided Span. | ||
41 | func NewSpanAnnotatingClientTrace(_ *http.Request, s *trace.Span) *httptrace.ClientTrace { | ||
42 | sa := spanAnnotator{sp: s} | ||
43 | |||
44 | return &httptrace.ClientTrace{ | ||
45 | GetConn: sa.getConn, | ||
46 | GotConn: sa.gotConn, | ||
47 | PutIdleConn: sa.putIdleConn, | ||
48 | GotFirstResponseByte: sa.gotFirstResponseByte, | ||
49 | Got100Continue: sa.got100Continue, | ||
50 | DNSStart: sa.dnsStart, | ||
51 | DNSDone: sa.dnsDone, | ||
52 | ConnectStart: sa.connectStart, | ||
53 | ConnectDone: sa.connectDone, | ||
54 | TLSHandshakeStart: sa.tlsHandshakeStart, | ||
55 | TLSHandshakeDone: sa.tlsHandshakeDone, | ||
56 | WroteHeaders: sa.wroteHeaders, | ||
57 | Wait100Continue: sa.wait100Continue, | ||
58 | WroteRequest: sa.wroteRequest, | ||
59 | } | ||
60 | } | ||
61 | |||
62 | func (s spanAnnotator) getConn(hostPort string) { | ||
63 | attrs := []trace.Attribute{ | ||
64 | trace.StringAttribute("httptrace.get_connection.host_port", hostPort), | ||
65 | } | ||
66 | s.sp.Annotate(attrs, "GetConn") | ||
67 | } | ||
68 | |||
69 | func (s spanAnnotator) gotConn(info httptrace.GotConnInfo) { | ||
70 | attrs := []trace.Attribute{ | ||
71 | trace.BoolAttribute("httptrace.got_connection.reused", info.Reused), | ||
72 | trace.BoolAttribute("httptrace.got_connection.was_idle", info.WasIdle), | ||
73 | } | ||
74 | if info.WasIdle { | ||
75 | attrs = append(attrs, | ||
76 | trace.StringAttribute("httptrace.got_connection.idle_time", info.IdleTime.String())) | ||
77 | } | ||
78 | s.sp.Annotate(attrs, "GotConn") | ||
79 | } | ||
80 | |||
81 | // PutIdleConn implements a httptrace.ClientTrace hook | ||
82 | func (s spanAnnotator) putIdleConn(err error) { | ||
83 | var attrs []trace.Attribute | ||
84 | if err != nil { | ||
85 | attrs = append(attrs, | ||
86 | trace.StringAttribute("httptrace.put_idle_connection.error", err.Error())) | ||
87 | } | ||
88 | s.sp.Annotate(attrs, "PutIdleConn") | ||
89 | } | ||
90 | |||
91 | func (s spanAnnotator) gotFirstResponseByte() { | ||
92 | s.sp.Annotate(nil, "GotFirstResponseByte") | ||
93 | } | ||
94 | |||
95 | func (s spanAnnotator) got100Continue() { | ||
96 | s.sp.Annotate(nil, "Got100Continue") | ||
97 | } | ||
98 | |||
99 | func (s spanAnnotator) dnsStart(info httptrace.DNSStartInfo) { | ||
100 | attrs := []trace.Attribute{ | ||
101 | trace.StringAttribute("httptrace.dns_start.host", info.Host), | ||
102 | } | ||
103 | s.sp.Annotate(attrs, "DNSStart") | ||
104 | } | ||
105 | |||
106 | func (s spanAnnotator) dnsDone(info httptrace.DNSDoneInfo) { | ||
107 | var addrs []string | ||
108 | for _, addr := range info.Addrs { | ||
109 | addrs = append(addrs, addr.String()) | ||
110 | } | ||
111 | attrs := []trace.Attribute{ | ||
112 | trace.StringAttribute("httptrace.dns_done.addrs", strings.Join(addrs, " , ")), | ||
113 | } | ||
114 | if info.Err != nil { | ||
115 | attrs = append(attrs, | ||
116 | trace.StringAttribute("httptrace.dns_done.error", info.Err.Error())) | ||
117 | } | ||
118 | s.sp.Annotate(attrs, "DNSDone") | ||
119 | } | ||
120 | |||
121 | func (s spanAnnotator) connectStart(network, addr string) { | ||
122 | attrs := []trace.Attribute{ | ||
123 | trace.StringAttribute("httptrace.connect_start.network", network), | ||
124 | trace.StringAttribute("httptrace.connect_start.addr", addr), | ||
125 | } | ||
126 | s.sp.Annotate(attrs, "ConnectStart") | ||
127 | } | ||
128 | |||
129 | func (s spanAnnotator) connectDone(network, addr string, err error) { | ||
130 | attrs := []trace.Attribute{ | ||
131 | trace.StringAttribute("httptrace.connect_done.network", network), | ||
132 | trace.StringAttribute("httptrace.connect_done.addr", addr), | ||
133 | } | ||
134 | if err != nil { | ||
135 | attrs = append(attrs, | ||
136 | trace.StringAttribute("httptrace.connect_done.error", err.Error())) | ||
137 | } | ||
138 | s.sp.Annotate(attrs, "ConnectDone") | ||
139 | } | ||
140 | |||
141 | func (s spanAnnotator) tlsHandshakeStart() { | ||
142 | s.sp.Annotate(nil, "TLSHandshakeStart") | ||
143 | } | ||
144 | |||
145 | func (s spanAnnotator) tlsHandshakeDone(_ tls.ConnectionState, err error) { | ||
146 | var attrs []trace.Attribute | ||
147 | if err != nil { | ||
148 | attrs = append(attrs, | ||
149 | trace.StringAttribute("httptrace.tls_handshake_done.error", err.Error())) | ||
150 | } | ||
151 | s.sp.Annotate(attrs, "TLSHandshakeDone") | ||
152 | } | ||
153 | |||
154 | func (s spanAnnotator) wroteHeaders() { | ||
155 | s.sp.Annotate(nil, "WroteHeaders") | ||
156 | } | ||
157 | |||
158 | func (s spanAnnotator) wait100Continue() { | ||
159 | s.sp.Annotate(nil, "Wait100Continue") | ||
160 | } | ||
161 | |||
162 | func (s spanAnnotator) wroteRequest(info httptrace.WroteRequestInfo) { | ||
163 | var attrs []trace.Attribute | ||
164 | if info.Err != nil { | ||
165 | attrs = append(attrs, | ||
166 | trace.StringAttribute("httptrace.wrote_request.error", info.Err.Error())) | ||
167 | } | ||
168 | s.sp.Annotate(attrs, "WroteRequest") | ||
169 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/stats.go b/vendor/go.opencensus.io/plugin/ochttp/stats.go new file mode 100644 index 0000000..46dcc8e --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/stats.go | |||
@@ -0,0 +1,265 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package ochttp | ||
16 | |||
17 | import ( | ||
18 | "go.opencensus.io/stats" | ||
19 | "go.opencensus.io/stats/view" | ||
20 | "go.opencensus.io/tag" | ||
21 | ) | ||
22 | |||
23 | // The following client HTTP measures are supported for use in custom views. | ||
24 | var ( | ||
25 | // Deprecated: Use a Count aggregation over one of the other client measures to achieve the same effect. | ||
26 | ClientRequestCount = stats.Int64("opencensus.io/http/client/request_count", "Number of HTTP requests started", stats.UnitDimensionless) | ||
27 | // Deprecated: Use ClientSentBytes. | ||
28 | ClientRequestBytes = stats.Int64("opencensus.io/http/client/request_bytes", "HTTP request body size if set as ContentLength (uncompressed)", stats.UnitBytes) | ||
29 | // Deprecated: Use ClientReceivedBytes. | ||
30 | ClientResponseBytes = stats.Int64("opencensus.io/http/client/response_bytes", "HTTP response body size (uncompressed)", stats.UnitBytes) | ||
31 | // Deprecated: Use ClientRoundtripLatency. | ||
32 | ClientLatency = stats.Float64("opencensus.io/http/client/latency", "End-to-end latency", stats.UnitMilliseconds) | ||
33 | ) | ||
34 | |||
35 | // Client measures supported for use in custom views. | ||
36 | var ( | ||
37 | ClientSentBytes = stats.Int64( | ||
38 | "opencensus.io/http/client/sent_bytes", | ||
39 | "Total bytes sent in request body (not including headers)", | ||
40 | stats.UnitBytes, | ||
41 | ) | ||
42 | ClientReceivedBytes = stats.Int64( | ||
43 | "opencensus.io/http/client/received_bytes", | ||
44 | "Total bytes received in response bodies (not including headers but including error responses with bodies)", | ||
45 | stats.UnitBytes, | ||
46 | ) | ||
47 | ClientRoundtripLatency = stats.Float64( | ||
48 | "opencensus.io/http/client/roundtrip_latency", | ||
49 | "Time between first byte of request headers sent to last byte of response received, or terminal error", | ||
50 | stats.UnitMilliseconds, | ||
51 | ) | ||
52 | ) | ||
53 | |||
54 | // The following server HTTP measures are supported for use in custom views: | ||
55 | var ( | ||
56 | ServerRequestCount = stats.Int64("opencensus.io/http/server/request_count", "Number of HTTP requests started", stats.UnitDimensionless) | ||
57 | ServerRequestBytes = stats.Int64("opencensus.io/http/server/request_bytes", "HTTP request body size if set as ContentLength (uncompressed)", stats.UnitBytes) | ||
58 | ServerResponseBytes = stats.Int64("opencensus.io/http/server/response_bytes", "HTTP response body size (uncompressed)", stats.UnitBytes) | ||
59 | ServerLatency = stats.Float64("opencensus.io/http/server/latency", "End-to-end latency", stats.UnitMilliseconds) | ||
60 | ) | ||
61 | |||
62 | // The following tags are applied to stats recorded by this package. Host, Path | ||
63 | // and Method are applied to all measures. StatusCode is not applied to | ||
64 | // ClientRequestCount or ServerRequestCount, since it is recorded before the status is known. | ||
65 | var ( | ||
66 | // Host is the value of the HTTP Host header. | ||
67 | // | ||
68 | // The value of this tag can be controlled by the HTTP client, so you need | ||
69 | // to watch out for potentially generating high-cardinality labels in your | ||
70 | // metrics backend if you use this tag in views. | ||
71 | Host, _ = tag.NewKey("http.host") | ||
72 | |||
73 | // StatusCode is the numeric HTTP response status code, | ||
74 | // or "error" if a transport error occurred and no status code was read. | ||
75 | StatusCode, _ = tag.NewKey("http.status") | ||
76 | |||
77 | // Path is the URL path (not including query string) in the request. | ||
78 | // | ||
79 | // The value of this tag can be controlled by the HTTP client, so you need | ||
80 | // to watch out for potentially generating high-cardinality labels in your | ||
81 | // metrics backend if you use this tag in views. | ||
82 | Path, _ = tag.NewKey("http.path") | ||
83 | |||
84 | // Method is the HTTP method of the request, capitalized (GET, POST, etc.). | ||
85 | Method, _ = tag.NewKey("http.method") | ||
86 | |||
87 | // KeyServerRoute is a low cardinality string representing the logical | ||
88 | // handler of the request. This is usually the pattern registered on the a | ||
89 | // ServeMux (or similar string). | ||
90 | KeyServerRoute, _ = tag.NewKey("http_server_route") | ||
91 | ) | ||
92 | |||
93 | // Client tag keys. | ||
94 | var ( | ||
95 | // KeyClientMethod is the HTTP method, capitalized (i.e. GET, POST, PUT, DELETE, etc.). | ||
96 | KeyClientMethod, _ = tag.NewKey("http_client_method") | ||
97 | // KeyClientPath is the URL path (not including query string). | ||
98 | KeyClientPath, _ = tag.NewKey("http_client_path") | ||
99 | // KeyClientStatus is the HTTP status code as an integer (e.g. 200, 404, 500.), or "error" if no response status line was received. | ||
100 | KeyClientStatus, _ = tag.NewKey("http_client_status") | ||
101 | // KeyClientHost is the value of the request Host header. | ||
102 | KeyClientHost, _ = tag.NewKey("http_client_host") | ||
103 | ) | ||
104 | |||
105 | // Default distributions used by views in this package. | ||
106 | var ( | ||
107 | DefaultSizeDistribution = view.Distribution(0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824, 4294967296) | ||
108 | DefaultLatencyDistribution = view.Distribution(0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000) | ||
109 | ) | ||
110 | |||
111 | // Package ochttp provides some convenience views. | ||
112 | // You still need to register these views for data to actually be collected. | ||
113 | var ( | ||
114 | ClientSentBytesDistribution = &view.View{ | ||
115 | Name: "opencensus.io/http/client/sent_bytes", | ||
116 | Measure: ClientSentBytes, | ||
117 | Aggregation: DefaultSizeDistribution, | ||
118 | Description: "Total bytes sent in request body (not including headers), by HTTP method and response status", | ||
119 | TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus}, | ||
120 | } | ||
121 | |||
122 | ClientReceivedBytesDistribution = &view.View{ | ||
123 | Name: "opencensus.io/http/client/received_bytes", | ||
124 | Measure: ClientReceivedBytes, | ||
125 | Aggregation: DefaultSizeDistribution, | ||
126 | Description: "Total bytes received in response bodies (not including headers but including error responses with bodies), by HTTP method and response status", | ||
127 | TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus}, | ||
128 | } | ||
129 | |||
130 | ClientRoundtripLatencyDistribution = &view.View{ | ||
131 | Name: "opencensus.io/http/client/roundtrip_latency", | ||
132 | Measure: ClientRoundtripLatency, | ||
133 | Aggregation: DefaultLatencyDistribution, | ||
134 | Description: "End-to-end latency, by HTTP method and response status", | ||
135 | TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus}, | ||
136 | } | ||
137 | |||
138 | ClientCompletedCount = &view.View{ | ||
139 | Name: "opencensus.io/http/client/completed_count", | ||
140 | Measure: ClientRoundtripLatency, | ||
141 | Aggregation: view.Count(), | ||
142 | Description: "Count of completed requests, by HTTP method and response status", | ||
143 | TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus}, | ||
144 | } | ||
145 | ) | ||
146 | |||
147 | var ( | ||
148 | // Deprecated: No direct replacement, but see ClientCompletedCount. | ||
149 | ClientRequestCountView = &view.View{ | ||
150 | Name: "opencensus.io/http/client/request_count", | ||
151 | Description: "Count of HTTP requests started", | ||
152 | Measure: ClientRequestCount, | ||
153 | Aggregation: view.Count(), | ||
154 | } | ||
155 | |||
156 | // Deprecated: Use ClientSentBytesDistribution. | ||
157 | ClientRequestBytesView = &view.View{ | ||
158 | Name: "opencensus.io/http/client/request_bytes", | ||
159 | Description: "Size distribution of HTTP request body", | ||
160 | Measure: ClientSentBytes, | ||
161 | Aggregation: DefaultSizeDistribution, | ||
162 | } | ||
163 | |||
164 | // Deprecated: Use ClientReceivedBytesDistribution. | ||
165 | ClientResponseBytesView = &view.View{ | ||
166 | Name: "opencensus.io/http/client/response_bytes", | ||
167 | Description: "Size distribution of HTTP response body", | ||
168 | Measure: ClientReceivedBytes, | ||
169 | Aggregation: DefaultSizeDistribution, | ||
170 | } | ||
171 | |||
172 | // Deprecated: Use ClientRoundtripLatencyDistribution. | ||
173 | ClientLatencyView = &view.View{ | ||
174 | Name: "opencensus.io/http/client/latency", | ||
175 | Description: "Latency distribution of HTTP requests", | ||
176 | Measure: ClientRoundtripLatency, | ||
177 | Aggregation: DefaultLatencyDistribution, | ||
178 | } | ||
179 | |||
180 | // Deprecated: Use ClientCompletedCount. | ||
181 | ClientRequestCountByMethod = &view.View{ | ||
182 | Name: "opencensus.io/http/client/request_count_by_method", | ||
183 | Description: "Client request count by HTTP method", | ||
184 | TagKeys: []tag.Key{Method}, | ||
185 | Measure: ClientSentBytes, | ||
186 | Aggregation: view.Count(), | ||
187 | } | ||
188 | |||
189 | // Deprecated: Use ClientCompletedCount. | ||
190 | ClientResponseCountByStatusCode = &view.View{ | ||
191 | Name: "opencensus.io/http/client/response_count_by_status_code", | ||
192 | Description: "Client response count by status code", | ||
193 | TagKeys: []tag.Key{StatusCode}, | ||
194 | Measure: ClientRoundtripLatency, | ||
195 | Aggregation: view.Count(), | ||
196 | } | ||
197 | ) | ||
198 | |||
199 | var ( | ||
200 | ServerRequestCountView = &view.View{ | ||
201 | Name: "opencensus.io/http/server/request_count", | ||
202 | Description: "Count of HTTP requests started", | ||
203 | Measure: ServerRequestCount, | ||
204 | Aggregation: view.Count(), | ||
205 | } | ||
206 | |||
207 | ServerRequestBytesView = &view.View{ | ||
208 | Name: "opencensus.io/http/server/request_bytes", | ||
209 | Description: "Size distribution of HTTP request body", | ||
210 | Measure: ServerRequestBytes, | ||
211 | Aggregation: DefaultSizeDistribution, | ||
212 | } | ||
213 | |||
214 | ServerResponseBytesView = &view.View{ | ||
215 | Name: "opencensus.io/http/server/response_bytes", | ||
216 | Description: "Size distribution of HTTP response body", | ||
217 | Measure: ServerResponseBytes, | ||
218 | Aggregation: DefaultSizeDistribution, | ||
219 | } | ||
220 | |||
221 | ServerLatencyView = &view.View{ | ||
222 | Name: "opencensus.io/http/server/latency", | ||
223 | Description: "Latency distribution of HTTP requests", | ||
224 | Measure: ServerLatency, | ||
225 | Aggregation: DefaultLatencyDistribution, | ||
226 | } | ||
227 | |||
228 | ServerRequestCountByMethod = &view.View{ | ||
229 | Name: "opencensus.io/http/server/request_count_by_method", | ||
230 | Description: "Server request count by HTTP method", | ||
231 | TagKeys: []tag.Key{Method}, | ||
232 | Measure: ServerRequestCount, | ||
233 | Aggregation: view.Count(), | ||
234 | } | ||
235 | |||
236 | ServerResponseCountByStatusCode = &view.View{ | ||
237 | Name: "opencensus.io/http/server/response_count_by_status_code", | ||
238 | Description: "Server response count by status code", | ||
239 | TagKeys: []tag.Key{StatusCode}, | ||
240 | Measure: ServerLatency, | ||
241 | Aggregation: view.Count(), | ||
242 | } | ||
243 | ) | ||
244 | |||
245 | // DefaultClientViews are the default client views provided by this package. | ||
246 | // Deprecated: No replacement. Register the views you would like individually. | ||
247 | var DefaultClientViews = []*view.View{ | ||
248 | ClientRequestCountView, | ||
249 | ClientRequestBytesView, | ||
250 | ClientResponseBytesView, | ||
251 | ClientLatencyView, | ||
252 | ClientRequestCountByMethod, | ||
253 | ClientResponseCountByStatusCode, | ||
254 | } | ||
255 | |||
256 | // DefaultServerViews are the default server views provided by this package. | ||
257 | // Deprecated: No replacement. Register the views you would like individually. | ||
258 | var DefaultServerViews = []*view.View{ | ||
259 | ServerRequestCountView, | ||
260 | ServerRequestBytesView, | ||
261 | ServerResponseBytesView, | ||
262 | ServerLatencyView, | ||
263 | ServerRequestCountByMethod, | ||
264 | ServerResponseCountByStatusCode, | ||
265 | } | ||
diff --git a/vendor/go.opencensus.io/plugin/ochttp/trace.go b/vendor/go.opencensus.io/plugin/ochttp/trace.go new file mode 100644 index 0000000..819a2d5 --- /dev/null +++ b/vendor/go.opencensus.io/plugin/ochttp/trace.go | |||
@@ -0,0 +1,228 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package ochttp | ||
16 | |||
17 | import ( | ||
18 | "io" | ||
19 | "net/http" | ||
20 | "net/http/httptrace" | ||
21 | |||
22 | "go.opencensus.io/plugin/ochttp/propagation/b3" | ||
23 | "go.opencensus.io/trace" | ||
24 | "go.opencensus.io/trace/propagation" | ||
25 | ) | ||
26 | |||
27 | // TODO(jbd): Add godoc examples. | ||
28 | |||
29 | var defaultFormat propagation.HTTPFormat = &b3.HTTPFormat{} | ||
30 | |||
31 | // Attributes recorded on the span for the requests. | ||
32 | // Only trace exporters will need them. | ||
33 | const ( | ||
34 | HostAttribute = "http.host" | ||
35 | MethodAttribute = "http.method" | ||
36 | PathAttribute = "http.path" | ||
37 | UserAgentAttribute = "http.user_agent" | ||
38 | StatusCodeAttribute = "http.status_code" | ||
39 | ) | ||
40 | |||
41 | type traceTransport struct { | ||
42 | base http.RoundTripper | ||
43 | startOptions trace.StartOptions | ||
44 | format propagation.HTTPFormat | ||
45 | formatSpanName func(*http.Request) string | ||
46 | newClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace | ||
47 | } | ||
48 | |||
49 | // TODO(jbd): Add message events for request and response size. | ||
50 | |||
51 | // RoundTrip creates a trace.Span and inserts it into the outgoing request's headers. | ||
52 | // The created span can follow a parent span, if a parent is presented in | ||
53 | // the request's context. | ||
54 | func (t *traceTransport) RoundTrip(req *http.Request) (*http.Response, error) { | ||
55 | name := t.formatSpanName(req) | ||
56 | // TODO(jbd): Discuss whether we want to prefix | ||
57 | // outgoing requests with Sent. | ||
58 | ctx, span := trace.StartSpan(req.Context(), name, | ||
59 | trace.WithSampler(t.startOptions.Sampler), | ||
60 | trace.WithSpanKind(trace.SpanKindClient)) | ||
61 | |||
62 | if t.newClientTrace != nil { | ||
63 | req = req.WithContext(httptrace.WithClientTrace(ctx, t.newClientTrace(req, span))) | ||
64 | } else { | ||
65 | req = req.WithContext(ctx) | ||
66 | } | ||
67 | |||
68 | if t.format != nil { | ||
69 | // SpanContextToRequest will modify its Request argument, which is | ||
70 | // contrary to the contract for http.RoundTripper, so we need to | ||
71 | // pass it a copy of the Request. | ||
72 | // However, the Request struct itself was already copied by | ||
73 | // the WithContext calls above and so we just need to copy the header. | ||
74 | header := make(http.Header) | ||
75 | for k, v := range req.Header { | ||
76 | header[k] = v | ||
77 | } | ||
78 | req.Header = header | ||
79 | t.format.SpanContextToRequest(span.SpanContext(), req) | ||
80 | } | ||
81 | |||
82 | span.AddAttributes(requestAttrs(req)...) | ||
83 | resp, err := t.base.RoundTrip(req) | ||
84 | if err != nil { | ||
85 | span.SetStatus(trace.Status{Code: trace.StatusCodeUnknown, Message: err.Error()}) | ||
86 | span.End() | ||
87 | return resp, err | ||
88 | } | ||
89 | |||
90 | span.AddAttributes(responseAttrs(resp)...) | ||
91 | span.SetStatus(TraceStatus(resp.StatusCode, resp.Status)) | ||
92 | |||
93 | // span.End() will be invoked after | ||
94 | // a read from resp.Body returns io.EOF or when | ||
95 | // resp.Body.Close() is invoked. | ||
96 | resp.Body = &bodyTracker{rc: resp.Body, span: span} | ||
97 | return resp, err | ||
98 | } | ||
99 | |||
100 | // bodyTracker wraps a response.Body and invokes | ||
101 | // trace.EndSpan on encountering io.EOF on reading | ||
102 | // the body of the original response. | ||
103 | type bodyTracker struct { | ||
104 | rc io.ReadCloser | ||
105 | span *trace.Span | ||
106 | } | ||
107 | |||
108 | var _ io.ReadCloser = (*bodyTracker)(nil) | ||
109 | |||
110 | func (bt *bodyTracker) Read(b []byte) (int, error) { | ||
111 | n, err := bt.rc.Read(b) | ||
112 | |||
113 | switch err { | ||
114 | case nil: | ||
115 | return n, nil | ||
116 | case io.EOF: | ||
117 | bt.span.End() | ||
118 | default: | ||
119 | // For all other errors, set the span status | ||
120 | bt.span.SetStatus(trace.Status{ | ||
121 | // Code 2 is the error code for Internal server error. | ||
122 | Code: 2, | ||
123 | Message: err.Error(), | ||
124 | }) | ||
125 | } | ||
126 | return n, err | ||
127 | } | ||
128 | |||
129 | func (bt *bodyTracker) Close() error { | ||
130 | // Invoking endSpan on Close will help catch the cases | ||
131 | // in which a read returned a non-nil error, we set the | ||
132 | // span status but didn't end the span. | ||
133 | bt.span.End() | ||
134 | return bt.rc.Close() | ||
135 | } | ||
136 | |||
137 | // CancelRequest cancels an in-flight request by closing its connection. | ||
138 | func (t *traceTransport) CancelRequest(req *http.Request) { | ||
139 | type canceler interface { | ||
140 | CancelRequest(*http.Request) | ||
141 | } | ||
142 | if cr, ok := t.base.(canceler); ok { | ||
143 | cr.CancelRequest(req) | ||
144 | } | ||
145 | } | ||
146 | |||
147 | func spanNameFromURL(req *http.Request) string { | ||
148 | return req.URL.Path | ||
149 | } | ||
150 | |||
151 | func requestAttrs(r *http.Request) []trace.Attribute { | ||
152 | return []trace.Attribute{ | ||
153 | trace.StringAttribute(PathAttribute, r.URL.Path), | ||
154 | trace.StringAttribute(HostAttribute, r.URL.Host), | ||
155 | trace.StringAttribute(MethodAttribute, r.Method), | ||
156 | trace.StringAttribute(UserAgentAttribute, r.UserAgent()), | ||
157 | } | ||
158 | } | ||
159 | |||
160 | func responseAttrs(resp *http.Response) []trace.Attribute { | ||
161 | return []trace.Attribute{ | ||
162 | trace.Int64Attribute(StatusCodeAttribute, int64(resp.StatusCode)), | ||
163 | } | ||
164 | } | ||
165 | |||
166 | // TraceStatus is a utility to convert the HTTP status code to a trace.Status that | ||
167 | // represents the outcome as closely as possible. | ||
168 | func TraceStatus(httpStatusCode int, statusLine string) trace.Status { | ||
169 | var code int32 | ||
170 | if httpStatusCode < 200 || httpStatusCode >= 400 { | ||
171 | code = trace.StatusCodeUnknown | ||
172 | } | ||
173 | switch httpStatusCode { | ||
174 | case 499: | ||
175 | code = trace.StatusCodeCancelled | ||
176 | case http.StatusBadRequest: | ||
177 | code = trace.StatusCodeInvalidArgument | ||
178 | case http.StatusGatewayTimeout: | ||
179 | code = trace.StatusCodeDeadlineExceeded | ||
180 | case http.StatusNotFound: | ||
181 | code = trace.StatusCodeNotFound | ||
182 | case http.StatusForbidden: | ||
183 | code = trace.StatusCodePermissionDenied | ||
184 | case http.StatusUnauthorized: // 401 is actually unauthenticated. | ||
185 | code = trace.StatusCodeUnauthenticated | ||
186 | case http.StatusTooManyRequests: | ||
187 | code = trace.StatusCodeResourceExhausted | ||
188 | case http.StatusNotImplemented: | ||
189 | code = trace.StatusCodeUnimplemented | ||
190 | case http.StatusServiceUnavailable: | ||
191 | code = trace.StatusCodeUnavailable | ||
192 | case http.StatusOK: | ||
193 | code = trace.StatusCodeOK | ||
194 | } | ||
195 | return trace.Status{Code: code, Message: codeToStr[code]} | ||
196 | } | ||
197 | |||
198 | var codeToStr = map[int32]string{ | ||
199 | trace.StatusCodeOK: `OK`, | ||
200 | trace.StatusCodeCancelled: `CANCELLED`, | ||
201 | trace.StatusCodeUnknown: `UNKNOWN`, | ||
202 | trace.StatusCodeInvalidArgument: `INVALID_ARGUMENT`, | ||
203 | trace.StatusCodeDeadlineExceeded: `DEADLINE_EXCEEDED`, | ||
204 | trace.StatusCodeNotFound: `NOT_FOUND`, | ||
205 | trace.StatusCodeAlreadyExists: `ALREADY_EXISTS`, | ||
206 | trace.StatusCodePermissionDenied: `PERMISSION_DENIED`, | ||
207 | trace.StatusCodeResourceExhausted: `RESOURCE_EXHAUSTED`, | ||
208 | trace.StatusCodeFailedPrecondition: `FAILED_PRECONDITION`, | ||
209 | trace.StatusCodeAborted: `ABORTED`, | ||
210 | trace.StatusCodeOutOfRange: `OUT_OF_RANGE`, | ||
211 | trace.StatusCodeUnimplemented: `UNIMPLEMENTED`, | ||
212 | trace.StatusCodeInternal: `INTERNAL`, | ||
213 | trace.StatusCodeUnavailable: `UNAVAILABLE`, | ||
214 | trace.StatusCodeDataLoss: `DATA_LOSS`, | ||
215 | trace.StatusCodeUnauthenticated: `UNAUTHENTICATED`, | ||
216 | } | ||
217 | |||
218 | func isHealthEndpoint(path string) bool { | ||
219 | // Health checking is pretty frequent and | ||
220 | // traces collected for health endpoints | ||
221 | // can be extremely noisy and expensive. | ||
222 | // Disable canonical health checking endpoints | ||
223 | // like /healthz and /_ah/health for now. | ||
224 | if path == "/healthz" || path == "/_ah/health" { | ||
225 | return true | ||
226 | } | ||
227 | return false | ||
228 | } | ||
diff --git a/vendor/go.opencensus.io/stats/doc.go b/vendor/go.opencensus.io/stats/doc.go new file mode 100644 index 0000000..00d473e --- /dev/null +++ b/vendor/go.opencensus.io/stats/doc.go | |||
@@ -0,0 +1,69 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | /* | ||
17 | Package stats contains support for OpenCensus stats recording. | ||
18 | |||
19 | OpenCensus allows users to create typed measures, record measurements, | ||
20 | aggregate the collected data, and export the aggregated data. | ||
21 | |||
22 | Measures | ||
23 | |||
24 | A measure represents a type of data point to be tracked and recorded. | ||
25 | For example, latency, request Mb/s, and response Mb/s are measures | ||
26 | to collect from a server. | ||
27 | |||
28 | Measure constructors such as Int64 and Float64 automatically | ||
29 | register the measure by the given name. Each registered measure needs | ||
30 | to be unique by name. Measures also have a description and a unit. | ||
31 | |||
32 | Libraries can define and export measures. Application authors can then | ||
33 | create views and collect and break down measures by the tags they are | ||
34 | interested in. | ||
35 | |||
36 | Recording measurements | ||
37 | |||
38 | Measurement is a data point to be collected for a measure. For example, | ||
39 | for a latency (ms) measure, 100 is a measurement that represents a 100ms | ||
40 | latency event. Measurements are created from measures with | ||
41 | the current context. Tags from the current context are recorded with the | ||
42 | measurements if they are any. | ||
43 | |||
44 | Recorded measurements are dropped immediately if no views are registered for them. | ||
45 | There is usually no need to conditionally enable and disable | ||
46 | recording to reduce cost. Recording of measurements is cheap. | ||
47 | |||
48 | Libraries can always record measurements, and applications can later decide | ||
49 | on which measurements they want to collect by registering views. This allows | ||
50 | libraries to turn on the instrumentation by default. | ||
51 | |||
52 | Exemplars | ||
53 | |||
54 | For a given recorded measurement, the associated exemplar is a diagnostic map | ||
55 | that gives more information about the measurement. | ||
56 | |||
57 | When aggregated using a Distribution aggregation, an exemplar is kept for each | ||
58 | bucket in the Distribution. This allows you to easily find an example of a | ||
59 | measurement that fell into each bucket. | ||
60 | |||
61 | For example, if you also use the OpenCensus trace package and you | ||
62 | record a measurement with a context that contains a sampled trace span, | ||
63 | then the trace span will be added to the exemplar associated with the measurement. | ||
64 | |||
65 | When exported to a supporting back end, you should be able to easily navigate | ||
66 | to example traces that fell into each bucket in the Distribution. | ||
67 | |||
68 | */ | ||
69 | package stats // import "go.opencensus.io/stats" | ||
diff --git a/vendor/go.opencensus.io/stats/internal/record.go b/vendor/go.opencensus.io/stats/internal/record.go new file mode 100644 index 0000000..ed54552 --- /dev/null +++ b/vendor/go.opencensus.io/stats/internal/record.go | |||
@@ -0,0 +1,25 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package internal | ||
16 | |||
17 | import ( | ||
18 | "go.opencensus.io/tag" | ||
19 | ) | ||
20 | |||
21 | // DefaultRecorder will be called for each Record call. | ||
22 | var DefaultRecorder func(tags *tag.Map, measurement interface{}, attachments map[string]string) | ||
23 | |||
24 | // SubscriptionReporter reports when a view subscribed with a measure. | ||
25 | var SubscriptionReporter func(measure string) | ||
diff --git a/vendor/go.opencensus.io/stats/internal/validation.go b/vendor/go.opencensus.io/stats/internal/validation.go new file mode 100644 index 0000000..b946667 --- /dev/null +++ b/vendor/go.opencensus.io/stats/internal/validation.go | |||
@@ -0,0 +1,28 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package internal // import "go.opencensus.io/stats/internal" | ||
16 | |||
17 | const ( | ||
18 | MaxNameLength = 255 | ||
19 | ) | ||
20 | |||
21 | func IsPrintable(str string) bool { | ||
22 | for _, r := range str { | ||
23 | if !(r >= ' ' && r <= '~') { | ||
24 | return false | ||
25 | } | ||
26 | } | ||
27 | return true | ||
28 | } | ||
diff --git a/vendor/go.opencensus.io/stats/measure.go b/vendor/go.opencensus.io/stats/measure.go new file mode 100644 index 0000000..64d02b1 --- /dev/null +++ b/vendor/go.opencensus.io/stats/measure.go | |||
@@ -0,0 +1,123 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package stats | ||
17 | |||
18 | import ( | ||
19 | "sync" | ||
20 | "sync/atomic" | ||
21 | ) | ||
22 | |||
23 | // Measure represents a single numeric value to be tracked and recorded. | ||
24 | // For example, latency, request bytes, and response bytes could be measures | ||
25 | // to collect from a server. | ||
26 | // | ||
27 | // Measures by themselves have no outside effects. In order to be exported, | ||
28 | // the measure needs to be used in a View. If no Views are defined over a | ||
29 | // measure, there is very little cost in recording it. | ||
30 | type Measure interface { | ||
31 | // Name returns the name of this measure. | ||
32 | // | ||
33 | // Measure names are globally unique (among all libraries linked into your program). | ||
34 | // We recommend prefixing the measure name with a domain name relevant to your | ||
35 | // project or application. | ||
36 | // | ||
37 | // Measure names are never sent over the wire or exported to backends. | ||
38 | // They are only used to create Views. | ||
39 | Name() string | ||
40 | |||
41 | // Description returns the human-readable description of this measure. | ||
42 | Description() string | ||
43 | |||
44 | // Unit returns the units for the values this measure takes on. | ||
45 | // | ||
46 | // Units are encoded according to the case-sensitive abbreviations from the | ||
47 | // Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html | ||
48 | Unit() string | ||
49 | } | ||
50 | |||
51 | // measureDescriptor is the untyped descriptor associated with each measure. | ||
52 | // Int64Measure and Float64Measure wrap measureDescriptor to provide typed | ||
53 | // recording APIs. | ||
54 | // Two Measures with the same name will have the same measureDescriptor. | ||
55 | type measureDescriptor struct { | ||
56 | subs int32 // access atomically | ||
57 | |||
58 | name string | ||
59 | description string | ||
60 | unit string | ||
61 | } | ||
62 | |||
63 | func (m *measureDescriptor) subscribe() { | ||
64 | atomic.StoreInt32(&m.subs, 1) | ||
65 | } | ||
66 | |||
67 | func (m *measureDescriptor) subscribed() bool { | ||
68 | return atomic.LoadInt32(&m.subs) == 1 | ||
69 | } | ||
70 | |||
71 | // Name returns the name of the measure. | ||
72 | func (m *measureDescriptor) Name() string { | ||
73 | return m.name | ||
74 | } | ||
75 | |||
76 | // Description returns the description of the measure. | ||
77 | func (m *measureDescriptor) Description() string { | ||
78 | return m.description | ||
79 | } | ||
80 | |||
81 | // Unit returns the unit of the measure. | ||
82 | func (m *measureDescriptor) Unit() string { | ||
83 | return m.unit | ||
84 | } | ||
85 | |||
86 | var ( | ||
87 | mu sync.RWMutex | ||
88 | measures = make(map[string]*measureDescriptor) | ||
89 | ) | ||
90 | |||
91 | func registerMeasureHandle(name, desc, unit string) *measureDescriptor { | ||
92 | mu.Lock() | ||
93 | defer mu.Unlock() | ||
94 | |||
95 | if stored, ok := measures[name]; ok { | ||
96 | return stored | ||
97 | } | ||
98 | m := &measureDescriptor{ | ||
99 | name: name, | ||
100 | description: desc, | ||
101 | unit: unit, | ||
102 | } | ||
103 | measures[name] = m | ||
104 | return m | ||
105 | } | ||
106 | |||
107 | // Measurement is the numeric value measured when recording stats. Each measure | ||
108 | // provides methods to create measurements of their kind. For example, Int64Measure | ||
109 | // provides M to convert an int64 into a measurement. | ||
110 | type Measurement struct { | ||
111 | v float64 | ||
112 | m *measureDescriptor | ||
113 | } | ||
114 | |||
115 | // Value returns the value of the Measurement as a float64. | ||
116 | func (m Measurement) Value() float64 { | ||
117 | return m.v | ||
118 | } | ||
119 | |||
120 | // Measure returns the Measure from which this Measurement was created. | ||
121 | func (m Measurement) Measure() Measure { | ||
122 | return m.m | ||
123 | } | ||
diff --git a/vendor/go.opencensus.io/stats/measure_float64.go b/vendor/go.opencensus.io/stats/measure_float64.go new file mode 100644 index 0000000..acedb21 --- /dev/null +++ b/vendor/go.opencensus.io/stats/measure_float64.go | |||
@@ -0,0 +1,36 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package stats | ||
17 | |||
18 | // Float64Measure is a measure for float64 values. | ||
19 | type Float64Measure struct { | ||
20 | *measureDescriptor | ||
21 | } | ||
22 | |||
23 | // M creates a new float64 measurement. | ||
24 | // Use Record to record measurements. | ||
25 | func (m *Float64Measure) M(v float64) Measurement { | ||
26 | return Measurement{m: m.measureDescriptor, v: v} | ||
27 | } | ||
28 | |||
29 | // Float64 creates a new measure for float64 values. | ||
30 | // | ||
31 | // See the documentation for interface Measure for more guidance on the | ||
32 | // parameters of this function. | ||
33 | func Float64(name, description, unit string) *Float64Measure { | ||
34 | mi := registerMeasureHandle(name, description, unit) | ||
35 | return &Float64Measure{mi} | ||
36 | } | ||
diff --git a/vendor/go.opencensus.io/stats/measure_int64.go b/vendor/go.opencensus.io/stats/measure_int64.go new file mode 100644 index 0000000..c4243ba --- /dev/null +++ b/vendor/go.opencensus.io/stats/measure_int64.go | |||
@@ -0,0 +1,36 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package stats | ||
17 | |||
18 | // Int64Measure is a measure for int64 values. | ||
19 | type Int64Measure struct { | ||
20 | *measureDescriptor | ||
21 | } | ||
22 | |||
23 | // M creates a new int64 measurement. | ||
24 | // Use Record to record measurements. | ||
25 | func (m *Int64Measure) M(v int64) Measurement { | ||
26 | return Measurement{m: m.measureDescriptor, v: float64(v)} | ||
27 | } | ||
28 | |||
29 | // Int64 creates a new measure for int64 values. | ||
30 | // | ||
31 | // See the documentation for interface Measure for more guidance on the | ||
32 | // parameters of this function. | ||
33 | func Int64(name, description, unit string) *Int64Measure { | ||
34 | mi := registerMeasureHandle(name, description, unit) | ||
35 | return &Int64Measure{mi} | ||
36 | } | ||
diff --git a/vendor/go.opencensus.io/stats/record.go b/vendor/go.opencensus.io/stats/record.go new file mode 100644 index 0000000..0aced02 --- /dev/null +++ b/vendor/go.opencensus.io/stats/record.go | |||
@@ -0,0 +1,69 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package stats | ||
17 | |||
18 | import ( | ||
19 | "context" | ||
20 | |||
21 | "go.opencensus.io/exemplar" | ||
22 | "go.opencensus.io/stats/internal" | ||
23 | "go.opencensus.io/tag" | ||
24 | ) | ||
25 | |||
26 | func init() { | ||
27 | internal.SubscriptionReporter = func(measure string) { | ||
28 | mu.Lock() | ||
29 | measures[measure].subscribe() | ||
30 | mu.Unlock() | ||
31 | } | ||
32 | } | ||
33 | |||
34 | // Record records one or multiple measurements with the same context at once. | ||
35 | // If there are any tags in the context, measurements will be tagged with them. | ||
36 | func Record(ctx context.Context, ms ...Measurement) { | ||
37 | recorder := internal.DefaultRecorder | ||
38 | if recorder == nil { | ||
39 | return | ||
40 | } | ||
41 | if len(ms) == 0 { | ||
42 | return | ||
43 | } | ||
44 | record := false | ||
45 | for _, m := range ms { | ||
46 | if m.m.subscribed() { | ||
47 | record = true | ||
48 | break | ||
49 | } | ||
50 | } | ||
51 | if !record { | ||
52 | return | ||
53 | } | ||
54 | recorder(tag.FromContext(ctx), ms, exemplar.AttachmentsFromContext(ctx)) | ||
55 | } | ||
56 | |||
57 | // RecordWithTags records one or multiple measurements at once. | ||
58 | // | ||
59 | // Measurements will be tagged with the tags in the context mutated by the mutators. | ||
60 | // RecordWithTags is useful if you want to record with tag mutations but don't want | ||
61 | // to propagate the mutations in the context. | ||
62 | func RecordWithTags(ctx context.Context, mutators []tag.Mutator, ms ...Measurement) error { | ||
63 | ctx, err := tag.New(ctx, mutators...) | ||
64 | if err != nil { | ||
65 | return err | ||
66 | } | ||
67 | Record(ctx, ms...) | ||
68 | return nil | ||
69 | } | ||
diff --git a/vendor/go.opencensus.io/stats/units.go b/vendor/go.opencensus.io/stats/units.go new file mode 100644 index 0000000..6931a5f --- /dev/null +++ b/vendor/go.opencensus.io/stats/units.go | |||
@@ -0,0 +1,25 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package stats | ||
17 | |||
18 | // Units are encoded according to the case-sensitive abbreviations from the | ||
19 | // Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html | ||
20 | const ( | ||
21 | UnitNone = "1" // Deprecated: Use UnitDimensionless. | ||
22 | UnitDimensionless = "1" | ||
23 | UnitBytes = "By" | ||
24 | UnitMilliseconds = "ms" | ||
25 | ) | ||
diff --git a/vendor/go.opencensus.io/stats/view/aggregation.go b/vendor/go.opencensus.io/stats/view/aggregation.go new file mode 100644 index 0000000..b7f169b --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/aggregation.go | |||
@@ -0,0 +1,120 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package view | ||
17 | |||
18 | // AggType represents the type of aggregation function used on a View. | ||
19 | type AggType int | ||
20 | |||
21 | // All available aggregation types. | ||
22 | const ( | ||
23 | AggTypeNone AggType = iota // no aggregation; reserved for future use. | ||
24 | AggTypeCount // the count aggregation, see Count. | ||
25 | AggTypeSum // the sum aggregation, see Sum. | ||
26 | AggTypeDistribution // the distribution aggregation, see Distribution. | ||
27 | AggTypeLastValue // the last value aggregation, see LastValue. | ||
28 | ) | ||
29 | |||
30 | func (t AggType) String() string { | ||
31 | return aggTypeName[t] | ||
32 | } | ||
33 | |||
34 | var aggTypeName = map[AggType]string{ | ||
35 | AggTypeNone: "None", | ||
36 | AggTypeCount: "Count", | ||
37 | AggTypeSum: "Sum", | ||
38 | AggTypeDistribution: "Distribution", | ||
39 | AggTypeLastValue: "LastValue", | ||
40 | } | ||
41 | |||
42 | // Aggregation represents a data aggregation method. Use one of the functions: | ||
43 | // Count, Sum, or Distribution to construct an Aggregation. | ||
44 | type Aggregation struct { | ||
45 | Type AggType // Type is the AggType of this Aggregation. | ||
46 | Buckets []float64 // Buckets are the bucket endpoints if this Aggregation represents a distribution, see Distribution. | ||
47 | |||
48 | newData func() AggregationData | ||
49 | } | ||
50 | |||
51 | var ( | ||
52 | aggCount = &Aggregation{ | ||
53 | Type: AggTypeCount, | ||
54 | newData: func() AggregationData { | ||
55 | return &CountData{} | ||
56 | }, | ||
57 | } | ||
58 | aggSum = &Aggregation{ | ||
59 | Type: AggTypeSum, | ||
60 | newData: func() AggregationData { | ||
61 | return &SumData{} | ||
62 | }, | ||
63 | } | ||
64 | ) | ||
65 | |||
66 | // Count indicates that data collected and aggregated | ||
67 | // with this method will be turned into a count value. | ||
68 | // For example, total number of accepted requests can be | ||
69 | // aggregated by using Count. | ||
70 | func Count() *Aggregation { | ||
71 | return aggCount | ||
72 | } | ||
73 | |||
74 | // Sum indicates that data collected and aggregated | ||
75 | // with this method will be summed up. | ||
76 | // For example, accumulated request bytes can be aggregated by using | ||
77 | // Sum. | ||
78 | func Sum() *Aggregation { | ||
79 | return aggSum | ||
80 | } | ||
81 | |||
82 | // Distribution indicates that the desired aggregation is | ||
83 | // a histogram distribution. | ||
84 | // | ||
85 | // An distribution aggregation may contain a histogram of the values in the | ||
86 | // population. The bucket boundaries for that histogram are described | ||
87 | // by the bounds. This defines len(bounds)+1 buckets. | ||
88 | // | ||
89 | // If len(bounds) >= 2 then the boundaries for bucket index i are: | ||
90 | // | ||
91 | // [-infinity, bounds[i]) for i = 0 | ||
92 | // [bounds[i-1], bounds[i]) for 0 < i < length | ||
93 | // [bounds[i-1], +infinity) for i = length | ||
94 | // | ||
95 | // If len(bounds) is 0 then there is no histogram associated with the | ||
96 | // distribution. There will be a single bucket with boundaries | ||
97 | // (-infinity, +infinity). | ||
98 | // | ||
99 | // If len(bounds) is 1 then there is no finite buckets, and that single | ||
100 | // element is the common boundary of the overflow and underflow buckets. | ||
101 | func Distribution(bounds ...float64) *Aggregation { | ||
102 | return &Aggregation{ | ||
103 | Type: AggTypeDistribution, | ||
104 | Buckets: bounds, | ||
105 | newData: func() AggregationData { | ||
106 | return newDistributionData(bounds) | ||
107 | }, | ||
108 | } | ||
109 | } | ||
110 | |||
111 | // LastValue only reports the last value recorded using this | ||
112 | // aggregation. All other measurements will be dropped. | ||
113 | func LastValue() *Aggregation { | ||
114 | return &Aggregation{ | ||
115 | Type: AggTypeLastValue, | ||
116 | newData: func() AggregationData { | ||
117 | return &LastValueData{} | ||
118 | }, | ||
119 | } | ||
120 | } | ||
diff --git a/vendor/go.opencensus.io/stats/view/aggregation_data.go b/vendor/go.opencensus.io/stats/view/aggregation_data.go new file mode 100644 index 0000000..960b946 --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/aggregation_data.go | |||
@@ -0,0 +1,235 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package view | ||
17 | |||
18 | import ( | ||
19 | "math" | ||
20 | |||
21 | "go.opencensus.io/exemplar" | ||
22 | ) | ||
23 | |||
24 | // AggregationData represents an aggregated value from a collection. | ||
25 | // They are reported on the view data during exporting. | ||
26 | // Mosts users won't directly access aggregration data. | ||
27 | type AggregationData interface { | ||
28 | isAggregationData() bool | ||
29 | addSample(e *exemplar.Exemplar) | ||
30 | clone() AggregationData | ||
31 | equal(other AggregationData) bool | ||
32 | } | ||
33 | |||
34 | const epsilon = 1e-9 | ||
35 | |||
36 | // CountData is the aggregated data for the Count aggregation. | ||
37 | // A count aggregation processes data and counts the recordings. | ||
38 | // | ||
39 | // Most users won't directly access count data. | ||
40 | type CountData struct { | ||
41 | Value int64 | ||
42 | } | ||
43 | |||
44 | func (a *CountData) isAggregationData() bool { return true } | ||
45 | |||
46 | func (a *CountData) addSample(_ *exemplar.Exemplar) { | ||
47 | a.Value = a.Value + 1 | ||
48 | } | ||
49 | |||
50 | func (a *CountData) clone() AggregationData { | ||
51 | return &CountData{Value: a.Value} | ||
52 | } | ||
53 | |||
54 | func (a *CountData) equal(other AggregationData) bool { | ||
55 | a2, ok := other.(*CountData) | ||
56 | if !ok { | ||
57 | return false | ||
58 | } | ||
59 | |||
60 | return a.Value == a2.Value | ||
61 | } | ||
62 | |||
63 | // SumData is the aggregated data for the Sum aggregation. | ||
64 | // A sum aggregation processes data and sums up the recordings. | ||
65 | // | ||
66 | // Most users won't directly access sum data. | ||
67 | type SumData struct { | ||
68 | Value float64 | ||
69 | } | ||
70 | |||
71 | func (a *SumData) isAggregationData() bool { return true } | ||
72 | |||
73 | func (a *SumData) addSample(e *exemplar.Exemplar) { | ||
74 | a.Value += e.Value | ||
75 | } | ||
76 | |||
77 | func (a *SumData) clone() AggregationData { | ||
78 | return &SumData{Value: a.Value} | ||
79 | } | ||
80 | |||
81 | func (a *SumData) equal(other AggregationData) bool { | ||
82 | a2, ok := other.(*SumData) | ||
83 | if !ok { | ||
84 | return false | ||
85 | } | ||
86 | return math.Pow(a.Value-a2.Value, 2) < epsilon | ||
87 | } | ||
88 | |||
89 | // DistributionData is the aggregated data for the | ||
90 | // Distribution aggregation. | ||
91 | // | ||
92 | // Most users won't directly access distribution data. | ||
93 | // | ||
94 | // For a distribution with N bounds, the associated DistributionData will have | ||
95 | // N+1 buckets. | ||
96 | type DistributionData struct { | ||
97 | Count int64 // number of data points aggregated | ||
98 | Min float64 // minimum value in the distribution | ||
99 | Max float64 // max value in the distribution | ||
100 | Mean float64 // mean of the distribution | ||
101 | SumOfSquaredDev float64 // sum of the squared deviation from the mean | ||
102 | CountPerBucket []int64 // number of occurrences per bucket | ||
103 | // ExemplarsPerBucket is slice the same length as CountPerBucket containing | ||
104 | // an exemplar for the associated bucket, or nil. | ||
105 | ExemplarsPerBucket []*exemplar.Exemplar | ||
106 | bounds []float64 // histogram distribution of the values | ||
107 | } | ||
108 | |||
109 | func newDistributionData(bounds []float64) *DistributionData { | ||
110 | bucketCount := len(bounds) + 1 | ||
111 | return &DistributionData{ | ||
112 | CountPerBucket: make([]int64, bucketCount), | ||
113 | ExemplarsPerBucket: make([]*exemplar.Exemplar, bucketCount), | ||
114 | bounds: bounds, | ||
115 | Min: math.MaxFloat64, | ||
116 | Max: math.SmallestNonzeroFloat64, | ||
117 | } | ||
118 | } | ||
119 | |||
120 | // Sum returns the sum of all samples collected. | ||
121 | func (a *DistributionData) Sum() float64 { return a.Mean * float64(a.Count) } | ||
122 | |||
123 | func (a *DistributionData) variance() float64 { | ||
124 | if a.Count <= 1 { | ||
125 | return 0 | ||
126 | } | ||
127 | return a.SumOfSquaredDev / float64(a.Count-1) | ||
128 | } | ||
129 | |||
130 | func (a *DistributionData) isAggregationData() bool { return true } | ||
131 | |||
132 | func (a *DistributionData) addSample(e *exemplar.Exemplar) { | ||
133 | f := e.Value | ||
134 | if f < a.Min { | ||
135 | a.Min = f | ||
136 | } | ||
137 | if f > a.Max { | ||
138 | a.Max = f | ||
139 | } | ||
140 | a.Count++ | ||
141 | a.addToBucket(e) | ||
142 | |||
143 | if a.Count == 1 { | ||
144 | a.Mean = f | ||
145 | return | ||
146 | } | ||
147 | |||
148 | oldMean := a.Mean | ||
149 | a.Mean = a.Mean + (f-a.Mean)/float64(a.Count) | ||
150 | a.SumOfSquaredDev = a.SumOfSquaredDev + (f-oldMean)*(f-a.Mean) | ||
151 | } | ||
152 | |||
153 | func (a *DistributionData) addToBucket(e *exemplar.Exemplar) { | ||
154 | var count *int64 | ||
155 | var ex **exemplar.Exemplar | ||
156 | for i, b := range a.bounds { | ||
157 | if e.Value < b { | ||
158 | count = &a.CountPerBucket[i] | ||
159 | ex = &a.ExemplarsPerBucket[i] | ||
160 | break | ||
161 | } | ||
162 | } | ||
163 | if count == nil { | ||
164 | count = &a.CountPerBucket[len(a.bounds)] | ||
165 | ex = &a.ExemplarsPerBucket[len(a.bounds)] | ||
166 | } | ||
167 | *count++ | ||
168 | *ex = maybeRetainExemplar(*ex, e) | ||
169 | } | ||
170 | |||
171 | func maybeRetainExemplar(old, cur *exemplar.Exemplar) *exemplar.Exemplar { | ||
172 | if old == nil { | ||
173 | return cur | ||
174 | } | ||
175 | |||
176 | // Heuristic to pick the "better" exemplar: first keep the one with a | ||
177 | // sampled trace attachment, if neither have a trace attachment, pick the | ||
178 | // one with more attachments. | ||
179 | _, haveTraceID := cur.Attachments[exemplar.KeyTraceID] | ||
180 | if haveTraceID || len(cur.Attachments) >= len(old.Attachments) { | ||
181 | return cur | ||
182 | } | ||
183 | return old | ||
184 | } | ||
185 | |||
186 | func (a *DistributionData) clone() AggregationData { | ||
187 | c := *a | ||
188 | c.CountPerBucket = append([]int64(nil), a.CountPerBucket...) | ||
189 | c.ExemplarsPerBucket = append([]*exemplar.Exemplar(nil), a.ExemplarsPerBucket...) | ||
190 | return &c | ||
191 | } | ||
192 | |||
193 | func (a *DistributionData) equal(other AggregationData) bool { | ||
194 | a2, ok := other.(*DistributionData) | ||
195 | if !ok { | ||
196 | return false | ||
197 | } | ||
198 | if a2 == nil { | ||
199 | return false | ||
200 | } | ||
201 | if len(a.CountPerBucket) != len(a2.CountPerBucket) { | ||
202 | return false | ||
203 | } | ||
204 | for i := range a.CountPerBucket { | ||
205 | if a.CountPerBucket[i] != a2.CountPerBucket[i] { | ||
206 | return false | ||
207 | } | ||
208 | } | ||
209 | 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 | ||
210 | } | ||
211 | |||
212 | // LastValueData returns the last value recorded for LastValue aggregation. | ||
213 | type LastValueData struct { | ||
214 | Value float64 | ||
215 | } | ||
216 | |||
217 | func (l *LastValueData) isAggregationData() bool { | ||
218 | return true | ||
219 | } | ||
220 | |||
221 | func (l *LastValueData) addSample(e *exemplar.Exemplar) { | ||
222 | l.Value = e.Value | ||
223 | } | ||
224 | |||
225 | func (l *LastValueData) clone() AggregationData { | ||
226 | return &LastValueData{l.Value} | ||
227 | } | ||
228 | |||
229 | func (l *LastValueData) equal(other AggregationData) bool { | ||
230 | a2, ok := other.(*LastValueData) | ||
231 | if !ok { | ||
232 | return false | ||
233 | } | ||
234 | return l.Value == a2.Value | ||
235 | } | ||
diff --git a/vendor/go.opencensus.io/stats/view/collector.go b/vendor/go.opencensus.io/stats/view/collector.go new file mode 100644 index 0000000..32415d4 --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/collector.go | |||
@@ -0,0 +1,87 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package view | ||
17 | |||
18 | import ( | ||
19 | "sort" | ||
20 | |||
21 | "go.opencensus.io/exemplar" | ||
22 | |||
23 | "go.opencensus.io/internal/tagencoding" | ||
24 | "go.opencensus.io/tag" | ||
25 | ) | ||
26 | |||
27 | type collector struct { | ||
28 | // signatures holds the aggregations values for each unique tag signature | ||
29 | // (values for all keys) to its aggregator. | ||
30 | signatures map[string]AggregationData | ||
31 | // Aggregation is the description of the aggregation to perform for this | ||
32 | // view. | ||
33 | a *Aggregation | ||
34 | } | ||
35 | |||
36 | func (c *collector) addSample(s string, e *exemplar.Exemplar) { | ||
37 | aggregator, ok := c.signatures[s] | ||
38 | if !ok { | ||
39 | aggregator = c.a.newData() | ||
40 | c.signatures[s] = aggregator | ||
41 | } | ||
42 | aggregator.addSample(e) | ||
43 | } | ||
44 | |||
45 | // collectRows returns a snapshot of the collected Row values. | ||
46 | func (c *collector) collectedRows(keys []tag.Key) []*Row { | ||
47 | rows := make([]*Row, 0, len(c.signatures)) | ||
48 | for sig, aggregator := range c.signatures { | ||
49 | tags := decodeTags([]byte(sig), keys) | ||
50 | row := &Row{Tags: tags, Data: aggregator.clone()} | ||
51 | rows = append(rows, row) | ||
52 | } | ||
53 | return rows | ||
54 | } | ||
55 | |||
56 | func (c *collector) clearRows() { | ||
57 | c.signatures = make(map[string]AggregationData) | ||
58 | } | ||
59 | |||
60 | // encodeWithKeys encodes the map by using values | ||
61 | // only associated with the keys provided. | ||
62 | func encodeWithKeys(m *tag.Map, keys []tag.Key) []byte { | ||
63 | vb := &tagencoding.Values{ | ||
64 | Buffer: make([]byte, len(keys)), | ||
65 | } | ||
66 | for _, k := range keys { | ||
67 | v, _ := m.Value(k) | ||
68 | vb.WriteValue([]byte(v)) | ||
69 | } | ||
70 | return vb.Bytes() | ||
71 | } | ||
72 | |||
73 | // decodeTags decodes tags from the buffer and | ||
74 | // orders them by the keys. | ||
75 | func decodeTags(buf []byte, keys []tag.Key) []tag.Tag { | ||
76 | vb := &tagencoding.Values{Buffer: buf} | ||
77 | var tags []tag.Tag | ||
78 | for _, k := range keys { | ||
79 | v := vb.ReadValue() | ||
80 | if v != nil { | ||
81 | tags = append(tags, tag.Tag{Key: k, Value: string(v)}) | ||
82 | } | ||
83 | } | ||
84 | vb.ReadIndex = 0 | ||
85 | sort.Slice(tags, func(i, j int) bool { return tags[i].Key.Name() < tags[j].Key.Name() }) | ||
86 | return tags | ||
87 | } | ||
diff --git a/vendor/go.opencensus.io/stats/view/doc.go b/vendor/go.opencensus.io/stats/view/doc.go new file mode 100644 index 0000000..dced225 --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/doc.go | |||
@@ -0,0 +1,47 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | // Package view contains support for collecting and exposing aggregates over stats. | ||
17 | // | ||
18 | // In order to collect measurements, views need to be defined and registered. | ||
19 | // A view allows recorded measurements to be filtered and aggregated. | ||
20 | // | ||
21 | // All recorded measurements can be grouped by a list of tags. | ||
22 | // | ||
23 | // OpenCensus provides several aggregation methods: Count, Distribution and Sum. | ||
24 | // | ||
25 | // Count only counts the number of measurement points recorded. | ||
26 | // Distribution provides statistical summary of the aggregated data by counting | ||
27 | // how many recorded measurements fall into each bucket. | ||
28 | // Sum adds up the measurement values. | ||
29 | // LastValue just keeps track of the most recently recorded measurement value. | ||
30 | // All aggregations are cumulative. | ||
31 | // | ||
32 | // Views can be registerd and unregistered at any time during program execution. | ||
33 | // | ||
34 | // Libraries can define views but it is recommended that in most cases registering | ||
35 | // views be left up to applications. | ||
36 | // | ||
37 | // Exporting | ||
38 | // | ||
39 | // Collected and aggregated data can be exported to a metric collection | ||
40 | // backend by registering its exporter. | ||
41 | // | ||
42 | // Multiple exporters can be registered to upload the data to various | ||
43 | // different back ends. | ||
44 | package view // import "go.opencensus.io/stats/view" | ||
45 | |||
46 | // TODO(acetechnologist): Add a link to the language independent OpenCensus | ||
47 | // spec when it is available. | ||
diff --git a/vendor/go.opencensus.io/stats/view/export.go b/vendor/go.opencensus.io/stats/view/export.go new file mode 100644 index 0000000..7cb5971 --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/export.go | |||
@@ -0,0 +1,58 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package view | ||
16 | |||
17 | import "sync" | ||
18 | |||
19 | var ( | ||
20 | exportersMu sync.RWMutex // guards exporters | ||
21 | exporters = make(map[Exporter]struct{}) | ||
22 | ) | ||
23 | |||
24 | // Exporter exports the collected records as view data. | ||
25 | // | ||
26 | // The ExportView method should return quickly; if an | ||
27 | // Exporter takes a significant amount of time to | ||
28 | // process a Data, that work should be done on another goroutine. | ||
29 | // | ||
30 | // It is safe to assume that ExportView will not be called concurrently from | ||
31 | // multiple goroutines. | ||
32 | // | ||
33 | // The Data should not be modified. | ||
34 | type Exporter interface { | ||
35 | ExportView(viewData *Data) | ||
36 | } | ||
37 | |||
38 | // RegisterExporter registers an exporter. | ||
39 | // Collected data will be reported via all the | ||
40 | // registered exporters. Once you no longer | ||
41 | // want data to be exported, invoke UnregisterExporter | ||
42 | // with the previously registered exporter. | ||
43 | // | ||
44 | // Binaries can register exporters, libraries shouldn't register exporters. | ||
45 | func RegisterExporter(e Exporter) { | ||
46 | exportersMu.Lock() | ||
47 | defer exportersMu.Unlock() | ||
48 | |||
49 | exporters[e] = struct{}{} | ||
50 | } | ||
51 | |||
52 | // UnregisterExporter unregisters an exporter. | ||
53 | func UnregisterExporter(e Exporter) { | ||
54 | exportersMu.Lock() | ||
55 | defer exportersMu.Unlock() | ||
56 | |||
57 | delete(exporters, e) | ||
58 | } | ||
diff --git a/vendor/go.opencensus.io/stats/view/view.go b/vendor/go.opencensus.io/stats/view/view.go new file mode 100644 index 0000000..c2a08af --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/view.go | |||
@@ -0,0 +1,185 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package view | ||
17 | |||
18 | import ( | ||
19 | "bytes" | ||
20 | "fmt" | ||
21 | "reflect" | ||
22 | "sort" | ||
23 | "sync/atomic" | ||
24 | "time" | ||
25 | |||
26 | "go.opencensus.io/exemplar" | ||
27 | |||
28 | "go.opencensus.io/stats" | ||
29 | "go.opencensus.io/stats/internal" | ||
30 | "go.opencensus.io/tag" | ||
31 | ) | ||
32 | |||
33 | // View allows users to aggregate the recorded stats.Measurements. | ||
34 | // Views need to be passed to the Register function to be before data will be | ||
35 | // collected and sent to Exporters. | ||
36 | type View struct { | ||
37 | Name string // Name of View. Must be unique. If unset, will default to the name of the Measure. | ||
38 | Description string // Description is a human-readable description for this view. | ||
39 | |||
40 | // TagKeys are the tag keys describing the grouping of this view. | ||
41 | // A single Row will be produced for each combination of associated tag values. | ||
42 | TagKeys []tag.Key | ||
43 | |||
44 | // Measure is a stats.Measure to aggregate in this view. | ||
45 | Measure stats.Measure | ||
46 | |||
47 | // Aggregation is the aggregation function tp apply to the set of Measurements. | ||
48 | Aggregation *Aggregation | ||
49 | } | ||
50 | |||
51 | // WithName returns a copy of the View with a new name. This is useful for | ||
52 | // renaming views to cope with limitations placed on metric names by various | ||
53 | // backends. | ||
54 | func (v *View) WithName(name string) *View { | ||
55 | vNew := *v | ||
56 | vNew.Name = name | ||
57 | return &vNew | ||
58 | } | ||
59 | |||
60 | // same compares two views and returns true if they represent the same aggregation. | ||
61 | func (v *View) same(other *View) bool { | ||
62 | if v == other { | ||
63 | return true | ||
64 | } | ||
65 | if v == nil { | ||
66 | return false | ||
67 | } | ||
68 | return reflect.DeepEqual(v.Aggregation, other.Aggregation) && | ||
69 | v.Measure.Name() == other.Measure.Name() | ||
70 | } | ||
71 | |||
72 | // canonicalize canonicalizes v by setting explicit | ||
73 | // defaults for Name and Description and sorting the TagKeys | ||
74 | func (v *View) canonicalize() error { | ||
75 | if v.Measure == nil { | ||
76 | return fmt.Errorf("cannot register view %q: measure not set", v.Name) | ||
77 | } | ||
78 | if v.Aggregation == nil { | ||
79 | return fmt.Errorf("cannot register view %q: aggregation not set", v.Name) | ||
80 | } | ||
81 | if v.Name == "" { | ||
82 | v.Name = v.Measure.Name() | ||
83 | } | ||
84 | if v.Description == "" { | ||
85 | v.Description = v.Measure.Description() | ||
86 | } | ||
87 | if err := checkViewName(v.Name); err != nil { | ||
88 | return err | ||
89 | } | ||
90 | sort.Slice(v.TagKeys, func(i, j int) bool { | ||
91 | return v.TagKeys[i].Name() < v.TagKeys[j].Name() | ||
92 | }) | ||
93 | return nil | ||
94 | } | ||
95 | |||
96 | // viewInternal is the internal representation of a View. | ||
97 | type viewInternal struct { | ||
98 | view *View // view is the canonicalized View definition associated with this view. | ||
99 | subscribed uint32 // 1 if someone is subscribed and data need to be exported, use atomic to access | ||
100 | collector *collector | ||
101 | } | ||
102 | |||
103 | func newViewInternal(v *View) (*viewInternal, error) { | ||
104 | return &viewInternal{ | ||
105 | view: v, | ||
106 | collector: &collector{make(map[string]AggregationData), v.Aggregation}, | ||
107 | }, nil | ||
108 | } | ||
109 | |||
110 | func (v *viewInternal) subscribe() { | ||
111 | atomic.StoreUint32(&v.subscribed, 1) | ||
112 | } | ||
113 | |||
114 | func (v *viewInternal) unsubscribe() { | ||
115 | atomic.StoreUint32(&v.subscribed, 0) | ||
116 | } | ||
117 | |||
118 | // isSubscribed returns true if the view is exporting | ||
119 | // data by subscription. | ||
120 | func (v *viewInternal) isSubscribed() bool { | ||
121 | return atomic.LoadUint32(&v.subscribed) == 1 | ||
122 | } | ||
123 | |||
124 | func (v *viewInternal) clearRows() { | ||
125 | v.collector.clearRows() | ||
126 | } | ||
127 | |||
128 | func (v *viewInternal) collectedRows() []*Row { | ||
129 | return v.collector.collectedRows(v.view.TagKeys) | ||
130 | } | ||
131 | |||
132 | func (v *viewInternal) addSample(m *tag.Map, e *exemplar.Exemplar) { | ||
133 | if !v.isSubscribed() { | ||
134 | return | ||
135 | } | ||
136 | sig := string(encodeWithKeys(m, v.view.TagKeys)) | ||
137 | v.collector.addSample(sig, e) | ||
138 | } | ||
139 | |||
140 | // A Data is a set of rows about usage of the single measure associated | ||
141 | // with the given view. Each row is specific to a unique set of tags. | ||
142 | type Data struct { | ||
143 | View *View | ||
144 | Start, End time.Time | ||
145 | Rows []*Row | ||
146 | } | ||
147 | |||
148 | // Row is the collected value for a specific set of key value pairs a.k.a tags. | ||
149 | type Row struct { | ||
150 | Tags []tag.Tag | ||
151 | Data AggregationData | ||
152 | } | ||
153 | |||
154 | func (r *Row) String() string { | ||
155 | var buffer bytes.Buffer | ||
156 | buffer.WriteString("{ ") | ||
157 | buffer.WriteString("{ ") | ||
158 | for _, t := range r.Tags { | ||
159 | buffer.WriteString(fmt.Sprintf("{%v %v}", t.Key.Name(), t.Value)) | ||
160 | } | ||
161 | buffer.WriteString(" }") | ||
162 | buffer.WriteString(fmt.Sprintf("%v", r.Data)) | ||
163 | buffer.WriteString(" }") | ||
164 | return buffer.String() | ||
165 | } | ||
166 | |||
167 | // Equal returns true if both rows are equal. Tags are expected to be ordered | ||
168 | // by the key name. Even both rows have the same tags but the tags appear in | ||
169 | // different orders it will return false. | ||
170 | func (r *Row) Equal(other *Row) bool { | ||
171 | if r == other { | ||
172 | return true | ||
173 | } | ||
174 | return reflect.DeepEqual(r.Tags, other.Tags) && r.Data.equal(other.Data) | ||
175 | } | ||
176 | |||
177 | func checkViewName(name string) error { | ||
178 | if len(name) > internal.MaxNameLength { | ||
179 | return fmt.Errorf("view name cannot be larger than %v", internal.MaxNameLength) | ||
180 | } | ||
181 | if !internal.IsPrintable(name) { | ||
182 | return fmt.Errorf("view name needs to be an ASCII string") | ||
183 | } | ||
184 | return nil | ||
185 | } | ||
diff --git a/vendor/go.opencensus.io/stats/view/worker.go b/vendor/go.opencensus.io/stats/view/worker.go new file mode 100644 index 0000000..63b0ee3 --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/worker.go | |||
@@ -0,0 +1,229 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package view | ||
17 | |||
18 | import ( | ||
19 | "fmt" | ||
20 | "time" | ||
21 | |||
22 | "go.opencensus.io/stats" | ||
23 | "go.opencensus.io/stats/internal" | ||
24 | "go.opencensus.io/tag" | ||
25 | ) | ||
26 | |||
27 | func init() { | ||
28 | defaultWorker = newWorker() | ||
29 | go defaultWorker.start() | ||
30 | internal.DefaultRecorder = record | ||
31 | } | ||
32 | |||
33 | type measureRef struct { | ||
34 | measure string | ||
35 | views map[*viewInternal]struct{} | ||
36 | } | ||
37 | |||
38 | type worker struct { | ||
39 | measures map[string]*measureRef | ||
40 | views map[string]*viewInternal | ||
41 | startTimes map[*viewInternal]time.Time | ||
42 | |||
43 | timer *time.Ticker | ||
44 | c chan command | ||
45 | quit, done chan bool | ||
46 | } | ||
47 | |||
48 | var defaultWorker *worker | ||
49 | |||
50 | var defaultReportingDuration = 10 * time.Second | ||
51 | |||
52 | // Find returns a registered view associated with this name. | ||
53 | // If no registered view is found, nil is returned. | ||
54 | func Find(name string) (v *View) { | ||
55 | req := &getViewByNameReq{ | ||
56 | name: name, | ||
57 | c: make(chan *getViewByNameResp), | ||
58 | } | ||
59 | defaultWorker.c <- req | ||
60 | resp := <-req.c | ||
61 | return resp.v | ||
62 | } | ||
63 | |||
64 | // Register begins collecting data for the given views. | ||
65 | // Once a view is registered, it reports data to the registered exporters. | ||
66 | func Register(views ...*View) error { | ||
67 | for _, v := range views { | ||
68 | if err := v.canonicalize(); err != nil { | ||
69 | return err | ||
70 | } | ||
71 | } | ||
72 | req := ®isterViewReq{ | ||
73 | views: views, | ||
74 | err: make(chan error), | ||
75 | } | ||
76 | defaultWorker.c <- req | ||
77 | return <-req.err | ||
78 | } | ||
79 | |||
80 | // Unregister the given views. Data will not longer be exported for these views | ||
81 | // after Unregister returns. | ||
82 | // It is not necessary to unregister from views you expect to collect for the | ||
83 | // duration of your program execution. | ||
84 | func Unregister(views ...*View) { | ||
85 | names := make([]string, len(views)) | ||
86 | for i := range views { | ||
87 | names[i] = views[i].Name | ||
88 | } | ||
89 | req := &unregisterFromViewReq{ | ||
90 | views: names, | ||
91 | done: make(chan struct{}), | ||
92 | } | ||
93 | defaultWorker.c <- req | ||
94 | <-req.done | ||
95 | } | ||
96 | |||
97 | // RetrieveData gets a snapshot of the data collected for the the view registered | ||
98 | // with the given name. It is intended for testing only. | ||
99 | func RetrieveData(viewName string) ([]*Row, error) { | ||
100 | req := &retrieveDataReq{ | ||
101 | now: time.Now(), | ||
102 | v: viewName, | ||
103 | c: make(chan *retrieveDataResp), | ||
104 | } | ||
105 | defaultWorker.c <- req | ||
106 | resp := <-req.c | ||
107 | return resp.rows, resp.err | ||
108 | } | ||
109 | |||
110 | func record(tags *tag.Map, ms interface{}, attachments map[string]string) { | ||
111 | req := &recordReq{ | ||
112 | tm: tags, | ||
113 | ms: ms.([]stats.Measurement), | ||
114 | attachments: attachments, | ||
115 | t: time.Now(), | ||
116 | } | ||
117 | defaultWorker.c <- req | ||
118 | } | ||
119 | |||
120 | // SetReportingPeriod sets the interval between reporting aggregated views in | ||
121 | // the program. If duration is less than or equal to zero, it enables the | ||
122 | // default behavior. | ||
123 | // | ||
124 | // Note: each exporter makes different promises about what the lowest supported | ||
125 | // duration is. For example, the Stackdriver exporter recommends a value no | ||
126 | // lower than 1 minute. Consult each exporter per your needs. | ||
127 | func SetReportingPeriod(d time.Duration) { | ||
128 | // TODO(acetechnologist): ensure that the duration d is more than a certain | ||
129 | // value. e.g. 1s | ||
130 | req := &setReportingPeriodReq{ | ||
131 | d: d, | ||
132 | c: make(chan bool), | ||
133 | } | ||
134 | defaultWorker.c <- req | ||
135 | <-req.c // don't return until the timer is set to the new duration. | ||
136 | } | ||
137 | |||
138 | func newWorker() *worker { | ||
139 | return &worker{ | ||
140 | measures: make(map[string]*measureRef), | ||
141 | views: make(map[string]*viewInternal), | ||
142 | startTimes: make(map[*viewInternal]time.Time), | ||
143 | timer: time.NewTicker(defaultReportingDuration), | ||
144 | c: make(chan command, 1024), | ||
145 | quit: make(chan bool), | ||
146 | done: make(chan bool), | ||
147 | } | ||
148 | } | ||
149 | |||
150 | func (w *worker) start() { | ||
151 | for { | ||
152 | select { | ||
153 | case cmd := <-w.c: | ||
154 | cmd.handleCommand(w) | ||
155 | case <-w.timer.C: | ||
156 | w.reportUsage(time.Now()) | ||
157 | case <-w.quit: | ||
158 | w.timer.Stop() | ||
159 | close(w.c) | ||
160 | w.done <- true | ||
161 | return | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | func (w *worker) stop() { | ||
167 | w.quit <- true | ||
168 | <-w.done | ||
169 | } | ||
170 | |||
171 | func (w *worker) getMeasureRef(name string) *measureRef { | ||
172 | if mr, ok := w.measures[name]; ok { | ||
173 | return mr | ||
174 | } | ||
175 | mr := &measureRef{ | ||
176 | measure: name, | ||
177 | views: make(map[*viewInternal]struct{}), | ||
178 | } | ||
179 | w.measures[name] = mr | ||
180 | return mr | ||
181 | } | ||
182 | |||
183 | func (w *worker) tryRegisterView(v *View) (*viewInternal, error) { | ||
184 | vi, err := newViewInternal(v) | ||
185 | if err != nil { | ||
186 | return nil, err | ||
187 | } | ||
188 | if x, ok := w.views[vi.view.Name]; ok { | ||
189 | if !x.view.same(vi.view) { | ||
190 | return nil, fmt.Errorf("cannot register view %q; a different view with the same name is already registered", v.Name) | ||
191 | } | ||
192 | |||
193 | // the view is already registered so there is nothing to do and the | ||
194 | // command is considered successful. | ||
195 | return x, nil | ||
196 | } | ||
197 | w.views[vi.view.Name] = vi | ||
198 | ref := w.getMeasureRef(vi.view.Measure.Name()) | ||
199 | ref.views[vi] = struct{}{} | ||
200 | return vi, nil | ||
201 | } | ||
202 | |||
203 | func (w *worker) reportView(v *viewInternal, now time.Time) { | ||
204 | if !v.isSubscribed() { | ||
205 | return | ||
206 | } | ||
207 | rows := v.collectedRows() | ||
208 | _, ok := w.startTimes[v] | ||
209 | if !ok { | ||
210 | w.startTimes[v] = now | ||
211 | } | ||
212 | viewData := &Data{ | ||
213 | View: v.view, | ||
214 | Start: w.startTimes[v], | ||
215 | End: time.Now(), | ||
216 | Rows: rows, | ||
217 | } | ||
218 | exportersMu.Lock() | ||
219 | for e := range exporters { | ||
220 | e.ExportView(viewData) | ||
221 | } | ||
222 | exportersMu.Unlock() | ||
223 | } | ||
224 | |||
225 | func (w *worker) reportUsage(now time.Time) { | ||
226 | for _, v := range w.views { | ||
227 | w.reportView(v, now) | ||
228 | } | ||
229 | } | ||
diff --git a/vendor/go.opencensus.io/stats/view/worker_commands.go b/vendor/go.opencensus.io/stats/view/worker_commands.go new file mode 100644 index 0000000..b38f26f --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/worker_commands.go | |||
@@ -0,0 +1,183 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package view | ||
17 | |||
18 | import ( | ||
19 | "errors" | ||
20 | "fmt" | ||
21 | "strings" | ||
22 | "time" | ||
23 | |||
24 | "go.opencensus.io/exemplar" | ||
25 | |||
26 | "go.opencensus.io/stats" | ||
27 | "go.opencensus.io/stats/internal" | ||
28 | "go.opencensus.io/tag" | ||
29 | ) | ||
30 | |||
31 | type command interface { | ||
32 | handleCommand(w *worker) | ||
33 | } | ||
34 | |||
35 | // getViewByNameReq is the command to get a view given its name. | ||
36 | type getViewByNameReq struct { | ||
37 | name string | ||
38 | c chan *getViewByNameResp | ||
39 | } | ||
40 | |||
41 | type getViewByNameResp struct { | ||
42 | v *View | ||
43 | } | ||
44 | |||
45 | func (cmd *getViewByNameReq) handleCommand(w *worker) { | ||
46 | v := w.views[cmd.name] | ||
47 | if v == nil { | ||
48 | cmd.c <- &getViewByNameResp{nil} | ||
49 | return | ||
50 | } | ||
51 | cmd.c <- &getViewByNameResp{v.view} | ||
52 | } | ||
53 | |||
54 | // registerViewReq is the command to register a view. | ||
55 | type registerViewReq struct { | ||
56 | views []*View | ||
57 | err chan error | ||
58 | } | ||
59 | |||
60 | func (cmd *registerViewReq) handleCommand(w *worker) { | ||
61 | var errstr []string | ||
62 | for _, view := range cmd.views { | ||
63 | vi, err := w.tryRegisterView(view) | ||
64 | if err != nil { | ||
65 | errstr = append(errstr, fmt.Sprintf("%s: %v", view.Name, err)) | ||
66 | continue | ||
67 | } | ||
68 | internal.SubscriptionReporter(view.Measure.Name()) | ||
69 | vi.subscribe() | ||
70 | } | ||
71 | if len(errstr) > 0 { | ||
72 | cmd.err <- errors.New(strings.Join(errstr, "\n")) | ||
73 | } else { | ||
74 | cmd.err <- nil | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // unregisterFromViewReq is the command to unregister to a view. Has no | ||
79 | // impact on the data collection for client that are pulling data from the | ||
80 | // library. | ||
81 | type unregisterFromViewReq struct { | ||
82 | views []string | ||
83 | done chan struct{} | ||
84 | } | ||
85 | |||
86 | func (cmd *unregisterFromViewReq) handleCommand(w *worker) { | ||
87 | for _, name := range cmd.views { | ||
88 | vi, ok := w.views[name] | ||
89 | if !ok { | ||
90 | continue | ||
91 | } | ||
92 | |||
93 | // Report pending data for this view before removing it. | ||
94 | w.reportView(vi, time.Now()) | ||
95 | |||
96 | vi.unsubscribe() | ||
97 | if !vi.isSubscribed() { | ||
98 | // this was the last subscription and view is not collecting anymore. | ||
99 | // The collected data can be cleared. | ||
100 | vi.clearRows() | ||
101 | } | ||
102 | delete(w.views, name) | ||
103 | } | ||
104 | cmd.done <- struct{}{} | ||
105 | } | ||
106 | |||
107 | // retrieveDataReq is the command to retrieve data for a view. | ||
108 | type retrieveDataReq struct { | ||
109 | now time.Time | ||
110 | v string | ||
111 | c chan *retrieveDataResp | ||
112 | } | ||
113 | |||
114 | type retrieveDataResp struct { | ||
115 | rows []*Row | ||
116 | err error | ||
117 | } | ||
118 | |||
119 | func (cmd *retrieveDataReq) handleCommand(w *worker) { | ||
120 | vi, ok := w.views[cmd.v] | ||
121 | if !ok { | ||
122 | cmd.c <- &retrieveDataResp{ | ||
123 | nil, | ||
124 | fmt.Errorf("cannot retrieve data; view %q is not registered", cmd.v), | ||
125 | } | ||
126 | return | ||
127 | } | ||
128 | |||
129 | if !vi.isSubscribed() { | ||
130 | cmd.c <- &retrieveDataResp{ | ||
131 | nil, | ||
132 | fmt.Errorf("cannot retrieve data; view %q has no subscriptions or collection is not forcibly started", cmd.v), | ||
133 | } | ||
134 | return | ||
135 | } | ||
136 | cmd.c <- &retrieveDataResp{ | ||
137 | vi.collectedRows(), | ||
138 | nil, | ||
139 | } | ||
140 | } | ||
141 | |||
142 | // recordReq is the command to record data related to multiple measures | ||
143 | // at once. | ||
144 | type recordReq struct { | ||
145 | tm *tag.Map | ||
146 | ms []stats.Measurement | ||
147 | attachments map[string]string | ||
148 | t time.Time | ||
149 | } | ||
150 | |||
151 | func (cmd *recordReq) handleCommand(w *worker) { | ||
152 | for _, m := range cmd.ms { | ||
153 | if (m == stats.Measurement{}) { // not registered | ||
154 | continue | ||
155 | } | ||
156 | ref := w.getMeasureRef(m.Measure().Name()) | ||
157 | for v := range ref.views { | ||
158 | e := &exemplar.Exemplar{ | ||
159 | Value: m.Value(), | ||
160 | Timestamp: cmd.t, | ||
161 | Attachments: cmd.attachments, | ||
162 | } | ||
163 | v.addSample(cmd.tm, e) | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | // setReportingPeriodReq is the command to modify the duration between | ||
169 | // reporting the collected data to the registered clients. | ||
170 | type setReportingPeriodReq struct { | ||
171 | d time.Duration | ||
172 | c chan bool | ||
173 | } | ||
174 | |||
175 | func (cmd *setReportingPeriodReq) handleCommand(w *worker) { | ||
176 | w.timer.Stop() | ||
177 | if cmd.d <= 0 { | ||
178 | w.timer = time.NewTicker(defaultReportingDuration) | ||
179 | } else { | ||
180 | w.timer = time.NewTicker(cmd.d) | ||
181 | } | ||
182 | cmd.c <- true | ||
183 | } | ||
diff --git a/vendor/go.opencensus.io/tag/context.go b/vendor/go.opencensus.io/tag/context.go new file mode 100644 index 0000000..dcc13f4 --- /dev/null +++ b/vendor/go.opencensus.io/tag/context.go | |||
@@ -0,0 +1,67 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package tag | ||
17 | |||
18 | import ( | ||
19 | "context" | ||
20 | |||
21 | "go.opencensus.io/exemplar" | ||
22 | ) | ||
23 | |||
24 | // FromContext returns the tag map stored in the context. | ||
25 | func FromContext(ctx context.Context) *Map { | ||
26 | // The returned tag map shouldn't be mutated. | ||
27 | ts := ctx.Value(mapCtxKey) | ||
28 | if ts == nil { | ||
29 | return nil | ||
30 | } | ||
31 | return ts.(*Map) | ||
32 | } | ||
33 | |||
34 | // NewContext creates a new context with the given tag map. | ||
35 | // To propagate a tag map to downstream methods and downstream RPCs, add a tag map | ||
36 | // to the current context. NewContext will return a copy of the current context, | ||
37 | // and put the tag map into the returned one. | ||
38 | // If there is already a tag map in the current context, it will be replaced with m. | ||
39 | func NewContext(ctx context.Context, m *Map) context.Context { | ||
40 | return context.WithValue(ctx, mapCtxKey, m) | ||
41 | } | ||
42 | |||
43 | type ctxKey struct{} | ||
44 | |||
45 | var mapCtxKey = ctxKey{} | ||
46 | |||
47 | func init() { | ||
48 | exemplar.RegisterAttachmentExtractor(extractTagsAttachments) | ||
49 | } | ||
50 | |||
51 | func extractTagsAttachments(ctx context.Context, a exemplar.Attachments) exemplar.Attachments { | ||
52 | m := FromContext(ctx) | ||
53 | if m == nil { | ||
54 | return a | ||
55 | } | ||
56 | if len(m.m) == 0 { | ||
57 | return a | ||
58 | } | ||
59 | if a == nil { | ||
60 | a = make(map[string]string) | ||
61 | } | ||
62 | |||
63 | for k, v := range m.m { | ||
64 | a[exemplar.KeyPrefixTag+k.Name()] = v | ||
65 | } | ||
66 | return a | ||
67 | } | ||
diff --git a/vendor/go.opencensus.io/tag/doc.go b/vendor/go.opencensus.io/tag/doc.go new file mode 100644 index 0000000..da16b74 --- /dev/null +++ b/vendor/go.opencensus.io/tag/doc.go | |||
@@ -0,0 +1,26 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | /* | ||
17 | Package tag contains OpenCensus tags. | ||
18 | |||
19 | Tags are key-value pairs. Tags provide additional cardinality to | ||
20 | the OpenCensus instrumentation data. | ||
21 | |||
22 | Tags can be propagated on the wire and in the same | ||
23 | process via context.Context. Encode and Decode should be | ||
24 | used to represent tags into their binary propagation form. | ||
25 | */ | ||
26 | package tag // import "go.opencensus.io/tag" | ||
diff --git a/vendor/go.opencensus.io/tag/key.go b/vendor/go.opencensus.io/tag/key.go new file mode 100644 index 0000000..ebbed95 --- /dev/null +++ b/vendor/go.opencensus.io/tag/key.go | |||
@@ -0,0 +1,35 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package tag | ||
17 | |||
18 | // Key represents a tag key. | ||
19 | type Key struct { | ||
20 | name string | ||
21 | } | ||
22 | |||
23 | // NewKey creates or retrieves a string key identified by name. | ||
24 | // Calling NewKey consequently with the same name returns the same key. | ||
25 | func NewKey(name string) (Key, error) { | ||
26 | if !checkKeyName(name) { | ||
27 | return Key{}, errInvalidKeyName | ||
28 | } | ||
29 | return Key{name: name}, nil | ||
30 | } | ||
31 | |||
32 | // Name returns the name of the key. | ||
33 | func (k Key) Name() string { | ||
34 | return k.name | ||
35 | } | ||
diff --git a/vendor/go.opencensus.io/tag/map.go b/vendor/go.opencensus.io/tag/map.go new file mode 100644 index 0000000..5b72ba6 --- /dev/null +++ b/vendor/go.opencensus.io/tag/map.go | |||
@@ -0,0 +1,197 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package tag | ||
17 | |||
18 | import ( | ||
19 | "bytes" | ||
20 | "context" | ||
21 | "fmt" | ||
22 | "sort" | ||
23 | ) | ||
24 | |||
25 | // Tag is a key value pair that can be propagated on wire. | ||
26 | type Tag struct { | ||
27 | Key Key | ||
28 | Value string | ||
29 | } | ||
30 | |||
31 | // Map is a map of tags. Use New to create a context containing | ||
32 | // a new Map. | ||
33 | type Map struct { | ||
34 | m map[Key]string | ||
35 | } | ||
36 | |||
37 | // Value returns the value for the key if a value for the key exists. | ||
38 | func (m *Map) Value(k Key) (string, bool) { | ||
39 | if m == nil { | ||
40 | return "", false | ||
41 | } | ||
42 | v, ok := m.m[k] | ||
43 | return v, ok | ||
44 | } | ||
45 | |||
46 | func (m *Map) String() string { | ||
47 | if m == nil { | ||
48 | return "nil" | ||
49 | } | ||
50 | keys := make([]Key, 0, len(m.m)) | ||
51 | for k := range m.m { | ||
52 | keys = append(keys, k) | ||
53 | } | ||
54 | sort.Slice(keys, func(i, j int) bool { return keys[i].Name() < keys[j].Name() }) | ||
55 | |||
56 | var buffer bytes.Buffer | ||
57 | buffer.WriteString("{ ") | ||
58 | for _, k := range keys { | ||
59 | buffer.WriteString(fmt.Sprintf("{%v %v}", k.name, m.m[k])) | ||
60 | } | ||
61 | buffer.WriteString(" }") | ||
62 | return buffer.String() | ||
63 | } | ||
64 | |||
65 | func (m *Map) insert(k Key, v string) { | ||
66 | if _, ok := m.m[k]; ok { | ||
67 | return | ||
68 | } | ||
69 | m.m[k] = v | ||
70 | } | ||
71 | |||
72 | func (m *Map) update(k Key, v string) { | ||
73 | if _, ok := m.m[k]; ok { | ||
74 | m.m[k] = v | ||
75 | } | ||
76 | } | ||
77 | |||
78 | func (m *Map) upsert(k Key, v string) { | ||
79 | m.m[k] = v | ||
80 | } | ||
81 | |||
82 | func (m *Map) delete(k Key) { | ||
83 | delete(m.m, k) | ||
84 | } | ||
85 | |||
86 | func newMap() *Map { | ||
87 | return &Map{m: make(map[Key]string)} | ||
88 | } | ||
89 | |||
90 | // Mutator modifies a tag map. | ||
91 | type Mutator interface { | ||
92 | Mutate(t *Map) (*Map, error) | ||
93 | } | ||
94 | |||
95 | // Insert returns a mutator that inserts a | ||
96 | // value associated with k. If k already exists in the tag map, | ||
97 | // mutator doesn't update the value. | ||
98 | func Insert(k Key, v string) Mutator { | ||
99 | return &mutator{ | ||
100 | fn: func(m *Map) (*Map, error) { | ||
101 | if !checkValue(v) { | ||
102 | return nil, errInvalidValue | ||
103 | } | ||
104 | m.insert(k, v) | ||
105 | return m, nil | ||
106 | }, | ||
107 | } | ||
108 | } | ||
109 | |||
110 | // Update returns a mutator that updates the | ||
111 | // value of the tag associated with k with v. If k doesn't | ||
112 | // exists in the tag map, the mutator doesn't insert the value. | ||
113 | func Update(k Key, v string) Mutator { | ||
114 | return &mutator{ | ||
115 | fn: func(m *Map) (*Map, error) { | ||
116 | if !checkValue(v) { | ||
117 | return nil, errInvalidValue | ||
118 | } | ||
119 | m.update(k, v) | ||
120 | return m, nil | ||
121 | }, | ||
122 | } | ||
123 | } | ||
124 | |||
125 | // Upsert returns a mutator that upserts the | ||
126 | // value of the tag associated with k with v. It inserts the | ||
127 | // value if k doesn't exist already. It mutates the value | ||
128 | // if k already exists. | ||
129 | func Upsert(k Key, v string) Mutator { | ||
130 | return &mutator{ | ||
131 | fn: func(m *Map) (*Map, error) { | ||
132 | if !checkValue(v) { | ||
133 | return nil, errInvalidValue | ||
134 | } | ||
135 | m.upsert(k, v) | ||
136 | return m, nil | ||
137 | }, | ||
138 | } | ||
139 | } | ||
140 | |||
141 | // Delete returns a mutator that deletes | ||
142 | // the value associated with k. | ||
143 | func Delete(k Key) Mutator { | ||
144 | return &mutator{ | ||
145 | fn: func(m *Map) (*Map, error) { | ||
146 | m.delete(k) | ||
147 | return m, nil | ||
148 | }, | ||
149 | } | ||
150 | } | ||
151 | |||
152 | // New returns a new context that contains a tag map | ||
153 | // originated from the incoming context and modified | ||
154 | // with the provided mutators. | ||
155 | func New(ctx context.Context, mutator ...Mutator) (context.Context, error) { | ||
156 | m := newMap() | ||
157 | orig := FromContext(ctx) | ||
158 | if orig != nil { | ||
159 | for k, v := range orig.m { | ||
160 | if !checkKeyName(k.Name()) { | ||
161 | return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName) | ||
162 | } | ||
163 | if !checkValue(v) { | ||
164 | return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue) | ||
165 | } | ||
166 | m.insert(k, v) | ||
167 | } | ||
168 | } | ||
169 | var err error | ||
170 | for _, mod := range mutator { | ||
171 | m, err = mod.Mutate(m) | ||
172 | if err != nil { | ||
173 | return ctx, err | ||
174 | } | ||
175 | } | ||
176 | return NewContext(ctx, m), nil | ||
177 | } | ||
178 | |||
179 | // Do is similar to pprof.Do: a convenience for installing the tags | ||
180 | // from the context as Go profiler labels. This allows you to | ||
181 | // correlated runtime profiling with stats. | ||
182 | // | ||
183 | // It converts the key/values from the given map to Go profiler labels | ||
184 | // and calls pprof.Do. | ||
185 | // | ||
186 | // Do is going to do nothing if your Go version is below 1.9. | ||
187 | func Do(ctx context.Context, f func(ctx context.Context)) { | ||
188 | do(ctx, f) | ||
189 | } | ||
190 | |||
191 | type mutator struct { | ||
192 | fn func(t *Map) (*Map, error) | ||
193 | } | ||
194 | |||
195 | func (m *mutator) Mutate(t *Map) (*Map, error) { | ||
196 | return m.fn(t) | ||
197 | } | ||
diff --git a/vendor/go.opencensus.io/tag/map_codec.go b/vendor/go.opencensus.io/tag/map_codec.go new file mode 100644 index 0000000..3e99895 --- /dev/null +++ b/vendor/go.opencensus.io/tag/map_codec.go | |||
@@ -0,0 +1,234 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | // | ||
15 | |||
16 | package tag | ||
17 | |||
18 | import ( | ||
19 | "encoding/binary" | ||
20 | "fmt" | ||
21 | ) | ||
22 | |||
23 | // KeyType defines the types of keys allowed. Currently only keyTypeString is | ||
24 | // supported. | ||
25 | type keyType byte | ||
26 | |||
27 | const ( | ||
28 | keyTypeString keyType = iota | ||
29 | keyTypeInt64 | ||
30 | keyTypeTrue | ||
31 | keyTypeFalse | ||
32 | |||
33 | tagsVersionID = byte(0) | ||
34 | ) | ||
35 | |||
36 | type encoderGRPC struct { | ||
37 | buf []byte | ||
38 | writeIdx, readIdx int | ||
39 | } | ||
40 | |||
41 | // writeKeyString writes the fieldID '0' followed by the key string and value | ||
42 | // string. | ||
43 | func (eg *encoderGRPC) writeTagString(k, v string) { | ||
44 | eg.writeByte(byte(keyTypeString)) | ||
45 | eg.writeStringWithVarintLen(k) | ||
46 | eg.writeStringWithVarintLen(v) | ||
47 | } | ||
48 | |||
49 | func (eg *encoderGRPC) writeTagUint64(k string, i uint64) { | ||
50 | eg.writeByte(byte(keyTypeInt64)) | ||
51 | eg.writeStringWithVarintLen(k) | ||
52 | eg.writeUint64(i) | ||
53 | } | ||
54 | |||
55 | func (eg *encoderGRPC) writeTagTrue(k string) { | ||
56 | eg.writeByte(byte(keyTypeTrue)) | ||
57 | eg.writeStringWithVarintLen(k) | ||
58 | } | ||
59 | |||
60 | func (eg *encoderGRPC) writeTagFalse(k string) { | ||
61 | eg.writeByte(byte(keyTypeFalse)) | ||
62 | eg.writeStringWithVarintLen(k) | ||
63 | } | ||
64 | |||
65 | func (eg *encoderGRPC) writeBytesWithVarintLen(bytes []byte) { | ||
66 | length := len(bytes) | ||
67 | |||
68 | eg.growIfRequired(binary.MaxVarintLen64 + length) | ||
69 | eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) | ||
70 | copy(eg.buf[eg.writeIdx:], bytes) | ||
71 | eg.writeIdx += length | ||
72 | } | ||
73 | |||
74 | func (eg *encoderGRPC) writeStringWithVarintLen(s string) { | ||
75 | length := len(s) | ||
76 | |||
77 | eg.growIfRequired(binary.MaxVarintLen64 + length) | ||
78 | eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) | ||
79 | copy(eg.buf[eg.writeIdx:], s) | ||
80 | eg.writeIdx += length | ||
81 | } | ||
82 | |||
83 | func (eg *encoderGRPC) writeByte(v byte) { | ||
84 | eg.growIfRequired(1) | ||
85 | eg.buf[eg.writeIdx] = v | ||
86 | eg.writeIdx++ | ||
87 | } | ||
88 | |||
89 | func (eg *encoderGRPC) writeUint32(i uint32) { | ||
90 | eg.growIfRequired(4) | ||
91 | binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i) | ||
92 | eg.writeIdx += 4 | ||
93 | } | ||
94 | |||
95 | func (eg *encoderGRPC) writeUint64(i uint64) { | ||
96 | eg.growIfRequired(8) | ||
97 | binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i) | ||
98 | eg.writeIdx += 8 | ||
99 | } | ||
100 | |||
101 | func (eg *encoderGRPC) readByte() byte { | ||
102 | b := eg.buf[eg.readIdx] | ||
103 | eg.readIdx++ | ||
104 | return b | ||
105 | } | ||
106 | |||
107 | func (eg *encoderGRPC) readUint32() uint32 { | ||
108 | i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:]) | ||
109 | eg.readIdx += 4 | ||
110 | return i | ||
111 | } | ||
112 | |||
113 | func (eg *encoderGRPC) readUint64() uint64 { | ||
114 | i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:]) | ||
115 | eg.readIdx += 8 | ||
116 | return i | ||
117 | } | ||
118 | |||
119 | func (eg *encoderGRPC) readBytesWithVarintLen() ([]byte, error) { | ||
120 | if eg.readEnded() { | ||
121 | return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) | ||
122 | } | ||
123 | length, valueStart := binary.Uvarint(eg.buf[eg.readIdx:]) | ||
124 | if valueStart <= 0 { | ||
125 | return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) | ||
126 | } | ||
127 | |||
128 | valueStart += eg.readIdx | ||
129 | valueEnd := valueStart + int(length) | ||
130 | if valueEnd > len(eg.buf) { | ||
131 | return nil, fmt.Errorf("malformed encoding: length:%v, upper:%v, maxLength:%v", length, valueEnd, len(eg.buf)) | ||
132 | } | ||
133 | |||
134 | eg.readIdx = valueEnd | ||
135 | return eg.buf[valueStart:valueEnd], nil | ||
136 | } | ||
137 | |||
138 | func (eg *encoderGRPC) readStringWithVarintLen() (string, error) { | ||
139 | bytes, err := eg.readBytesWithVarintLen() | ||
140 | if err != nil { | ||
141 | return "", err | ||
142 | } | ||
143 | return string(bytes), nil | ||
144 | } | ||
145 | |||
146 | func (eg *encoderGRPC) growIfRequired(expected int) { | ||
147 | if len(eg.buf)-eg.writeIdx < expected { | ||
148 | tmp := make([]byte, 2*(len(eg.buf)+1)+expected) | ||
149 | copy(tmp, eg.buf) | ||
150 | eg.buf = tmp | ||
151 | } | ||
152 | } | ||
153 | |||
154 | func (eg *encoderGRPC) readEnded() bool { | ||
155 | return eg.readIdx >= len(eg.buf) | ||
156 | } | ||
157 | |||
158 | func (eg *encoderGRPC) bytes() []byte { | ||
159 | return eg.buf[:eg.writeIdx] | ||
160 | } | ||
161 | |||
162 | // Encode encodes the tag map into a []byte. It is useful to propagate | ||
163 | // the tag maps on wire in binary format. | ||
164 | func Encode(m *Map) []byte { | ||
165 | eg := &encoderGRPC{ | ||
166 | buf: make([]byte, len(m.m)), | ||
167 | } | ||
168 | eg.writeByte(byte(tagsVersionID)) | ||
169 | for k, v := range m.m { | ||
170 | eg.writeByte(byte(keyTypeString)) | ||
171 | eg.writeStringWithVarintLen(k.name) | ||
172 | eg.writeBytesWithVarintLen([]byte(v)) | ||
173 | } | ||
174 | return eg.bytes() | ||
175 | } | ||
176 | |||
177 | // Decode decodes the given []byte into a tag map. | ||
178 | func Decode(bytes []byte) (*Map, error) { | ||
179 | ts := newMap() | ||
180 | err := DecodeEach(bytes, ts.upsert) | ||
181 | if err != nil { | ||
182 | // no partial failures | ||
183 | return nil, err | ||
184 | } | ||
185 | return ts, nil | ||
186 | } | ||
187 | |||
188 | // DecodeEach decodes the given serialized tag map, calling handler for each | ||
189 | // tag key and value decoded. | ||
190 | func DecodeEach(bytes []byte, fn func(key Key, val string)) error { | ||
191 | eg := &encoderGRPC{ | ||
192 | buf: bytes, | ||
193 | } | ||
194 | if len(eg.buf) == 0 { | ||
195 | return nil | ||
196 | } | ||
197 | |||
198 | version := eg.readByte() | ||
199 | if version > tagsVersionID { | ||
200 | return fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID) | ||
201 | } | ||
202 | |||
203 | for !eg.readEnded() { | ||
204 | typ := keyType(eg.readByte()) | ||
205 | |||
206 | if typ != keyTypeString { | ||
207 | return fmt.Errorf("cannot decode: invalid key type: %q", typ) | ||
208 | } | ||
209 | |||
210 | k, err := eg.readBytesWithVarintLen() | ||
211 | if err != nil { | ||
212 | return err | ||
213 | } | ||
214 | |||
215 | v, err := eg.readBytesWithVarintLen() | ||
216 | if err != nil { | ||
217 | return err | ||
218 | } | ||
219 | |||
220 | key, err := NewKey(string(k)) | ||
221 | if err != nil { | ||
222 | return err | ||
223 | } | ||
224 | val := string(v) | ||
225 | if !checkValue(val) { | ||
226 | return errInvalidValue | ||
227 | } | ||
228 | fn(key, val) | ||
229 | if err != nil { | ||
230 | return err | ||
231 | } | ||
232 | } | ||
233 | return nil | ||
234 | } | ||
diff --git a/vendor/go.opencensus.io/tag/profile_19.go b/vendor/go.opencensus.io/tag/profile_19.go new file mode 100644 index 0000000..f81cd0b --- /dev/null +++ b/vendor/go.opencensus.io/tag/profile_19.go | |||
@@ -0,0 +1,31 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // +build go1.9 | ||
16 | |||
17 | package tag | ||
18 | |||
19 | import ( | ||
20 | "context" | ||
21 | "runtime/pprof" | ||
22 | ) | ||
23 | |||
24 | func do(ctx context.Context, f func(ctx context.Context)) { | ||
25 | m := FromContext(ctx) | ||
26 | keyvals := make([]string, 0, 2*len(m.m)) | ||
27 | for k, v := range m.m { | ||
28 | keyvals = append(keyvals, k.Name(), v) | ||
29 | } | ||
30 | pprof.Do(ctx, pprof.Labels(keyvals...), f) | ||
31 | } | ||
diff --git a/vendor/go.opencensus.io/tag/profile_not19.go b/vendor/go.opencensus.io/tag/profile_not19.go new file mode 100644 index 0000000..83adbce --- /dev/null +++ b/vendor/go.opencensus.io/tag/profile_not19.go | |||
@@ -0,0 +1,23 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // +build !go1.9 | ||
16 | |||
17 | package tag | ||
18 | |||
19 | import "context" | ||
20 | |||
21 | func do(ctx context.Context, f func(ctx context.Context)) { | ||
22 | f(ctx) | ||
23 | } | ||
diff --git a/vendor/go.opencensus.io/tag/validate.go b/vendor/go.opencensus.io/tag/validate.go new file mode 100644 index 0000000..0939fc6 --- /dev/null +++ b/vendor/go.opencensus.io/tag/validate.go | |||
@@ -0,0 +1,56 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package tag | ||
16 | |||
17 | import "errors" | ||
18 | |||
19 | const ( | ||
20 | maxKeyLength = 255 | ||
21 | |||
22 | // valid are restricted to US-ASCII subset (range 0x20 (' ') to 0x7e ('~')). | ||
23 | validKeyValueMin = 32 | ||
24 | validKeyValueMax = 126 | ||
25 | ) | ||
26 | |||
27 | var ( | ||
28 | errInvalidKeyName = errors.New("invalid key name: only ASCII characters accepted; max length must be 255 characters") | ||
29 | errInvalidValue = errors.New("invalid value: only ASCII characters accepted; max length must be 255 characters") | ||
30 | ) | ||
31 | |||
32 | func checkKeyName(name string) bool { | ||
33 | if len(name) == 0 { | ||
34 | return false | ||
35 | } | ||
36 | if len(name) > maxKeyLength { | ||
37 | return false | ||
38 | } | ||
39 | return isASCII(name) | ||
40 | } | ||
41 | |||
42 | func isASCII(s string) bool { | ||
43 | for _, c := range s { | ||
44 | if (c < validKeyValueMin) || (c > validKeyValueMax) { | ||
45 | return false | ||
46 | } | ||
47 | } | ||
48 | return true | ||
49 | } | ||
50 | |||
51 | func checkValue(v string) bool { | ||
52 | if len(v) > maxKeyLength { | ||
53 | return false | ||
54 | } | ||
55 | return isASCII(v) | ||
56 | } | ||
diff --git a/vendor/go.opencensus.io/trace/basetypes.go b/vendor/go.opencensus.io/trace/basetypes.go new file mode 100644 index 0000000..01f0f90 --- /dev/null +++ b/vendor/go.opencensus.io/trace/basetypes.go | |||
@@ -0,0 +1,114 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "fmt" | ||
19 | "time" | ||
20 | ) | ||
21 | |||
22 | type ( | ||
23 | // TraceID is a 16-byte identifier for a set of spans. | ||
24 | TraceID [16]byte | ||
25 | |||
26 | // SpanID is an 8-byte identifier for a single span. | ||
27 | SpanID [8]byte | ||
28 | ) | ||
29 | |||
30 | func (t TraceID) String() string { | ||
31 | return fmt.Sprintf("%02x", t[:]) | ||
32 | } | ||
33 | |||
34 | func (s SpanID) String() string { | ||
35 | return fmt.Sprintf("%02x", s[:]) | ||
36 | } | ||
37 | |||
38 | // Annotation represents a text annotation with a set of attributes and a timestamp. | ||
39 | type Annotation struct { | ||
40 | Time time.Time | ||
41 | Message string | ||
42 | Attributes map[string]interface{} | ||
43 | } | ||
44 | |||
45 | // Attribute represents a key-value pair on a span, link or annotation. | ||
46 | // Construct with one of: BoolAttribute, Int64Attribute, or StringAttribute. | ||
47 | type Attribute struct { | ||
48 | key string | ||
49 | value interface{} | ||
50 | } | ||
51 | |||
52 | // BoolAttribute returns a bool-valued attribute. | ||
53 | func BoolAttribute(key string, value bool) Attribute { | ||
54 | return Attribute{key: key, value: value} | ||
55 | } | ||
56 | |||
57 | // Int64Attribute returns an int64-valued attribute. | ||
58 | func Int64Attribute(key string, value int64) Attribute { | ||
59 | return Attribute{key: key, value: value} | ||
60 | } | ||
61 | |||
62 | // StringAttribute returns a string-valued attribute. | ||
63 | func StringAttribute(key string, value string) Attribute { | ||
64 | return Attribute{key: key, value: value} | ||
65 | } | ||
66 | |||
67 | // LinkType specifies the relationship between the span that had the link | ||
68 | // added, and the linked span. | ||
69 | type LinkType int32 | ||
70 | |||
71 | // LinkType values. | ||
72 | const ( | ||
73 | LinkTypeUnspecified LinkType = iota // The relationship of the two spans is unknown. | ||
74 | LinkTypeChild // The current span is a child of the linked span. | ||
75 | LinkTypeParent // The current span is the parent of the linked span. | ||
76 | ) | ||
77 | |||
78 | // Link represents a reference from one span to another span. | ||
79 | type Link struct { | ||
80 | TraceID TraceID | ||
81 | SpanID SpanID | ||
82 | Type LinkType | ||
83 | // Attributes is a set of attributes on the link. | ||
84 | Attributes map[string]interface{} | ||
85 | } | ||
86 | |||
87 | // MessageEventType specifies the type of message event. | ||
88 | type MessageEventType int32 | ||
89 | |||
90 | // MessageEventType values. | ||
91 | const ( | ||
92 | MessageEventTypeUnspecified MessageEventType = iota // Unknown event type. | ||
93 | MessageEventTypeSent // Indicates a sent RPC message. | ||
94 | MessageEventTypeRecv // Indicates a received RPC message. | ||
95 | ) | ||
96 | |||
97 | // MessageEvent represents an event describing a message sent or received on the network. | ||
98 | type MessageEvent struct { | ||
99 | Time time.Time | ||
100 | EventType MessageEventType | ||
101 | MessageID int64 | ||
102 | UncompressedByteSize int64 | ||
103 | CompressedByteSize int64 | ||
104 | } | ||
105 | |||
106 | // Status is the status of a Span. | ||
107 | type Status struct { | ||
108 | // Code is a status code. Zero indicates success. | ||
109 | // | ||
110 | // If Code will be propagated to Google APIs, it ideally should be a value from | ||
111 | // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto . | ||
112 | Code int32 | ||
113 | Message string | ||
114 | } | ||
diff --git a/vendor/go.opencensus.io/trace/config.go b/vendor/go.opencensus.io/trace/config.go new file mode 100644 index 0000000..0816892 --- /dev/null +++ b/vendor/go.opencensus.io/trace/config.go | |||
@@ -0,0 +1,48 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "sync" | ||
19 | |||
20 | "go.opencensus.io/trace/internal" | ||
21 | ) | ||
22 | |||
23 | // Config represents the global tracing configuration. | ||
24 | type Config struct { | ||
25 | // DefaultSampler is the default sampler used when creating new spans. | ||
26 | DefaultSampler Sampler | ||
27 | |||
28 | // IDGenerator is for internal use only. | ||
29 | IDGenerator internal.IDGenerator | ||
30 | } | ||
31 | |||
32 | var configWriteMu sync.Mutex | ||
33 | |||
34 | // ApplyConfig applies changes to the global tracing configuration. | ||
35 | // | ||
36 | // Fields not provided in the given config are going to be preserved. | ||
37 | func ApplyConfig(cfg Config) { | ||
38 | configWriteMu.Lock() | ||
39 | defer configWriteMu.Unlock() | ||
40 | c := *config.Load().(*Config) | ||
41 | if cfg.DefaultSampler != nil { | ||
42 | c.DefaultSampler = cfg.DefaultSampler | ||
43 | } | ||
44 | if cfg.IDGenerator != nil { | ||
45 | c.IDGenerator = cfg.IDGenerator | ||
46 | } | ||
47 | config.Store(&c) | ||
48 | } | ||
diff --git a/vendor/go.opencensus.io/trace/doc.go b/vendor/go.opencensus.io/trace/doc.go new file mode 100644 index 0000000..04b1ee4 --- /dev/null +++ b/vendor/go.opencensus.io/trace/doc.go | |||
@@ -0,0 +1,53 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | /* | ||
16 | Package trace contains support for OpenCensus distributed tracing. | ||
17 | |||
18 | The following assumes a basic familiarity with OpenCensus concepts. | ||
19 | See http://opencensus.io | ||
20 | |||
21 | |||
22 | Exporting Traces | ||
23 | |||
24 | To export collected tracing data, register at least one exporter. You can use | ||
25 | one of the provided exporters or write your own. | ||
26 | |||
27 | trace.RegisterExporter(exporter) | ||
28 | |||
29 | By default, traces will be sampled relatively rarely. To change the sampling | ||
30 | frequency for your entire program, call ApplyConfig. Use a ProbabilitySampler | ||
31 | to sample a subset of traces, or use AlwaysSample to collect a trace on every run: | ||
32 | |||
33 | trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) | ||
34 | |||
35 | Be careful about using trace.AlwaysSample in a production application with | ||
36 | significant traffic: a new trace will be started and exported for every request. | ||
37 | |||
38 | Adding Spans to a Trace | ||
39 | |||
40 | A trace consists of a tree of spans. In Go, the current span is carried in a | ||
41 | context.Context. | ||
42 | |||
43 | It is common to want to capture all the activity of a function call in a span. For | ||
44 | this to work, the function must take a context.Context as a parameter. Add these two | ||
45 | lines to the top of the function: | ||
46 | |||
47 | ctx, span := trace.StartSpan(ctx, "example.com/Run") | ||
48 | defer span.End() | ||
49 | |||
50 | StartSpan will create a new top-level span if the context | ||
51 | doesn't contain another span, otherwise it will create a child span. | ||
52 | */ | ||
53 | package trace // import "go.opencensus.io/trace" | ||
diff --git a/vendor/go.opencensus.io/trace/exemplar.go b/vendor/go.opencensus.io/trace/exemplar.go new file mode 100644 index 0000000..416d805 --- /dev/null +++ b/vendor/go.opencensus.io/trace/exemplar.go | |||
@@ -0,0 +1,43 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "context" | ||
19 | "encoding/hex" | ||
20 | |||
21 | "go.opencensus.io/exemplar" | ||
22 | ) | ||
23 | |||
24 | func init() { | ||
25 | exemplar.RegisterAttachmentExtractor(attachSpanContext) | ||
26 | } | ||
27 | |||
28 | func attachSpanContext(ctx context.Context, a exemplar.Attachments) exemplar.Attachments { | ||
29 | span := FromContext(ctx) | ||
30 | if span == nil { | ||
31 | return a | ||
32 | } | ||
33 | sc := span.SpanContext() | ||
34 | if !sc.IsSampled() { | ||
35 | return a | ||
36 | } | ||
37 | if a == nil { | ||
38 | a = make(exemplar.Attachments) | ||
39 | } | ||
40 | a[exemplar.KeyTraceID] = hex.EncodeToString(sc.TraceID[:]) | ||
41 | a[exemplar.KeySpanID] = hex.EncodeToString(sc.SpanID[:]) | ||
42 | return a | ||
43 | } | ||
diff --git a/vendor/go.opencensus.io/trace/export.go b/vendor/go.opencensus.io/trace/export.go new file mode 100644 index 0000000..77a8c73 --- /dev/null +++ b/vendor/go.opencensus.io/trace/export.go | |||
@@ -0,0 +1,90 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "sync" | ||
19 | "sync/atomic" | ||
20 | "time" | ||
21 | ) | ||
22 | |||
23 | // Exporter is a type for functions that receive sampled trace spans. | ||
24 | // | ||
25 | // The ExportSpan method should be safe for concurrent use and should return | ||
26 | // quickly; if an Exporter takes a significant amount of time to process a | ||
27 | // SpanData, that work should be done on another goroutine. | ||
28 | // | ||
29 | // The SpanData should not be modified, but a pointer to it can be kept. | ||
30 | type Exporter interface { | ||
31 | ExportSpan(s *SpanData) | ||
32 | } | ||
33 | |||
34 | type exportersMap map[Exporter]struct{} | ||
35 | |||
36 | var ( | ||
37 | exporterMu sync.Mutex | ||
38 | exporters atomic.Value | ||
39 | ) | ||
40 | |||
41 | // RegisterExporter adds to the list of Exporters that will receive sampled | ||
42 | // trace spans. | ||
43 | // | ||
44 | // Binaries can register exporters, libraries shouldn't register exporters. | ||
45 | func RegisterExporter(e Exporter) { | ||
46 | exporterMu.Lock() | ||
47 | new := make(exportersMap) | ||
48 | if old, ok := exporters.Load().(exportersMap); ok { | ||
49 | for k, v := range old { | ||
50 | new[k] = v | ||
51 | } | ||
52 | } | ||
53 | new[e] = struct{}{} | ||
54 | exporters.Store(new) | ||
55 | exporterMu.Unlock() | ||
56 | } | ||
57 | |||
58 | // UnregisterExporter removes from the list of Exporters the Exporter that was | ||
59 | // registered with the given name. | ||
60 | func UnregisterExporter(e Exporter) { | ||
61 | exporterMu.Lock() | ||
62 | new := make(exportersMap) | ||
63 | if old, ok := exporters.Load().(exportersMap); ok { | ||
64 | for k, v := range old { | ||
65 | new[k] = v | ||
66 | } | ||
67 | } | ||
68 | delete(new, e) | ||
69 | exporters.Store(new) | ||
70 | exporterMu.Unlock() | ||
71 | } | ||
72 | |||
73 | // SpanData contains all the information collected by a Span. | ||
74 | type SpanData struct { | ||
75 | SpanContext | ||
76 | ParentSpanID SpanID | ||
77 | SpanKind int | ||
78 | Name string | ||
79 | StartTime time.Time | ||
80 | // The wall clock time of EndTime will be adjusted to always be offset | ||
81 | // from StartTime by the duration of the span. | ||
82 | EndTime time.Time | ||
83 | // The values of Attributes each have type string, bool, or int64. | ||
84 | Attributes map[string]interface{} | ||
85 | Annotations []Annotation | ||
86 | MessageEvents []MessageEvent | ||
87 | Status | ||
88 | Links []Link | ||
89 | HasRemoteParent bool | ||
90 | } | ||
diff --git a/vendor/go.opencensus.io/trace/internal/internal.go b/vendor/go.opencensus.io/trace/internal/internal.go new file mode 100644 index 0000000..1c8b9b3 --- /dev/null +++ b/vendor/go.opencensus.io/trace/internal/internal.go | |||
@@ -0,0 +1,21 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // Package internal provides trace internals. | ||
16 | package internal | ||
17 | |||
18 | type IDGenerator interface { | ||
19 | NewTraceID() [16]byte | ||
20 | NewSpanID() [8]byte | ||
21 | } | ||
diff --git a/vendor/go.opencensus.io/trace/propagation/propagation.go b/vendor/go.opencensus.io/trace/propagation/propagation.go new file mode 100644 index 0000000..1eb190a --- /dev/null +++ b/vendor/go.opencensus.io/trace/propagation/propagation.go | |||
@@ -0,0 +1,108 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // Package propagation implements the binary trace context format. | ||
16 | package propagation // import "go.opencensus.io/trace/propagation" | ||
17 | |||
18 | // TODO: link to external spec document. | ||
19 | |||
20 | // BinaryFormat format: | ||
21 | // | ||
22 | // Binary value: <version_id><version_format> | ||
23 | // version_id: 1 byte representing the version id. | ||
24 | // | ||
25 | // For version_id = 0: | ||
26 | // | ||
27 | // version_format: <field><field> | ||
28 | // field_format: <field_id><field_format> | ||
29 | // | ||
30 | // Fields: | ||
31 | // | ||
32 | // TraceId: (field_id = 0, len = 16, default = "0000000000000000") - 16-byte array representing the trace_id. | ||
33 | // SpanId: (field_id = 1, len = 8, default = "00000000") - 8-byte array representing the span_id. | ||
34 | // TraceOptions: (field_id = 2, len = 1, default = "0") - 1-byte array representing the trace_options. | ||
35 | // | ||
36 | // Fields MUST be encoded using the field id order (smaller to higher). | ||
37 | // | ||
38 | // Valid value example: | ||
39 | // | ||
40 | // {0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97, | ||
41 | // 98, 99, 100, 101, 102, 103, 104, 2, 1} | ||
42 | // | ||
43 | // version_id = 0; | ||
44 | // trace_id = {64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79} | ||
45 | // span_id = {97, 98, 99, 100, 101, 102, 103, 104}; | ||
46 | // trace_options = {1}; | ||
47 | |||
48 | import ( | ||
49 | "net/http" | ||
50 | |||
51 | "go.opencensus.io/trace" | ||
52 | ) | ||
53 | |||
54 | // Binary returns the binary format representation of a SpanContext. | ||
55 | // | ||
56 | // If sc is the zero value, Binary returns nil. | ||
57 | func Binary(sc trace.SpanContext) []byte { | ||
58 | if sc == (trace.SpanContext{}) { | ||
59 | return nil | ||
60 | } | ||
61 | var b [29]byte | ||
62 | copy(b[2:18], sc.TraceID[:]) | ||
63 | b[18] = 1 | ||
64 | copy(b[19:27], sc.SpanID[:]) | ||
65 | b[27] = 2 | ||
66 | b[28] = uint8(sc.TraceOptions) | ||
67 | return b[:] | ||
68 | } | ||
69 | |||
70 | // FromBinary returns the SpanContext represented by b. | ||
71 | // | ||
72 | // If b has an unsupported version ID or contains no TraceID, FromBinary | ||
73 | // returns with ok==false. | ||
74 | func FromBinary(b []byte) (sc trace.SpanContext, ok bool) { | ||
75 | if len(b) == 0 || b[0] != 0 { | ||
76 | return trace.SpanContext{}, false | ||
77 | } | ||
78 | b = b[1:] | ||
79 | if len(b) >= 17 && b[0] == 0 { | ||
80 | copy(sc.TraceID[:], b[1:17]) | ||
81 | b = b[17:] | ||
82 | } else { | ||
83 | return trace.SpanContext{}, false | ||
84 | } | ||
85 | if len(b) >= 9 && b[0] == 1 { | ||
86 | copy(sc.SpanID[:], b[1:9]) | ||
87 | b = b[9:] | ||
88 | } | ||
89 | if len(b) >= 2 && b[0] == 2 { | ||
90 | sc.TraceOptions = trace.TraceOptions(b[1]) | ||
91 | } | ||
92 | return sc, true | ||
93 | } | ||
94 | |||
95 | // HTTPFormat implementations propagate span contexts | ||
96 | // in HTTP requests. | ||
97 | // | ||
98 | // SpanContextFromRequest extracts a span context from incoming | ||
99 | // requests. | ||
100 | // | ||
101 | // SpanContextToRequest modifies the given request to include the given | ||
102 | // span context. | ||
103 | type HTTPFormat interface { | ||
104 | SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) | ||
105 | SpanContextToRequest(sc trace.SpanContext, req *http.Request) | ||
106 | } | ||
107 | |||
108 | // TODO(jbd): Find a more representative but short name for HTTPFormat. | ||
diff --git a/vendor/go.opencensus.io/trace/sampling.go b/vendor/go.opencensus.io/trace/sampling.go new file mode 100644 index 0000000..71c10f9 --- /dev/null +++ b/vendor/go.opencensus.io/trace/sampling.go | |||
@@ -0,0 +1,75 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "encoding/binary" | ||
19 | ) | ||
20 | |||
21 | const defaultSamplingProbability = 1e-4 | ||
22 | |||
23 | // Sampler decides whether a trace should be sampled and exported. | ||
24 | type Sampler func(SamplingParameters) SamplingDecision | ||
25 | |||
26 | // SamplingParameters contains the values passed to a Sampler. | ||
27 | type SamplingParameters struct { | ||
28 | ParentContext SpanContext | ||
29 | TraceID TraceID | ||
30 | SpanID SpanID | ||
31 | Name string | ||
32 | HasRemoteParent bool | ||
33 | } | ||
34 | |||
35 | // SamplingDecision is the value returned by a Sampler. | ||
36 | type SamplingDecision struct { | ||
37 | Sample bool | ||
38 | } | ||
39 | |||
40 | // ProbabilitySampler returns a Sampler that samples a given fraction of traces. | ||
41 | // | ||
42 | // It also samples spans whose parents are sampled. | ||
43 | func ProbabilitySampler(fraction float64) Sampler { | ||
44 | if !(fraction >= 0) { | ||
45 | fraction = 0 | ||
46 | } else if fraction >= 1 { | ||
47 | return AlwaysSample() | ||
48 | } | ||
49 | |||
50 | traceIDUpperBound := uint64(fraction * (1 << 63)) | ||
51 | return Sampler(func(p SamplingParameters) SamplingDecision { | ||
52 | if p.ParentContext.IsSampled() { | ||
53 | return SamplingDecision{Sample: true} | ||
54 | } | ||
55 | x := binary.BigEndian.Uint64(p.TraceID[0:8]) >> 1 | ||
56 | return SamplingDecision{Sample: x < traceIDUpperBound} | ||
57 | }) | ||
58 | } | ||
59 | |||
60 | // AlwaysSample returns a Sampler that samples every trace. | ||
61 | // Be careful about using this sampler in a production application with | ||
62 | // significant traffic: a new trace will be started and exported for every | ||
63 | // request. | ||
64 | func AlwaysSample() Sampler { | ||
65 | return func(p SamplingParameters) SamplingDecision { | ||
66 | return SamplingDecision{Sample: true} | ||
67 | } | ||
68 | } | ||
69 | |||
70 | // NeverSample returns a Sampler that samples no traces. | ||
71 | func NeverSample() Sampler { | ||
72 | return func(p SamplingParameters) SamplingDecision { | ||
73 | return SamplingDecision{Sample: false} | ||
74 | } | ||
75 | } | ||
diff --git a/vendor/go.opencensus.io/trace/spanbucket.go b/vendor/go.opencensus.io/trace/spanbucket.go new file mode 100644 index 0000000..fbabad3 --- /dev/null +++ b/vendor/go.opencensus.io/trace/spanbucket.go | |||
@@ -0,0 +1,130 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "time" | ||
19 | ) | ||
20 | |||
21 | // samplePeriod is the minimum time between accepting spans in a single bucket. | ||
22 | const samplePeriod = time.Second | ||
23 | |||
24 | // defaultLatencies contains the default latency bucket bounds. | ||
25 | // TODO: consider defaults, make configurable | ||
26 | var defaultLatencies = [...]time.Duration{ | ||
27 | 10 * time.Microsecond, | ||
28 | 100 * time.Microsecond, | ||
29 | time.Millisecond, | ||
30 | 10 * time.Millisecond, | ||
31 | 100 * time.Millisecond, | ||
32 | time.Second, | ||
33 | 10 * time.Second, | ||
34 | time.Minute, | ||
35 | } | ||
36 | |||
37 | // bucket is a container for a set of spans for a particular error code or latency range. | ||
38 | type bucket struct { | ||
39 | nextTime time.Time // next time we can accept a span | ||
40 | buffer []*SpanData // circular buffer of spans | ||
41 | nextIndex int // location next SpanData should be placed in buffer | ||
42 | overflow bool // whether the circular buffer has wrapped around | ||
43 | } | ||
44 | |||
45 | func makeBucket(bufferSize int) bucket { | ||
46 | return bucket{ | ||
47 | buffer: make([]*SpanData, bufferSize), | ||
48 | } | ||
49 | } | ||
50 | |||
51 | // add adds a span to the bucket, if nextTime has been reached. | ||
52 | func (b *bucket) add(s *SpanData) { | ||
53 | if s.EndTime.Before(b.nextTime) { | ||
54 | return | ||
55 | } | ||
56 | if len(b.buffer) == 0 { | ||
57 | return | ||
58 | } | ||
59 | b.nextTime = s.EndTime.Add(samplePeriod) | ||
60 | b.buffer[b.nextIndex] = s | ||
61 | b.nextIndex++ | ||
62 | if b.nextIndex == len(b.buffer) { | ||
63 | b.nextIndex = 0 | ||
64 | b.overflow = true | ||
65 | } | ||
66 | } | ||
67 | |||
68 | // size returns the number of spans in the bucket. | ||
69 | func (b *bucket) size() int { | ||
70 | if b.overflow { | ||
71 | return len(b.buffer) | ||
72 | } | ||
73 | return b.nextIndex | ||
74 | } | ||
75 | |||
76 | // span returns the ith span in the bucket. | ||
77 | func (b *bucket) span(i int) *SpanData { | ||
78 | if !b.overflow { | ||
79 | return b.buffer[i] | ||
80 | } | ||
81 | if i < len(b.buffer)-b.nextIndex { | ||
82 | return b.buffer[b.nextIndex+i] | ||
83 | } | ||
84 | return b.buffer[b.nextIndex+i-len(b.buffer)] | ||
85 | } | ||
86 | |||
87 | // resize changes the size of the bucket to n, keeping up to n existing spans. | ||
88 | func (b *bucket) resize(n int) { | ||
89 | cur := b.size() | ||
90 | newBuffer := make([]*SpanData, n) | ||
91 | if cur < n { | ||
92 | for i := 0; i < cur; i++ { | ||
93 | newBuffer[i] = b.span(i) | ||
94 | } | ||
95 | b.buffer = newBuffer | ||
96 | b.nextIndex = cur | ||
97 | b.overflow = false | ||
98 | return | ||
99 | } | ||
100 | for i := 0; i < n; i++ { | ||
101 | newBuffer[i] = b.span(i + cur - n) | ||
102 | } | ||
103 | b.buffer = newBuffer | ||
104 | b.nextIndex = 0 | ||
105 | b.overflow = true | ||
106 | } | ||
107 | |||
108 | // latencyBucket returns the appropriate bucket number for a given latency. | ||
109 | func latencyBucket(latency time.Duration) int { | ||
110 | i := 0 | ||
111 | for i < len(defaultLatencies) && latency >= defaultLatencies[i] { | ||
112 | i++ | ||
113 | } | ||
114 | return i | ||
115 | } | ||
116 | |||
117 | // latencyBucketBounds returns the lower and upper bounds for a latency bucket | ||
118 | // number. | ||
119 | // | ||
120 | // The lower bound is inclusive, the upper bound is exclusive (except for the | ||
121 | // last bucket.) | ||
122 | func latencyBucketBounds(index int) (lower time.Duration, upper time.Duration) { | ||
123 | if index == 0 { | ||
124 | return 0, defaultLatencies[index] | ||
125 | } | ||
126 | if index == len(defaultLatencies) { | ||
127 | return defaultLatencies[index-1], 1<<63 - 1 | ||
128 | } | ||
129 | return defaultLatencies[index-1], defaultLatencies[index] | ||
130 | } | ||
diff --git a/vendor/go.opencensus.io/trace/spanstore.go b/vendor/go.opencensus.io/trace/spanstore.go new file mode 100644 index 0000000..c442d99 --- /dev/null +++ b/vendor/go.opencensus.io/trace/spanstore.go | |||
@@ -0,0 +1,306 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "sync" | ||
19 | "time" | ||
20 | |||
21 | "go.opencensus.io/internal" | ||
22 | ) | ||
23 | |||
24 | const ( | ||
25 | maxBucketSize = 100000 | ||
26 | defaultBucketSize = 10 | ||
27 | ) | ||
28 | |||
29 | var ( | ||
30 | ssmu sync.RWMutex // protects spanStores | ||
31 | spanStores = make(map[string]*spanStore) | ||
32 | ) | ||
33 | |||
34 | // This exists purely to avoid exposing internal methods used by z-Pages externally. | ||
35 | type internalOnly struct{} | ||
36 | |||
37 | func init() { | ||
38 | //TODO(#412): remove | ||
39 | internal.Trace = &internalOnly{} | ||
40 | } | ||
41 | |||
42 | // ReportActiveSpans returns the active spans for the given name. | ||
43 | func (i internalOnly) ReportActiveSpans(name string) []*SpanData { | ||
44 | s := spanStoreForName(name) | ||
45 | if s == nil { | ||
46 | return nil | ||
47 | } | ||
48 | var out []*SpanData | ||
49 | s.mu.Lock() | ||
50 | defer s.mu.Unlock() | ||
51 | for span := range s.active { | ||
52 | out = append(out, span.makeSpanData()) | ||
53 | } | ||
54 | return out | ||
55 | } | ||
56 | |||
57 | // ReportSpansByError returns a sample of error spans. | ||
58 | // | ||
59 | // If code is nonzero, only spans with that status code are returned. | ||
60 | func (i internalOnly) ReportSpansByError(name string, code int32) []*SpanData { | ||
61 | s := spanStoreForName(name) | ||
62 | if s == nil { | ||
63 | return nil | ||
64 | } | ||
65 | var out []*SpanData | ||
66 | s.mu.Lock() | ||
67 | defer s.mu.Unlock() | ||
68 | if code != 0 { | ||
69 | if b, ok := s.errors[code]; ok { | ||
70 | for _, sd := range b.buffer { | ||
71 | if sd == nil { | ||
72 | break | ||
73 | } | ||
74 | out = append(out, sd) | ||
75 | } | ||
76 | } | ||
77 | } else { | ||
78 | for _, b := range s.errors { | ||
79 | for _, sd := range b.buffer { | ||
80 | if sd == nil { | ||
81 | break | ||
82 | } | ||
83 | out = append(out, sd) | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | return out | ||
88 | } | ||
89 | |||
90 | // ConfigureBucketSizes sets the number of spans to keep per latency and error | ||
91 | // bucket for different span names. | ||
92 | func (i internalOnly) ConfigureBucketSizes(bcs []internal.BucketConfiguration) { | ||
93 | for _, bc := range bcs { | ||
94 | latencyBucketSize := bc.MaxRequestsSucceeded | ||
95 | if latencyBucketSize < 0 { | ||
96 | latencyBucketSize = 0 | ||
97 | } | ||
98 | if latencyBucketSize > maxBucketSize { | ||
99 | latencyBucketSize = maxBucketSize | ||
100 | } | ||
101 | errorBucketSize := bc.MaxRequestsErrors | ||
102 | if errorBucketSize < 0 { | ||
103 | errorBucketSize = 0 | ||
104 | } | ||
105 | if errorBucketSize > maxBucketSize { | ||
106 | errorBucketSize = maxBucketSize | ||
107 | } | ||
108 | spanStoreSetSize(bc.Name, latencyBucketSize, errorBucketSize) | ||
109 | } | ||
110 | } | ||
111 | |||
112 | // ReportSpansPerMethod returns a summary of what spans are being stored for each span name. | ||
113 | func (i internalOnly) ReportSpansPerMethod() map[string]internal.PerMethodSummary { | ||
114 | out := make(map[string]internal.PerMethodSummary) | ||
115 | ssmu.RLock() | ||
116 | defer ssmu.RUnlock() | ||
117 | for name, s := range spanStores { | ||
118 | s.mu.Lock() | ||
119 | p := internal.PerMethodSummary{ | ||
120 | Active: len(s.active), | ||
121 | } | ||
122 | for code, b := range s.errors { | ||
123 | p.ErrorBuckets = append(p.ErrorBuckets, internal.ErrorBucketSummary{ | ||
124 | ErrorCode: code, | ||
125 | Size: b.size(), | ||
126 | }) | ||
127 | } | ||
128 | for i, b := range s.latency { | ||
129 | min, max := latencyBucketBounds(i) | ||
130 | p.LatencyBuckets = append(p.LatencyBuckets, internal.LatencyBucketSummary{ | ||
131 | MinLatency: min, | ||
132 | MaxLatency: max, | ||
133 | Size: b.size(), | ||
134 | }) | ||
135 | } | ||
136 | s.mu.Unlock() | ||
137 | out[name] = p | ||
138 | } | ||
139 | return out | ||
140 | } | ||
141 | |||
142 | // ReportSpansByLatency returns a sample of successful spans. | ||
143 | // | ||
144 | // minLatency is the minimum latency of spans to be returned. | ||
145 | // maxLatency, if nonzero, is the maximum latency of spans to be returned. | ||
146 | func (i internalOnly) ReportSpansByLatency(name string, minLatency, maxLatency time.Duration) []*SpanData { | ||
147 | s := spanStoreForName(name) | ||
148 | if s == nil { | ||
149 | return nil | ||
150 | } | ||
151 | var out []*SpanData | ||
152 | s.mu.Lock() | ||
153 | defer s.mu.Unlock() | ||
154 | for i, b := range s.latency { | ||
155 | min, max := latencyBucketBounds(i) | ||
156 | if i+1 != len(s.latency) && max <= minLatency { | ||
157 | continue | ||
158 | } | ||
159 | if maxLatency != 0 && maxLatency < min { | ||
160 | continue | ||
161 | } | ||
162 | for _, sd := range b.buffer { | ||
163 | if sd == nil { | ||
164 | break | ||
165 | } | ||
166 | if minLatency != 0 || maxLatency != 0 { | ||
167 | d := sd.EndTime.Sub(sd.StartTime) | ||
168 | if d < minLatency { | ||
169 | continue | ||
170 | } | ||
171 | if maxLatency != 0 && d > maxLatency { | ||
172 | continue | ||
173 | } | ||
174 | } | ||
175 | out = append(out, sd) | ||
176 | } | ||
177 | } | ||
178 | return out | ||
179 | } | ||
180 | |||
181 | // spanStore keeps track of spans stored for a particular span name. | ||
182 | // | ||
183 | // It contains all active spans; a sample of spans for failed requests, | ||
184 | // categorized by error code; and a sample of spans for successful requests, | ||
185 | // bucketed by latency. | ||
186 | type spanStore struct { | ||
187 | mu sync.Mutex // protects everything below. | ||
188 | active map[*Span]struct{} | ||
189 | errors map[int32]*bucket | ||
190 | latency []bucket | ||
191 | maxSpansPerErrorBucket int | ||
192 | } | ||
193 | |||
194 | // newSpanStore creates a span store. | ||
195 | func newSpanStore(name string, latencyBucketSize int, errorBucketSize int) *spanStore { | ||
196 | s := &spanStore{ | ||
197 | active: make(map[*Span]struct{}), | ||
198 | latency: make([]bucket, len(defaultLatencies)+1), | ||
199 | maxSpansPerErrorBucket: errorBucketSize, | ||
200 | } | ||
201 | for i := range s.latency { | ||
202 | s.latency[i] = makeBucket(latencyBucketSize) | ||
203 | } | ||
204 | return s | ||
205 | } | ||
206 | |||
207 | // spanStoreForName returns the spanStore for the given name. | ||
208 | // | ||
209 | // It returns nil if it doesn't exist. | ||
210 | func spanStoreForName(name string) *spanStore { | ||
211 | var s *spanStore | ||
212 | ssmu.RLock() | ||
213 | s, _ = spanStores[name] | ||
214 | ssmu.RUnlock() | ||
215 | return s | ||
216 | } | ||
217 | |||
218 | // spanStoreForNameCreateIfNew returns the spanStore for the given name. | ||
219 | // | ||
220 | // It creates it if it didn't exist. | ||
221 | func spanStoreForNameCreateIfNew(name string) *spanStore { | ||
222 | ssmu.RLock() | ||
223 | s, ok := spanStores[name] | ||
224 | ssmu.RUnlock() | ||
225 | if ok { | ||
226 | return s | ||
227 | } | ||
228 | ssmu.Lock() | ||
229 | defer ssmu.Unlock() | ||
230 | s, ok = spanStores[name] | ||
231 | if ok { | ||
232 | return s | ||
233 | } | ||
234 | s = newSpanStore(name, defaultBucketSize, defaultBucketSize) | ||
235 | spanStores[name] = s | ||
236 | return s | ||
237 | } | ||
238 | |||
239 | // spanStoreSetSize resizes the spanStore for the given name. | ||
240 | // | ||
241 | // It creates it if it didn't exist. | ||
242 | func spanStoreSetSize(name string, latencyBucketSize int, errorBucketSize int) { | ||
243 | ssmu.RLock() | ||
244 | s, ok := spanStores[name] | ||
245 | ssmu.RUnlock() | ||
246 | if ok { | ||
247 | s.resize(latencyBucketSize, errorBucketSize) | ||
248 | return | ||
249 | } | ||
250 | ssmu.Lock() | ||
251 | defer ssmu.Unlock() | ||
252 | s, ok = spanStores[name] | ||
253 | if ok { | ||
254 | s.resize(latencyBucketSize, errorBucketSize) | ||
255 | return | ||
256 | } | ||
257 | s = newSpanStore(name, latencyBucketSize, errorBucketSize) | ||
258 | spanStores[name] = s | ||
259 | } | ||
260 | |||
261 | func (s *spanStore) resize(latencyBucketSize int, errorBucketSize int) { | ||
262 | s.mu.Lock() | ||
263 | for i := range s.latency { | ||
264 | s.latency[i].resize(latencyBucketSize) | ||
265 | } | ||
266 | for _, b := range s.errors { | ||
267 | b.resize(errorBucketSize) | ||
268 | } | ||
269 | s.maxSpansPerErrorBucket = errorBucketSize | ||
270 | s.mu.Unlock() | ||
271 | } | ||
272 | |||
273 | // add adds a span to the active bucket of the spanStore. | ||
274 | func (s *spanStore) add(span *Span) { | ||
275 | s.mu.Lock() | ||
276 | s.active[span] = struct{}{} | ||
277 | s.mu.Unlock() | ||
278 | } | ||
279 | |||
280 | // finished removes a span from the active set, and adds a corresponding | ||
281 | // SpanData to a latency or error bucket. | ||
282 | func (s *spanStore) finished(span *Span, sd *SpanData) { | ||
283 | latency := sd.EndTime.Sub(sd.StartTime) | ||
284 | if latency < 0 { | ||
285 | latency = 0 | ||
286 | } | ||
287 | code := sd.Status.Code | ||
288 | |||
289 | s.mu.Lock() | ||
290 | delete(s.active, span) | ||
291 | if code == 0 { | ||
292 | s.latency[latencyBucket(latency)].add(sd) | ||
293 | } else { | ||
294 | if s.errors == nil { | ||
295 | s.errors = make(map[int32]*bucket) | ||
296 | } | ||
297 | if b := s.errors[code]; b != nil { | ||
298 | b.add(sd) | ||
299 | } else { | ||
300 | b := makeBucket(s.maxSpansPerErrorBucket) | ||
301 | s.errors[code] = &b | ||
302 | b.add(sd) | ||
303 | } | ||
304 | } | ||
305 | s.mu.Unlock() | ||
306 | } | ||
diff --git a/vendor/go.opencensus.io/trace/status_codes.go b/vendor/go.opencensus.io/trace/status_codes.go new file mode 100644 index 0000000..ec60eff --- /dev/null +++ b/vendor/go.opencensus.io/trace/status_codes.go | |||
@@ -0,0 +1,37 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | // Status codes for use with Span.SetStatus. These correspond to the status | ||
18 | // codes used by gRPC defined here: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto | ||
19 | const ( | ||
20 | StatusCodeOK = 0 | ||
21 | StatusCodeCancelled = 1 | ||
22 | StatusCodeUnknown = 2 | ||
23 | StatusCodeInvalidArgument = 3 | ||
24 | StatusCodeDeadlineExceeded = 4 | ||
25 | StatusCodeNotFound = 5 | ||
26 | StatusCodeAlreadyExists = 6 | ||
27 | StatusCodePermissionDenied = 7 | ||
28 | StatusCodeResourceExhausted = 8 | ||
29 | StatusCodeFailedPrecondition = 9 | ||
30 | StatusCodeAborted = 10 | ||
31 | StatusCodeOutOfRange = 11 | ||
32 | StatusCodeUnimplemented = 12 | ||
33 | StatusCodeInternal = 13 | ||
34 | StatusCodeUnavailable = 14 | ||
35 | StatusCodeDataLoss = 15 | ||
36 | StatusCodeUnauthenticated = 16 | ||
37 | ) | ||
diff --git a/vendor/go.opencensus.io/trace/trace.go b/vendor/go.opencensus.io/trace/trace.go new file mode 100644 index 0000000..9e5e5f0 --- /dev/null +++ b/vendor/go.opencensus.io/trace/trace.go | |||
@@ -0,0 +1,516 @@ | |||
1 | // Copyright 2017, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | package trace | ||
16 | |||
17 | import ( | ||
18 | "context" | ||
19 | crand "crypto/rand" | ||
20 | "encoding/binary" | ||
21 | "fmt" | ||
22 | "math/rand" | ||
23 | "sync" | ||
24 | "sync/atomic" | ||
25 | "time" | ||
26 | |||
27 | "go.opencensus.io/internal" | ||
28 | "go.opencensus.io/trace/tracestate" | ||
29 | ) | ||
30 | |||
31 | // Span represents a span of a trace. It has an associated SpanContext, and | ||
32 | // stores data accumulated while the span is active. | ||
33 | // | ||
34 | // Ideally users should interact with Spans by calling the functions in this | ||
35 | // package that take a Context parameter. | ||
36 | type Span struct { | ||
37 | // data contains information recorded about the span. | ||
38 | // | ||
39 | // It will be non-nil if we are exporting the span or recording events for it. | ||
40 | // Otherwise, data is nil, and the Span is simply a carrier for the | ||
41 | // SpanContext, so that the trace ID is propagated. | ||
42 | data *SpanData | ||
43 | mu sync.Mutex // protects the contents of *data (but not the pointer value.) | ||
44 | spanContext SpanContext | ||
45 | // spanStore is the spanStore this span belongs to, if any, otherwise it is nil. | ||
46 | *spanStore | ||
47 | endOnce sync.Once | ||
48 | |||
49 | executionTracerTaskEnd func() // ends the execution tracer span | ||
50 | } | ||
51 | |||
52 | // IsRecordingEvents returns true if events are being recorded for this span. | ||
53 | // Use this check to avoid computing expensive annotations when they will never | ||
54 | // be used. | ||
55 | func (s *Span) IsRecordingEvents() bool { | ||
56 | if s == nil { | ||
57 | return false | ||
58 | } | ||
59 | return s.data != nil | ||
60 | } | ||
61 | |||
62 | // TraceOptions contains options associated with a trace span. | ||
63 | type TraceOptions uint32 | ||
64 | |||
65 | // IsSampled returns true if the span will be exported. | ||
66 | func (sc SpanContext) IsSampled() bool { | ||
67 | return sc.TraceOptions.IsSampled() | ||
68 | } | ||
69 | |||
70 | // setIsSampled sets the TraceOptions bit that determines whether the span will be exported. | ||
71 | func (sc *SpanContext) setIsSampled(sampled bool) { | ||
72 | if sampled { | ||
73 | sc.TraceOptions |= 1 | ||
74 | } else { | ||
75 | sc.TraceOptions &= ^TraceOptions(1) | ||
76 | } | ||
77 | } | ||
78 | |||
79 | // IsSampled returns true if the span will be exported. | ||
80 | func (t TraceOptions) IsSampled() bool { | ||
81 | return t&1 == 1 | ||
82 | } | ||
83 | |||
84 | // SpanContext contains the state that must propagate across process boundaries. | ||
85 | // | ||
86 | // SpanContext is not an implementation of context.Context. | ||
87 | // TODO: add reference to external Census docs for SpanContext. | ||
88 | type SpanContext struct { | ||
89 | TraceID TraceID | ||
90 | SpanID SpanID | ||
91 | TraceOptions TraceOptions | ||
92 | Tracestate *tracestate.Tracestate | ||
93 | } | ||
94 | |||
95 | type contextKey struct{} | ||
96 | |||
97 | // FromContext returns the Span stored in a context, or nil if there isn't one. | ||
98 | func FromContext(ctx context.Context) *Span { | ||
99 | s, _ := ctx.Value(contextKey{}).(*Span) | ||
100 | return s | ||
101 | } | ||
102 | |||
103 | // NewContext returns a new context with the given Span attached. | ||
104 | func NewContext(parent context.Context, s *Span) context.Context { | ||
105 | return context.WithValue(parent, contextKey{}, s) | ||
106 | } | ||
107 | |||
108 | // All available span kinds. Span kind must be either one of these values. | ||
109 | const ( | ||
110 | SpanKindUnspecified = iota | ||
111 | SpanKindServer | ||
112 | SpanKindClient | ||
113 | ) | ||
114 | |||
115 | // StartOptions contains options concerning how a span is started. | ||
116 | type StartOptions struct { | ||
117 | // Sampler to consult for this Span. If provided, it is always consulted. | ||
118 | // | ||
119 | // If not provided, then the behavior differs based on whether | ||
120 | // the parent of this Span is remote, local, or there is no parent. | ||
121 | // In the case of a remote parent or no parent, the | ||
122 | // default sampler (see Config) will be consulted. Otherwise, | ||
123 | // when there is a non-remote parent, no new sampling decision will be made: | ||
124 | // we will preserve the sampling of the parent. | ||
125 | Sampler Sampler | ||
126 | |||
127 | // SpanKind represents the kind of a span. If none is set, | ||
128 | // SpanKindUnspecified is used. | ||
129 | SpanKind int | ||
130 | } | ||
131 | |||
132 | // StartOption apply changes to StartOptions. | ||
133 | type StartOption func(*StartOptions) | ||
134 | |||
135 | // WithSpanKind makes new spans to be created with the given kind. | ||
136 | func WithSpanKind(spanKind int) StartOption { | ||
137 | return func(o *StartOptions) { | ||
138 | o.SpanKind = spanKind | ||
139 | } | ||
140 | } | ||
141 | |||
142 | // WithSampler makes new spans to be be created with a custom sampler. | ||
143 | // Otherwise, the global sampler is used. | ||
144 | func WithSampler(sampler Sampler) StartOption { | ||
145 | return func(o *StartOptions) { | ||
146 | o.Sampler = sampler | ||
147 | } | ||
148 | } | ||
149 | |||
150 | // StartSpan starts a new child span of the current span in the context. If | ||
151 | // there is no span in the context, creates a new trace and span. | ||
152 | // | ||
153 | // Returned context contains the newly created span. You can use it to | ||
154 | // propagate the returned span in process. | ||
155 | func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) { | ||
156 | var opts StartOptions | ||
157 | var parent SpanContext | ||
158 | if p := FromContext(ctx); p != nil { | ||
159 | parent = p.spanContext | ||
160 | } | ||
161 | for _, op := range o { | ||
162 | op(&opts) | ||
163 | } | ||
164 | span := startSpanInternal(name, parent != SpanContext{}, parent, false, opts) | ||
165 | |||
166 | ctx, end := startExecutionTracerTask(ctx, name) | ||
167 | span.executionTracerTaskEnd = end | ||
168 | return NewContext(ctx, span), span | ||
169 | } | ||
170 | |||
171 | // StartSpanWithRemoteParent starts a new child span of the span from the given parent. | ||
172 | // | ||
173 | // If the incoming context contains a parent, it ignores. StartSpanWithRemoteParent is | ||
174 | // preferred for cases where the parent is propagated via an incoming request. | ||
175 | // | ||
176 | // Returned context contains the newly created span. You can use it to | ||
177 | // propagate the returned span in process. | ||
178 | func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) { | ||
179 | var opts StartOptions | ||
180 | for _, op := range o { | ||
181 | op(&opts) | ||
182 | } | ||
183 | span := startSpanInternal(name, parent != SpanContext{}, parent, true, opts) | ||
184 | ctx, end := startExecutionTracerTask(ctx, name) | ||
185 | span.executionTracerTaskEnd = end | ||
186 | return NewContext(ctx, span), span | ||
187 | } | ||
188 | |||
189 | func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *Span { | ||
190 | span := &Span{} | ||
191 | span.spanContext = parent | ||
192 | |||
193 | cfg := config.Load().(*Config) | ||
194 | |||
195 | if !hasParent { | ||
196 | span.spanContext.TraceID = cfg.IDGenerator.NewTraceID() | ||
197 | } | ||
198 | span.spanContext.SpanID = cfg.IDGenerator.NewSpanID() | ||
199 | sampler := cfg.DefaultSampler | ||
200 | |||
201 | if !hasParent || remoteParent || o.Sampler != nil { | ||
202 | // If this span is the child of a local span and no Sampler is set in the | ||
203 | // options, keep the parent's TraceOptions. | ||
204 | // | ||
205 | // Otherwise, consult the Sampler in the options if it is non-nil, otherwise | ||
206 | // the default sampler. | ||
207 | if o.Sampler != nil { | ||
208 | sampler = o.Sampler | ||
209 | } | ||
210 | span.spanContext.setIsSampled(sampler(SamplingParameters{ | ||
211 | ParentContext: parent, | ||
212 | TraceID: span.spanContext.TraceID, | ||
213 | SpanID: span.spanContext.SpanID, | ||
214 | Name: name, | ||
215 | HasRemoteParent: remoteParent}).Sample) | ||
216 | } | ||
217 | |||
218 | if !internal.LocalSpanStoreEnabled && !span.spanContext.IsSampled() { | ||
219 | return span | ||
220 | } | ||
221 | |||
222 | span.data = &SpanData{ | ||
223 | SpanContext: span.spanContext, | ||
224 | StartTime: time.Now(), | ||
225 | SpanKind: o.SpanKind, | ||
226 | Name: name, | ||
227 | HasRemoteParent: remoteParent, | ||
228 | } | ||
229 | if hasParent { | ||
230 | span.data.ParentSpanID = parent.SpanID | ||
231 | } | ||
232 | if internal.LocalSpanStoreEnabled { | ||
233 | var ss *spanStore | ||
234 | ss = spanStoreForNameCreateIfNew(name) | ||
235 | if ss != nil { | ||
236 | span.spanStore = ss | ||
237 | ss.add(span) | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return span | ||
242 | } | ||
243 | |||
244 | // End ends the span. | ||
245 | func (s *Span) End() { | ||
246 | if s == nil { | ||
247 | return | ||
248 | } | ||
249 | if s.executionTracerTaskEnd != nil { | ||
250 | s.executionTracerTaskEnd() | ||
251 | } | ||
252 | if !s.IsRecordingEvents() { | ||
253 | return | ||
254 | } | ||
255 | s.endOnce.Do(func() { | ||
256 | exp, _ := exporters.Load().(exportersMap) | ||
257 | mustExport := s.spanContext.IsSampled() && len(exp) > 0 | ||
258 | if s.spanStore != nil || mustExport { | ||
259 | sd := s.makeSpanData() | ||
260 | sd.EndTime = internal.MonotonicEndTime(sd.StartTime) | ||
261 | if s.spanStore != nil { | ||
262 | s.spanStore.finished(s, sd) | ||
263 | } | ||
264 | if mustExport { | ||
265 | for e := range exp { | ||
266 | e.ExportSpan(sd) | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | }) | ||
271 | } | ||
272 | |||
273 | // makeSpanData produces a SpanData representing the current state of the Span. | ||
274 | // It requires that s.data is non-nil. | ||
275 | func (s *Span) makeSpanData() *SpanData { | ||
276 | var sd SpanData | ||
277 | s.mu.Lock() | ||
278 | sd = *s.data | ||
279 | if s.data.Attributes != nil { | ||
280 | sd.Attributes = make(map[string]interface{}) | ||
281 | for k, v := range s.data.Attributes { | ||
282 | sd.Attributes[k] = v | ||
283 | } | ||
284 | } | ||
285 | s.mu.Unlock() | ||
286 | return &sd | ||
287 | } | ||
288 | |||
289 | // SpanContext returns the SpanContext of the span. | ||
290 | func (s *Span) SpanContext() SpanContext { | ||
291 | if s == nil { | ||
292 | return SpanContext{} | ||
293 | } | ||
294 | return s.spanContext | ||
295 | } | ||
296 | |||
297 | // SetName sets the name of the span, if it is recording events. | ||
298 | func (s *Span) SetName(name string) { | ||
299 | if !s.IsRecordingEvents() { | ||
300 | return | ||
301 | } | ||
302 | s.mu.Lock() | ||
303 | s.data.Name = name | ||
304 | s.mu.Unlock() | ||
305 | } | ||
306 | |||
307 | // SetStatus sets the status of the span, if it is recording events. | ||
308 | func (s *Span) SetStatus(status Status) { | ||
309 | if !s.IsRecordingEvents() { | ||
310 | return | ||
311 | } | ||
312 | s.mu.Lock() | ||
313 | s.data.Status = status | ||
314 | s.mu.Unlock() | ||
315 | } | ||
316 | |||
317 | // AddAttributes sets attributes in the span. | ||
318 | // | ||
319 | // Existing attributes whose keys appear in the attributes parameter are overwritten. | ||
320 | func (s *Span) AddAttributes(attributes ...Attribute) { | ||
321 | if !s.IsRecordingEvents() { | ||
322 | return | ||
323 | } | ||
324 | s.mu.Lock() | ||
325 | if s.data.Attributes == nil { | ||
326 | s.data.Attributes = make(map[string]interface{}) | ||
327 | } | ||
328 | copyAttributes(s.data.Attributes, attributes) | ||
329 | s.mu.Unlock() | ||
330 | } | ||
331 | |||
332 | // copyAttributes copies a slice of Attributes into a map. | ||
333 | func copyAttributes(m map[string]interface{}, attributes []Attribute) { | ||
334 | for _, a := range attributes { | ||
335 | m[a.key] = a.value | ||
336 | } | ||
337 | } | ||
338 | |||
339 | func (s *Span) lazyPrintfInternal(attributes []Attribute, format string, a ...interface{}) { | ||
340 | now := time.Now() | ||
341 | msg := fmt.Sprintf(format, a...) | ||
342 | var m map[string]interface{} | ||
343 | s.mu.Lock() | ||
344 | if len(attributes) != 0 { | ||
345 | m = make(map[string]interface{}) | ||
346 | copyAttributes(m, attributes) | ||
347 | } | ||
348 | s.data.Annotations = append(s.data.Annotations, Annotation{ | ||
349 | Time: now, | ||
350 | Message: msg, | ||
351 | Attributes: m, | ||
352 | }) | ||
353 | s.mu.Unlock() | ||
354 | } | ||
355 | |||
356 | func (s *Span) printStringInternal(attributes []Attribute, str string) { | ||
357 | now := time.Now() | ||
358 | var a map[string]interface{} | ||
359 | s.mu.Lock() | ||
360 | if len(attributes) != 0 { | ||
361 | a = make(map[string]interface{}) | ||
362 | copyAttributes(a, attributes) | ||
363 | } | ||
364 | s.data.Annotations = append(s.data.Annotations, Annotation{ | ||
365 | Time: now, | ||
366 | Message: str, | ||
367 | Attributes: a, | ||
368 | }) | ||
369 | s.mu.Unlock() | ||
370 | } | ||
371 | |||
372 | // Annotate adds an annotation with attributes. | ||
373 | // Attributes can be nil. | ||
374 | func (s *Span) Annotate(attributes []Attribute, str string) { | ||
375 | if !s.IsRecordingEvents() { | ||
376 | return | ||
377 | } | ||
378 | s.printStringInternal(attributes, str) | ||
379 | } | ||
380 | |||
381 | // Annotatef adds an annotation with attributes. | ||
382 | func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}) { | ||
383 | if !s.IsRecordingEvents() { | ||
384 | return | ||
385 | } | ||
386 | s.lazyPrintfInternal(attributes, format, a...) | ||
387 | } | ||
388 | |||
389 | // AddMessageSendEvent adds a message send event to the span. | ||
390 | // | ||
391 | // messageID is an identifier for the message, which is recommended to be | ||
392 | // unique in this span and the same between the send event and the receive | ||
393 | // event (this allows to identify a message between the sender and receiver). | ||
394 | // For example, this could be a sequence id. | ||
395 | func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) { | ||
396 | if !s.IsRecordingEvents() { | ||
397 | return | ||
398 | } | ||
399 | now := time.Now() | ||
400 | s.mu.Lock() | ||
401 | s.data.MessageEvents = append(s.data.MessageEvents, MessageEvent{ | ||
402 | Time: now, | ||
403 | EventType: MessageEventTypeSent, | ||
404 | MessageID: messageID, | ||
405 | UncompressedByteSize: uncompressedByteSize, | ||
406 | CompressedByteSize: compressedByteSize, | ||
407 | }) | ||
408 | s.mu.Unlock() | ||
409 | } | ||
410 | |||
411 | // AddMessageReceiveEvent adds a message receive event to the span. | ||
412 | // | ||
413 | // messageID is an identifier for the message, which is recommended to be | ||
414 | // unique in this span and the same between the send event and the receive | ||
415 | // event (this allows to identify a message between the sender and receiver). | ||
416 | // For example, this could be a sequence id. | ||
417 | func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) { | ||
418 | if !s.IsRecordingEvents() { | ||
419 | return | ||
420 | } | ||
421 | now := time.Now() | ||
422 | s.mu.Lock() | ||
423 | s.data.MessageEvents = append(s.data.MessageEvents, MessageEvent{ | ||
424 | Time: now, | ||
425 | EventType: MessageEventTypeRecv, | ||
426 | MessageID: messageID, | ||
427 | UncompressedByteSize: uncompressedByteSize, | ||
428 | CompressedByteSize: compressedByteSize, | ||
429 | }) | ||
430 | s.mu.Unlock() | ||
431 | } | ||
432 | |||
433 | // AddLink adds a link to the span. | ||
434 | func (s *Span) AddLink(l Link) { | ||
435 | if !s.IsRecordingEvents() { | ||
436 | return | ||
437 | } | ||
438 | s.mu.Lock() | ||
439 | s.data.Links = append(s.data.Links, l) | ||
440 | s.mu.Unlock() | ||
441 | } | ||
442 | |||
443 | func (s *Span) String() string { | ||
444 | if s == nil { | ||
445 | return "<nil>" | ||
446 | } | ||
447 | if s.data == nil { | ||
448 | return fmt.Sprintf("span %s", s.spanContext.SpanID) | ||
449 | } | ||
450 | s.mu.Lock() | ||
451 | str := fmt.Sprintf("span %s %q", s.spanContext.SpanID, s.data.Name) | ||
452 | s.mu.Unlock() | ||
453 | return str | ||
454 | } | ||
455 | |||
456 | var config atomic.Value // access atomically | ||
457 | |||
458 | func init() { | ||
459 | gen := &defaultIDGenerator{} | ||
460 | // initialize traceID and spanID generators. | ||
461 | var rngSeed int64 | ||
462 | for _, p := range []interface{}{ | ||
463 | &rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc, | ||
464 | } { | ||
465 | binary.Read(crand.Reader, binary.LittleEndian, p) | ||
466 | } | ||
467 | gen.traceIDRand = rand.New(rand.NewSource(rngSeed)) | ||
468 | gen.spanIDInc |= 1 | ||
469 | |||
470 | config.Store(&Config{ | ||
471 | DefaultSampler: ProbabilitySampler(defaultSamplingProbability), | ||
472 | IDGenerator: gen, | ||
473 | }) | ||
474 | } | ||
475 | |||
476 | type defaultIDGenerator struct { | ||
477 | sync.Mutex | ||
478 | |||
479 | // Please keep these as the first fields | ||
480 | // so that these 8 byte fields will be aligned on addresses | ||
481 | // divisible by 8, on both 32-bit and 64-bit machines when | ||
482 | // performing atomic increments and accesses. | ||
483 | // See: | ||
484 | // * https://github.com/census-instrumentation/opencensus-go/issues/587 | ||
485 | // * https://github.com/census-instrumentation/opencensus-go/issues/865 | ||
486 | // * https://golang.org/pkg/sync/atomic/#pkg-note-BUG | ||
487 | nextSpanID uint64 | ||
488 | spanIDInc uint64 | ||
489 | |||
490 | traceIDAdd [2]uint64 | ||
491 | traceIDRand *rand.Rand | ||
492 | } | ||
493 | |||
494 | // NewSpanID returns a non-zero span ID from a randomly-chosen sequence. | ||
495 | func (gen *defaultIDGenerator) NewSpanID() [8]byte { | ||
496 | var id uint64 | ||
497 | for id == 0 { | ||
498 | id = atomic.AddUint64(&gen.nextSpanID, gen.spanIDInc) | ||
499 | } | ||
500 | var sid [8]byte | ||
501 | binary.LittleEndian.PutUint64(sid[:], id) | ||
502 | return sid | ||
503 | } | ||
504 | |||
505 | // NewTraceID returns a non-zero trace ID from a randomly-chosen sequence. | ||
506 | // mu should be held while this function is called. | ||
507 | func (gen *defaultIDGenerator) NewTraceID() [16]byte { | ||
508 | var tid [16]byte | ||
509 | // Construct the trace ID from two outputs of traceIDRand, with a constant | ||
510 | // added to each half for additional entropy. | ||
511 | gen.Lock() | ||
512 | binary.LittleEndian.PutUint64(tid[0:8], gen.traceIDRand.Uint64()+gen.traceIDAdd[0]) | ||
513 | binary.LittleEndian.PutUint64(tid[8:16], gen.traceIDRand.Uint64()+gen.traceIDAdd[1]) | ||
514 | gen.Unlock() | ||
515 | return tid | ||
516 | } | ||
diff --git a/vendor/go.opencensus.io/trace/trace_go11.go b/vendor/go.opencensus.io/trace/trace_go11.go new file mode 100644 index 0000000..b7d8aaf --- /dev/null +++ b/vendor/go.opencensus.io/trace/trace_go11.go | |||
@@ -0,0 +1,32 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // +build go1.11 | ||
16 | |||
17 | package trace | ||
18 | |||
19 | import ( | ||
20 | "context" | ||
21 | t "runtime/trace" | ||
22 | ) | ||
23 | |||
24 | func startExecutionTracerTask(ctx context.Context, name string) (context.Context, func()) { | ||
25 | if !t.IsEnabled() { | ||
26 | // Avoid additional overhead if | ||
27 | // runtime/trace is not enabled. | ||
28 | return ctx, func() {} | ||
29 | } | ||
30 | nctx, task := t.NewTask(ctx, name) | ||
31 | return nctx, task.End | ||
32 | } | ||
diff --git a/vendor/go.opencensus.io/trace/trace_nongo11.go b/vendor/go.opencensus.io/trace/trace_nongo11.go new file mode 100644 index 0000000..e254198 --- /dev/null +++ b/vendor/go.opencensus.io/trace/trace_nongo11.go | |||
@@ -0,0 +1,25 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // +build !go1.11 | ||
16 | |||
17 | package trace | ||
18 | |||
19 | import ( | ||
20 | "context" | ||
21 | ) | ||
22 | |||
23 | func startExecutionTracerTask(ctx context.Context, name string) (context.Context, func()) { | ||
24 | return ctx, func() {} | ||
25 | } | ||
diff --git a/vendor/go.opencensus.io/trace/tracestate/tracestate.go b/vendor/go.opencensus.io/trace/tracestate/tracestate.go new file mode 100644 index 0000000..2d6c713 --- /dev/null +++ b/vendor/go.opencensus.io/trace/tracestate/tracestate.go | |||
@@ -0,0 +1,147 @@ | |||
1 | // Copyright 2018, OpenCensus Authors | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | // Package tracestate implements support for the Tracestate header of the | ||
16 | // W3C TraceContext propagation format. | ||
17 | package tracestate | ||
18 | |||
19 | import ( | ||
20 | "fmt" | ||
21 | "regexp" | ||
22 | ) | ||
23 | |||
24 | const ( | ||
25 | keyMaxSize = 256 | ||
26 | valueMaxSize = 256 | ||
27 | maxKeyValuePairs = 32 | ||
28 | ) | ||
29 | |||
30 | const ( | ||
31 | keyWithoutVendorFormat = `[a-z][_0-9a-z\-\*\/]{0,255}` | ||
32 | keyWithVendorFormat = `[a-z][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}` | ||
33 | keyFormat = `(` + keyWithoutVendorFormat + `)|(` + keyWithVendorFormat + `)` | ||
34 | valueFormat = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]{0,255}[\x21-\x2b\x2d-\x3c\x3e-\x7e]` | ||
35 | ) | ||
36 | |||
37 | var keyValidationRegExp = regexp.MustCompile(`^(` + keyFormat + `)$`) | ||
38 | var valueValidationRegExp = regexp.MustCompile(`^(` + valueFormat + `)$`) | ||
39 | |||
40 | // Tracestate represents tracing-system specific context in a list of key-value pairs. Tracestate allows different | ||
41 | // vendors propagate additional information and inter-operate with their legacy Id formats. | ||
42 | type Tracestate struct { | ||
43 | entries []Entry | ||
44 | } | ||
45 | |||
46 | // Entry represents one key-value pair in a list of key-value pair of Tracestate. | ||
47 | type Entry struct { | ||
48 | // Key is an opaque string up to 256 characters printable. It MUST begin with a lowercase letter, | ||
49 | // and can only contain lowercase letters a-z, digits 0-9, underscores _, dashes -, asterisks *, and | ||
50 | // forward slashes /. | ||
51 | Key string | ||
52 | |||
53 | // Value is an opaque string up to 256 characters printable ASCII RFC0020 characters (i.e., the | ||
54 | // range 0x20 to 0x7E) except comma , and =. | ||
55 | Value string | ||
56 | } | ||
57 | |||
58 | // Entries returns a slice of Entry. | ||
59 | func (ts *Tracestate) Entries() []Entry { | ||
60 | if ts == nil { | ||
61 | return nil | ||
62 | } | ||
63 | return ts.entries | ||
64 | } | ||
65 | |||
66 | func (ts *Tracestate) remove(key string) *Entry { | ||
67 | for index, entry := range ts.entries { | ||
68 | if entry.Key == key { | ||
69 | ts.entries = append(ts.entries[:index], ts.entries[index+1:]...) | ||
70 | return &entry | ||
71 | } | ||
72 | } | ||
73 | return nil | ||
74 | } | ||
75 | |||
76 | func (ts *Tracestate) add(entries []Entry) error { | ||
77 | for _, entry := range entries { | ||
78 | ts.remove(entry.Key) | ||
79 | } | ||
80 | if len(ts.entries)+len(entries) > maxKeyValuePairs { | ||
81 | return fmt.Errorf("adding %d key-value pairs to current %d pairs exceeds the limit of %d", | ||
82 | len(entries), len(ts.entries), maxKeyValuePairs) | ||
83 | } | ||
84 | ts.entries = append(entries, ts.entries...) | ||
85 | return nil | ||
86 | } | ||
87 | |||
88 | func isValid(entry Entry) bool { | ||
89 | return keyValidationRegExp.MatchString(entry.Key) && | ||
90 | valueValidationRegExp.MatchString(entry.Value) | ||
91 | } | ||
92 | |||
93 | func containsDuplicateKey(entries ...Entry) (string, bool) { | ||
94 | keyMap := make(map[string]int) | ||
95 | for _, entry := range entries { | ||
96 | if _, ok := keyMap[entry.Key]; ok { | ||
97 | return entry.Key, true | ||
98 | } | ||
99 | keyMap[entry.Key] = 1 | ||
100 | } | ||
101 | return "", false | ||
102 | } | ||
103 | |||
104 | func areEntriesValid(entries ...Entry) (*Entry, bool) { | ||
105 | for _, entry := range entries { | ||
106 | if !isValid(entry) { | ||
107 | return &entry, false | ||
108 | } | ||
109 | } | ||
110 | return nil, true | ||
111 | } | ||
112 | |||
113 | // New creates a Tracestate object from a parent and/or entries (key-value pair). | ||
114 | // Entries from the parent are copied if present. The entries passed to this function | ||
115 | // are inserted in front of those copied from the parent. If an entry copied from the | ||
116 | // parent contains the same key as one of the entry in entries then the entry copied | ||
117 | // from the parent is removed. See add func. | ||
118 | // | ||
119 | // An error is returned with nil Tracestate if | ||
120 | // 1. one or more entry in entries is invalid. | ||
121 | // 2. two or more entries in the input entries have the same key. | ||
122 | // 3. the number of entries combined from the parent and the input entries exceeds maxKeyValuePairs. | ||
123 | // (duplicate entry is counted only once). | ||
124 | func New(parent *Tracestate, entries ...Entry) (*Tracestate, error) { | ||
125 | if parent == nil && len(entries) == 0 { | ||
126 | return nil, nil | ||
127 | } | ||
128 | if entry, ok := areEntriesValid(entries...); !ok { | ||
129 | return nil, fmt.Errorf("key-value pair {%s, %s} is invalid", entry.Key, entry.Value) | ||
130 | } | ||
131 | |||
132 | if key, duplicate := containsDuplicateKey(entries...); duplicate { | ||
133 | return nil, fmt.Errorf("contains duplicate keys (%s)", key) | ||
134 | } | ||
135 | |||
136 | tracestate := Tracestate{} | ||
137 | |||
138 | if parent != nil && len(parent.entries) > 0 { | ||
139 | tracestate.entries = append([]Entry{}, parent.entries...) | ||
140 | } | ||
141 | |||
142 | err := tracestate.add(entries) | ||
143 | if err != nil { | ||
144 | return nil, err | ||
145 | } | ||
146 | return &tracestate, nil | ||
147 | } | ||