/
error.go
96 lines (77 loc) · 1.76 KB
/
error.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
89
90
91
92
93
94
95
96
package customapm
import (
"context"
"errors"
"expvar"
"github.com/thalesfsp/dal/internal/logging"
"github.com/thalesfsp/sypl"
"github.com/thalesfsp/sypl/fields"
"github.com/thalesfsp/sypl/level"
"go.elastic.co/apm"
)
//////
// Vars, consts, and types.
//////
// Outcome is the outcome of a span. It can be either success or failure.
type Outcome string
const (
// Failure is the outcome when the span failed.
Failure Outcome = "failure"
// Success is the outcome when the span succeeded.
Success Outcome = "success"
)
func (o Outcome) String() string {
return string(o)
}
//////
// Exported functionalities.
//////
// TraceError is a helper function to trace an error. It will log the error
// with the APM fields, and tell APM that it was an error. It will also set
// the span outcome to failure.
func TraceError(
ctx context.Context,
err error,
l sypl.ISypl,
metric *expvar.Int,
) error {
//////
// Metric.
//////
if metric != nil {
metric.Add(1)
}
//////
// APM.
//////
// Get the current span from the context, if any, set the outcome.
span := apm.SpanFromContext(ctx)
if span != nil {
span.Outcome = string(Failure)
}
originalError := err
// Unwrap any nested errorcatalog. By default, apm.CaptureError() does not
// automatically unwrap nested errors or extract any additional context or
// metadata from the error.
for {
unwrapped := errors.Unwrap(err)
if unwrapped == nil {
break
}
err = unwrapped
}
// Tells APM that it that was an error.
apm.CaptureError(ctx, err).Send()
//////
// Logging
//////
// Correlates the transaction, span and log, and logs it.
if l != nil {
l.PrintlnWithOptions(
level.Error,
err.Error(),
sypl.WithFields(logging.ToAPM(ctx, make(fields.Fields))),
)
}
return originalError
}