/
ot_tracing.go
77 lines (65 loc) · 2.29 KB
/
ot_tracing.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
package main
import (
"log"
"github.com/emicklei/go-restful"
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
)
const DefaultComponentName = "go-restful"
const DefaultOperationName = "go-restful client"
var (
DefaultOperationNameFunc = func(r *restful.Request) string {
// extract the route that the request maps to and use it as the operation name.
return r.SelectedRoutePath()
}
)
type filterOptions struct {
operationNameFunc func(r *restful.Request) string
componentName string
}
// FilterOption controls the behavior of the Filter.
type FilterOption func(*filterOptions)
// OperationNameFunc returns a FilterOption that uses given function f
// to generate operation name for each server-side span.
func OperationNameFunc(f func(r *restful.Request) string) FilterOption {
return func(options *filterOptions) {
options.operationNameFunc = f
}
}
// ComponentName returns a FilterOption that sets the component name
// name for the server-side span.
func ComponentName(componentName string) FilterOption {
return func(options *filterOptions) {
options.componentName = componentName
}
}
// NewOTFilter returns a go-restful filter which add OpenTracing instrument
func NewOTFilter(tracer opentracing.Tracer, options ...FilterOption) restful.FilterFunction {
opts := filterOptions{
operationNameFunc: DefaultOperationNameFunc,
componentName: DefaultComponentName,
}
for _, opt := range options {
opt(&opts)
}
// return a go-restful filter which add OpenTracing instrument
// NOTE: "filter" in go-restful is similar with "middleware" mechanism in modern web framework
return func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
ctx, err := tracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Request.Header))
if err != nil {
log.Println(err)
}
// record operation name
sp := tracer.StartSpan(opts.operationNameFunc(req), ext.RPCServerOption(ctx))
defer sp.Finish()
// record HTTP method
ext.HTTPMethod.Set(sp, req.Request.Method)
// record HTTP url
ext.HTTPUrl.Set(sp, req.Request.URL.String())
// record component name
ext.Component.Set(sp, opts.componentName)
// record HTTP status code
ext.HTTPStatusCode.Set(sp, uint16(resp.StatusCode()))
chain.ProcessFilter(req, resp)
}
}