...
1 package opencensus
2
3 import (
4 "context"
5 "strconv"
6
7 "go.opencensus.io/trace"
8
9 "github.com/go-kit/kit/endpoint"
10 "github.com/go-kit/kit/sd/lb"
11 )
12
13
14 const TraceEndpointDefaultName = "gokit/endpoint"
15
16
17
18
19
20
21 func TraceEndpoint(name string, options ...EndpointOption) endpoint.Middleware {
22 if name == "" {
23 name = TraceEndpointDefaultName
24 }
25
26 cfg := &EndpointOptions{}
27
28 for _, o := range options {
29 o(cfg)
30 }
31
32 return func(next endpoint.Endpoint) endpoint.Endpoint {
33 return func(ctx context.Context, request interface{}) (response interface{}, err error) {
34 if cfg.GetName != nil {
35 if newName := cfg.GetName(ctx, name); newName != "" {
36 name = newName
37 }
38 }
39
40 ctx, span := trace.StartSpan(ctx, name)
41 if len(cfg.Attributes) > 0 {
42 span.AddAttributes(cfg.Attributes...)
43 }
44 defer span.End()
45
46 if cfg.GetAttributes != nil {
47 if attrs := cfg.GetAttributes(ctx); len(attrs) > 0 {
48 span.AddAttributes(attrs...)
49 }
50 }
51
52 defer func() {
53 if err != nil {
54 if lberr, ok := err.(lb.RetryError); ok {
55
56 attrs := make([]trace.Attribute, 0, len(lberr.RawErrors))
57 for idx, rawErr := range lberr.RawErrors {
58 attrs = append(attrs, trace.StringAttribute(
59 "gokit.retry.error."+strconv.Itoa(idx+1), rawErr.Error(),
60 ))
61 }
62 span.AddAttributes(attrs...)
63 span.SetStatus(trace.Status{
64 Code: trace.StatusCodeUnknown,
65 Message: lberr.Final.Error(),
66 })
67 return
68 }
69
70 span.SetStatus(trace.Status{
71 Code: trace.StatusCodeUnknown,
72 Message: err.Error(),
73 })
74 return
75 }
76
77
78 if res, ok := response.(endpoint.Failer); ok && res.Failed() != nil {
79 span.AddAttributes(
80 trace.StringAttribute("gokit.business.error", res.Failed().Error()),
81 )
82 if cfg.IgnoreBusinessError {
83 span.SetStatus(trace.Status{Code: trace.StatusCodeOK})
84 return
85 }
86
87 span.SetStatus(trace.Status{
88 Code: trace.StatusCodeUnknown,
89 Message: res.Failed().Error(),
90 })
91 return
92 }
93
94
95 span.SetStatus(trace.Status{Code: trace.StatusCodeOK})
96 }()
97 response, err = next(ctx, request)
98 return
99 }
100 }
101 }
102
View as plain text