forked from opentracing-contrib/go-gin
/
server.go
104 lines (88 loc) · 2.94 KB
/
server.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
// +build go1.7
// This is the middleware from github.com/opentracing-contrib/go-stdlib
// tweaked slightly to work as a native gin middleware.
//
// It removes the need for the additional complexity of using a middleware
// adapter.
package ginhttp
import (
"net/http"
"net/url"
"github.com/gin-gonic/gin"
opentracing "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
)
const defaultComponentName = "net/http"
type mwOptions struct {
opNameFunc func(r *http.Request) string
spanObserver func(span opentracing.Span, r *http.Request)
urlTagFunc func(u *url.URL) string
componentName string
}
// MWOption controls the behavior of the Middleware.
type MWOption func(*mwOptions)
// OperationNameFunc returns a MWOption that uses given function f
// to generate operation name for each server-side span.
func OperationNameFunc(f func(r *http.Request) string) MWOption {
return func(options *mwOptions) {
options.opNameFunc = f
}
}
// MWComponentName returns a MWOption that sets the component name
// for the server-side span.
func MWComponentName(componentName string) MWOption {
return func(options *mwOptions) {
options.componentName = componentName
}
}
// MWSpanObserver returns a MWOption that observe the span
// for the server-side span.
func MWSpanObserver(f func(span opentracing.Span, r *http.Request)) MWOption {
return func(options *mwOptions) {
options.spanObserver = f
}
}
// MWURLTagFunc returns a MWOption that uses given function f
// to set the span's http.url tag. Can be used to change the default
// http.url tag, eg to redact sensitive information.
func MWURLTagFunc(f func(u *url.URL) string) MWOption {
return func(options *mwOptions) {
options.urlTagFunc = f
}
}
// Middleware is a gin native version of the equivalent middleware in:
// https://github.com/opentracing-contrib/go-stdlib/
func Middleware(tr opentracing.Tracer, options ...MWOption) gin.HandlerFunc {
opts := mwOptions{
opNameFunc: func(r *http.Request) string {
return "HTTP " + r.Method
},
spanObserver: func(span opentracing.Span, r *http.Request) {},
urlTagFunc: func(u *url.URL) string {
return u.String()
},
}
for _, opt := range options {
opt(&opts)
}
return func(c *gin.Context) {
carrier := opentracing.HTTPHeadersCarrier(c.Request.Header)
ctx, _ := tr.Extract(opentracing.HTTPHeaders, carrier)
op := opts.opNameFunc(c.Request)
sp := tr.StartSpan(op, ext.RPCServerOption(ctx))
ext.HTTPMethod.Set(sp, c.Request.Method)
ext.HTTPUrl.Set(sp, opts.urlTagFunc(c.Request.URL))
opts.spanObserver(sp, c.Request)
// set component name, use "net/http" if caller does not specify
componentName := opts.componentName
if componentName == "" {
componentName = defaultComponentName
}
ext.Component.Set(sp, componentName)
c.Request = c.Request.WithContext(
opentracing.ContextWithSpan(c.Request.Context(), sp))
c.Next()
ext.HTTPStatusCode.Set(sp, uint16(c.Writer.Status()))
sp.Finish()
}
}