aboutsummaryrefslogtreecommitdiff
path: root/backend/storage/stats.go
diff options
context:
space:
mode:
authorWilliam Hergès <william@herges.fr>2025-12-30 18:59:30 +0100
committerWilliam Hergès <william@herges.fr>2025-12-30 18:59:30 +0100
commit1c4ec0e4fe4a765dad1db9ab332ebfdcc8c2b11e (patch)
treecced72df8b1db7827ce2fa28361fb18130e1304f /backend/storage/stats.go
parent87b27187b93912fc22e61fd298606af7d7bce710 (diff)
feat(storage): scope stats per ip instead of target
Diffstat (limited to 'backend/storage/stats.go')
-rw-r--r--backend/storage/stats.go48
1 files changed, 29 insertions, 19 deletions
diff --git a/backend/storage/stats.go b/backend/storage/stats.go
index b30cb8c..76d1c82 100644
--- a/backend/storage/stats.go
+++ b/backend/storage/stats.go
@@ -12,42 +12,52 @@ import (
"time"
)
+const IPAddressKey = "ip_address"
+
type loaded struct {
- data map[string]struct{}
+ data map[string]string
mu *sync.RWMutex
}
-func (l *loaded) Has(k string) bool {
+func (l *loaded) Has(k string, v string) bool {
l.mu.RLock()
defer l.mu.RUnlock()
- _, ok := l.data[k]
- return ok
+ val, ok := l.data[k]
+ if !ok {
+ return false
+ }
+ return val == v
}
-func (l *loaded) Add(k string) {
+func (l *loaded) Add(k string, v string) {
l.mu.Lock()
defer l.mu.Unlock()
- l.data[k] = struct{}{}
+ l.data[k] = v
}
-func (l *loaded) Remove(k string) {
- l.mu.Lock()
- defer l.mu.Unlock()
- delete(l.data, k)
+func (l *loaded) Remove(k string, v string) {
+ if l.Has(k, v) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ delete(l.data, k)
+ }
}
func newLoaded() *loaded {
return &loaded{
- data: make(map[string]struct{}),
+ data: make(map[string]string),
mu: new(sync.RWMutex),
}
}
var load = newLoaded()
+// using /assets/styles.css to detect if a page is loaded → majority of bots will not load this
+const HumanPageLoad = "/assets/styles.css"
+
func UpdateStats(ctx context.Context, r *http.Request, domain string) error {
target := r.URL.Path
- if strings.HasPrefix(target, "/static") || strings.HasPrefix(target, "/admin") {
+ if strings.HasPrefix(target, "/admin") {
return nil
}
ref := r.Header.Get("Referer")
@@ -65,12 +75,12 @@ func UpdateStats(ctx context.Context, r *http.Request, domain string) error {
return nil
}
}
- // using /assets/styles.css to detect if a page is loaded → majority of bots will not load this
- if target == "/assets/styles.css" {
+ if target == HumanPageLoad {
target = ref
ref = "?"
}
- if load.Has(target) {
+ ip := ctx.Value(IPAddressKey).(string)
+ if load.Has(ip, target) {
return nil
}
db := getDB(ctx)
@@ -81,11 +91,11 @@ func UpdateStats(ctx context.Context, r *http.Request, domain string) error {
defer func() {
if err == nil {
slog.Debug("stats updated")
- load.Add(target)
- go func(target string) {
+ load.Add(ip, target)
+ go func(ip, target string) {
time.Sleep(5 * time.Second)
- load.Remove(target)
- }(target)
+ load.Remove(ip, target)
+ }(ip, target)
}
}()
if !rows.Next() {