generated from kinbiko/go-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
context.go
55 lines (46 loc) · 1.6 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package rogerr
import (
"context"
"errors"
)
type ctxKey int
const ctxDataKey ctxKey = 0
// WithMetadatum attaches the given key and value to the rogerr metadata
// associated with this context.
// Returns a new context with the metadatum attached, or nil if the given ctx was nil.
func WithMetadatum(ctx context.Context, key string, value interface{}) context.Context {
return WithMetadata(ctx, map[string]interface{}{key: value})
}
// WithMetadata attaches the given keys and values to the rogerr metadata
// associated with this context.
// Returns a new context with the metadata attached, or nil if the given ctx was nil.
func WithMetadata(ctx context.Context, data map[string]interface{}) context.Context {
if ctx == nil {
return nil
}
md := getOrInitializeMetadata(ctx)
for k, v := range data {
md[k] = v
}
return context.WithValue(ctx, ctxDataKey, md)
}
// Metadata pulls out all the metadata known by this package as a
// map[key]value from the given error.
func Metadata(err error) map[string]interface{} {
rErr := &rError{}
// Yes, that's a double pointer. The error type is a struct pointer, and
// errors.As requires a pointer to a type that implements the error
// interface, which is *Error, hence passing **Error here.
errors.As(err, &rErr)
return getOrInitializeMetadata(rErr.ctx)
}
func getOrInitializeMetadata(ctx context.Context) map[string]interface{} {
if ctx == nil {
return nil
}
m := map[string]interface{}{}
if val := ctx.Value(ctxDataKey); val != nil {
m = val.(map[string]interface{}) //nolint:errcheck // this package owns the ctx key type so this cast is safe.
}
return m
}