aboutsummaryrefslogtreecommitdiff
path: root/vendor/go.opencensus.io/exporter/stackdriver/propagation/http.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.opencensus.io/exporter/stackdriver/propagation/http.go')
-rw-r--r--vendor/go.opencensus.io/exporter/stackdriver/propagation/http.go94
1 files changed, 94 insertions, 0 deletions
diff --git a/vendor/go.opencensus.io/exporter/stackdriver/propagation/http.go b/vendor/go.opencensus.io/exporter/stackdriver/propagation/http.go
new file mode 100644
index 0000000..7cc02a1
--- /dev/null
+++ b/vendor/go.opencensus.io/exporter/stackdriver/propagation/http.go
@@ -0,0 +1,94 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package propagation implement X-Cloud-Trace-Context header propagation used
+// by Google Cloud products.
+package propagation // import "go.opencensus.io/exporter/stackdriver/propagation"
+
+import (
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+
+ "go.opencensus.io/trace"
+ "go.opencensus.io/trace/propagation"
+)
+
+const (
+ httpHeaderMaxSize = 200
+ httpHeader = `X-Cloud-Trace-Context`
+)
+
+var _ propagation.HTTPFormat = (*HTTPFormat)(nil)
+
+// HTTPFormat implements propagation.HTTPFormat to propagate
+// traces in HTTP headers for Google Cloud Platform and Stackdriver Trace.
+type HTTPFormat struct{}
+
+// SpanContextFromRequest extracts a Stackdriver Trace span context from incoming requests.
+func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) {
+ h := req.Header.Get(httpHeader)
+ // See https://cloud.google.com/trace/docs/faq for the header HTTPFormat.
+ // Return if the header is empty or missing, or if the header is unreasonably
+ // large, to avoid making unnecessary copies of a large string.
+ if h == "" || len(h) > httpHeaderMaxSize {
+ return trace.SpanContext{}, false
+ }
+
+ // Parse the trace id field.
+ slash := strings.Index(h, `/`)
+ if slash == -1 {
+ return trace.SpanContext{}, false
+ }
+ tid, h := h[:slash], h[slash+1:]
+
+ buf, err := hex.DecodeString(tid)
+ if err != nil {
+ return trace.SpanContext{}, false
+ }
+ copy(sc.TraceID[:], buf)
+
+ // Parse the span id field.
+ spanstr := h
+ semicolon := strings.Index(h, `;`)
+ if semicolon != -1 {
+ spanstr, h = h[:semicolon], h[semicolon+1:]
+ }
+ sid, err := strconv.ParseUint(spanstr, 10, 64)
+ if err != nil {
+ return trace.SpanContext{}, false
+ }
+ binary.BigEndian.PutUint64(sc.SpanID[:], sid)
+
+ // Parse the options field, options field is optional.
+ if !strings.HasPrefix(h, "o=") {
+ return sc, true
+ }
+ o, err := strconv.ParseUint(h[2:], 10, 64)
+ if err != nil {
+ return trace.SpanContext{}, false
+ }
+ sc.TraceOptions = trace.TraceOptions(o)
+ return sc, true
+}
+
+// SpanContextToRequest modifies the given request to include a Stackdriver Trace header.
+func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) {
+ sid := binary.BigEndian.Uint64(sc.SpanID[:])
+ header := fmt.Sprintf("%s/%d;o=%d", hex.EncodeToString(sc.TraceID[:]), sid, int64(sc.TraceOptions))
+ req.Header.Set(httpHeader, header)
+}