This repository has been archived by the owner on Sep 9, 2022. It is now read-only.
/
middleware.go
126 lines (107 loc) · 4.07 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
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package echo
import (
"fmt"
"log"
"github.com/labstack/echo"
"github.com/opentracing/opentracing-go"
"github.com/wavefronthq/wavefront-opentracing-sdk-go/tracer"
)
//AddDynamicTags injects the dyanmic tags to the span
func AddDynamicTags(context *echo.Context, tags map[string]interface{}) {
(*context).Set("dynamicTags", tags)
}
//TracingHandler custom echoWeb middleware.
//Enables tracing for the routes defined in tracer-config.go.
//Injects respective tags for each route defined in the span of each trace.
func TracingHandler(next echo.HandlerFunc) echo.HandlerFunc {
return func(context echo.Context) error {
//Mapping path and request type to Http request to get corresponding tags
if routeToTagMapValue, ok := globalTracerConfig.RouteToTagsMap[context.Path()+"."+context.Request().Method]; ok {
span, parentSpanID := StartTraceSpan(context, routeToTagMapValue.OperationName, routeToTagMapValue.Metatags)
/*EXTRACTING TRACID AND SPANID FROM SPAN
CREATING THE IDENTIFIER TO INJECT IN CONTEXT*/
logPrefix := ""
sc, ok := span.Context().(tracer.SpanContext)
if ok {
//If it is null both parent and child will have same span id. Adding parent.span.id as tag
if parentSpanID != "" {
logPrefix = "traceId:" + sc.TraceID + " " + "spanId:" + sc.SpanID + " " + "parentId:" + parentSpanID + " "
span.SetTag("parentId", parentSpanID)
} else {
logPrefix = "traceId:" + sc.TraceID + " " + "spanId:" + sc.SpanID + " " + "parentId:" + sc.SpanID + " "
span.SetTag("parentId", sc.SpanID)
}
//Span reference in context
context.Set("spanPointer", &span)
}
//Injecting the prefix in echo context
context.Set("tracePrefix", logPrefix)
//Injecting propagation headers in context
propagationHeaders := GetTracingHeadersToInjectFromSpan(Tracer, span)
context.Set("propagationHeaders", propagationHeaders)
//Executing function after the response is written
context.Response().After(func() {
populateTagsForTrace(context, &span)
//Finishing the span
span.Finish()
})
} else {
log.Println("wavefront middleware: tracing not configured for this route")
}
return next(context)
}
}
//populateDefaultTagsForTrace extracts the required information from context and adds them as tags to the trace
func populateTagsForTrace(context echo.Context, span *opentracing.Span) {
//Extracting Http info to populate as default tags
requestMethod := context.Request().Method
requestURL := context.Request().Host + context.Request().RequestURI
requestStatus := context.Response().Status
userAgent := context.Request().UserAgent()
host := context.Request().Host
//Populating tags with http info
(*span).SetTag("http.url", requestURL)
(*span).SetTag("http.method", requestMethod)
(*span).SetTag("http.status_code", requestStatus)
(*span).SetTag("http.user_agent", userAgent)
(*span).SetTag("http.hostname", host)
if requestStatus > 399 {
(*span).SetTag("error", "true")
}
//Populating dynamically added tags
populateDynamicTagsForTrace(context, span)
//Populating JWT tags
if len(globalTracerConfig.CustomApplicationTags.JwtClaims) > 0 {
populateJwtTagsByClaims(context, span)
}
}
//populateDynamicTagsForTrace extracts the dynamically added tags from context and adds them as tags to the trace
func populateDynamicTagsForTrace(context echo.Context, span *opentracing.Span) {
//Extracing the tags from echo context
dynamicTags := context.Get("dynamicTags")
tags, ok := dynamicTags.(map[string]interface{})
if !ok {
return
}
//Populating the tags
for key, value := range tags {
(*span).SetTag(key, value)
}
}
//populateJwtTagsByClaims
func populateJwtTagsByClaims(context echo.Context, span *opentracing.Span) {
jwtClaimsFields := globalTracerConfig.CustomApplicationTags.JwtClaims
// Fetch all claims from JWT
claims, err := parseJwtClaimsFromHeaders(context)
if err != nil {
return
}
// Fetch claim value. Throw error if username
// claim is not present
for _, claim := range jwtClaimsFields {
claimValue := fmt.Sprintf("%v", claims[claim])
if claimValue != "" {
(*span).SetTag("jwt."+claim, claimValue)
}
}
}