package trace
import (
"encoding/json"
)
const (
FlagsSampled = TraceFlags (0x01 )
errInvalidHexID errorConst = "trace-id and span-id can only contain [0-9a-f] characters, all lowercase"
errInvalidTraceIDLength errorConst = "hex encoded trace-id must have length equals to 32"
errNilTraceID errorConst = "trace-id can't be all zero"
errInvalidSpanIDLength errorConst = "hex encoded span-id must have length equals to 16"
errNilSpanID errorConst = "span-id can't be all zero"
)
type errorConst string
func (e errorConst ) Error () string {
return string (e )
}
type TraceID [16 ]byte
var (
nilTraceID TraceID
_ json .Marshaler = nilTraceID
)
func (t TraceID ) IsValid () bool {
return t != nilTraceID
}
func (t TraceID ) MarshalJSON () ([]byte , error ) {
b := [32 + 2 ]byte {0 : '"' , 33 : '"' }
h := t .hexBytes ()
copy (b [1 :], h [:])
return b [:], nil
}
func (t TraceID ) String () string {
h := t .hexBytes ()
return string (h [:])
}
func (t TraceID ) hexBytes () [32 ]byte {
return [32 ]byte {
hexLU [t [0x0 ]>>4 ], hexLU [t [0x0 ]&0xf ],
hexLU [t [0x1 ]>>4 ], hexLU [t [0x1 ]&0xf ],
hexLU [t [0x2 ]>>4 ], hexLU [t [0x2 ]&0xf ],
hexLU [t [0x3 ]>>4 ], hexLU [t [0x3 ]&0xf ],
hexLU [t [0x4 ]>>4 ], hexLU [t [0x4 ]&0xf ],
hexLU [t [0x5 ]>>4 ], hexLU [t [0x5 ]&0xf ],
hexLU [t [0x6 ]>>4 ], hexLU [t [0x6 ]&0xf ],
hexLU [t [0x7 ]>>4 ], hexLU [t [0x7 ]&0xf ],
hexLU [t [0x8 ]>>4 ], hexLU [t [0x8 ]&0xf ],
hexLU [t [0x9 ]>>4 ], hexLU [t [0x9 ]&0xf ],
hexLU [t [0xa ]>>4 ], hexLU [t [0xa ]&0xf ],
hexLU [t [0xb ]>>4 ], hexLU [t [0xb ]&0xf ],
hexLU [t [0xc ]>>4 ], hexLU [t [0xc ]&0xf ],
hexLU [t [0xd ]>>4 ], hexLU [t [0xd ]&0xf ],
hexLU [t [0xe ]>>4 ], hexLU [t [0xe ]&0xf ],
hexLU [t [0xf ]>>4 ], hexLU [t [0xf ]&0xf ],
}
}
type SpanID [8 ]byte
var (
nilSpanID SpanID
_ json .Marshaler = nilSpanID
)
func (s SpanID ) IsValid () bool {
return s != nilSpanID
}
func (s SpanID ) MarshalJSON () ([]byte , error ) {
b := [16 + 2 ]byte {0 : '"' , 17 : '"' }
h := s .hexBytes ()
copy (b [1 :], h [:])
return b [:], nil
}
func (s SpanID ) String () string {
b := s .hexBytes ()
return string (b [:])
}
func (s SpanID ) hexBytes () [16 ]byte {
return [16 ]byte {
hexLU [s [0 ]>>4 ], hexLU [s [0 ]&0xf ],
hexLU [s [1 ]>>4 ], hexLU [s [1 ]&0xf ],
hexLU [s [2 ]>>4 ], hexLU [s [2 ]&0xf ],
hexLU [s [3 ]>>4 ], hexLU [s [3 ]&0xf ],
hexLU [s [4 ]>>4 ], hexLU [s [4 ]&0xf ],
hexLU [s [5 ]>>4 ], hexLU [s [5 ]&0xf ],
hexLU [s [6 ]>>4 ], hexLU [s [6 ]&0xf ],
hexLU [s [7 ]>>4 ], hexLU [s [7 ]&0xf ],
}
}
func TraceIDFromHex (h string ) (TraceID , error ) {
if len (h ) != 32 {
return [16 ]byte {}, errInvalidTraceIDLength
}
var b [16 ]byte
invalidMark := byte (0 )
for i := 0 ; i < len (h ); i += 4 {
b [i /2 ] = (hexRev [h [i ]] << 4 ) | hexRev [h [i +1 ]]
b [i /2 +1 ] = (hexRev [h [i +2 ]] << 4 ) | hexRev [h [i +3 ]]
invalidMark |= hexRev [h [i ]] | hexRev [h [i +1 ]] | hexRev [h [i +2 ]] | hexRev [h [i +3 ]]
}
if invalidMark &0xf0 != 0 {
return [16 ]byte {}, errInvalidHexID
}
if invalidMark == 0 {
return [16 ]byte {}, errNilTraceID
}
return b , nil
}
func SpanIDFromHex (h string ) (SpanID , error ) {
if len (h ) != 16 {
return [8 ]byte {}, errInvalidSpanIDLength
}
var b [8 ]byte
invalidMark := byte (0 )
for i := 0 ; i < len (h ); i += 4 {
b [i /2 ] = (hexRev [h [i ]] << 4 ) | hexRev [h [i +1 ]]
b [i /2 +1 ] = (hexRev [h [i +2 ]] << 4 ) | hexRev [h [i +3 ]]
invalidMark |= hexRev [h [i ]] | hexRev [h [i +1 ]] | hexRev [h [i +2 ]] | hexRev [h [i +3 ]]
}
if invalidMark &0xf0 != 0 {
return [8 ]byte {}, errInvalidHexID
}
if invalidMark == 0 {
return [8 ]byte {}, errNilSpanID
}
return b , nil
}
type TraceFlags byte
func (tf TraceFlags ) IsSampled () bool {
return tf &FlagsSampled == FlagsSampled
}
func (tf TraceFlags ) WithSampled (sampled bool ) TraceFlags {
if sampled {
return tf | FlagsSampled
}
return tf &^ FlagsSampled
}
func (tf TraceFlags ) MarshalJSON () ([]byte , error ) {
b := [2 + 2 ]byte {0 : '"' , 3 : '"' }
h := tf .hexBytes ()
copy (b [1 :], h [:])
return b [:], nil
}
func (tf TraceFlags ) String () string {
h := tf .hexBytes ()
return string (h [:])
}
func (tf TraceFlags ) hexBytes () [2 ]byte {
return [2 ]byte {hexLU [tf >>4 ], hexLU [tf &0xf ]}
}
type SpanContextConfig struct {
TraceID TraceID
SpanID SpanID
TraceFlags TraceFlags
TraceState TraceState
Remote bool
}
func NewSpanContext (config SpanContextConfig ) SpanContext {
return SpanContext {
traceID : config .TraceID ,
spanID : config .SpanID ,
traceFlags : config .TraceFlags ,
traceState : config .TraceState ,
remote : config .Remote ,
}
}
type SpanContext struct {
traceID TraceID
spanID SpanID
traceFlags TraceFlags
traceState TraceState
remote bool
}
var _ json .Marshaler = SpanContext {}
func (sc SpanContext ) IsValid () bool {
return sc .HasTraceID () && sc .HasSpanID ()
}
func (sc SpanContext ) IsRemote () bool {
return sc .remote
}
func (sc SpanContext ) WithRemote (remote bool ) SpanContext {
return SpanContext {
traceID : sc .traceID ,
spanID : sc .spanID ,
traceFlags : sc .traceFlags ,
traceState : sc .traceState ,
remote : remote ,
}
}
func (sc SpanContext ) TraceID () TraceID {
return sc .traceID
}
func (sc SpanContext ) HasTraceID () bool {
return sc .traceID .IsValid ()
}
func (sc SpanContext ) WithTraceID (traceID TraceID ) SpanContext {
return SpanContext {
traceID : traceID ,
spanID : sc .spanID ,
traceFlags : sc .traceFlags ,
traceState : sc .traceState ,
remote : sc .remote ,
}
}
func (sc SpanContext ) SpanID () SpanID {
return sc .spanID
}
func (sc SpanContext ) HasSpanID () bool {
return sc .spanID .IsValid ()
}
func (sc SpanContext ) WithSpanID (spanID SpanID ) SpanContext {
return SpanContext {
traceID : sc .traceID ,
spanID : spanID ,
traceFlags : sc .traceFlags ,
traceState : sc .traceState ,
remote : sc .remote ,
}
}
func (sc SpanContext ) TraceFlags () TraceFlags {
return sc .traceFlags
}
func (sc SpanContext ) IsSampled () bool {
return sc .traceFlags .IsSampled ()
}
func (sc SpanContext ) WithTraceFlags (flags TraceFlags ) SpanContext {
return SpanContext {
traceID : sc .traceID ,
spanID : sc .spanID ,
traceFlags : flags ,
traceState : sc .traceState ,
remote : sc .remote ,
}
}
func (sc SpanContext ) TraceState () TraceState {
return sc .traceState
}
func (sc SpanContext ) WithTraceState (state TraceState ) SpanContext {
return SpanContext {
traceID : sc .traceID ,
spanID : sc .spanID ,
traceFlags : sc .traceFlags ,
traceState : state ,
remote : sc .remote ,
}
}
func (sc SpanContext ) Equal (other SpanContext ) bool {
return sc .traceID == other .traceID &&
sc .spanID == other .spanID &&
sc .traceFlags == other .traceFlags &&
sc .traceState .String () == other .traceState .String () &&
sc .remote == other .remote
}
func (sc SpanContext ) MarshalJSON () ([]byte , error ) {
return json .Marshal (SpanContextConfig {
TraceID : sc .traceID ,
SpanID : sc .spanID ,
TraceFlags : sc .traceFlags ,
TraceState : sc .traceState ,
Remote : sc .remote ,
})
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .