aboutsummaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
Diffstat (limited to 'routers')
-rw-r--r--routers/common/middleware.go15
-rw-r--r--routers/web/admin/admin.go1
-rw-r--r--routers/web/admin/diagnosis.go18
-rw-r--r--routers/web/admin/perftrace.go18
-rw-r--r--routers/web/admin/stacktrace.go11
-rw-r--r--routers/web/web.go1
6 files changed, 57 insertions, 7 deletions
diff --git a/routers/common/middleware.go b/routers/common/middleware.go
index de59b78583..2ba02de8ed 100644
--- a/routers/common/middleware.go
+++ b/routers/common/middleware.go
@@ -9,6 +9,7 @@ import (
"strings"
"code.gitea.io/gitea/modules/cache"
+ "code.gitea.io/gitea/modules/gtprof"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
@@ -52,6 +53,14 @@ func RequestContextHandler() func(h http.Handler) http.Handler {
ctx, finished := reqctx.NewRequestContext(req.Context(), profDesc)
defer finished()
+ ctx, span := gtprof.GetTracer().Start(ctx, gtprof.TraceSpanHTTP)
+ req = req.WithContext(ctx)
+ defer func() {
+ chiCtx := chi.RouteContext(req.Context())
+ span.SetAttributeString(gtprof.TraceAttrHTTPRoute, chiCtx.RoutePattern())
+ span.End()
+ }()
+
defer func() {
if err := recover(); err != nil {
RenderPanicErrorPage(respWriter, req, err) // it should never panic
@@ -75,11 +84,11 @@ func ChiRoutePathHandler() func(h http.Handler) http.Handler {
// make sure chi uses EscapedPath(RawPath) as RoutePath, then "%2f" could be handled correctly
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- ctx := chi.RouteContext(req.Context())
+ chiCtx := chi.RouteContext(req.Context())
if req.URL.RawPath == "" {
- ctx.RoutePath = req.URL.EscapedPath()
+ chiCtx.RoutePath = req.URL.EscapedPath()
} else {
- ctx.RoutePath = req.URL.RawPath
+ chiCtx.RoutePath = req.URL.RawPath
}
next.ServeHTTP(resp, req)
})
diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go
index 3902a1efb1..0cd13acf60 100644
--- a/routers/web/admin/admin.go
+++ b/routers/web/admin/admin.go
@@ -37,6 +37,7 @@ const (
tplSelfCheck templates.TplName = "admin/self_check"
tplCron templates.TplName = "admin/cron"
tplQueue templates.TplName = "admin/queue"
+ tplPerfTrace templates.TplName = "admin/perftrace"
tplStacktrace templates.TplName = "admin/stacktrace"
tplQueueManage templates.TplName = "admin/queue_manage"
tplStats templates.TplName = "admin/stats"
diff --git a/routers/web/admin/diagnosis.go b/routers/web/admin/diagnosis.go
index 020554a35a..d040dbe0ba 100644
--- a/routers/web/admin/diagnosis.go
+++ b/routers/web/admin/diagnosis.go
@@ -10,13 +10,15 @@ import (
"time"
"code.gitea.io/gitea/modules/httplib"
+ "code.gitea.io/gitea/modules/tailmsg"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
)
func MonitorDiagnosis(ctx *context.Context) {
seconds := ctx.FormInt64("seconds")
- if seconds <= 5 {
- seconds = 5
+ if seconds <= 1 {
+ seconds = 1
}
if seconds > 300 {
seconds = 300
@@ -65,4 +67,16 @@ func MonitorDiagnosis(ctx *context.Context) {
return
}
_ = pprof.Lookup("heap").WriteTo(f, 0)
+
+ f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "perftrace.txt", Method: zip.Deflate, Modified: time.Now()})
+ if err != nil {
+ ctx.ServerError("Failed to create zip file", err)
+ return
+ }
+ for _, record := range tailmsg.GetManager().GetTraceRecorder().GetRecords() {
+ _, _ = f.Write(util.UnsafeStringToBytes(record.Time.Format(time.RFC3339)))
+ _, _ = f.Write([]byte(" "))
+ _, _ = f.Write(util.UnsafeStringToBytes((record.Content)))
+ _, _ = f.Write([]byte("\n\n"))
+ }
}
diff --git a/routers/web/admin/perftrace.go b/routers/web/admin/perftrace.go
new file mode 100644
index 0000000000..51ee57da10
--- /dev/null
+++ b/routers/web/admin/perftrace.go
@@ -0,0 +1,18 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package admin
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/modules/tailmsg"
+ "code.gitea.io/gitea/services/context"
+)
+
+func PerfTrace(ctx *context.Context) {
+ monitorTraceCommon(ctx)
+ ctx.Data["PageIsAdminMonitorPerfTrace"] = true
+ ctx.Data["PerfTraceRecords"] = tailmsg.GetManager().GetTraceRecorder().GetRecords()
+ ctx.HTML(http.StatusOK, tplPerfTrace)
+}
diff --git a/routers/web/admin/stacktrace.go b/routers/web/admin/stacktrace.go
index ff751be621..2b8c2fb4af 100644
--- a/routers/web/admin/stacktrace.go
+++ b/routers/web/admin/stacktrace.go
@@ -12,10 +12,17 @@ import (
"code.gitea.io/gitea/services/context"
)
+func monitorTraceCommon(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("admin.monitor")
+ ctx.Data["PageIsAdminMonitorTrace"] = true
+ // Hide the performance trace tab in production, because it shows a lot of SQLs and is not that useful for end users.
+ // To avoid confusing end users, do not let them know this tab. End users should "download diagnosis report" instead.
+ ctx.Data["ShowAdminPerformanceTraceTab"] = !setting.IsProd
+}
+
// Stacktrace show admin monitor goroutines page
func Stacktrace(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("admin.monitor")
- ctx.Data["PageIsAdminMonitorStacktrace"] = true
+ monitorTraceCommon(ctx)
ctx.Data["GoroutineCount"] = runtime.NumGoroutine()
diff --git a/routers/web/web.go b/routers/web/web.go
index c1790398f8..ef26dd9a74 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -720,6 +720,7 @@ func registerRoutes(m *web.Router) {
m.Group("/monitor", func() {
m.Get("/stats", admin.MonitorStats)
m.Get("/cron", admin.CronTasks)
+ m.Get("/perftrace", admin.PerfTrace)
m.Get("/stacktrace", admin.Stacktrace)
m.Post("/stacktrace/cancel/{pid}", admin.StacktraceCancel)
m.Get("/queue", admin.Queues)