Skip to content

Commit

Permalink
improve session storage to support multiple sessions from single visitor
Browse files Browse the repository at this point in the history
  • Loading branch information
negrel committed Sep 15, 2024
1 parent c58700c commit a8ef328
Show file tree
Hide file tree
Showing 5 changed files with 473 additions and 230 deletions.
2 changes: 1 addition & 1 deletion pkg/handlers/events_custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func eventsCustomHandler(
)

var ok bool
customEv.Session, ok = sessionStorage.WaitSession(deviceId, hutils.ContextTimeout(ctx))
customEv.Session, ok = sessionStorage.WaitSession(deviceId, customEv.PageUri, hutils.ContextTimeout(ctx))
// Session not found.
if !ok {
return errSessionNotFound
Expand Down
27 changes: 24 additions & 3 deletions pkg/handlers/events_pageviews.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,27 @@ func eventsPageviewsHandler(
ipAddr, utils.UnsafeBytes(pageView.PageUri.Host()),
)

// Special case, referrer URI is the same as page URI.
// This happens when user refresh page or a tab is duplicated.
// In both cases we want to insert a new session in temporary storage (memory)
// but we don't want to send it to the persisten store (eventstore). This new
// duplicated session will be persisted on next page view. This way we're sure
// that duplicated session is used.
if (referrerUri.IsValid() && pageView.PageUri.IsValid() && referrerUri.Host() == pageView.PageUri.Host() &&
referrerUri.Path() == pageView.PageUri.Path()) || !referrerUri.IsValid() {
session, found := sessionStorage.WaitSession(deviceId, pageView.PageUri, time.Duration(0))
if found {
session.SessionUuid, err = uuid.NewV7()
if err != nil {
return fmt.Errorf("failed to generate session uuid: %w", err)
}
sessionStorage.InsertSession(deviceId, session)

// Early return as we don't send event to the eventstore.
return nil
}
}

isInternalTraffic := referrerUri.IsValid() && referrerUri.Host() == pageView.PageUri.Host()
newSession := !isInternalTraffic

Expand All @@ -93,18 +114,18 @@ func eventsPageviewsHandler(
sessionExists := false
if visitorId != "" { // Identify session.
visitorId = utils.CopyString(visitorId)
_, sessionExists = sessionStorage.IdentifySession(deviceId, visitorId)
_, sessionExists = sessionStorage.IdentifySession(deviceId, pageView.PageUri, visitorId)
if sessionExists {

// Increment pageview count.
pageView.Session, sessionExists = sessionStorage.IncSessionPageviewCount(deviceId)
pageView.Session, sessionExists = sessionStorage.AddPageview(deviceId, referrerUri, pageView.PageUri)
if !sessionExists { // Should never happend.
logger.Panic().Msg("failed to increment session pageview count after IdentifySession returned a session")
}
}
} else { // Anon session.
// Increment pageview count.
pageView.Session, sessionExists = sessionStorage.IncSessionPageviewCount(deviceId)
pageView.Session, sessionExists = sessionStorage.AddPageview(deviceId, referrerUri, pageView.PageUri)
}

if !sessionExists {
Expand Down
6 changes: 0 additions & 6 deletions pkg/services/sessionstorage/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ type metrics struct {
sessionsWait prometheus.Gauge
sessionsCounter *prometheus.CounterVec
sessionsPageviews prometheus.Histogram
getSessionsMiss prometheus.Counter
}

func newMetrics(promRegistry *prometheus.Registry) metrics {
Expand All @@ -29,18 +28,13 @@ func newMetrics(promRegistry *prometheus.Registry) metrics {
Help: "Number of pageviews per sessions",
Buckets: []float64{1, 2, 3, 5, 10, 15, 25, 30, 50, 100},
}),
getSessionsMiss: prometheus.NewCounter(prometheus.CounterOpts{
Name: "sessionstorage_get_session_misses",
Help: "Number of get sessions call that wasn't found",
}),
}

promRegistry.MustRegister(
m.activeSessions,
m.sessionsWait,
m.sessionsCounter,
m.sessionsPageviews,
m.getSessionsMiss,
)

return m
Expand Down
Loading

0 comments on commit a8ef328

Please sign in to comment.