Skip to content

Commit

Permalink
add the option to clobber to clients or not
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanfkeepers committed Dec 3, 2024
1 parent 0dc56d0 commit a284603
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 28 deletions.
7 changes: 4 additions & 3 deletions chttp/chttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ func NewInheritorHTTPMiddleware(
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rctx := r.Context()

rctx = clues.Inherit(ctx, rctx)
rctx = clog.Inherit(ctx, rctx)
rctx = ctats.Inherit(ctx, rctx)
// always assume the request context needs to be clobbered.
rctx = clues.Inherit(ctx, rctx, true)
rctx = clog.Inherit(ctx, rctx, true)
rctx = ctats.Inherit(ctx, rctx, true)

r = r.WithContext(rctx)

Expand Down
8 changes: 6 additions & 2 deletions clog/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,11 @@ func Flush(ctx context.Context) {
// is available for request-bound conetxts, such as in a http server pattern.
//
// If the 'to' context already contains an initialized logger, no change is made.
func Inherit(from, to context.Context) context.Context {
// Callers can force a 'from' logger to override a 'to' logger by setting clobber=true.
func Inherit(
from, to context.Context,
clobber bool,
) context.Context {
fromClogger, foundFrom := fromCtx(from)
_, foundTo := fromCtx(to)

Expand All @@ -275,7 +279,7 @@ func Inherit(from, to context.Context) context.Context {
}

// return the 'to' context unmodified if we won't update the context.
if !foundFrom || foundTo {
if !foundFrom || (foundTo && !clobber) {
return to
}

Expand Down
27 changes: 22 additions & 5 deletions clog/logger_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ func TestInherit(t *testing.T) {
stubClogger2 := &clogger{}

table := []struct {
name string
from func() context.Context
to func() context.Context
assert func(t *testing.T, ctx context.Context)
name string
from func() context.Context
to func() context.Context
clobber bool
assert func(t *testing.T, ctx context.Context)
}{
{
name: "from: nil, to: nil",
Expand Down Expand Up @@ -129,10 +130,26 @@ func TestInherit(t *testing.T) {
assert.Equal(t, stubClogger2, logger)
},
},
{
name: "from: populated, to: populated, clobbered",
from: func() context.Context {
return plantLoggerInCtx(context.Background(), stubClogger1)
},
to: func() context.Context {
return plantLoggerInCtx(context.Background(), stubClogger2)
},
clobber: true,
assert: func(t *testing.T, ctx context.Context) {
logger, found := fromCtx(ctx)
require.NotNil(t, logger)
assert.True(t, found)
assert.Equal(t, stubClogger1, logger)
},
},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
result := Inherit(test.from(), test.to())
result := Inherit(test.from(), test.to(), test.clobber)
require.NotNil(t, result)
test.assert(t, result)
})
Expand Down
21 changes: 15 additions & 6 deletions clues.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,31 @@ func Close(ctx context.Context) error {
// are available for request-bound conetxts, such as in a http server pattern.
//
// If the 'to' context already contains an initialized client, no change is made.
func Inherit(from, to context.Context) context.Context {
// Callers can force a 'from' client to override a 'to' client by setting clobber=true.
func Inherit(
from, to context.Context,
clobber bool,
) context.Context {
fromNode := node.FromCtx(from)
toNode := node.FromCtx(to)

if toNode.OTEL == nil && fromNode.OTEL != nil {
toNode.OTEL = fromNode.OTEL
// A span may already exist in the 'to' context thanks to otel packar integration.
if to == nil {
to = context.Background()
} else if toNode.Span == nil {
// A span may already exist in the 'to' context thanks to otel package integration.
// Likewise, the 'from' ctx is not expected to contain a span, so we only want to
// maintain the span information that's currently live.
toNode.Span = trace.SpanFromContext(to)
}

if to == nil {
to = context.Background()
// if we have no fromNode OTEL, or are not clobbering, return the toNode.
if fromNode.OTEL == nil || (toNode.OTEL != nil && !clobber) {
return node.EmbedInCtx(to, toNode)
}

// otherwise pass along the fromNode OTEL client.
toNode.OTEL = fromNode.OTEL

return node.EmbedInCtx(to, toNode)
}

Expand Down
36 changes: 31 additions & 5 deletions clues_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import (

func TestInherit(t *testing.T) {
table := []struct {
name string
from func() context.Context
to func() context.Context
assert func(t *testing.T, ctx context.Context)
name string
from func() context.Context
to func() context.Context
clobber bool
assert func(t *testing.T, ctx context.Context)
}{
{
name: "from: nil, to: nil",
Expand Down Expand Up @@ -145,10 +146,35 @@ func TestInherit(t *testing.T) {
assert.Equal(t, "to", n.OTEL.ServiceName)
},
},
{
name: "from: populated, to: populated, clobbered",
from: func() context.Context {
n := node.Node{
OTEL: &node.OTELClient{
ServiceName: "from",
},
}
return node.EmbedInCtx(context.Background(), &n)
},
to: func() context.Context {
n := node.Node{
OTEL: &node.OTELClient{
ServiceName: "to",
},
}
return node.EmbedInCtx(context.Background(), &n)
},
clobber: true,
assert: func(t *testing.T, ctx context.Context) {
n := node.FromCtx(ctx)
require.NotNil(t, n.OTEL)
assert.Equal(t, "from", n.OTEL.ServiceName)
},
},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
result := Inherit(test.from(), test.to())
result := Inherit(test.from(), test.to(), test.clobber)
require.NotNil(t, result)
test.assert(t, result)
})
Expand Down
8 changes: 6 additions & 2 deletions ctats/ctats.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ func Initialize(ctx context.Context) (context.Context, error) {
// is available for request-bound conetxts, such as in a http server pattern.
//
// If the 'to' context already contains an initialized ctats, no change is made.
func Inherit(from, to context.Context) context.Context {
// Callers can force a 'from' ctats to override a 'to' ctats by setting clobber=true.
func Inherit(
from, to context.Context,
clobber bool,
) context.Context {
fromBus := fromCtx(from)
toBus := fromCtx(to)

Expand All @@ -81,7 +85,7 @@ func Inherit(from, to context.Context) context.Context {
}

// return the 'to' context unmodified if we won't update the context.
if fromBus == nil || toBus != nil {
if fromBus == nil || (toBus != nil && !clobber) {
return to
}

Expand Down
26 changes: 21 additions & 5 deletions ctats/ctats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ func TestInherit(t *testing.T) {
stubBus2 := &bus{}

table := []struct {
name string
from func() context.Context
to func() context.Context
assert func(t *testing.T, ctx context.Context)
name string
from func() context.Context
to func() context.Context
clobber bool
assert func(t *testing.T, ctx context.Context)
}{
{
name: "from: nil, to: nil",
Expand Down Expand Up @@ -181,10 +182,25 @@ func TestInherit(t *testing.T) {
assert.Equal(t, stubBus2, b)
},
},
{
name: "from: populated, to: populated, clobbered",
from: func() context.Context {
return embedInCtx(context.Background(), stubBus1)
},
to: func() context.Context {
return embedInCtx(context.Background(), stubBus2)
},
clobber: true,
assert: func(t *testing.T, ctx context.Context) {
b := fromCtx(ctx)
require.NotNil(t, b)
assert.Equal(t, stubBus1, b)
},
},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
result := Inherit(test.from(), test.to())
result := Inherit(test.from(), test.to(), test.clobber)
require.NotNil(t, result)
test.assert(t, result)
})
Expand Down

0 comments on commit a284603

Please sign in to comment.