-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler_sentry.go
More file actions
122 lines (102 loc) · 4.08 KB
/
Copy pathhandler_sentry.go
File metadata and controls
122 lines (102 loc) · 4.08 KB
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
package errorshandler
import (
"encoding/json"
"fmt"
"time"
"github.com/codex-team/hawk.collector/pkg/broker"
log "github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
)
const SentryQueueName = "external/sentry"
const CatcherType = "external/sentry"
// HandleHTTP processes HTTP requests with JSON body
func (handler *Handler) HandleSentry(ctx *fasthttp.RequestCtx) {
if ctx.Request.Header.ContentLength() > handler.MaxErrorCatcherMessageSize {
log.Warnf("Incoming request with size %d", ctx.Request.Header.ContentLength())
sendAnswerHTTP(ctx, ResponseMessage{Code: 400, Error: true, Message: "Request is too large"})
return
}
var hawkToken string
var err error
// parse incoming get request params
sentryKey := ctx.QueryArgs().Peek("sentry_key")
if sentryKey == nil {
// check that X-Sentry-Auth header is available
auth := ctx.Request.Header.Peek("X-Sentry-Auth")
if auth == nil {
log.Warnf("Incoming request without X-Sentry-Auth header")
sendAnswerHTTP(ctx, ResponseMessage{Code: 400, Error: true, Message: "X-Sentry-Auth header is missing"})
return
}
hawkToken, err = getSentryKeyFromAuth(string(auth))
if err != nil {
log.Warnf("Incoming request with invalid X-Sentry-Auth header=%s: %s", auth, err)
sendAnswerHTTP(ctx, ResponseMessage{Code: 400, Error: true, Message: err.Error()})
return
}
} else {
hawkToken = string(sentryKey)
}
log.Debugf("Incoming request with hawk integration token: %s", hawkToken)
sentryEnvelopeBody := ctx.PostBody()
contentEncoding := string(ctx.Request.Header.Peek("Content-Encoding"))
if contentEncoding == "gzip" {
sentryEnvelopeBody, err = decompressGzipString(sentryEnvelopeBody)
if err != nil {
log.Warnf("Failed to decompress gzip body: %s", err)
sendAnswerHTTP(ctx, ResponseMessage{Code: 400, Error: true, Message: "Failed to decompress gzip body"})
return
}
log.Debugf("Decompressed body: %s", sentryEnvelopeBody)
} else {
log.Debugf("Body: %s", sentryEnvelopeBody)
}
projectId, ok := handler.AccountsMongoDBClient.GetValidToken(hawkToken)
if !ok {
log.Warnf("Token %s is not in the accounts cache", hawkToken)
sendAnswerHTTP(ctx, ResponseMessage{400, true, fmt.Sprintf("Integration token invalid: %s", hawkToken)})
return
}
log.Debugf("Found project with ID %s for integration token %s", projectId, hawkToken)
projectLimits, ok := handler.AccountsMongoDBClient.GetProjectLimits(projectId)
if !ok {
log.Warnf("Project %s is not in the projects limits cache", projectId)
} else {
log.Debugf("Project %s limits: %+v", projectId, projectLimits)
}
if handler.RedisClient.IsBlocked(projectId) {
handler.ErrorsBlockedByLimit.Inc()
sendAnswerHTTP(ctx, ResponseMessage{402, true, "Project has exceeded the events limit"})
return
}
rateWithinLimit, err := handler.RedisClient.UpdateRateLimit(projectId, projectLimits.EventsLimit, projectLimits.EventsPeriod)
if err != nil {
log.Errorf("Failed to update rate limit: %s", err)
sendAnswerHTTP(ctx, ResponseMessage{402, true, "Failed to update rate limit"})
return
}
if !rateWithinLimit {
sendAnswerHTTP(ctx, ResponseMessage{402, true, "Rate limit exceeded"})
return
}
// convert message to JSON format
rawMessage := RawSentryMessage{Envelope: sentryEnvelopeBody}
jsonMessage, err := json.Marshal(rawMessage)
if err != nil {
log.Errorf("Message marshalling error: %v", err)
sendAnswerHTTP(ctx, ResponseMessage{400, true, "Cannot serialize envelope"})
}
messageToSend := BrokerMessage{Timestamp: time.Now().Unix(), ProjectId: projectId, Payload: json.RawMessage(jsonMessage), CatcherType: CatcherType}
payloadToSend, err := json.Marshal(messageToSend)
if err != nil {
log.Errorf("Message marshalling error: %v", err)
sendAnswerHTTP(ctx, ResponseMessage{400, true, "Cannot serialize envelope"})
}
// send serialized message to a broker
brokerMessage := broker.Message{Payload: payloadToSend, Route: SentryQueueName}
log.Debugf("Send to queue: %s", brokerMessage)
handler.Broker.Chan <- brokerMessage
// increment processed errors counter
handler.ErrorsProcessed.Inc()
sendAnswerHTTP(ctx, ResponseMessage{200, false, "OK"})
}