-
Notifications
You must be signed in to change notification settings - Fork 301
/
Copy pathnrpkgerrors.go
88 lines (76 loc) · 1.88 KB
/
nrpkgerrors.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2020 New Relic Corporation. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
// Package nrpkgerrors introduces support for https://github.com/pkg/errors.
//
// This package improves the class and stack-trace fields of pkg/error errors
// when they are recorded with Transaction.NoticeError.
//
package nrpkgerrors
import (
"fmt"
"github.com/newrelic/go-agent/v3/internal"
newrelic "github.com/newrelic/go-agent/v3/newrelic"
"github.com/pkg/errors"
)
func init() { internal.TrackUsage("integration", "pkg-errors") }
// stackTracer is an error that also knows about its StackTrace.
// All wrapped errors from github.com/pkg/errors implement this interface.
type stackTracer interface {
StackTrace() errors.StackTrace
}
func deepestStackTrace(err error) errors.StackTrace {
var last stackTracer
for err != nil {
if err, ok := err.(stackTracer); ok {
last = err
}
cause, ok := err.(interface {
Cause() error
})
if !ok {
break
}
err = cause.Cause()
}
if last == nil {
return nil
}
return last.StackTrace()
}
func transformStackTrace(orig errors.StackTrace) []uintptr {
st := make([]uintptr, len(orig))
for i, frame := range orig {
st[i] = uintptr(frame)
}
return st
}
func stackTrace(e error) []uintptr {
st := deepestStackTrace(e)
if nil == st {
return nil
}
return transformStackTrace(st)
}
type errorClasser interface {
ErrorClass() string
}
func errorClass(e error) string {
if ec, ok := e.(errorClasser); ok {
return ec.ErrorClass()
}
cause := errors.Cause(e)
if ec, ok := cause.(errorClasser); ok {
return ec.ErrorClass()
}
return fmt.Sprintf("%T", cause)
}
// Wrap wraps a pkg/errors error so that when noticed by
// newrelic.Transaction.NoticeError it gives an improved stacktrace and class
// type.
func Wrap(e error) error {
return newrelic.Error{
Message: e.Error(),
Class: errorClass(e),
Stack: stackTrace(e),
}
}