Skip to content

Commit

Permalink
feat: add store name in tracekv-emitted store traces (backport #11646)
Browse files Browse the repository at this point in the history
* feature: Clone and Merge methods on TraceContext

* chore: use TraceContext.Merge method in SetTracingContext

* feature: add Store name in TraceContext during execution

* chore: update rootmulti Store TraceContext on *Store after Merge()
  • Loading branch information
gsora authored and robert-zaremba committed Apr 27, 2022
1 parent 1dbab82 commit d086df7
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 8 deletions.
10 changes: 9 additions & 1 deletion store/cachemulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import (
"github.com/cosmos/cosmos-sdk/store/types"
)

// storeNameCtxKey is the TraceContext metadata key that identifies
// the store which emitted a given trace.
const storeNameCtxKey = "store_name"

//----------------------------------------
// Store

Expand Down Expand Up @@ -52,7 +56,11 @@ func NewFromKVStore(

for key, store := range stores {
if cms.TracingEnabled() {
store = tracekv.NewStore(store.(types.KVStore), cms.traceWriter, cms.traceContext)
tctx := cms.traceContext.Clone().Merge(types.TraceContext{
storeNameCtxKey: key.Name(),
})

store = tracekv.NewStore(store.(types.KVStore), cms.traceWriter, tctx)
}
if cms.ListeningEnabled(key) {
store = listenkv.NewStore(store.(types.KVStore), key, listeners[key])
Expand Down
8 changes: 1 addition & 7 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,13 +330,7 @@ func (rs *Store) SetTracer(w io.Writer) types.MultiStore {
func (rs *Store) SetTracingContext(tc types.TraceContext) types.MultiStore {
rs.traceContextMutex.Lock()
defer rs.traceContextMutex.Unlock()
if rs.traceContext != nil {
for k, v := range tc {
rs.traceContext[k] = v
}
} else {
rs.traceContext = tc
}
rs.traceContext = rs.traceContext.Merge(tc)

return rs
}
Expand Down
23 changes: 23 additions & 0 deletions store/types/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,29 @@ type KVPair kv.Pair
// every trace operation.
type TraceContext map[string]interface{}

// Clone clones tc into another instance of TraceContext.
func (tc TraceContext) Clone() TraceContext {
ret := TraceContext{}
for k, v := range tc {
ret[k] = v
}

return ret
}

// Merge merges value of newTc into tc.
func (tc TraceContext) Merge(newTc TraceContext) TraceContext {
if tc == nil {
tc = TraceContext{}
}

for k, v := range newTc {
tc[k] = v
}

return tc
}

// MultiStorePersistentCache defines an interface which provides inter-block
// (persistent) caching capabilities for multiple CommitKVStores based on StoreKeys.
type MultiStorePersistentCache interface {
Expand Down
117 changes: 117 additions & 0 deletions store/types/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,120 @@ func TestTransientStoreKey(t *testing.T) {
require.Equal(t, key.name, key.Name())
require.Equal(t, fmt.Sprintf("TransientStoreKey{%p, test}", key), key.String())
}

func TestTraceContext_Clone(t *testing.T) {
tests := []struct {
name string
tc TraceContext
want TraceContext
}{
{
"nil TraceContext yields empty TraceContext",
nil,
TraceContext{},
},
{
"non-nil TraceContext yields equal TraceContext",
TraceContext{
"value": 42,
},
TraceContext{
"value": 42,
},
},
{
"non-nil TraceContext yields equal TraceContext, for more than one key",
TraceContext{
"value": 42,
"another": 24,
"weird": "string",
},
TraceContext{
"value": 42,
"another": 24,
"weird": "string",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, tt.tc.Clone())
})
}
}

func TestTraceContext_Clone_is_deep(t *testing.T) {
original := TraceContext{
"value": 42,
"another": 24,
"weird": "string",
}

clone := original.Clone()

clone["other"] = true

require.NotEqual(t, original, clone)
}

func TestTraceContext_Merge(t *testing.T) {
tests := []struct {
name string
tc TraceContext
other TraceContext
want TraceContext
}{
{
"tc is nil, other is empty, yields an empty TraceContext",
nil,
TraceContext{},
TraceContext{},
},
{
"tc is nil, other is nil, yields an empty TraceContext",
nil,
nil,
TraceContext{},
},
{
"tc is not nil, other is nil, yields tc",
TraceContext{
"data": 42,
},
nil,
TraceContext{
"data": 42,
},
},
{
"tc is not nil, other is not nil, yields tc + other",
TraceContext{
"data": 42,
},
TraceContext{
"data2": 42,
},
TraceContext{
"data": 42,
"data2": 42,
},
},
{
"tc is not nil, other is not nil, other updates value in tc, yields tc updated with value from other",
TraceContext{
"data": 42,
},
TraceContext{
"data": 24,
},
TraceContext{
"data": 24,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, tt.tc.Merge(tt.other))
})
}
}

0 comments on commit d086df7

Please sign in to comment.