From a01a66afeb4f688bafff691fa40e33a19feb1662 Mon Sep 17 00:00:00 2001 From: Alexander Zavorotynskiy Date: Wed, 9 Aug 2023 10:34:38 +0400 Subject: [PATCH] feat(backend): fixed issue in sessions cache layer --- backend/pkg/metrics/database/metrics.go | 29 ++++++++ backend/pkg/sessions/cache.go | 6 +- backend/pkg/sessions/sessions.go | 93 ------------------------- ee/backend/pkg/sessions/redis.go | 9 ++- 4 files changed, 41 insertions(+), 96 deletions(-) diff --git a/backend/pkg/metrics/database/metrics.go b/backend/pkg/metrics/database/metrics.go index f0a45f4d9..8a2f0530f 100644 --- a/backend/pkg/metrics/database/metrics.go +++ b/backend/pkg/metrics/database/metrics.go @@ -100,6 +100,33 @@ func IncreaseTotalRequests(method, table string) { dbTotalRequests.WithLabelValues(method, table).Inc() } +var cacheRedisRequests = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "cache", + Name: "redis_requests_total", + Help: "A counter showing the total number of all Redis requests.", + }, + []string{"method", "table"}, +) + +func IncreaseRedisRequests(method, table string) { + cacheRedisRequests.WithLabelValues(method, table).Inc() +} + +var cacheRedisRequestDuration = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: "cache", + Name: "redis_request_duration_seconds", + Help: "A histogram displaying the duration of each Redis request in seconds.", + Buckets: common.DefaultDurationBuckets, + }, + []string{"method", "table"}, +) + +func RecordRedisRequestDuration(durMillis float64, method, table string) { + cacheRedisRequestDuration.WithLabelValues(method, table).Observe(durMillis / 1000.0) +} + func List() []prometheus.Collector { return []prometheus.Collector{ dbBatchElements, @@ -109,5 +136,7 @@ func List() []prometheus.Collector { dbBulkInsertDuration, dbRequestDuration, dbTotalRequests, + cacheRedisRequests, + cacheRedisRequestDuration, } } diff --git a/backend/pkg/sessions/cache.go b/backend/pkg/sessions/cache.go index 73fe43b7f..64f87ca99 100644 --- a/backend/pkg/sessions/cache.go +++ b/backend/pkg/sessions/cache.go @@ -3,8 +3,9 @@ package sessions import ( "errors" "log" - "openreplay/backend/pkg/cache" "time" + + "openreplay/backend/pkg/cache" ) type Cache interface { @@ -33,6 +34,7 @@ func (i *inMemoryCacheImpl) Get(sessionID uint64) (*Session, error) { } session, err := i.redis.Get(sessionID) if err == nil { + i.sessions.Set(sessionID, session) return session, nil } if !errors.Is(err, ErrDisabledCache) && err.Error() != "redis: nil" { @@ -43,7 +45,7 @@ func (i *inMemoryCacheImpl) Get(sessionID uint64) (*Session, error) { func NewInMemoryCache(redisCache Cache) Cache { return &inMemoryCacheImpl{ - sessions: cache.New(time.Minute*3, time.Minute*5), + sessions: cache.New(time.Minute*3, time.Minute*10), redis: redisCache, } } diff --git a/backend/pkg/sessions/sessions.go b/backend/pkg/sessions/sessions.go index 83d0341b6..c8a3f00af 100644 --- a/backend/pkg/sessions/sessions.go +++ b/backend/pkg/sessions/sessions.go @@ -179,56 +179,12 @@ func (s *sessionsImpl) UpdateUserID(sessionID uint64, userID string) error { return nil } -func (s *sessionsImpl) _updateUserID(sessionID uint64, userID string) error { - if err := s.storage.InsertUserID(sessionID, userID); err != nil { - return err - } - if session, err := s.cache.Get(sessionID); err != nil { - session.UserID = &userID - if err := s.cache.Set(session); err != nil { - log.Printf("Failed to cache session: %v", err) - } - return nil - } - session, err := s.getFromDB(sessionID) - if err != nil { - log.Printf("Failed to get session from postgres: %v", err) - return nil - } - if err := s.cache.Set(session); err != nil { - log.Printf("Failed to cache session: %v", err) - } - return nil -} - // UpdateAnonymousID usage: in db handler func (s *sessionsImpl) UpdateAnonymousID(sessionID uint64, userAnonymousID string) error { s.updates.AddUserID(sessionID, userAnonymousID) return nil } -func (s *sessionsImpl) _updateAnonymousID(sessionID uint64, userAnonymousID string) error { - if err := s.storage.InsertUserAnonymousID(sessionID, userAnonymousID); err != nil { - return err - } - if session, err := s.cache.Get(sessionID); err != nil { - session.UserAnonymousID = &userAnonymousID - if err := s.cache.Set(session); err != nil { - log.Printf("Failed to cache session: %v", err) - } - return nil - } - session, err := s.getFromDB(sessionID) - if err != nil { - log.Printf("Failed to get session from postgres: %v", err) - return nil - } - if err := s.cache.Set(session); err != nil { - log.Printf("Failed to cache session: %v", err) - } - return nil -} - // UpdateReferrer usage: in db handler on each page event func (s *sessionsImpl) UpdateReferrer(sessionID uint64, referrer string) error { if referrer == "" { @@ -239,30 +195,6 @@ func (s *sessionsImpl) UpdateReferrer(sessionID uint64, referrer string) error { return nil } -func (s *sessionsImpl) _updateReferrer(sessionID uint64, referrer string) error { - baseReferrer := url.DiscardURLQuery(referrer) - if err := s.storage.InsertReferrer(sessionID, referrer, baseReferrer); err != nil { - return err - } - if session, err := s.cache.Get(sessionID); err != nil { - session.Referrer = &referrer - session.ReferrerBase = &baseReferrer - if err := s.cache.Set(session); err != nil { - log.Printf("Failed to cache session: %v", err) - } - return nil - } - session, err := s.getFromDB(sessionID) - if err != nil { - log.Printf("Failed to get session from postgres: %v", err) - return nil - } - if err := s.cache.Set(session); err != nil { - log.Printf("Failed to cache session: %v", err) - } - return nil -} - // UpdateMetadata usage: in db handler on each metadata event func (s *sessionsImpl) UpdateMetadata(sessionID uint64, key, value string) error { session, err := s.Get(sessionID) @@ -283,31 +215,6 @@ func (s *sessionsImpl) UpdateMetadata(sessionID uint64, key, value string) error return nil } -func (s *sessionsImpl) _updateMetadata(sessionID uint64, key, value string) error { - session, err := s.Get(sessionID) - if err != nil { - return err - } - project, err := s.projects.GetProject(session.ProjectID) - if err != nil { - return err - } - - keyNo := project.GetMetadataNo(key) - if keyNo == 0 { - return nil - } - - if err := s.storage.InsertMetadata(sessionID, keyNo, value); err != nil { - return err - } - session.SetMetadata(keyNo, value) - if err := s.cache.Set(session); err != nil { - log.Printf("Failed to cache session: %v", err) - } - return nil -} - func (s *sessionsImpl) UpdateEventsStats(sessionID uint64, events, pages int) error { s.updates.AddEvents(sessionID, events, pages) return nil diff --git a/ee/backend/pkg/sessions/redis.go b/ee/backend/pkg/sessions/redis.go index 5f86dd53f..0da788533 100644 --- a/ee/backend/pkg/sessions/redis.go +++ b/ee/backend/pkg/sessions/redis.go @@ -7,6 +7,7 @@ import ( "time" "openreplay/backend/pkg/db/redis" + "openreplay/backend/pkg/metrics/database" ) type cacheImpl struct { @@ -23,13 +24,16 @@ func (c *cacheImpl) Set(session *Session) error { if session.SessionID == 0 { return errors.New("session id is 0") } + start := time.Now() sessionBytes, err := json.Marshal(session) if err != nil { return err } - if _, err = c.db.Redis.Set(fmt.Sprintf("session:id:%d", session.SessionID), sessionBytes, time.Minute*30).Result(); err != nil { + if _, err = c.db.Redis.Set(fmt.Sprintf("session:id:%d", session.SessionID), sessionBytes, time.Minute*60).Result(); err != nil { return err } + database.RecordRedisRequestDuration(float64(time.Now().Sub(start).Milliseconds()), "set", "session") + database.IncreaseRedisRequests("set", "sessions") return nil } @@ -40,6 +44,7 @@ func (c *cacheImpl) Get(sessionID uint64) (*Session, error) { if sessionID == 0 { return nil, errors.New("session id is 0") } + start := time.Now() result, err := c.db.Redis.Get(fmt.Sprintf("session:id:%d", sessionID)).Result() if err != nil { return nil, err @@ -48,6 +53,8 @@ func (c *cacheImpl) Get(sessionID uint64) (*Session, error) { if err = json.Unmarshal([]byte(result), session); err != nil { return nil, err } + database.RecordRedisRequestDuration(float64(time.Now().Sub(start).Milliseconds()), "get", "session") + database.IncreaseRedisRequests("get", "sessions") return session, nil }