91 lines
2.0 KiB
Go
91 lines
2.0 KiB
Go
|
package sentry
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"encoding/json"
|
||
|
)
|
||
|
|
||
|
type PropagationContext struct {
|
||
|
TraceID TraceID `json:"trace_id"`
|
||
|
SpanID SpanID `json:"span_id"`
|
||
|
ParentSpanID SpanID `json:"parent_span_id"`
|
||
|
DynamicSamplingContext DynamicSamplingContext `json:"-"`
|
||
|
}
|
||
|
|
||
|
func (p PropagationContext) MarshalJSON() ([]byte, error) {
|
||
|
type propagationContext PropagationContext
|
||
|
var parentSpanID string
|
||
|
if p.ParentSpanID != zeroSpanID {
|
||
|
parentSpanID = p.ParentSpanID.String()
|
||
|
}
|
||
|
return json.Marshal(struct {
|
||
|
*propagationContext
|
||
|
ParentSpanID string `json:"parent_span_id,omitempty"`
|
||
|
}{
|
||
|
propagationContext: (*propagationContext)(&p),
|
||
|
ParentSpanID: parentSpanID,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func (p PropagationContext) Map() map[string]interface{} {
|
||
|
m := map[string]interface{}{
|
||
|
"trace_id": p.TraceID,
|
||
|
"span_id": p.SpanID,
|
||
|
}
|
||
|
|
||
|
if p.ParentSpanID != zeroSpanID {
|
||
|
m["parent_span_id"] = p.ParentSpanID
|
||
|
}
|
||
|
|
||
|
return m
|
||
|
}
|
||
|
|
||
|
func NewPropagationContext() PropagationContext {
|
||
|
p := PropagationContext{}
|
||
|
|
||
|
if _, err := rand.Read(p.TraceID[:]); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
if _, err := rand.Read(p.SpanID[:]); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func PropagationContextFromHeaders(trace, baggage string) (PropagationContext, error) {
|
||
|
p := NewPropagationContext()
|
||
|
|
||
|
if _, err := rand.Read(p.SpanID[:]); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
hasTrace := false
|
||
|
if trace != "" {
|
||
|
if tpc, valid := ParseTraceParentContext([]byte(trace)); valid {
|
||
|
hasTrace = true
|
||
|
p.TraceID = tpc.TraceID
|
||
|
p.ParentSpanID = tpc.ParentSpanID
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if baggage != "" {
|
||
|
dsc, err := DynamicSamplingContextFromHeader([]byte(baggage))
|
||
|
if err != nil {
|
||
|
return PropagationContext{}, err
|
||
|
}
|
||
|
p.DynamicSamplingContext = dsc
|
||
|
}
|
||
|
|
||
|
// In case a sentry-trace header is present but there are no sentry-related
|
||
|
// values in the baggage, create an empty, frozen DynamicSamplingContext.
|
||
|
if hasTrace && !p.DynamicSamplingContext.HasEntries() {
|
||
|
p.DynamicSamplingContext = DynamicSamplingContext{
|
||
|
Frozen: true,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return p, nil
|
||
|
}
|