mlog: remove ErrKV/ErrWithKV, merr.KV/merr.WithValue are used instead
This commit is contained in:
parent
56f3e71acd
commit
0e80e1fd3d
13
README.md
13
README.md
@ -4,14 +4,13 @@ This is a collection of packages which I use across many of my personal
|
||||
projects. All packages intended to be used start with an `m`, packages not
|
||||
starting with `m` are for internal use within this set of packages.
|
||||
|
||||
Other third-party packages which integrate into these:
|
||||
## Usage notes
|
||||
|
||||
* [merry](github.com/ansel1/merry): used by `mlog` to embed KV logging
|
||||
information into `error` instances, it should be assumed that all errors
|
||||
returned from these packages are `merry.Error` instances. In cases where a
|
||||
package has a specific error it might return and which might be checked for a
|
||||
function to perform that equality check will be supplied as part of the
|
||||
package.
|
||||
* In general, all checking of equality of errors, e.g. `err == io.EOF`, done on
|
||||
errors returned from the packages in this project should be done using
|
||||
`merr.Equal`, e.g. `merr.Equal(err, io.EOF)`. The `merr` package is used to
|
||||
wrap errors and embed further metadata in them, like stack traces and so
|
||||
forth.
|
||||
|
||||
## Styleguide
|
||||
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -58,7 +58,7 @@ func (pk PublicKey) verify(s Signature, r io.Reader) error {
|
||||
return err
|
||||
}
|
||||
if err := rsa.VerifyPSS(&pk.PublicKey, crypto.SHA256, h.Sum(nil), s.sig, nil); err != nil {
|
||||
return mlog.ErrWithKV(ErrInvalidSig, s)
|
||||
return merr.WithValue(ErrInvalidSig, "sig", s, true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -88,12 +88,12 @@ func (pk *PublicKey) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, pubKeyV0)
|
||||
if !ok || len(strEnc) <= hex.EncodedLen(8) {
|
||||
return mlog.ErrWithKV(errMalformedPublicKey, mlog.KV{"pubKeyStr": str})
|
||||
return merr.WithValue(errMalformedPublicKey, "pubKeyStr", str, true)
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return mlog.ErrWithKV(err, mlog.KV{"pubKeyStr": str})
|
||||
return merr.WithValue(err, "pubKeyStr", str, true)
|
||||
}
|
||||
|
||||
pk.E = int(binary.BigEndian.Uint64(b))
|
||||
@ -184,17 +184,17 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, privKeyV0)
|
||||
if !ok {
|
||||
return mlog.ErrWithKV(errMalformedPrivateKey, mlog.KV{"privKeyStr": str})
|
||||
return merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return mlog.ErrWithKV(err, mlog.KV{"privKeyStr": str})
|
||||
return merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
|
||||
e, n := binary.Uvarint(b)
|
||||
if n <= 0 {
|
||||
return mlog.ErrWithKV(errMalformedPrivateKey, mlog.KV{"privKeyStr": str})
|
||||
return merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
pk.PublicKey.E = int(e)
|
||||
b = b[n:]
|
||||
@ -205,7 +205,7 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
||||
}
|
||||
l, n := binary.Uvarint(b)
|
||||
if n <= 0 {
|
||||
err = errMalformedPrivateKey
|
||||
err = merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
b = b[n:]
|
||||
i := new(big.Int)
|
||||
@ -221,7 +221,7 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return mlog.ErrWithKV(err, mlog.KV{"privKeyStr": str})
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
)
|
||||
|
||||
// Secret contains a set of bytes which are inteded to remain secret within some
|
||||
@ -76,9 +76,9 @@ func (s Secret) sign(r io.Reader) (Signature, error) {
|
||||
func (s Secret) verify(sig Signature, r io.Reader) error {
|
||||
sigB, err := s.signRaw(r, uint8(len(sig.sig)), sig.salt, sig.t)
|
||||
if err != nil {
|
||||
return mlog.ErrWithKV(err, sig)
|
||||
return merr.WithValue(err, "sig", sig, true)
|
||||
} else if !hmac.Equal(sigB, sig.sig) {
|
||||
return mlog.ErrWithKV(ErrInvalidSig, sig)
|
||||
return merr.WithValue(ErrInvalidSig, "sig", sig, true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
. "testing"
|
||||
"time"
|
||||
|
||||
"github.com/ansel1/merry"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -43,9 +43,9 @@ func TestSecretSignVerify(t *T) {
|
||||
assert.NotEqual(t, prevSig.String(), thisSigStr)
|
||||
assert.NotEqual(t, prevWeakSig.String(), thisWeakSigStr)
|
||||
err := VerifyString(secret, prevSig, thisStr)
|
||||
assert.True(t, merry.Is(err, ErrInvalidSig))
|
||||
assert.True(t, merr.Equal(err, ErrInvalidSig))
|
||||
err = VerifyString(secret, prevWeakSig, thisStr)
|
||||
assert.True(t, merry.Is(err, ErrInvalidSig))
|
||||
assert.True(t, merr.Equal(err, ErrInvalidSig))
|
||||
}
|
||||
prevStr = thisStr
|
||||
prevSig = thisSig
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -66,12 +66,12 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, sigV0)
|
||||
if !ok || len(strEnc) < hex.EncodedLen(10) {
|
||||
return mlog.ErrWithKV(errMalformedSig, mlog.KV{"sigStr": str})
|
||||
return merr.WithValue(errMalformedSig, "sigStr", str, true)
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return mlog.ErrWithKV(err, mlog.KV{"sigStr": str})
|
||||
return merr.WithValue(err, "sigStr", str, true)
|
||||
}
|
||||
|
||||
unixNano, b := int64(binary.BigEndian.Uint64(b[:8])), b[8:]
|
||||
@ -81,7 +81,7 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
} else if len(b) < 1+int(b[0]) {
|
||||
err = mlog.ErrWithKV(errMalformedSig, mlog.KV{"sigStr": str})
|
||||
err = merr.WithValue(errMalformedSig, "sigStr", str, true)
|
||||
return nil
|
||||
}
|
||||
out := b[1 : 1+b[0]]
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
. "testing"
|
||||
"time"
|
||||
|
||||
"github.com/ansel1/merry"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -36,7 +36,7 @@ func TestSignerVerifier(t *T) {
|
||||
if prevStr != "" {
|
||||
assert.NotEqual(t, prevSig.String(), thisSigStr)
|
||||
err := VerifyString(secret, prevSig, thisStr)
|
||||
assert.True(t, merry.Is(err, ErrInvalidSig))
|
||||
assert.True(t, merr.Equal(err, ErrInvalidSig))
|
||||
}
|
||||
prevStr = thisStr
|
||||
prevSig = thisSig
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
)
|
||||
|
||||
var errMalformedUUID = errors.New("malformed UUID string")
|
||||
@ -68,11 +68,11 @@ func (u *UUID) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, uuidV0)
|
||||
if !ok || len(strEnc) != hex.EncodedLen(16) {
|
||||
return mlog.ErrWithKV(errMalformedUUID, mlog.KV{"uuidStr": str})
|
||||
return merr.WithValue(errMalformedUUID, "uuidStr", str, true)
|
||||
}
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return mlog.ErrWithKV(err, mlog.KV{"uuidStr": str})
|
||||
return merr.WithValue(err, "uuidStr", str, true)
|
||||
}
|
||||
u.b = b
|
||||
return nil
|
||||
|
@ -2,52 +2,10 @@ package mlog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ansel1/merry"
|
||||
)
|
||||
|
||||
type kvKey int
|
||||
|
||||
// ErrWithKV embeds the merging of a set of KVs into an error, returning a new
|
||||
// error instance. If the error already has a KV embedded in it then the
|
||||
// returned error will have the merging of them all, with the given KVs taking
|
||||
// precedence.
|
||||
func ErrWithKV(err error, kvs ...KVer) merry.Error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
merr := merry.WrapSkipping(err, 1)
|
||||
var kv KV
|
||||
if exKV := merry.Value(merr, kvKey(0)); exKV != nil {
|
||||
kv = mergeInto(exKV.(KV), kvs...)
|
||||
} else {
|
||||
kv = Merge(kvs...).KV()
|
||||
}
|
||||
return merr.WithValue(kvKey(0), kv)
|
||||
}
|
||||
|
||||
// ErrKV returns a KV which includes the KV embedded in the error by ErrWithKV,
|
||||
// if any. The KV will also include an "err" field containing the output of
|
||||
// err.Error(), and an "errSrc" field if the given error is a merry error which
|
||||
// contains an embedded stacktrace.
|
||||
func ErrKV(err error) KVer {
|
||||
var kv KV
|
||||
if kvi := merry.Value(err, kvKey(0)); kvi != nil {
|
||||
kv = kvi.(KV)
|
||||
} else {
|
||||
kv = KV{}
|
||||
}
|
||||
kv["err"] = err.Error()
|
||||
if fileFull, line := merry.Location(err); fileFull != "" {
|
||||
file, dir := filepath.Base(fileFull), filepath.Dir(fileFull)
|
||||
dir = filepath.Base(dir) // only want the first dirname, ie the pkg name
|
||||
kv["errSrc"] = fmt.Sprintf("%s/%s:%d", dir, file, line)
|
||||
}
|
||||
return kv
|
||||
}
|
||||
|
||||
// CtxWithKV embeds a KV into a Context, returning a new Context instance. If
|
||||
// the Context already has a KV embedded in it then the returned error will have
|
||||
// the merging of the two, with the given KVs taking precedence.
|
||||
|
@ -2,60 +2,11 @@ package mlog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
. "testing"
|
||||
|
||||
"github.com/ansel1/merry"
|
||||
"github.com/mediocregopher/mediocre-go-lib/mtest/massert"
|
||||
)
|
||||
|
||||
func TestErrKV(t *T) {
|
||||
assertErrKV := func(err error, exp KV) massert.Assertion {
|
||||
got := KV(ErrKV(err).KV())
|
||||
errSrc := got["errSrc"]
|
||||
delete(got, "errSrc")
|
||||
return massert.All(
|
||||
massert.Not(massert.Nil(errSrc)),
|
||||
massert.Equal(true, strings.HasPrefix(errSrc.(string), "mlog/errctx_test.go")),
|
||||
massert.Equal(exp, got),
|
||||
)
|
||||
}
|
||||
|
||||
err := merry.New("foo")
|
||||
massert.Fatal(t, assertErrKV(err, KV{"err": err.Error()}))
|
||||
|
||||
kv := KV{"a": "a"}
|
||||
err2 := ErrWithKV(err, kv)
|
||||
massert.Fatal(t, massert.All(
|
||||
assertErrKV(err, KV{"err": err.Error()}),
|
||||
assertErrKV(err2, KV{"err": err.Error(), "a": "a"}),
|
||||
))
|
||||
|
||||
// changing the kv now shouldn't do anything
|
||||
kv["a"] = "b"
|
||||
massert.Fatal(t, massert.All(
|
||||
assertErrKV(err, KV{"err": err.Error()}),
|
||||
assertErrKV(err2, KV{"err": err.Error(), "a": "a"}),
|
||||
))
|
||||
|
||||
// a new ErrWithKV shouldn't affect the previous one
|
||||
err3 := ErrWithKV(err2, KV{"b": "b"})
|
||||
massert.Fatal(t, massert.All(
|
||||
assertErrKV(err, KV{"err": err.Error()}),
|
||||
assertErrKV(err2, KV{"err": err2.Error(), "a": "a"}),
|
||||
assertErrKV(err3, KV{"err": err3.Error(), "a": "a", "b": "b"}),
|
||||
))
|
||||
|
||||
// make sure precedence works
|
||||
err4 := ErrWithKV(err3, KV{"b": "bb"})
|
||||
massert.Fatal(t, massert.All(
|
||||
assertErrKV(err, KV{"err": err.Error()}),
|
||||
assertErrKV(err2, KV{"err": err2.Error(), "a": "a"}),
|
||||
assertErrKV(err3, KV{"err": err3.Error(), "a": "a", "b": "b"}),
|
||||
assertErrKV(err4, KV{"err": err4.Error(), "a": "a", "b": "bb"}),
|
||||
))
|
||||
}
|
||||
|
||||
func TestCtxKV(t *T) {
|
||||
ctx := context.Background()
|
||||
massert.Fatal(t, massert.Equal(KV{}, CtxKV(ctx)))
|
||||
|
@ -10,7 +10,7 @@
|
||||
// Examples:
|
||||
//
|
||||
// Info("Something important has occurred")
|
||||
// Error("Could not open file", llog.KV{"filename": filename}, llog.ErrKV(err))
|
||||
// Error("Could not open file", llog.KV{"filename": filename}, merr.KV(err))
|
||||
//
|
||||
package mlog
|
||||
|
||||
@ -22,6 +22,8 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
)
|
||||
|
||||
// Truncate is a helper function to truncate a string to a given size. It will
|
||||
@ -339,7 +341,7 @@ func (l *Logger) Log(msg Message) {
|
||||
}
|
||||
|
||||
if err := l.h(msg); err != nil {
|
||||
go l.Error("Logger.Handler returned error", ErrKV(err))
|
||||
go l.Error("Logger.Handler returned error", merr.KV(err))
|
||||
return
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user