Use a separate admin page to show global stats, remove actions stat (#25062)

Before, Gitea shows the database table stats on the `admin dashboard`
page.

It has some problems:

* `count(*)` is quite heavy. If tables have many records, this blocks
loading the admin page blocks for a long time
* Some users had even reported issues that they can't visit their admin
page because this page causes blocking or `50x error (reverse proxy
timeout)`
* The `actions` stat is not useful. The table is simply too large. Does
it really matter if it contains 1,000,000 rows or 9,999,999 rows?
* The translation `admin.dashboard.statistic_info` is difficult to
maintain.

So, this PR uses a separate page to show the stats and removes the
`actions` stat.


![image](babf7c61-b93b-4a62-bfaa-22983636427e)

## ⚠️ BREAKING

The `actions` Prometheus metrics collector has been removed for the
reasons mentioned beforehand.
Please do not rely on its output anymore.
This commit is contained in:
wxiaoguang 2023-06-03 22:03:41 +08:00 committed by GitHub
parent 4486dd39e7
commit 520eb57d76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 57 additions and 53 deletions

View file

@ -8,11 +8,13 @@ import (
"fmt"
"net/http"
"runtime"
"sort"
"time"
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/updatechecker"
"code.gitea.io/gitea/modules/web"
@ -26,6 +28,7 @@ const (
tplQueue base.TplName = "admin/queue"
tplStacktrace base.TplName = "admin/stacktrace"
tplQueueManage base.TplName = "admin/queue_manage"
tplStats base.TplName = "admin/stats"
)
var sysStatus struct {
@ -111,7 +114,6 @@ func updateSystemStatus() {
func Dashboard(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("admin.dashboard")
ctx.Data["PageIsAdminDashboard"] = true
ctx.Data["Stats"] = activities_model.GetStatistic()
ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate()
ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion()
// FIXME: update periodically
@ -126,7 +128,6 @@ func DashboardPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.AdminDashboardForm)
ctx.Data["Title"] = ctx.Tr("admin.dashboard")
ctx.Data["PageIsAdminDashboard"] = true
ctx.Data["Stats"] = activities_model.GetStatistic()
updateSystemStatus()
ctx.Data["SysStatus"] = sysStatus
@ -153,3 +154,30 @@ func CronTasks(ctx *context.Context) {
ctx.Data["Entries"] = cron.ListTasks()
ctx.HTML(http.StatusOK, tplCron)
}
func MonitorStats(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("admin.monitor.stats")
ctx.Data["PageIsAdminMonitorStats"] = true
bs, err := json.Marshal(activities_model.GetStatistic().Counter)
if err != nil {
ctx.ServerError("MonitorStats", err)
return
}
statsCounter := map[string]any{}
err = json.Unmarshal(bs, &statsCounter)
if err != nil {
ctx.ServerError("MonitorStats", err)
return
}
statsKeys := make([]string, 0, len(statsCounter))
for k := range statsCounter {
if statsCounter[k] == nil {
continue
}
statsKeys = append(statsKeys, k)
}
sort.Strings(statsKeys)
ctx.Data["StatsKeys"] = statsKeys
ctx.Data["StatsCounter"] = statsCounter
ctx.HTML(http.StatusOK, tplStats)
}

View file

@ -538,8 +538,8 @@ func registerRoutes(m *web.Route) {
// ***** START: Admin *****
m.Group("/admin", func() {
m.Get("", adminReq, admin.Dashboard)
m.Post("", adminReq, web.Bind(forms.AdminDashboardForm{}), admin.DashboardPost)
m.Get("", admin.Dashboard)
m.Post("", web.Bind(forms.AdminDashboardForm{}), admin.DashboardPost)
m.Group("/config", func() {
m.Get("", admin.Config)
@ -548,6 +548,7 @@ func registerRoutes(m *web.Route) {
})
m.Group("/monitor", func() {
m.Get("/stats", admin.MonitorStats)
m.Get("/cron", admin.CronTasks)
m.Get("/stacktrace", admin.Stacktrace)
m.Post("/stacktrace/cancel/{pid}", admin.StacktraceCancel)