From 1562c4e8f62269b40f641fcd590354383ae974b4 Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Mon, 14 Jan 2019 22:32:26 -0500 Subject: [PATCH] mlog: redefine KVer to return a map[string]interface, not a KV, to allow other packages to implement KVer without importing mlog --- mcrypto/pair.go | 8 ++++---- mcrypto/sig.go | 4 ++-- mcrypto/uuid.go | 4 ++-- mlog/mlog.go | 51 +++++++++++++++++++++++++++-------------------- mlog/mlog_test.go | 26 ++++++++++++------------ mnet/mnet.go | 4 ++-- 6 files changed, 52 insertions(+), 45 deletions(-) diff --git a/mcrypto/pair.go b/mcrypto/pair.go index 2e4cf5d..651f0ed 100644 --- a/mcrypto/pair.go +++ b/mcrypto/pair.go @@ -73,8 +73,8 @@ func (pk PublicKey) String() string { } // KV implements the method for the mlog.KVer interface -func (pk PublicKey) KV() mlog.KV { - return mlog.KV{"publicKey": pk.String()} +func (pk PublicKey) KV() map[string]interface{} { + return map[string]interface{}{"publicKey": pk.String()} } // MarshalText implements the method for the encoding.TextMarshaler interface @@ -169,8 +169,8 @@ func (pk PrivateKey) String() string { } // KV implements the method for the mlog.KVer interface -func (pk PrivateKey) KV() mlog.KV { - return mlog.KV{"privateKey": pk.String()} +func (pk PrivateKey) KV() map[string]interface{} { + return map[string]interface{}{"privateKey": pk.String()} } // MarshalText implements the method for the encoding.TextMarshaler interface diff --git a/mcrypto/sig.go b/mcrypto/sig.go index b8c2f6c..42259ed 100644 --- a/mcrypto/sig.go +++ b/mcrypto/sig.go @@ -51,8 +51,8 @@ func (s Signature) String() string { } // KV implements the method for the mlog.KVer interface -func (s Signature) KV() mlog.KV { - return mlog.KV{"sig": s.String()} +func (s Signature) KV() map[string]interface{} { + return map[string]interface{}{"sig": s.String()} } // MarshalText implements the method for the encoding.TextMarshaler interface diff --git a/mcrypto/uuid.go b/mcrypto/uuid.go index 1a50e85..2773e66 100644 --- a/mcrypto/uuid.go +++ b/mcrypto/uuid.go @@ -53,8 +53,8 @@ func (u UUID) Time() time.Time { } // KV implements the method for the mlog.KVer interface -func (u UUID) KV() mlog.KV { - return mlog.KV{"uuid": u.String()} +func (u UUID) KV() map[string]interface{} { + return map[string]interface{}{"uuid": u.String()} } // MarshalText implements the method for the encoding.TextMarshaler interface diff --git a/mlog/mlog.go b/mlog/mlog.go index e7fcdce..8d2fe74 100644 --- a/mlog/mlog.go +++ b/mlog/mlog.go @@ -76,26 +76,25 @@ var ( // KVer is used to provide context to a log entry in the form of a dynamic set // of key/value pairs which can be different for every entry. // -// Each returned KV should be modifiable. +// Each returned map should be modifiable. type KVer interface { - KV() KV + KV() map[string]interface{} } // KVerFunc is a function which implements the KVer interface by calling itself. -type KVerFunc func() KV +type KVerFunc func() map[string]interface{} // KV implements the KVer interface by calling the KVerFunc itself. -func (kvf KVerFunc) KV() KV { +func (kvf KVerFunc) KV() map[string]interface{} { return kvf() } -// KV is a set of key/value pairs which provides context for a log entry by a -// KVer. KV is itself also a KVer. +// KV is a KVer which returns a copy of itself when KV is called. type KV map[string]interface{} -// KV implements the KVer method by returning a copy of the KV -func (kv KV) KV() KV { - nkv := make(KV, len(kv)) +// KV implements the KVer method by returning a copy of itself. +func (kv KV) KV() map[string]interface{} { + nkv := make(map[string]interface{}, len(kv)) for k, v := range kv { nkv[k] = v } @@ -110,17 +109,25 @@ func (kv KV) Set(k string, v interface{}) KV { return nkv } +// returns a key/value map which should not be written to. saves a map-cloning +// if KVer is a KV +func readOnlyKVM(kver KVer) map[string]interface{} { + if kver == nil { + return map[string]interface{}(nil) + } else if kv, ok := kver.(KV); ok { + return map[string]interface{}(kv) + } + return kver.KV() +} + // this may take in any amount of nil values, but should never return nil -func mergeInto(kv KVer, kvs ...KVer) KV { +func mergeInto(kv KVer, kvs ...KVer) map[string]interface{} { if kv == nil { kv = KV(nil) // will return empty map when KV is called on it } kvm := kv.KV() - for _, kv := range kvs { - if kv == nil { - continue - } - for k, v := range kv.KV() { + for _, innerKV := range kvs { + for k, v := range readOnlyKVM(innerKV) { kvm[k] = v } } @@ -150,20 +157,20 @@ func MergeInto(kv KVer, kvs ...KVer) KVer { return merger{base: kv, rest: kvs} } -func (m merger) KV() KV { +func (m merger) KV() map[string]interface{} { return mergeInto(m.base, m.rest...) } // Prefix prefixes the all keys returned from the given KVer with the given // prefix string. func Prefix(kv KVer, prefix string) KVer { - return KVerFunc(func() KV { - kvv := kv.KV() - newKVV := make(KV, len(kvv)) - for k, v := range kvv { - newKVV[prefix+k] = v + return KVerFunc(func() map[string]interface{} { + kvm := readOnlyKVM(kv) + newKVM := make(map[string]interface{}, len(kvm)) + for k, v := range kvm { + newKVM[prefix+k] = v } - return newKVV + return newKVM }) } diff --git a/mlog/mlog_test.go b/mlog/mlog_test.go index 2dd495d..b9a0417 100644 --- a/mlog/mlog_test.go +++ b/mlog/mlog_test.go @@ -25,23 +25,23 @@ func TestKV(t *T) { massert.Len(kv.KV(), 0), )) - // test that the KV method returns a new KV instance + // test that the KV method returns a copy kv = KV{"foo": "a"} - kv2 := kv.KV() + kvm := kv.KV() kv["bur"] = "b" - kv2["bar"] = "bb" + kvm["bar"] = "bb" massert.Fatal(t, massert.All( massert.Equal(KV{"foo": "a", "bur": "b"}, kv), - massert.Equal(KV{"foo": "a", "bar": "bb"}, kv2), + massert.Equal(map[string]interface{}{"foo": "a", "bar": "bb"}, kvm), )) - // test that the Set method returns a new KV instance + // test that the Set method returns a copy kv = KV{"foo": "a"} - kv2 = kv.Set("bar", "wat") + kvm = kv.Set("bar", "wat") kv["bur"] = "ok" massert.Fatal(t, massert.All( massert.Equal(KV{"foo": "a", "bur": "ok"}, kv), - massert.Equal(KV{"foo": "a", "bar": "wat"}, kv2), + massert.Equal(map[string]interface{}{"foo": "a", "bar": "wat"}, kvm), )) } @@ -144,7 +144,7 @@ func TestDefaultFormat(t *T) { func TestMerge(t *T) { assertMerge := func(exp KV, kvs ...KVer) massert.Assertion { - return massert.Equal(exp, Merge(kvs...).KV()) + return massert.Equal(exp.KV(), Merge(kvs...).KV()) } massert.Fatal(t, massert.All( @@ -178,8 +178,8 @@ func TestMerge(t *T) { kv["a"] = "b" massert.Fatal(t, massert.All( massert.Equal(KV{"a": "b"}, kv), - massert.Equal(KV{"a": "b"}, kv.KV()), - massert.Equal(KV{"a": "b"}, mergedKV.KV()), + massert.Equal(map[string]interface{}{"a": "b"}, kv.KV()), + massert.Equal(map[string]interface{}{"a": "b"}, mergedKV.KV()), )) } } @@ -189,8 +189,8 @@ func TestPrefix(t *T) { prefixKV := Prefix(kv, "aa") massert.Fatal(t, massert.All( - massert.Equal(kv.KV(), KV{"foo": "bar"}), - massert.Equal(prefixKV.KV(), KV{"aafoo": "bar"}), - massert.Equal(kv.KV(), KV{"foo": "bar"}), + massert.Equal(map[string]interface{}{"foo": "bar"}, kv.KV()), + massert.Equal(map[string]interface{}{"aafoo": "bar"}, prefixKV.KV()), + massert.Equal(map[string]interface{}{"foo": "bar"}, kv.KV()), )) } diff --git a/mnet/mnet.go b/mnet/mnet.go index b7867ac..725e545 100644 --- a/mnet/mnet.go +++ b/mnet/mnet.go @@ -53,8 +53,8 @@ func MListen(ctx mctx.Context, network, defaultAddr string) net.Listener { return l } -func (l *listener) KV() mlog.KV { - return mlog.KV{"addr": l.Addr().String()} +func (l *listener) KV() map[string]interface{} { + return map[string]interface{}{"addr": l.Addr().String()} } ////////////////////////////////////////////////////////////////////////////////