* feat(backend): try a new approach for logs formatting (http) * feat(backend): added logger module * feat(backend): added project/session info to /i endpoint * feat(backend): found a solution for correct caller information * feat(backend): finished logs for http handlers * feat(backend): finished logs for mobile http handlers * feat(backend): finished ender * feat(backend): finished assets * feat(backend): finished heuristics * feat(backend): finished image-storage * feat(backend): finished sink * feat(backend): finished storage * feat(backend): formatted logs in all services * feat(backend): finished foss part * feat(backend): added missed foss part * feat(backend): fixed panic in memory manager and sink service * feat(backend): connectors
87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package web
|
|
|
|
import (
|
|
"encoding/json"
|
|
. "openreplay/backend/pkg/messages"
|
|
)
|
|
|
|
const MaxTimeDiff = 300
|
|
const MinClicksInARow = 3
|
|
|
|
type ClickRageDetector struct {
|
|
lastTimestamp uint64
|
|
lastLabel string
|
|
lastSelector string
|
|
firstInARawTimestamp uint64
|
|
firstInARawMessageId uint64
|
|
countsInARow int
|
|
url string
|
|
}
|
|
|
|
func (crd *ClickRageDetector) reset() {
|
|
crd.lastTimestamp = 0
|
|
crd.lastLabel = ""
|
|
crd.lastSelector = ""
|
|
crd.firstInARawTimestamp = 0
|
|
crd.firstInARawMessageId = 0
|
|
crd.countsInARow = 0
|
|
crd.url = ""
|
|
}
|
|
|
|
func (crd *ClickRageDetector) createPayload() string {
|
|
p, err := json.Marshal(struct{ Count int }{crd.countsInARow})
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return string(p)
|
|
}
|
|
|
|
func (crd *ClickRageDetector) Build() Message {
|
|
defer crd.reset()
|
|
if crd.countsInARow < MinClicksInARow {
|
|
return nil
|
|
}
|
|
return &IssueEvent{
|
|
Type: "click_rage",
|
|
ContextString: crd.lastLabel,
|
|
Payload: crd.createPayload(),
|
|
Timestamp: crd.firstInARawTimestamp,
|
|
MessageID: crd.firstInARawMessageId,
|
|
URL: crd.url,
|
|
Context: crd.lastSelector, // hack to pass selector to db (tags filter)
|
|
}
|
|
}
|
|
|
|
func (crd *ClickRageDetector) Handle(message Message, timestamp uint64) Message {
|
|
switch msg := message.(type) {
|
|
case *MouseClick:
|
|
// Set click url
|
|
if crd.url == "" && msg.Url != "" {
|
|
crd.url = msg.Url
|
|
}
|
|
// Click on different object -> build if we can and reset the builder
|
|
if msg.Label == "" {
|
|
return crd.Build()
|
|
}
|
|
// Update builder with last information
|
|
if crd.lastLabel == msg.Label && timestamp-crd.lastTimestamp < MaxTimeDiff {
|
|
crd.lastTimestamp = timestamp
|
|
crd.countsInARow += 1
|
|
return nil
|
|
}
|
|
// Try to build event
|
|
event := crd.Build()
|
|
// Use current message as init values for new event
|
|
crd.lastTimestamp = timestamp
|
|
crd.lastLabel = msg.Label
|
|
crd.lastSelector = msg.Selector
|
|
crd.firstInARawTimestamp = timestamp
|
|
crd.firstInARawMessageId = message.MsgID()
|
|
crd.countsInARow = 1
|
|
if crd.url == "" && msg.Url != "" {
|
|
crd.url = msg.Url
|
|
}
|
|
return event
|
|
}
|
|
return nil
|
|
}
|