-
Notifications
You must be signed in to change notification settings - Fork 6
/
middleware.go
81 lines (70 loc) · 2.43 KB
/
middleware.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
package metricsmiddleware
import (
"context"
"github.com/arquivei/foundationkit/errors"
"github.com/arquivei/foundationkit/gokitmiddlewares"
logutil "github.com/arquivei/foundationkit/log"
"github.com/arquivei/foundationkit/metrifier"
"github.com/go-kit/kit/endpoint"
"github.com/rs/zerolog/log"
)
// MustNew returns a new metrics middleware but panics in case of error.
func MustNew(c Config) endpoint.Middleware {
return gokitmiddlewares.Must(New(c))
}
// New returns a new metrics middleware.
func New(c Config) (endpoint.Middleware, error) {
m, err := metrifier.New(c.Metrifier)
if err != nil {
return nil, err
}
return func(next endpoint.Endpoint) endpoint.Endpoint {
log.Debug().Str("config", logutil.Flatten(c)).Msg("[metricsmiddleware] New metrics endpoint middleware")
return func(ctx context.Context, req interface{}) (resp interface{}, err error) {
defer func(s metrifier.Span) {
var r interface{}
// Panics are handled as errors and re-raised
if r = recover(); r != nil {
err = errors.E(errors.NewFromRecover(r), errors.SeverityFatal, errors.CodePanic)
log.Ctx(ctx).Warn().Err(err).
Msg("[metricsmiddleware] Metrics endpoint middleware is handling an uncaught a panic. Please fix it!")
}
metrify(ctx, c.LabelsDecoder, s, req, resp, err)
if panicErr := tryRunExternalMetrics(ctx, c.ExternalMetrics, req, resp, err); panicErr != nil {
log.Ctx(ctx).Error().Err(panicErr).
Msg("[metricsmiddleware] External Metrics panicked. Please check you ExternalMetrics function.")
}
// re-raise panic
if r != nil {
panic(r)
}
}(m.Begin())
return next(ctx, req)
}
}, nil
}
func metrify(ctx context.Context, labelsDecoder LabelsDecoder, s metrifier.Span, req, resp interface{}, err error) {
defer func() {
if r := recover(); r != nil {
log.Ctx(ctx).Error().
Err(errors.NewFromRecover(r)).
Msg("[metricsmiddleware] Metrics middleware panicked! Please check your code and configuration.")
}
}()
if labelsDecoder != nil {
s = s.WithLabels(labelsDecoder.Decode(ctx, req, resp, err))
}
s.End(err)
}
func tryRunExternalMetrics(ctx context.Context, externalMetrics ExternalMetrics, req, resp interface{}, err error) (panicErr error) {
if externalMetrics == nil {
return
}
defer func() {
if r := recover(); r != nil {
panicErr = errors.E(errors.NewFromRecover(r), errors.SeverityFatal, errors.CodePanic)
}
}()
externalMetrics(ctx, req, resp, err)
return
}