From 24c0224dd90533bc962d5e1a198cdc464018176c Mon Sep 17 00:00:00 2001 From: Kyren223 Date: Sat, 19 Jul 2025 11:31:07 +0300 Subject: Changed session durations metric to classic histogram, added last_activity to calculate monthly active users --- internal/server/api/api.go | 15 ++++++++++++++ .../20250718210459_users_last_activity.sql | 5 +++++ internal/server/metrics/metrics.go | 24 ++++++++++++++++++---- internal/server/server.go | 5 +++++ 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 internal/server/api/migrations/20250718210459_users_last_activity.sql (limited to 'internal/server') diff --git a/internal/server/api/api.go b/internal/server/api/api.go index 5159186..6c602ea 100644 --- a/internal/server/api/api.go +++ b/internal/server/api/api.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" "sync" + "time" "github.com/kyren223/eko/internal/data" "github.com/kyren223/eko/internal/packet" @@ -1703,3 +1704,17 @@ func DeviceAnalytics(ctx context.Context, sess *session.Session, request *packet return nil } + +func SetLastUserActivity(ctx context.Context, sess *session.Session) { + queries := data.New(db) + now := time.Now().UnixMilli() + err := queries.UpdateUserLastActivity(ctx, data.UpdateUserLastActivityParams{ + LastActivity: &now, + ID: sess.ID(), + }) + if err != nil { + slog.ErrorContext(ctx, "database error", "error", err) + } else { + slog.DebugContext(ctx, "set user activity", "now", now) + } +} diff --git a/internal/server/api/migrations/20250718210459_users_last_activity.sql b/internal/server/api/migrations/20250718210459_users_last_activity.sql new file mode 100644 index 0000000..2fbc2c8 --- /dev/null +++ b/internal/server/api/migrations/20250718210459_users_last_activity.sql @@ -0,0 +1,5 @@ +-- +goose Up +ALTER TABLE users ADD COLUMN last_activity INTEGER; + +-- +goose Down +ALTER TABLE users DROP COLUMN last_activity; diff --git a/internal/server/metrics/metrics.go b/internal/server/metrics/metrics.go index d465b6c..e317be6 100644 --- a/internal/server/metrics/metrics.go +++ b/internal/server/metrics/metrics.go @@ -56,9 +56,25 @@ var UsersActive = promauto.NewGauge(prometheus.GaugeOpts{ Help: "The total number of active users", }) +const ( + Minute = 60 + Hour = 60 * Minute + Day = 24 * Hour +) + var SessionDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: namespace, - Name: "session_duration_seconds", - Help: "The duration in seconds of an authenticated session", - NativeHistogramBucketFactor: 1.00271, + Namespace: namespace, + Name: "session_duration_seconds", + Help: "The duration in seconds of an authenticated session", + Buckets: []float64{ + 1, 30, 5 * Minute, 10 * Minute, 30 * Minute, + Hour, 2 * Hour, 3 * Hour, 4 * Hour, + 5 * Hour, 6 * Hour, 7 * Hour, 8 * Hour, + 10 * Hour, 12 * Hour, 14 * Hour, 16 * Hour, + 18 * Hour, 20 * Hour, 22 * Hour, Day, + 2 * Day, 7 * Day, 14 * Day, 28 * Day, + }, + // NativeHistogramBucketFactor: 1.00271, + // NativeHistogramMaxBucketNumber: 100, + // NativeHistogramMinResetDuration: time.Hour, }, []string{"os", "arch", "term", "colorterm"}) diff --git a/internal/server/server.go b/internal/server/server.go index d94dca6..f38a570 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -528,6 +528,9 @@ func processAuthenticatedRequests(ctx context.Context, sess *session.Session, re response = nil } + // TODO: add a timeout for this (even tho it should be super fast) + api.SetLastUserActivity(ctx, sess) + return response } @@ -690,9 +693,11 @@ func (s *server) handleSessionMetrics(ctx context.Context, sess *session.Session metrics.SessionDuration.WithLabelValues( analytics.OS, analytics.Arch, analytics.Term, analytics.Colorterm, ).Observe(duration.Seconds()) + slog.DebugContext(ctx, "observed session duration", "session_duration", duration.Seconds()) } else { metrics.SessionDuration.WithLabelValues( "", "", "", "", ).Observe(duration.Seconds()) + slog.DebugContext(ctx, "observed session duration (empty)", "session_duration", duration.Seconds()) } } -- cgit v1.3.1