Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
10141c5e
Unverified
Commit
10141c5e
authored
Sep 08, 2020
by
Emil Tullstedt
Committed by
GitHub
Sep 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Stats: Use more efficient SQL and add timeouts (#27390)
parent
2a2992b0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
59 additions
and
26 deletions
+59
-26
pkg/services/sqlstore/stats.go
+23
-20
pkg/services/sqlstore/stats_integration_test.go
+34
-4
pkg/services/sqlstore/stats_test.go
+2
-2
No files found.
pkg/services/sqlstore/stats.go
View file @
10141c5e
...
@@ -14,7 +14,7 @@ func init() {
...
@@ -14,7 +14,7 @@ func init() {
bus
.
AddHandler
(
"sql"
,
GetDataSourceStats
)
bus
.
AddHandler
(
"sql"
,
GetDataSourceStats
)
bus
.
AddHandler
(
"sql"
,
GetDataSourceAccessStats
)
bus
.
AddHandler
(
"sql"
,
GetDataSourceAccessStats
)
bus
.
AddHandler
(
"sql"
,
GetAdminStats
)
bus
.
AddHandler
(
"sql"
,
GetAdminStats
)
bus
.
AddHandler
(
"sql"
,
GetUserStats
)
bus
.
AddHandler
Ctx
(
"sql"
,
GetUserStats
)
bus
.
AddHandlerCtx
(
"sql"
,
GetAlertNotifiersUsageStats
)
bus
.
AddHandlerCtx
(
"sql"
,
GetAlertNotifiersUsageStats
)
bus
.
AddHandlerCtx
(
"sql"
,
GetSystemUserCountStats
)
bus
.
AddHandlerCtx
(
"sql"
,
GetSystemUserCountStats
)
}
}
...
@@ -95,7 +95,10 @@ func GetSystemStats(query *models.GetSystemStatsQuery) error {
...
@@ -95,7 +95,10 @@ func GetSystemStats(query *models.GetSystemStatsQuery) error {
}
}
func
roleCounterSQL
()
string
{
func
roleCounterSQL
()
string
{
_
=
updateUserRoleCountsIfNecessary
(
false
)
const
roleCounterTimeout
=
20
*
time
.
Second
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
roleCounterTimeout
)
defer
cancel
()
_
=
updateUserRoleCountsIfNecessary
(
ctx
,
false
)
sqlQuery
:=
sqlQuery
:=
strconv
.
FormatInt
(
userStatsCache
.
total
.
Admins
,
10
)
+
` AS admins, `
+
strconv
.
FormatInt
(
userStatsCache
.
total
.
Admins
,
10
)
+
` AS admins, `
+
strconv
.
FormatInt
(
userStatsCache
.
total
.
Editors
,
10
)
+
` AS editors, `
+
strconv
.
FormatInt
(
userStatsCache
.
total
.
Editors
,
10
)
+
` AS editors, `
+
...
@@ -182,8 +185,8 @@ func GetSystemUserCountStats(ctx context.Context, query *models.GetSystemUserCou
...
@@ -182,8 +185,8 @@ func GetSystemUserCountStats(ctx context.Context, query *models.GetSystemUserCou
})
})
}
}
func
GetUserStats
(
query
*
models
.
GetUserStatsQuery
)
error
{
func
GetUserStats
(
ctx
context
.
Context
,
query
*
models
.
GetUserStatsQuery
)
error
{
err
:=
updateUserRoleCountsIfNecessary
(
query
.
MustUpdate
)
err
:=
updateUserRoleCountsIfNecessary
(
ctx
,
query
.
MustUpdate
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -197,10 +200,10 @@ func GetUserStats(query *models.GetUserStatsQuery) error {
...
@@ -197,10 +200,10 @@ func GetUserStats(query *models.GetUserStatsQuery) error {
return
nil
return
nil
}
}
func
updateUserRoleCountsIfNecessary
(
forced
bool
)
error
{
func
updateUserRoleCountsIfNecessary
(
ctx
context
.
Context
,
forced
bool
)
error
{
memoizationPeriod
:=
time
.
Now
()
.
Add
(
-
userStatsCacheLimetime
)
memoizationPeriod
:=
time
.
Now
()
.
Add
(
-
userStatsCacheLimetime
)
if
forced
||
userStatsCache
.
memoized
.
Before
(
memoizationPeriod
)
{
if
forced
||
userStatsCache
.
memoized
.
Before
(
memoizationPeriod
)
{
err
:=
updateUserRoleCounts
()
err
:=
updateUserRoleCounts
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -220,21 +223,21 @@ var (
...
@@ -220,21 +223,21 @@ var (
userStatsCacheLimetime
=
5
*
time
.
Minute
userStatsCacheLimetime
=
5
*
time
.
Minute
)
)
func
updateUserRoleCounts
()
error
{
func
updateUserRoleCounts
(
ctx
context
.
Context
)
error
{
query
:=
`
query
:=
`
SELECT role AS bitrole, active, COUNT(role) AS count FROM
SELECT role AS bitrole, active, COUNT(role) AS count FROM
(SELECT
active, SUM(role) AS role
(SELECT last_seen_at>? AS
active, SUM(role) AS role
FROM (SELECT
FROM (SELECT
u.id,
u.id,
CASE org_user.role
CASE org_user.role
WHEN 'Admin' THEN 4
WHEN 'Admin' THEN 4
WHEN 'Editor' THEN 2
WHEN 'Editor' THEN 2
ELSE 1
ELSE 1
END AS role,
END AS role,
u.last_seen_at>? AS active
u.last_seen_at
FROM `
+
dialect
.
Quote
(
"user"
)
+
` AS u LEFT
JOIN org_user ON org_user.user_id = u.id
FROM `
+
dialect
.
Quote
(
"user"
)
+
` AS u INNER
JOIN org_user ON org_user.user_id = u.id
GROUP BY u.id, u.last_seen_at, org_user.role) AS t2
GROUP BY u.id, u.last_seen_at, org_user.role) AS t2
GROUP BY active, id
) AS t1
GROUP BY id, last_seen_at
) AS t1
GROUP BY active, role;`
GROUP BY active, role;`
activeUserDeadline
:=
time
.
Now
()
.
Add
(
-
activeUserTimeLimit
)
activeUserDeadline
:=
time
.
Now
()
.
Add
(
-
activeUserTimeLimit
)
...
@@ -246,7 +249,7 @@ GROUP BY active, role;`
...
@@ -246,7 +249,7 @@ GROUP BY active, role;`
}
}
bitmap
:=
[]
rolebitmap
{}
bitmap
:=
[]
rolebitmap
{}
err
:=
x
.
SQL
(
query
,
activeUserDeadline
)
.
Find
(
&
bitmap
)
err
:=
x
.
Context
(
ctx
)
.
SQL
(
query
,
activeUserDeadline
)
.
Find
(
&
bitmap
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
...
pkg/services/sqlstore/stats_integration_test.go
View file @
10141c5e
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"context"
"context"
"fmt"
"fmt"
"testing"
"testing"
"time"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/setting"
...
@@ -51,7 +52,8 @@ func TestIntegration_GetUserStats(t *testing.T) {
...
@@ -51,7 +52,8 @@ func TestIntegration_GetUserStats(t *testing.T) {
}()
}()
}
}
users
:=
make
([]
models
.
User
,
5
)
const
nUsers
=
100
users
:=
make
([]
models
.
User
,
nUsers
)
for
i
:=
range
users
{
for
i
:=
range
users
{
cmd
:=
&
models
.
CreateUserCommand
{
cmd
:=
&
models
.
CreateUserCommand
{
...
@@ -65,15 +67,43 @@ func TestIntegration_GetUserStats(t *testing.T) {
...
@@ -65,15 +67,43 @@ func TestIntegration_GetUserStats(t *testing.T) {
users
[
i
]
=
cmd
.
Result
users
[
i
]
=
cmd
.
Result
}
}
orgs
:=
make
([]
models
.
Org
,
10
)
for
i
:=
range
orgs
{
cmd
:=
&
models
.
CreateOrgCommand
{
Name
:
fmt
.
Sprintf
(
"org %d"
,
i
),
UserId
:
firstUser
.
Id
,
}
err
:=
CreateOrg
(
cmd
)
require
.
NoError
(
t
,
err
)
orgs
[
i
]
=
cmd
.
Result
}
for
_
,
u
:=
range
users
{
for
_
,
o
:=
range
orgs
{
cmd
:=
&
models
.
AddOrgUserCommand
{
Role
:
"Viewer"
,
UserId
:
u
.
Id
,
OrgId
:
o
.
Id
,
}
err
:=
AddOrgUser
(
cmd
)
require
.
NoErrorf
(
t
,
err
,
"uID %d oID %d"
,
u
.
Id
,
o
.
Id
)
}
}
query
:=
models
.
GetUserStatsQuery
{
query
:=
models
.
GetUserStatsQuery
{
MustUpdate
:
true
,
MustUpdate
:
true
,
}
}
err
=
GetUserStats
(
&
query
)
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
10
*
time
.
Second
)
defer
cancel
()
err
=
GetUserStats
(
ctx
,
&
query
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
assert
.
EqualValues
(
t
,
models
.
UserStats
{
assert
.
EqualValues
(
t
,
models
.
UserStats
{
Users
:
6
,
Users
:
nUsers
+
1
,
Admins
:
1
,
Admins
:
1
,
Editors
:
5
,
Editors
:
nUsers
,
Viewers
:
0
,
Viewers
:
0
,
},
query
.
Result
)
},
query
.
Result
)
}
}
pkg/services/sqlstore/stats_test.go
View file @
10141c5e
...
@@ -59,7 +59,7 @@ func TestStatsDataAccess(t *testing.T) {
...
@@ -59,7 +59,7 @@ func TestStatsDataAccess(t *testing.T) {
MustUpdate
:
true
,
MustUpdate
:
true
,
Active
:
true
,
Active
:
true
,
}
}
err
:=
GetUserStats
(
&
query
)
err
:=
GetUserStats
(
context
.
Background
(),
&
query
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
int64
(
1
),
query
.
Result
.
Users
)
assert
.
Equal
(
t
,
int64
(
1
),
query
.
Result
.
Users
)
assert
.
Equal
(
t
,
int64
(
1
),
query
.
Result
.
Admins
)
assert
.
Equal
(
t
,
int64
(
1
),
query
.
Result
.
Admins
)
...
@@ -133,6 +133,6 @@ func populateDB(t *testing.T) {
...
@@ -133,6 +133,6 @@ func populateDB(t *testing.T) {
MustUpdate
:
true
,
MustUpdate
:
true
,
Active
:
true
,
Active
:
true
,
}
}
err
=
GetUserStats
(
&
query
)
err
=
GetUserStats
(
context
.
Background
(),
&
query
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment