// Copyright 2017, 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 implements the binary trace context format. package propagation // import "go.opencensus.io/trace/propagation" // TODO: link to external spec document. // BinaryFormat format: // // Binary value: // version_id: 1 byte representing the version id. // // For version_id = 0: // // version_format: // field_format: // // Fields: // // TraceId: (field_id = 0, len = 16, default = "0000000000000000") - 16-byte array representing the trace_id. // SpanId: (field_id = 1, len = 8, default = "00000000") - 8-byte array representing the span_id. // TraceOptions: (field_id = 2, len = 1, default = "0") - 1-byte array representing the trace_options. // // Fields MUST be encoded using the field id order (smaller to higher). // // Valid value example: // // {0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97, // 98, 99, 100, 101, 102, 103, 104, 2, 1} // // version_id = 0; // trace_id = {64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79} // span_id = {97, 98, 99, 100, 101, 102, 103, 104}; // trace_options = {1}; import ( "net/http" "go.opencensus.io/trace" ) // Binary returns the binary format representation of a SpanContext. // // If sc is the zero value, Binary returns nil. func Binary(sc trace.SpanContext) []byte { if sc == (trace.SpanContext{}) { return nil } var b [29]byte copy(b[2:18], sc.TraceID[:]) b[18] = 1 copy(b[19:27], sc.SpanID[:]) b[27] = 2 b[28] = uint8(sc.TraceOptions) return b[:] } // FromBinary returns the SpanContext represented by b. // // If b has an unsupported version ID or contains no TraceID, FromBinary // returns with ok==false. func FromBinary(b []byte) (sc trace.SpanContext, ok bool) { if len(b) == 0 || b[0] != 0 { return trace.SpanContext{}, false } b = b[1:] if len(b) >= 17 && b[0] == 0 { copy(sc.TraceID[:], b[1:17]) b = b[17:] } else { return trace.SpanContext{}, false } if len(b) >= 9 && b[0] == 1 { copy(sc.SpanID[:], b[1:9]) b = b[9:] } if len(b) >= 2 && b[0] == 2 { sc.TraceOptions = trace.TraceOptions(b[1]) } return sc, true } // HTTPFormat implementations propagate span contexts // in HTTP requests. // // SpanContextFromRequest extracts a span context from incoming // requests. // // SpanContextToRequest modifies the given request to include the given // span context. type HTTPFormat interface { SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) SpanContextToRequest(sc trace.SpanContext, req *http.Request) } // TODO(jbd): Find a more representative but short name for HTTPFormat.