feat: add store name in `tracekv`-emitted store traces (#11646)

* 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()
This commit is contained in:
Gianguido Sorà 2022-04-14 18:44:22 +02:00 committed by GitHub
parent 0dbf7dce06
commit ce44b35cac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 150 additions and 8 deletions

View File

@ -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
@ -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])

View File

@ -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
}

View File

@ -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 {

View File

@ -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))
})
}
}