diff --git a/package-lock.json b/package-lock.json
index 48da8124e0c5..13f03b8d2825 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,6 +31,7 @@
"escape-goat": "4.0.0",
"fast-glob": "3.3.2",
"htmx.org": "1.9.10",
+ "idiomorph": "0.3.0",
"jquery": "3.7.1",
"katex": "0.16.9",
"license-checker-webpack-plugin": "0.2.1",
@@ -6174,6 +6175,11 @@
"postcss": "^8.1.0"
}
},
+ "node_modules/idiomorph": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/idiomorph/-/idiomorph-0.3.0.tgz",
+ "integrity": "sha512-UhV1Ey5xCxIwR9B+OgIjQa+1Jx99XQ1vQHUsKBU1RpQzCx1u+b+N6SOXgf5mEJDqemUI/ffccu6+71l2mJUsRA=="
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
diff --git a/package.json b/package.json
index ac7974171111..3d753a567c1b 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"escape-goat": "4.0.0",
"fast-glob": "3.3.2",
"htmx.org": "1.9.10",
+ "idiomorph": "0.3.0",
"jquery": "3.7.1",
"katex": "0.16.9",
"license-checker-webpack-plugin": "0.2.1",
diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go
index d31cb1cd2551..9fbd429f7432 100644
--- a/routers/web/admin/admin.go
+++ b/routers/web/admin/admin.go
@@ -28,13 +28,14 @@ import (
)
const (
- tplDashboard base.TplName = "admin/dashboard"
- tplSelfCheck base.TplName = "admin/self_check"
- tplCron base.TplName = "admin/cron"
- tplQueue base.TplName = "admin/queue"
- tplStacktrace base.TplName = "admin/stacktrace"
- tplQueueManage base.TplName = "admin/queue_manage"
- tplStats base.TplName = "admin/stats"
+ tplDashboard base.TplName = "admin/dashboard"
+ tplSystemStatus base.TplName = "admin/system_status"
+ tplSelfCheck base.TplName = "admin/self_check"
+ tplCron base.TplName = "admin/cron"
+ tplQueue base.TplName = "admin/queue"
+ tplStacktrace base.TplName = "admin/stacktrace"
+ tplQueueManage base.TplName = "admin/queue_manage"
+ tplStats base.TplName = "admin/stats"
)
var sysStatus struct {
@@ -72,7 +73,7 @@ var sysStatus struct {
// Garbage collector statistics.
NextGC string // next run in HeapAlloc time (bytes)
- LastGC string // last run in absolute time (ns)
+ LastGCTime string // last run time
PauseTotalNs string
PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
NumGC uint32
@@ -110,7 +111,7 @@ func updateSystemStatus() {
sysStatus.OtherSys = base.FileSize(int64(m.OtherSys))
sysStatus.NextGC = base.FileSize(int64(m.NextGC))
- sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000)
+ sysStatus.LastGCTime = time.Unix(0, int64(m.LastGC)).Format(time.RFC3339)
sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000)
sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000)
sysStatus.NumGC = m.NumGC
@@ -132,7 +133,6 @@ func Dashboard(ctx *context.Context) {
ctx.Data["PageIsAdminDashboard"] = true
ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate(ctx)
ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion(ctx)
- // FIXME: update periodically
updateSystemStatus()
ctx.Data["SysStatus"] = sysStatus
ctx.Data["SSH"] = setting.SSH
@@ -140,6 +140,12 @@ func Dashboard(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplDashboard)
}
+func SystemStatus(ctx *context.Context) {
+ updateSystemStatus()
+ ctx.Data["SysStatus"] = sysStatus
+ ctx.HTML(http.StatusOK, tplSystemStatus)
+}
+
// DashboardPost run an admin operation
func DashboardPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.AdminDashboardForm)
diff --git a/routers/web/web.go b/routers/web/web.go
index a6288caaf610..0528b20328eb 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -677,6 +677,7 @@ func registerRoutes(m *web.Route) {
// ***** START: Admin *****
m.Group("/admin", func() {
m.Get("", admin.Dashboard)
+ m.Get("/system_status", admin.SystemStatus)
m.Post("", web.Bind(forms.AdminDashboardForm{}), admin.DashboardPost)
m.Get("/self_check", admin.SelfCheck)
diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl
index f43b4c5385c5..8088315f179e 100644
--- a/templates/admin/dashboard.tmpl
+++ b/templates/admin/dashboard.tmpl
@@ -75,69 +75,9 @@
-
-
- - {{ctx.Locale.Tr "admin.dashboard.server_uptime"}}
- - {{.SysStatus.StartTime}}
- - {{ctx.Locale.Tr "admin.dashboard.current_goroutine"}}
- - {{.SysStatus.NumGoroutine}}
-
- - {{ctx.Locale.Tr "admin.dashboard.current_memory_usage"}}
- - {{.SysStatus.MemAllocated}}
- - {{ctx.Locale.Tr "admin.dashboard.total_memory_allocated"}}
- - {{.SysStatus.MemTotal}}
- - {{ctx.Locale.Tr "admin.dashboard.memory_obtained"}}
- - {{.SysStatus.MemSys}}
- - {{ctx.Locale.Tr "admin.dashboard.pointer_lookup_times"}}
- - {{.SysStatus.Lookups}}
- - {{ctx.Locale.Tr "admin.dashboard.memory_allocate_times"}}
- - {{.SysStatus.MemMallocs}}
- - {{ctx.Locale.Tr "admin.dashboard.memory_free_times"}}
- - {{.SysStatus.MemFrees}}
-
- - {{ctx.Locale.Tr "admin.dashboard.current_heap_usage"}}
- - {{.SysStatus.HeapAlloc}}
- - {{ctx.Locale.Tr "admin.dashboard.heap_memory_obtained"}}
- - {{.SysStatus.HeapSys}}
- - {{ctx.Locale.Tr "admin.dashboard.heap_memory_idle"}}
- - {{.SysStatus.HeapIdle}}
- - {{ctx.Locale.Tr "admin.dashboard.heap_memory_in_use"}}
- - {{.SysStatus.HeapInuse}}
- - {{ctx.Locale.Tr "admin.dashboard.heap_memory_released"}}
- - {{.SysStatus.HeapReleased}}
- - {{ctx.Locale.Tr "admin.dashboard.heap_objects"}}
- - {{.SysStatus.HeapObjects}}
-
- - {{ctx.Locale.Tr "admin.dashboard.bootstrap_stack_usage"}}
- - {{.SysStatus.StackInuse}}
- - {{ctx.Locale.Tr "admin.dashboard.stack_memory_obtained"}}
- - {{.SysStatus.StackSys}}
- - {{ctx.Locale.Tr "admin.dashboard.mspan_structures_usage"}}
- - {{.SysStatus.MSpanInuse}}
- - {{ctx.Locale.Tr "admin.dashboard.mspan_structures_obtained"}}
- - {{.SysStatus.MSpanSys}}
- - {{ctx.Locale.Tr "admin.dashboard.mcache_structures_usage"}}
- - {{.SysStatus.MCacheInuse}}
- - {{ctx.Locale.Tr "admin.dashboard.mcache_structures_obtained"}}
- - {{.SysStatus.MCacheSys}}
- - {{ctx.Locale.Tr "admin.dashboard.profiling_bucket_hash_table_obtained"}}
- - {{.SysStatus.BuckHashSys}}
- - {{ctx.Locale.Tr "admin.dashboard.gc_metadata_obtained"}}
- - {{.SysStatus.GCSys}}
- - {{ctx.Locale.Tr "admin.dashboard.other_system_allocation_obtained"}}
- - {{.SysStatus.OtherSys}}
-
- - {{ctx.Locale.Tr "admin.dashboard.next_gc_recycle"}}
- - {{.SysStatus.NextGC}}
- - {{ctx.Locale.Tr "admin.dashboard.last_gc_time"}}
- - {{.SysStatus.LastGC}}
- - {{ctx.Locale.Tr "admin.dashboard.total_gc_pause"}}
- - {{.SysStatus.PauseTotalNs}}
- - {{ctx.Locale.Tr "admin.dashboard.last_gc_pause"}}
- - {{.SysStatus.PauseNs}}
- - {{ctx.Locale.Tr "admin.dashboard.gc_times"}}
- - {{.SysStatus.NumGC}}
-
+ {{/* TODO: make these stats work in multi-server deployments, likely needs per-server stats in DB */}}
+
+ {{template "admin/system_status" .}}
{{template "admin/layout_footer" .}}
diff --git a/templates/admin/system_status.tmpl b/templates/admin/system_status.tmpl
new file mode 100644
index 000000000000..7b5c9be6ccce
--- /dev/null
+++ b/templates/admin/system_status.tmpl
@@ -0,0 +1,62 @@
+
+ - {{ctx.Locale.Tr "admin.dashboard.server_uptime"}}
+ - {{.SysStatus.StartTime}}
+ - {{ctx.Locale.Tr "admin.dashboard.current_goroutine"}}
+ - {{.SysStatus.NumGoroutine}}
+
+ - {{ctx.Locale.Tr "admin.dashboard.current_memory_usage"}}
+ - {{.SysStatus.MemAllocated}}
+ - {{ctx.Locale.Tr "admin.dashboard.total_memory_allocated"}}
+ - {{.SysStatus.MemTotal}}
+ - {{ctx.Locale.Tr "admin.dashboard.memory_obtained"}}
+ - {{.SysStatus.MemSys}}
+ - {{ctx.Locale.Tr "admin.dashboard.pointer_lookup_times"}}
+ - {{.SysStatus.Lookups}}
+ - {{ctx.Locale.Tr "admin.dashboard.memory_allocate_times"}}
+ - {{.SysStatus.MemMallocs}}
+ - {{ctx.Locale.Tr "admin.dashboard.memory_free_times"}}
+ - {{.SysStatus.MemFrees}}
+
+ - {{ctx.Locale.Tr "admin.dashboard.current_heap_usage"}}
+ - {{.SysStatus.HeapAlloc}}
+ - {{ctx.Locale.Tr "admin.dashboard.heap_memory_obtained"}}
+ - {{.SysStatus.HeapSys}}
+ - {{ctx.Locale.Tr "admin.dashboard.heap_memory_idle"}}
+ - {{.SysStatus.HeapIdle}}
+ - {{ctx.Locale.Tr "admin.dashboard.heap_memory_in_use"}}
+ - {{.SysStatus.HeapInuse}}
+ - {{ctx.Locale.Tr "admin.dashboard.heap_memory_released"}}
+ - {{.SysStatus.HeapReleased}}
+ - {{ctx.Locale.Tr "admin.dashboard.heap_objects"}}
+ - {{.SysStatus.HeapObjects}}
+
+ - {{ctx.Locale.Tr "admin.dashboard.bootstrap_stack_usage"}}
+ - {{.SysStatus.StackInuse}}
+ - {{ctx.Locale.Tr "admin.dashboard.stack_memory_obtained"}}
+ - {{.SysStatus.StackSys}}
+ - {{ctx.Locale.Tr "admin.dashboard.mspan_structures_usage"}}
+ - {{.SysStatus.MSpanInuse}}
+ - {{ctx.Locale.Tr "admin.dashboard.mspan_structures_obtained"}}
+ - {{.SysStatus.MSpanSys}}
+ - {{ctx.Locale.Tr "admin.dashboard.mcache_structures_usage"}}
+ - {{.SysStatus.MCacheInuse}}
+ - {{ctx.Locale.Tr "admin.dashboard.mcache_structures_obtained"}}
+ - {{.SysStatus.MCacheSys}}
+ - {{ctx.Locale.Tr "admin.dashboard.profiling_bucket_hash_table_obtained"}}
+ - {{.SysStatus.BuckHashSys}}
+ - {{ctx.Locale.Tr "admin.dashboard.gc_metadata_obtained"}}
+ - {{.SysStatus.GCSys}}
+ - {{ctx.Locale.Tr "admin.dashboard.other_system_allocation_obtained"}}
+ - {{.SysStatus.OtherSys}}
+
+ - {{ctx.Locale.Tr "admin.dashboard.next_gc_recycle"}}
+ - {{.SysStatus.NextGC}}
+ - {{ctx.Locale.Tr "admin.dashboard.last_gc_time"}}
+ - {{.SysStatus.LastGCTime}}
+ - {{ctx.Locale.Tr "admin.dashboard.total_gc_pause"}}
+ - {{.SysStatus.PauseTotalNs}}
+ - {{ctx.Locale.Tr "admin.dashboard.last_gc_pause"}}
+ - {{.SysStatus.PauseNs}}
+ - {{ctx.Locale.Tr "admin.dashboard.gc_times"}}
+ - {{.SysStatus.NumGC}}
+
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index b9c050fdd5c1..e910bb0cd992 100644
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -29,7 +29,7 @@
{{template "base/head_style" .}}
{{template "custom/header" .}}
-
+
{{ctx.DataRaceCheck $.Context}}
{{template "custom/body_outer_pre" .}}
diff --git a/web_src/js/htmx.js b/web_src/js/htmx.js
index 92400d1cbe44..5ca30183082d 100644
--- a/web_src/js/htmx.js
+++ b/web_src/js/htmx.js
@@ -1,6 +1,9 @@
import * as htmx from 'htmx.org';
import {showErrorToast} from './modules/toast.js';
+// https://github.com/bigskysoftware/idiomorph#htmx
+import 'idiomorph/dist/idiomorph-ext.js';
+
// https://htmx.org/reference/#config
htmx.config.requestClass = 'is-loading';
htmx.config.scrollIntoViewOnBoost = false;
diff --git a/webpack.config.js b/webpack.config.js
index 8b3b8477c10b..82d76d9e8daa 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -169,6 +169,9 @@ export default {
],
},
plugins: [
+ new webpack.ProvidePlugin({ // for htmx extensions
+ htmx: 'htmx.org',
+ }),
new DefinePlugin({
__VUE_OPTIONS_API__: true, // at the moment, many Vue components still use the Vue Options API
__VUE_PROD_DEVTOOLS__: false, // do not enable devtools support in production
@@ -207,6 +210,7 @@ export default {
override: {
'khroma@*': {licenseName: 'MIT'}, // https://github.com/fabiospampinato/khroma/pull/33
'htmx.org@1.9.10': {licenseName: 'BSD-2-Clause'}, // "BSD 2-Clause" -> "BSD-2-Clause"
+ 'idiomorph@0.3.0': {licenseName: 'BSD-2-Clause'}, // "BSD 2-Clause" -> "BSD-2-Clause"
},
emitError: true,
allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0 OR Unlicense OR EPL-1.0 OR EPL-2.0)',