Skip to content

Commit

Permalink
remove namespace management (#59)
Browse files Browse the repository at this point in the history
back at the beginning of this package I thought it would be neat to give
users a way to isolate different sets of clues into silos. Afaik it's
never been used, and all it does is duplicate the interfaces. Time for
it to go.
  • Loading branch information
ryanfkeepers authored Oct 31, 2024
1 parent 721af7f commit 1f44bd5
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 288 deletions.
136 changes: 15 additions & 121 deletions clues.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,23 @@ import (

// Add adds all key-value pairs to the clues.
func Add(ctx context.Context, kvs ...any) context.Context {
nc := nodeFromCtx(ctx, defaultNamespace)
return setDefaultNodeInCtx(ctx, nc.addValues(normalize(kvs...)))
}

// AddTo adds all key-value pairs to a namespaced set of clues.
func AddTo(
ctx context.Context,
namespace string,
kvs ...any,
) context.Context {
nc := nodeFromCtx(ctx, ctxKey(namespace))
return setNodeInCtx(ctx, namespace, nc.addValues(normalize(kvs...)))
nc := nodeFromCtx(ctx)
return setNodeInCtx(ctx, nc.addValues(normalize(kvs...)))
}

// AddMap adds a shallow clone of the map to a namespaced set of clues.
func AddMap[K comparable, V any](
ctx context.Context,
m map[K]V,
) context.Context {
nc := nodeFromCtx(ctx, defaultNamespace)

kvs := make([]any, 0, len(m)*2)
for k, v := range m {
kvs = append(kvs, k, v)
}

return setDefaultNodeInCtx(ctx, nc.addValues(normalize(kvs...)))
}

// AddMapTo adds a shallow clone of the map to a namespaced set of clues.
func AddMapTo[K comparable, V any](
ctx context.Context,
namespace string,
m map[K]V,
) context.Context {
nc := nodeFromCtx(ctx, ctxKey(namespace))
nc := nodeFromCtx(ctx)

kvs := make([]any, 0, len(m)*2)
for k, v := range m {
kvs = append(kvs, k, v)
}

return setNodeInCtx(ctx, namespace, nc.addValues(normalize(kvs...)))
return setNodeInCtx(ctx, nc.addValues(normalize(kvs...)))
}

// ---------------------------------------------------------------------------
Expand All @@ -68,19 +42,8 @@ func AddTrace(
ctx context.Context,
traceID string,
) context.Context {
nc := nodeFromCtx(ctx, defaultNamespace)
return setDefaultNodeInCtx(ctx, nc.trace(traceID))
}

// AddTraceTo stacks a clues node onto this context within the specified
// namespace. Adding a node ensures that a point in code is identified
// by an ID, which can later be used to correlate and isolate logs to
// certain trace branches. AddTraceTo is only needed for layers that don't
// otherwise call AddTo() or similar functions, since those funcs already
// attach a new node.
func AddTraceTo(ctx context.Context, traceID, namespace string) context.Context {
nc := nodeFromCtx(ctx, ctxKey(namespace))
return setNodeInCtx(ctx, namespace, nc.trace(traceID))
nc := nodeFromCtx(ctx)
return setNodeInCtx(ctx, nc.trace(traceID))
}

// AddTraceWith stacks a clues node onto this context and uses the provided
Expand All @@ -91,7 +54,7 @@ func AddTraceWith(
traceID string,
kvs ...any,
) context.Context {
nc := nodeFromCtx(ctx, defaultNamespace)
nc := nodeFromCtx(ctx)

var node *dataNode
if len(kvs) > 0 {
Expand All @@ -101,28 +64,7 @@ func AddTraceWith(
node = nc.trace(traceID)
}

return setDefaultNodeInCtx(ctx, node)
}

// AddTraceWithTo stacks a clues node onto this context and uses the provided
// name for the trace id, instead of a randomly generated hash. AddTraceWithTo
// can be called without additional values if you only want to add a trace marker.
func AddTraceWithTo(
ctx context.Context,
traceID, namespace string,
kvs ...any,
) context.Context {
nc := nodeFromCtx(ctx, ctxKey(namespace))

var node *dataNode
if len(kvs) > 0 {
node = nc.addValues(normalize(kvs...))
node.id = traceID
} else {
node = nc.trace(traceID)
}

return setNodeInCtx(ctx, namespace, node)
return setNodeInCtx(ctx, node)
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -155,42 +97,10 @@ func AddComment(
msg string,
vs ...any,
) context.Context {
nc := nodeFromCtx(ctx, defaultNamespace)
nn := nc.addComment(1, msg, vs...)

return setDefaultNodeInCtx(ctx, nn)
}

// AddCommentTo adds a long form comment to the clues in a certain namespace.
//
// Comments are special case additions to the context. They're here to, well,
// let you add comments! Why? Because sometimes it's not sufficient to have a
// log let you know that a line of code was reached. Even a bunch of clues to
// describe system state may not be enough. Sometimes what you need in order
// to debug the situation is a long-form explanation (you do already add that
// to your code, don't you?). Or, even better, a linear history of long-form
// explanations, each one building on the prior (which you can't easily do in
// code).
//
// Should you transfer all your comments to clues? Absolutely not. But in
// cases where extra explantion is truly important to debugging production,
// when all you've got are some logs and (maybe if you're lucky) a span trace?
// Those are the ones you want.
//
// Unlike other additions, which are added as top-level key:value pairs to the
// context, comments are all held as a single array of additions, persisted in
// order of appearance, and prefixed by the file and line in which they appeared.
// This means comments are always added to the context and never clobber each
// other, regardless of their location. IE: don't add them to a loop.
func AddCommentTo(
ctx context.Context,
namespace, msg string,
vs ...any,
) context.Context {
nc := nodeFromCtx(ctx, ctxKey(namespace))
nc := nodeFromCtx(ctx)
nn := nc.addComment(1, msg, vs...)

return setNodeInCtx(ctx, namespace, nn)
return setNodeInCtx(ctx, nn)
}

// ---------------------------------------------------------------------------
Expand All @@ -214,10 +124,10 @@ func AddAgent(
ctx context.Context,
name string,
) context.Context {
nc := nodeFromCtx(ctx, defaultNamespace)
nc := nodeFromCtx(ctx)
nn := nc.addAgent(name)

return setDefaultNodeInCtx(ctx, nn)
return setNodeInCtx(ctx, nn)
}

// Relay adds all key-value pairs to the provided agent. The agent will
Expand All @@ -228,7 +138,7 @@ func Relay(
agent string,
vs ...any,
) {
nc := nodeFromCtx(ctx, defaultNamespace)
nc := nodeFromCtx(ctx)
ag, ok := nc.agents[agent]

if !ok {
Expand All @@ -248,25 +158,9 @@ func Relay(
// LabelCounter will use the label as the key for the Add call, and increment
// the count of that label by one.
func AddLabelCounter(ctx context.Context, counter Adder) context.Context {
nc := nodeFromCtx(ctx, defaultNamespace)
nn := nc.addValues(nil)
nn.labelCounter = counter

return setDefaultNodeInCtx(ctx, nn)
}

// AddLabelCounterTo embeds an Adder interface into this context. Any already
// embedded Adder will get replaced. When adding Labels to a clues.Err the
// LabelCounter will use the label as the key for the Add call, and increment
// the count of that label by one.
func AddLabelCounterTo(
ctx context.Context,
namespace string,
counter Adder,
) context.Context {
nc := nodeFromCtx(ctx, ctxKey(namespace))
nc := nodeFromCtx(ctx)
nn := nc.addValues(nil)
nn.labelCounter = counter

return setNodeInCtx(ctx, namespace, nn)
return setNodeInCtx(ctx, nn)
}
136 changes: 0 additions & 136 deletions clues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,8 @@ func assert(
eS, eSns sa,
) {
vs := clues.In(ctx)
nvs := clues.InNamespace(ctx, ns)
mustEquals(t, eM, vs.Map(), true)
mustEquals(t, eMns, nvs.Map(), true)
eS.equals(t, vs.Slice())
eSns.equals(t, nvs.Slice())
}

func assertMSA(
Expand All @@ -170,11 +167,8 @@ func assertMSA(
eS, eSns sa,
) {
vs := clues.In(ctx)
nvs := clues.InNamespace(ctx, ns)
mustEquals(t, eM, toMSA(vs.Map()), true)
mustEquals(t, eMns, toMSA(nvs.Map()), true)
eS.equals(t, vs.Slice())
eSns.equals(t, nvs.Slice())
}

type testCtx struct{}
Expand Down Expand Up @@ -309,136 +303,6 @@ func TestAddTraceName(t *testing.T) {
}
}

func TestAddTo(t *testing.T) {
table := []struct {
name string
kvs [][]string
expectM msa
expectS sa
}{
{"single", [][]string{{"k", "v"}}, msa{"k": "v"}, sa{"k", "v"}},
{"multiple", [][]string{{"a", "1"}, {"b", "2"}}, msa{"a": "1", "b": "2"}, sa{"a", "1", "b", "2"}},
{"duplicates", [][]string{{"a", "1"}, {"a", "2"}}, msa{"a": "2"}, sa{"a", "2"}},
{"none", [][]string{}, msa{}, sa{}},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
ctx := context.WithValue(context.Background(), testCtx{}, "instance")
check := msa{}
mustEquals(t, check, clues.InNamespace(ctx, "ns").Map(), true)

for _, kv := range test.kvs {
ctx = clues.AddTo(ctx, "ns", kv[0], kv[1])
check[kv[0]] = kv[1]
mustEquals(t, check, clues.InNamespace(ctx, "ns").Map(), true)
}

assert(
t, ctx, "ns",
msa{}, test.expectM,
sa{}, test.expectS)
})
}
}

func TestAddMapTo(t *testing.T) {
table := []struct {
name string
ms []msa
expectM msa
expectS sa
}{
{"single", []msa{{"k": "v"}}, msa{"k": "v"}, sa{"k", "v"}},
{"multiple", []msa{{"a": "1"}, {"b": "2"}}, msa{"a": "1", "b": "2"}, sa{"a", "1", "b", "2"}},
{"duplicate", []msa{{"a": "1"}, {"a": "2"}}, msa{"a": "2"}, sa{"a", "2"}},
{"none", []msa{}, msa{}, sa{}},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
ctx := context.WithValue(context.Background(), testCtx{}, "instance")
check := msa{}
mustEquals(t, check, clues.InNamespace(ctx, "ns").Map(), true)

for _, m := range test.ms {
ctx = clues.AddMapTo(ctx, "ns", m)
for k, v := range m {
check[k] = v
}
mustEquals(t, check, clues.InNamespace(ctx, "ns").Map(), true)
}

assert(
t, ctx, "ns",
msa{}, test.expectM,
sa{}, test.expectS)
})
}
}

func TestAddTraceTo(t *testing.T) {
table := []struct {
name string
expectM msa
expectS sa
}{
{"single", msa{}, sa{}},
{"multiple", msa{}, sa{}},
{"duplicates", msa{}, sa{}},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
ctx := context.WithValue(context.Background(), testCtx{}, "instance")
check := msa{}
mustEquals(t, check, clues.InNamespace(ctx, "ns").Map(), true)

ctx = clues.AddTraceTo(ctx, "", "ns")

assert(
t, ctx, "ns",
msa{}, test.expectM,
sa{}, test.expectS)
})
}
}

func TestAddTraceNameTo(t *testing.T) {
table := []struct {
name string
names []string
expectTrace string
kvs sa
expectM msa
expectS sa
}{
{"single", []string{"single"}, "single", nil, msa{}, sa{}},
{"multiple", []string{"single", "multiple"}, "single,multiple", nil, msa{}, sa{}},
{"duplicates", []string{"single", "multiple", "multiple"}, "single,multiple,multiple", nil, msa{}, sa{}},
{"single with kvs", []string{"single"}, "single", sa{"k", "v"}, msa{"k": "v"}, sa{"k", "v"}},
{"multiple with kvs", []string{"single", "multiple"}, "single,multiple", sa{"k", "v"}, msa{"k": "v"}, sa{"k", "v"}},
{"duplicates with kvs", []string{"single", "multiple", "multiple"}, "single,multiple,multiple", sa{"k", "v"}, msa{"k": "v"}, sa{"k", "v"}},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
ctx := context.WithValue(context.Background(), testCtx{}, "instance")
mustEquals(t, msa{}, clues.InNamespace(ctx, "ns").Map(), true)

for _, name := range test.names {
ctx = clues.AddTraceWithTo(ctx, name, "ns", test.kvs...)
}

assert(
t, ctx, "ns",
msa{}, test.expectM,
sa{}, test.expectS)

c := clues.InNamespace(ctx, "ns").Map()
if c["clues_trace"] != test.expectTrace {
t.Errorf("expected clues_trace to equal %q, got %q", test.expectTrace, c["clues_trace"])
}
})
}
}

func TestImmutableCtx(t *testing.T) {
var (
ctx = context.Background()
Expand Down
Loading

0 comments on commit 1f44bd5

Please sign in to comment.