Skip to content

Commit

Permalink
change to use the options pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
NLincoln committed Jan 10, 2024
1 parent 1cb8b4f commit 9ba1ae7
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 30 deletions.
50 changes: 23 additions & 27 deletions trace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,41 +120,37 @@ func NewTrace(ctx context.Context, prop *propagation.PropagationContext) (contex
return NewTraceFromPropagationContext(ctx, prop)
}

type addFieldOptions struct {
isOverridable *bool
}

func Overridable(overridable bool) addFieldOptions {
return addFieldOptions{isOverridable: &overridable}
}

// AddField adds a field to the trace. Every span in the trace will have this
// field added to it. These fields are also passed along to downstream services.
// It is useful to add fields here that pertain to the entire trace, to aid in
// filtering spans at many different areas of the trace together.
func (t *Trace) AddField(key string, val interface{}) {
func (t *Trace) AddField(key string, val interface{}, opts ...addFieldOptions) {
t.tlfLock.Lock()
defer t.tlfLock.Unlock()
if t.traceLevelFields != nil {
t.traceLevelFields[key] = val
isOverridable := false

for _, opt := range opts {
if opt.isOverridable != nil {
isOverridable = *opt.isOverridable
}
}
}

// AddOverridableField adds a default field to the trace.
// It is similar to AddField, with two key differences:
// 1. Individual spans can override the value at a per-span level, using AddField on the Span.
//
// Overriding a field on a span does not override the entire subtree - in the following hypothetical
// trace, overriding a field on the parent span will not override that field in the child span.
//
// root
// parent
// child
//
// 2. Overridable fields are sent to downstream services, but we cannot encode the "overrideability"
// of the field in the propagation context, so the field will cease to be overrideable in the downstream
// service.
//
// AddOverridableField is best suited to niche cases where you are not propagating the span context,
//
// or cases where you only wish to overwrite the field in a small number of cases, usually in leaf spans.
func (t *Trace) AddOverridableField(key string, val interface{}) {
t.tlfLock.Lock()
defer t.tlfLock.Unlock()
if t.overridableTraceLevelFields != nil {
t.overridableTraceLevelFields[key] = val
if isOverridable {
if t.overridableTraceLevelFields != nil {
t.overridableTraceLevelFields[key] = val
}
} else {
if t.traceLevelFields != nil {
t.traceLevelFields[key] = val
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions trace/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,10 @@ func TestTraceLevelFields(t *testing.T) {
// span will attempt to override, but will fail to do so
tr.AddField("overridden", 1)
// span will attempt to override, and will succeed
tr.AddOverridableField("overridden_overridable", 1)
tr.AddField("overridden_overridable", 1, Overridable(true))
// span will leave these alone
tr.AddOverridableField("left_alone", 1)
tr.AddOverridableField("left_alone_overridable", 1)
tr.AddField("left_alone", 1)
tr.AddField("left_alone_overridable", 1, Overridable(true))

rs := tr.GetRootSpan()
rs.AddField("overridden", 2)
Expand Down

0 comments on commit 9ba1ae7

Please sign in to comment.