openreplay/ee/backend/internal/db/datasaver/fts.go
Alexander 4b8f3bee25
Sessions refactoring (#1371)
* feat(backend): moved sql requests related to sessions table to one place

* feat(backend): refactoring in db.Saver handler

* feat(backend): hude refactoring in db/postgres module

* fix(backend): workable feature flags

* fix(backend): workable integrations

* fix(backend): workable sessions and projects modules

* fix(backend): added missed projects module to sessions

* feat(backend): renaming

* feat(backend): moved session struct to sessions module and split methods into interface, cache and storage levels

* feat(backend): moved project struct to projects module

* feat(backend): added projects model

* feat(backend): implemented new in memory cache for sessions and projects

* feat(backend): implemented new cache in projects

* feat(backend): there are 2 methods in cache module now: Get() and GetAndRefresh()

* feat(backend): added cache update operations

* fix(backend): fixed import cycle

* fix(backend): fixed panic in db message handler

* fix(backend): fixed panic in projects module

* fix(backend): fixed panic in sessions.GetDuration

* feat(backend): added direct call to get session duration if session is already in cache

* feat(backend): used pg pool everywhere except db service

* fix(backend): added missing part after rebase

* fix(backend): removed old sessions file

* feat(backend): added refactored redis client with produce/consume options

* feat(backend): added cache layer for projects

* fix(backend): added missing redis config

* fix(backend): added missing method for producer

* feat(backend): cache integration for sessions

* feat(backend): temporary method to get session directly from db

* feat(backend): adapt EE version of message handler

* fix(backend): fixed issue in fts realisation

* fix(backend): added redis cache to sessions module

* fix(backend): set 0 duration or hesitation time for inputs without focus event

* feat(backend): added cache for session updates and failover mechanism for batch.Insert() operation

* feat(backend): debug log

* feat(backend): more debug log

* feat(backend): removed debug log

* fix(backend): fixed an issue of tracking input events with empty label

* fix(backend): disabled debug log in projects cache

* fix(backend): renamed session updater

* fix(backend): fixed closed pool issue in DB service

* fix(backend): fixed dead lock in db Stop() method

* fix(backend): fixed panic in heuristics service

* feat(backend): enabled redis cache in projects

* feat(backend): clear cache on each update operation

* feat(backend): fully integrated cache layer with auto switch

* feat(backend): small refactoring in session updates

* fix(backend): fixed wrong events counter issue

* feat(backend): enabled full cache support in ender and http services

* fix(backend/ee): added missed import

* feat(backend): added second cache layer for db to speed up the service

* feat(backend): disable redis cache

* feat(backend): moved redis cache to ee
2023-07-06 10:55:43 +02:00

129 lines
4.1 KiB
Go

package datasaver
import (
"encoding/json"
"log"
"openreplay/backend/pkg/messages"
)
type NetworkRequestFTS struct {
SessionID uint64 `json:"session_id"`
ProjectID uint32 `json:"project_id"`
Method string `json:"method"`
URL string `json:"url"`
Request string `json:"request"`
Response string `json:"response"`
Status uint64 `json:"status"`
Timestamp uint64 `json:"timestamp"`
Duration uint64 `json:"duration"`
}
func WrapNetworkRequest(m *messages.NetworkRequest, projID uint32) *NetworkRequestFTS {
return &NetworkRequestFTS{
SessionID: m.SessionID(),
ProjectID: projID,
Method: m.Method,
URL: m.URL,
Request: m.Request,
Response: m.Response,
Status: m.Status,
Timestamp: m.Timestamp,
Duration: m.Duration,
}
}
type PageEventFTS struct {
SessionID uint64 `json:"session_id"`
ProjectID uint32 `json:"project_id"`
MessageID uint64 `json:"message_id"`
Timestamp uint64 `json:"timestamp"`
URL string `json:"url"`
Referrer string `json:"referrer"`
Loaded bool `json:"loaded"`
RequestStart uint64 `json:"request_start"`
ResponseStart uint64 `json:"response_start"`
ResponseEnd uint64 `json:"response_end"`
DomContentLoadedEventStart uint64 `json:"dom_content_loaded_event_start"`
DomContentLoadedEventEnd uint64 `json:"dom_content_loaded_event_end"`
LoadEventStart uint64 `json:"load_event_start"`
LoadEventEnd uint64 `json:"load_event_end"`
FirstPaint uint64 `json:"first_paint"`
FirstContentfulPaint uint64 `json:"first_contentful_paint"`
SpeedIndex uint64 `json:"speed_index"`
VisuallyComplete uint64 `json:"visually_complete"`
TimeToInteractive uint64 `json:"time_to_interactive"`
}
func WrapPageEvent(m *messages.PageEvent, projID uint32) *PageEventFTS {
return &PageEventFTS{
SessionID: m.SessionID(),
ProjectID: projID,
MessageID: m.MessageID,
Timestamp: m.Timestamp,
URL: m.URL,
Referrer: m.Referrer,
Loaded: m.Loaded,
RequestStart: m.RequestStart,
ResponseStart: m.ResponseStart,
ResponseEnd: m.ResponseEnd,
DomContentLoadedEventStart: m.DomContentLoadedEventStart,
DomContentLoadedEventEnd: m.DomContentLoadedEventEnd,
LoadEventStart: m.LoadEventStart,
LoadEventEnd: m.LoadEventEnd,
FirstPaint: m.FirstPaint,
FirstContentfulPaint: m.FirstContentfulPaint,
SpeedIndex: m.SpeedIndex,
VisuallyComplete: m.VisuallyComplete,
TimeToInteractive: m.TimeToInteractive,
}
}
type GraphQLFTS struct {
SessionID uint64 `json:"session_id"`
ProjectID uint32 `json:"project_id"`
OperationKind string `json:"operation_kind"`
OperationName string `json:"operation_name"`
Variables string `json:"variables"`
Response string `json:"response"`
}
func WrapGraphQL(m *messages.GraphQL, projID uint32) *GraphQLFTS {
return &GraphQLFTS{
SessionID: m.SessionID(),
ProjectID: projID,
OperationKind: m.OperationKind,
OperationName: m.OperationName,
Variables: m.Variables,
Response: m.Response,
}
}
func (s *saverImpl) sendToFTS(msg messages.Message, projID uint32) {
// Skip, if FTS is disabled
if s.producer == nil {
return
}
var (
event []byte
err error
)
switch m := msg.(type) {
// Common
case *messages.NetworkRequest:
event, err = json.Marshal(WrapNetworkRequest(m, projID))
case *messages.PageEvent:
event, err = json.Marshal(WrapPageEvent(m, projID))
case *messages.GraphQL:
event, err = json.Marshal(WrapGraphQL(m, projID))
}
if err != nil {
log.Printf("can't marshal json for quickwit: %s", err)
} else {
if len(event) > 0 {
if err := s.producer.Produce(s.cfg.QuickwitTopic, msg.SessionID(), event); err != nil {
log.Printf("can't send event to quickwit: %s", err)
}
}
}
}