1// Licensed to Elasticsearch B.V. under one or more contributor 2// license agreements. See the NOTICE file distributed with 3// this work for additional information regarding copyright 4// ownership. Elasticsearch B.V. licenses this file to you under 5// the Apache License, Version 2.0 (the "License"); you may 6// not use this file except in compliance with the License. 7// You may obtain a copy of the License at 8// 9// http://www.apache.org/licenses/LICENSE-2.0 10// 11// Unless required by applicable law or agreed to in writing, 12// software distributed under the License is distributed on an 13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14// KIND, either express or implied. See the License for the 15// specific language governing permissions and limitations 16// under the License. 17 18package apm 19 20import ( 21 "encoding/hex" 22 "errors" 23) 24 25var ( 26 errZeroTraceID = errors.New("zero trace-id is invalid") 27 errZeroSpanID = errors.New("zero span-id is invalid") 28) 29 30const ( 31 traceOptionsRecordedFlag = 0x01 32) 33 34// TraceContext holds trace context for an incoming or outgoing request. 35type TraceContext struct { 36 // Trace identifies the trace forest. 37 Trace TraceID 38 39 // Span identifies a span: the parent span if this context 40 // corresponds to an incoming request, or the current span 41 // if this is an outgoing request. 42 Span SpanID 43 44 // Options holds the trace options propagated by the parent. 45 Options TraceOptions 46} 47 48// TraceID identifies a trace forest. 49type TraceID [16]byte 50 51// Validate validates the trace ID. 52// This will return non-nil for a zero trace ID. 53func (id TraceID) Validate() error { 54 if id.isZero() { 55 return errZeroTraceID 56 } 57 return nil 58} 59 60func (id TraceID) isZero() bool { 61 return id == (TraceID{}) 62} 63 64// String returns id encoded as hex. 65func (id TraceID) String() string { 66 text, _ := id.MarshalText() 67 return string(text) 68} 69 70// MarshalText returns id encoded as hex, satisfying encoding.TextMarshaler. 71func (id TraceID) MarshalText() ([]byte, error) { 72 text := make([]byte, hex.EncodedLen(len(id))) 73 hex.Encode(text, id[:]) 74 return text, nil 75} 76 77// SpanID identifies a span within a trace. 78type SpanID [8]byte 79 80// Validate validates the span ID. 81// This will return non-nil for a zero span ID. 82func (id SpanID) Validate() error { 83 if id.isZero() { 84 return errZeroSpanID 85 } 86 return nil 87} 88 89func (id SpanID) isZero() bool { 90 return id == SpanID{} 91} 92 93// String returns id encoded as hex. 94func (id SpanID) String() string { 95 text, _ := id.MarshalText() 96 return string(text) 97} 98 99// MarshalText returns id encoded as hex, satisfying encoding.TextMarshaler. 100func (id SpanID) MarshalText() ([]byte, error) { 101 text := make([]byte, hex.EncodedLen(len(id))) 102 hex.Encode(text, id[:]) 103 return text, nil 104} 105 106// TraceOptions describes the options for a trace. 107type TraceOptions uint8 108 109// Recorded reports whether or not the transaction/span may have been (or may be) recorded. 110func (o TraceOptions) Recorded() bool { 111 return (o & traceOptionsRecordedFlag) == traceOptionsRecordedFlag 112} 113 114// WithRecorded changes the "recorded" flag, and returns the new options 115// without modifying the original value. 116func (o TraceOptions) WithRecorded(recorded bool) TraceOptions { 117 if recorded { 118 return o | traceOptionsRecordedFlag 119 } 120 return o & (0xFF ^ traceOptionsRecordedFlag) 121} 122