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
|
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.
|
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
|
* In general, all checking of equality of errors, e.g. `err == io.EOF`, done on
|
||||||
information into `error` instances, it should be assumed that all errors
|
errors returned from the packages in this project should be done using
|
||||||
returned from these packages are `merry.Error` instances. In cases where a
|
`merr.Equal`, e.g. `merr.Equal(err, io.EOF)`. The `merr` package is used to
|
||||||
package has a specific error it might return and which might be checked for a
|
wrap errors and embed further metadata in them, like stack traces and so
|
||||||
function to perform that equality check will be supplied as part of the
|
forth.
|
||||||
package.
|
|
||||||
|
|
||||||
## Styleguide
|
## Styleguide
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -58,7 +58,7 @@ func (pk PublicKey) verify(s Signature, r io.Reader) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := rsa.VerifyPSS(&pk.PublicKey, crypto.SHA256, h.Sum(nil), s.sig, nil); err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -88,12 +88,12 @@ func (pk *PublicKey) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, pubKeyV0)
|
strEnc, ok := stripPrefix(str, pubKeyV0)
|
||||||
if !ok || len(strEnc) <= hex.EncodedLen(8) {
|
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)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
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))
|
pk.E = int(binary.BigEndian.Uint64(b))
|
||||||
@ -184,17 +184,17 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, privKeyV0)
|
strEnc, ok := stripPrefix(str, privKeyV0)
|
||||||
if !ok {
|
if !ok {
|
||||||
return mlog.ErrWithKV(errMalformedPrivateKey, mlog.KV{"privKeyStr": str})
|
return merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := hex.DecodeString(strEnc)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mlog.ErrWithKV(err, mlog.KV{"privKeyStr": str})
|
return merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
e, n := binary.Uvarint(b)
|
e, n := binary.Uvarint(b)
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return mlog.ErrWithKV(errMalformedPrivateKey, mlog.KV{"privKeyStr": str})
|
return merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
pk.PublicKey.E = int(e)
|
pk.PublicKey.E = int(e)
|
||||||
b = b[n:]
|
b = b[n:]
|
||||||
@ -205,7 +205,7 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
|||||||
}
|
}
|
||||||
l, n := binary.Uvarint(b)
|
l, n := binary.Uvarint(b)
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
err = errMalformedPrivateKey
|
err = merr.Wrap(errMalformedPrivateKey)
|
||||||
}
|
}
|
||||||
b = b[n:]
|
b = b[n:]
|
||||||
i := new(big.Int)
|
i := new(big.Int)
|
||||||
@ -221,7 +221,7 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mlog.ErrWithKV(err, mlog.KV{"privKeyStr": str})
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"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
|
// 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 {
|
func (s Secret) verify(sig Signature, r io.Reader) error {
|
||||||
sigB, err := s.signRaw(r, uint8(len(sig.sig)), sig.salt, sig.t)
|
sigB, err := s.signRaw(r, uint8(len(sig.sig)), sig.salt, sig.t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mlog.ErrWithKV(err, sig)
|
return merr.WithValue(err, "sig", sig, true)
|
||||||
} else if !hmac.Equal(sigB, sig.sig) {
|
} else if !hmac.Equal(sigB, sig.sig) {
|
||||||
return mlog.ErrWithKV(ErrInvalidSig, sig)
|
return merr.WithValue(ErrInvalidSig, "sig", sig, true)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
. "testing"
|
. "testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ansel1/merry"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -43,9 +43,9 @@ func TestSecretSignVerify(t *T) {
|
|||||||
assert.NotEqual(t, prevSig.String(), thisSigStr)
|
assert.NotEqual(t, prevSig.String(), thisSigStr)
|
||||||
assert.NotEqual(t, prevWeakSig.String(), thisWeakSigStr)
|
assert.NotEqual(t, prevWeakSig.String(), thisWeakSigStr)
|
||||||
err := VerifyString(secret, prevSig, thisStr)
|
err := VerifyString(secret, prevSig, thisStr)
|
||||||
assert.True(t, merry.Is(err, ErrInvalidSig))
|
assert.True(t, merr.Equal(err, ErrInvalidSig))
|
||||||
err = VerifyString(secret, prevWeakSig, thisStr)
|
err = VerifyString(secret, prevWeakSig, thisStr)
|
||||||
assert.True(t, merry.Is(err, ErrInvalidSig))
|
assert.True(t, merr.Equal(err, ErrInvalidSig))
|
||||||
}
|
}
|
||||||
prevStr = thisStr
|
prevStr = thisStr
|
||||||
prevSig = thisSig
|
prevSig = thisSig
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -66,12 +66,12 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, sigV0)
|
strEnc, ok := stripPrefix(str, sigV0)
|
||||||
if !ok || len(strEnc) < hex.EncodedLen(10) {
|
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)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
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:]
|
unixNano, b := int64(binary.BigEndian.Uint64(b[:8])), b[8:]
|
||||||
@ -81,7 +81,7 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
} else if len(b) < 1+int(b[0]) {
|
} 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
|
return nil
|
||||||
}
|
}
|
||||||
out := b[1 : 1+b[0]]
|
out := b[1 : 1+b[0]]
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
. "testing"
|
. "testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ansel1/merry"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -36,7 +36,7 @@ func TestSignerVerifier(t *T) {
|
|||||||
if prevStr != "" {
|
if prevStr != "" {
|
||||||
assert.NotEqual(t, prevSig.String(), thisSigStr)
|
assert.NotEqual(t, prevSig.String(), thisSigStr)
|
||||||
err := VerifyString(secret, prevSig, thisStr)
|
err := VerifyString(secret, prevSig, thisStr)
|
||||||
assert.True(t, merry.Is(err, ErrInvalidSig))
|
assert.True(t, merr.Equal(err, ErrInvalidSig))
|
||||||
}
|
}
|
||||||
prevStr = thisStr
|
prevStr = thisStr
|
||||||
prevSig = thisSig
|
prevSig = thisSig
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mlog"
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errMalformedUUID = errors.New("malformed UUID string")
|
var errMalformedUUID = errors.New("malformed UUID string")
|
||||||
@ -68,11 +68,11 @@ func (u *UUID) UnmarshalText(b []byte) error {
|
|||||||
str := string(b)
|
str := string(b)
|
||||||
strEnc, ok := stripPrefix(str, uuidV0)
|
strEnc, ok := stripPrefix(str, uuidV0)
|
||||||
if !ok || len(strEnc) != hex.EncodedLen(16) {
|
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)
|
b, err := hex.DecodeString(strEnc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mlog.ErrWithKV(err, mlog.KV{"uuidStr": str})
|
return merr.WithValue(err, "uuidStr", str, true)
|
||||||
}
|
}
|
||||||
u.b = b
|
u.b = b
|
||||||
return nil
|
return nil
|
||||||
|
@ -2,52 +2,10 @@ package mlog
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/ansel1/merry"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type kvKey int
|
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
|
// 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 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.
|
// the merging of the two, with the given KVs taking precedence.
|
||||||
|
@ -2,60 +2,11 @@ package mlog
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
|
||||||
. "testing"
|
. "testing"
|
||||||
|
|
||||||
"github.com/ansel1/merry"
|
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mtest/massert"
|
"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) {
|
func TestCtxKV(t *T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
massert.Fatal(t, massert.Equal(KV{}, CtxKV(ctx)))
|
massert.Fatal(t, massert.Equal(KV{}, CtxKV(ctx)))
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
// Examples:
|
// Examples:
|
||||||
//
|
//
|
||||||
// Info("Something important has occurred")
|
// 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
|
package mlog
|
||||||
|
|
||||||
@ -22,6 +22,8 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Truncate is a helper function to truncate a string to a given size. It will
|
// 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 {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user