openreplay/backend/pkg/handlers/web/cpuIssue.go
Alexander c6aac11cbf
Heuristics refactoring (#987)
* feat(backend): refactored heuristics service

* feat(backend): refactored db service (moved several events to heuristics)
2023-03-09 09:54:12 +01:00

89 lines
1.9 KiB
Go

package web
import (
"encoding/json"
"log"
. "openreplay/backend/pkg/messages"
"openreplay/backend/pkg/messages/performance"
)
/*
Handler name: CpuIssue
Input events: PerformanceTrack,
SetPageLocation
Output event: IssueEvent
*/
const CpuThreshold = 70 // % out of 100
const CpuMinDurationTrigger = 6 * 1000
type CpuIssueDetector struct {
startTimestamp uint64
startMessageID uint64
lastTimestamp uint64
maxRate uint64
contextString string
}
func (f *CpuIssueDetector) createPayload() string {
p, err := json.Marshal(struct {
Duration uint64
Rate uint64
}{f.duration(), f.maxRate})
if err != nil {
log.Printf("can't marshal CpuIssue payload to json: %s", err)
}
return string(p)
}
func (f *CpuIssueDetector) duration() uint64 {
return f.lastTimestamp - f.startTimestamp
}
func (f *CpuIssueDetector) reset() {
f.startTimestamp = 0
f.startMessageID = 0
f.maxRate = 0
}
func (f *CpuIssueDetector) Build() Message {
defer f.reset()
if f.startTimestamp == 0 || f.duration() < CpuMinDurationTrigger {
return nil
}
return &IssueEvent{
Type: "cpu",
Timestamp: f.startTimestamp,
MessageID: f.startMessageID,
ContextString: f.contextString,
Payload: f.createPayload(),
}
}
func (f *CpuIssueDetector) Handle(message Message, timestamp uint64) Message {
switch msg := message.(type) {
case *PerformanceTrack:
// Ignore if it's a wrong message order
if timestamp < f.lastTimestamp {
return nil
}
f.lastTimestamp = timestamp
cpuRate := performance.CPURate(msg.Ticks, performance.TimeDiff(timestamp, f.lastTimestamp))
// Build event if cpu issue have gone
if msg.Frames == -1 || msg.Ticks == -1 || cpuRate < CpuThreshold {
return f.Build()
}
// Update values
if f.startTimestamp == 0 {
f.startTimestamp = timestamp
f.startMessageID = message.MsgID()
}
if f.maxRate < cpuRate {
f.maxRate = cpuRate
}
case *SetPageLocation:
f.contextString = msg.URL
}
return nil
}