mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-19 08:46:38 +00:00
Include users' own activity in active users calculation
This commit is contained in:
@@ -676,28 +676,33 @@ func (s *FileStore) CalculateUsageStats(_ context.Context, accountID string, sta
|
|||||||
return nil, fmt.Errorf("account not found")
|
return nil, fmt.Errorf("account not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
stats := &AccountUsageStats{
|
stats := &AccountUsageStats{}
|
||||||
TotalUsers: 0,
|
|
||||||
TotalPeers: int64(len(account.Peers)),
|
activeUsers := make(map[string]struct{})
|
||||||
}
|
for userID, user := range account.Users {
|
||||||
|
if user.LastLogin.After(start) && user.LastLogin.Before(end) && !user.IsServiceUser {
|
||||||
|
activeUsers[userID] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
for _, user := range account.Users {
|
|
||||||
if !user.IsServiceUser {
|
if !user.IsServiceUser {
|
||||||
stats.TotalUsers++
|
stats.TotalUsers++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activeUsers := make(map[string]bool)
|
|
||||||
for _, peer := range account.Peers {
|
for _, peer := range account.Peers {
|
||||||
lastSeen := peer.Status.LastSeen
|
if peer.Status.LastSeen.After(start) && peer.Status.LastSeen.Before(end) {
|
||||||
if lastSeen.Compare(start) >= 0 && lastSeen.Compare(end) <= 0 {
|
|
||||||
if _, exists := account.Users[peer.UserID]; exists && !activeUsers[peer.UserID] {
|
|
||||||
activeUsers[peer.UserID] = true
|
|
||||||
stats.ActiveUsers++
|
|
||||||
}
|
|
||||||
stats.ActivePeers++
|
stats.ActivePeers++
|
||||||
|
|
||||||
|
// service users don't have peers, but we check regardless.
|
||||||
|
if _, exists := account.Users[peer.UserID]; exists && !account.Users[peer.UserID].IsServiceUser {
|
||||||
|
activeUsers[peer.UserID] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stats.ActiveUsers = int64(len(activeUsers))
|
||||||
|
|
||||||
|
stats.TotalPeers = int64(len(account.Peers))
|
||||||
|
|
||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -674,15 +674,15 @@ func TestFileStore_CalculateUsageStats(t *testing.T) {
|
|||||||
stats1, err := store.CalculateUsageStats(context.TODO(), "account-1", startDate, endDate)
|
stats1, err := store.CalculateUsageStats(context.TODO(), "account-1", startDate, endDate)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, int64(2), stats1.ActiveUsers)
|
assert.Equal(t, int64(3), stats1.ActiveUsers)
|
||||||
assert.Equal(t, int64(4), stats1.TotalUsers)
|
assert.Equal(t, int64(5), stats1.TotalUsers)
|
||||||
assert.Equal(t, int64(3), stats1.ActivePeers)
|
assert.Equal(t, int64(3), stats1.ActivePeers)
|
||||||
assert.Equal(t, int64(7), stats1.TotalPeers)
|
assert.Equal(t, int64(8), stats1.TotalPeers)
|
||||||
|
|
||||||
stats2, err := store.CalculateUsageStats(context.TODO(), "account-2", startDate, endDate)
|
stats2, err := store.CalculateUsageStats(context.TODO(), "account-2", startDate, endDate)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, int64(1), stats2.ActiveUsers)
|
assert.Equal(t, int64(2), stats2.ActiveUsers)
|
||||||
assert.Equal(t, int64(2), stats2.TotalUsers)
|
assert.Equal(t, int64(2), stats2.TotalUsers)
|
||||||
assert.Equal(t, int64(1), stats2.ActivePeers)
|
assert.Equal(t, int64(1), stats2.ActivePeers)
|
||||||
assert.Equal(t, int64(2), stats2.TotalPeers)
|
assert.Equal(t, int64(2), stats2.TotalPeers)
|
||||||
|
|||||||
@@ -505,10 +505,13 @@ func (s *SqliteStore) CalculateUsageStats(ctx context.Context, accountID string,
|
|||||||
stats := &AccountUsageStats{}
|
stats := &AccountUsageStats{}
|
||||||
|
|
||||||
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||||
err := tx.Model(&nbpeer.Peer{}).
|
err := tx.Raw(`
|
||||||
Where("account_id = ? AND peer_status_last_seen BETWEEN ? AND ?", accountID, start, end).
|
SELECT COUNT(DISTINCT user_id) FROM (
|
||||||
Distinct("user_id").
|
SELECT id as user_id FROM users WHERE account_id = ? AND last_login BETWEEN ? AND ? AND is_service_user = ?
|
||||||
Count(&stats.ActiveUsers).Error
|
UNION
|
||||||
|
SELECT user_id FROM peers WHERE account_id = ? AND peer_status_last_seen BETWEEN ? AND ?
|
||||||
|
) AS combined`, accountID, start, end, false, accountID, start, end).Scan(&stats.ActiveUsers).Error
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get active users: %w", err)
|
return fmt.Errorf("get active users: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,15 +360,15 @@ func TestSqliteStore_CalculateUsageStats(t *testing.T) {
|
|||||||
stats1, err := store.CalculateUsageStats(context.TODO(), "account-1", startDate, endDate)
|
stats1, err := store.CalculateUsageStats(context.TODO(), "account-1", startDate, endDate)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, int64(2), stats1.ActiveUsers)
|
assert.Equal(t, int64(3), stats1.ActiveUsers)
|
||||||
assert.Equal(t, int64(4), stats1.TotalUsers)
|
assert.Equal(t, int64(5), stats1.TotalUsers)
|
||||||
assert.Equal(t, int64(3), stats1.ActivePeers)
|
assert.Equal(t, int64(3), stats1.ActivePeers)
|
||||||
assert.Equal(t, int64(7), stats1.TotalPeers)
|
assert.Equal(t, int64(8), stats1.TotalPeers)
|
||||||
|
|
||||||
stats2, err := store.CalculateUsageStats(context.TODO(), "account-2", startDate, endDate)
|
stats2, err := store.CalculateUsageStats(context.TODO(), "account-2", startDate, endDate)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, int64(1), stats2.ActiveUsers)
|
assert.Equal(t, int64(2), stats2.ActiveUsers)
|
||||||
assert.Equal(t, int64(2), stats2.TotalUsers)
|
assert.Equal(t, int64(2), stats2.TotalUsers)
|
||||||
assert.Equal(t, int64(1), stats2.ActivePeers)
|
assert.Equal(t, int64(1), stats2.ActivePeers)
|
||||||
assert.Equal(t, int64(2), stats2.TotalPeers)
|
assert.Equal(t, int64(2), stats2.TotalPeers)
|
||||||
|
|||||||
39
management/server/testdata/store_stats.json
vendored
39
management/server/testdata/store_stats.json
vendored
@@ -13,20 +13,29 @@
|
|||||||
},
|
},
|
||||||
"Users": {
|
"Users": {
|
||||||
"user-1-account-1": {
|
"user-1-account-1": {
|
||||||
"Id": "user-1-account-1"
|
"Id": "user-1-account-1",
|
||||||
|
"LastLogin": "2023-01-15T00:00:00Z"
|
||||||
},
|
},
|
||||||
"user-2-account-1": {
|
"user-2-account-1": {
|
||||||
"Id": "user-2-account-1"
|
"Id": "user-2-account-1",
|
||||||
|
"LastLogin": "2024-01-02T00:00:00Z"
|
||||||
},
|
},
|
||||||
"user-3-account-1": {
|
"user-3-account-1": {
|
||||||
"Id": "user-3-account-1"
|
"Id": "user-3-account-1",
|
||||||
|
"LastLogin": "2024-02-05T00:00:00Z"
|
||||||
},
|
},
|
||||||
"user-4-account-1": {
|
"user-4-account-1": {
|
||||||
"Id": "user-4-account-1"
|
"Id": "user-4-account-1",
|
||||||
|
"LastLogin": "2024-01-20T00:00:00Z"
|
||||||
},
|
},
|
||||||
"user-5-account-1": {
|
"user-5-account-1": {
|
||||||
"Id": "user-5-account-1",
|
"Id": "user-5-account-1",
|
||||||
"IsServiceUser": true
|
"IsServiceUser": true,
|
||||||
|
"LastLogin": "2024-02-15T00:00:00Z"
|
||||||
|
},
|
||||||
|
"user-6-account-1": {
|
||||||
|
"Id": "user-6-account-1",
|
||||||
|
"LastLogin": "2024-02-10T00:00:00Z"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Peers": {
|
"Peers": {
|
||||||
@@ -106,6 +115,17 @@
|
|||||||
"Meta": {
|
"Meta": {
|
||||||
"Hostname": "peer7-host"
|
"Hostname": "peer7-host"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"peer-8-account-1": {
|
||||||
|
"ID": "peer-8-account-1",
|
||||||
|
"UserID": "user-6-account-1",
|
||||||
|
"Status": {
|
||||||
|
"LastSeen": "2024-01-01T00:00:00Z"
|
||||||
|
},
|
||||||
|
"Name": "Peer Eight",
|
||||||
|
"Meta": {
|
||||||
|
"Hostname": "peer8-host"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -122,14 +142,17 @@
|
|||||||
},
|
},
|
||||||
"Users": {
|
"Users": {
|
||||||
"user-1-account-2": {
|
"user-1-account-2": {
|
||||||
"Id": "user-1-account-2"
|
"Id": "user-1-account-2",
|
||||||
|
"LastLogin": "2023-12-15T00:00:00Z"
|
||||||
},
|
},
|
||||||
"user-2-account-2": {
|
"user-2-account-2": {
|
||||||
"Id": "user-1-account-2"
|
"Id": "user-2-account-2",
|
||||||
|
"LastLogin": "2024-02-28T00:00:00Z"
|
||||||
},
|
},
|
||||||
"user-3-account-2": {
|
"user-3-account-2": {
|
||||||
"Id": "user-3-account-2",
|
"Id": "user-3-account-2",
|
||||||
"IsServiceUser": true
|
"IsServiceUser": true,
|
||||||
|
"LastLogin": "2024-01-30T00:00:00Z"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Peers": {
|
"Peers": {
|
||||||
|
|||||||
Reference in New Issue
Block a user