forked from signalfx/signalfx-go-tracing
/
aws.go
106 lines (91 loc) · 2.98 KB
/
aws.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
97
98
99
100
101
102
103
104
105
106
// Package aws provides functions to trace aws/aws-sdk-go (https://github.com/aws/aws-sdk-go).
package aws // import "github.com/signalfx/signalfx-go-tracing/contrib/aws/aws-sdk-go/aws"
import (
"strconv"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/signalfx/signalfx-go-tracing/ddtrace"
"github.com/signalfx/signalfx-go-tracing/ddtrace/ext"
"github.com/signalfx/signalfx-go-tracing/ddtrace/tracer"
)
const (
tagAWSAgent = "aws.agent"
tagAWSOperation = "aws.operation"
tagAWSRegion = "aws.region"
)
type handlers struct {
cfg *config
}
// WrapSession wraps a session.Session, causing requests and responses to be traced.
func WrapSession(s *session.Session, opts ...Option) *session.Session {
cfg := new(config)
defaults(cfg)
for _, opt := range opts {
opt(cfg)
}
h := &handlers{cfg: cfg}
s = s.Copy()
s.Handlers.Send.PushFrontNamed(request.NamedHandler{
Name: "github.com/signalfx/signalfx-go-tracing/contrib/aws/aws-sdk-go/aws/handlers.Send",
Fn: h.Send,
})
s.Handlers.Complete.PushBackNamed(request.NamedHandler{
Name: "github.com/signalfx/signalfx-go-tracing/contrib/aws/aws-sdk-go/aws/handlers.Complete",
Fn: h.Complete,
})
return s
}
func (h *handlers) Send(req *request.Request) {
opts := []ddtrace.StartSpanOption{
tracer.SpanType(ext.SpanTypeHTTP),
tracer.ServiceName(h.serviceName(req)),
tracer.ResourceName(h.resourceName(req)),
tracer.Tag(tagAWSAgent, h.awsAgent(req)),
tracer.Tag(tagAWSOperation, h.awsOperation(req)),
tracer.Tag(tagAWSRegion, h.awsRegion(req)),
tracer.Tag(ext.HTTPMethod, req.Operation.HTTPMethod),
tracer.Tag(ext.HTTPURL, req.HTTPRequest.URL.String()),
}
if h.cfg.analyticsRate > 0 {
opts = append(opts, tracer.Tag(ext.EventSampleRate, h.cfg.analyticsRate))
}
_, ctx := tracer.StartSpanFromContext(req.Context(), h.operationName(req), opts...)
req.SetContext(ctx)
}
func (h *handlers) Complete(req *request.Request) {
span, ok := tracer.SpanFromContext(req.Context())
if !ok {
return
}
if req.HTTPResponse != nil {
span.SetTag(ext.HTTPCode, strconv.Itoa(req.HTTPResponse.StatusCode))
}
span.FinishWithOptionsExt(tracer.WithError(req.Error))
}
func (h *handlers) operationName(req *request.Request) string {
return h.awsService(req) + ".command"
}
func (h *handlers) resourceName(req *request.Request) string {
return h.awsService(req) + "." + req.Operation.Name
}
func (h *handlers) serviceName(req *request.Request) string {
if h.cfg.serviceName != "" {
return h.cfg.serviceName
}
return "aws." + h.awsService(req)
}
func (h *handlers) awsAgent(req *request.Request) string {
if agent := req.HTTPRequest.Header.Get("User-Agent"); agent != "" {
return agent
}
return "aws-sdk-go"
}
func (h *handlers) awsOperation(req *request.Request) string {
return req.Operation.Name
}
func (h *handlers) awsRegion(req *request.Request) string {
return req.ClientInfo.SigningRegion
}
func (h *handlers) awsService(req *request.Request) string {
return req.ClientInfo.ServiceName
}