-
Notifications
You must be signed in to change notification settings - Fork 225
/
httpstartstop.go
92 lines (78 loc) · 2.62 KB
/
httpstartstop.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
package handlers
import (
"maps"
"net/http"
"time"
"code.cloudfoundry.org/gorouter/logger"
"code.cloudfoundry.org/gorouter/proxy/utils"
"github.com/cloudfoundry/dropsonde"
"github.com/cloudfoundry/dropsonde/emitter"
"github.com/cloudfoundry/dropsonde/factories"
"github.com/cloudfoundry/sonde-go/events"
uuid "github.com/nu7hatch/gouuid"
"github.com/uber-go/zap"
"github.com/urfave/negroni/v3"
"google.golang.org/protobuf/proto"
)
type httpStartStopHandler struct {
emitter dropsonde.EventEmitter
logger logger.Logger
}
// NewHTTPStartStop creates a new handler that handles emitting frontend
// HTTP StartStop events
func NewHTTPStartStop(emitter dropsonde.EventEmitter, logger logger.Logger) negroni.Handler {
return &httpStartStopHandler{
emitter: emitter,
logger: logger,
}
}
// ServeHTTP handles emitting a StartStop event after the request has been completed
func (hh *httpStartStopHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
logger := LoggerWithTraceInfo(hh.logger, r)
requestID, err := uuid.ParseHex(r.Header.Get(VcapRequestIdHeader))
if err != nil {
logger.Panic("start-stop-handler-err", zap.String("error", "X-Vcap-Request-Id not found"))
return
}
prw, ok := rw.(utils.ProxyResponseWriter)
if !ok {
logger.Panic("request-info-err", zap.String("error", "ProxyResponseWriter not found"))
return
}
// Remove these headers if pre-set so they aren't logged in the event.
// ProxyRoundTripper will set them to correct values later
r.Header.Del("X-CF-ApplicationID")
r.Header.Del("X-CF-InstanceIndex")
r.Header.Del("X-CF-InstanceID")
startTime := time.Now()
next(rw, r)
startStopEvent := factories.NewHttpStartStop(r, int32(prw.Status()), int64(prw.Size()), events.PeerType_Server, requestID)
startStopEvent.StartTimestamp = proto.Int64(startTime.UnixNano())
envelope, err := emitter.Wrap(startStopEvent, hh.emitter.Origin())
if err != nil {
logger.Info("failed-to-create-startstop-envelope", zap.Error(err))
return
}
info, err := ContextRequestInfo(r)
if err != nil {
logger.Error("request-info-err", zap.Error(err))
} else {
envelope.Tags = hh.envelopeTags(info)
}
err = hh.emitter.EmitEnvelope(envelope)
if err != nil {
logger.Info("failed-to-emit-startstop-event", zap.Error(err))
}
}
func (hh *httpStartStopHandler) envelopeTags(ri *RequestInfo) map[string]string {
tags := make(map[string]string)
endpoint := ri.RouteEndpoint
if endpoint != nil {
maps.Copy(tags, endpoint.Tags)
}
if ri.TraceInfo.SpanID != "" && ri.TraceInfo.TraceID != "" {
tags["span_id"] = ri.TraceInfo.SpanID
tags["trace_id"] = ri.TraceInfo.TraceID
}
return tags
}