chore(logging): include request + caller context in jsonMsgObj warnings

The generic "X-UI: Something went wrong. Error: record not found" log
gave no clue about which endpoint, client, or controller line emitted
it. Prepend a context block:

  [POST /panel/api/clients/del/ADMIN ip=109.124.234.127
   handler=controller.(*ClientController).delete client.go:146]

Handler frame is located by scanning the stack for the first caller
outside util.go, so it points at the right controller method whether
the path went through jsonMsg, jsonObj, or jsonMsgObj directly.
This commit is contained in:
MHSanaei 2026-05-27 20:43:05 +02:00
parent afe1e42b5f
commit 16b4ca0c26
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A

View file

@ -5,6 +5,8 @@ import (
"net"
"net/http"
"net/netip"
"path/filepath"
"runtime"
"strings"
"github.com/mhsanaei/3x-ui/v3/logger"
@ -125,6 +127,32 @@ func jsonObj(c *gin.Context, obj any, err error) {
jsonMsgObj(c, "", obj, err)
}
func requestErrorContext(c *gin.Context) string {
handler, loc := callerOutsideUtil()
return fmt.Sprintf("[%s %s handler=%s %s]", c.Request.Method, c.Request.URL.Path, handler, loc)
}
func callerOutsideUtil() (string, string) {
var pcs [12]uintptr
n := runtime.Callers(2, pcs[:])
frames := runtime.CallersFrames(pcs[:n])
for {
frame, more := frames.Next()
base := filepath.Base(frame.File)
if base != "util.go" {
name := frame.Function
if idx := strings.LastIndex(name, "/"); idx >= 0 {
name = name[idx+1:]
}
return name, fmt.Sprintf("%s:%d", base, frame.Line)
}
if !more {
break
}
}
return "unknown", "unknown"
}
// jsonMsgObj sends a JSON response with a message, object, and error status.
func jsonMsgObj(c *gin.Context, msg string, obj any, err error) {
m := entity.Msg{
@ -137,16 +165,18 @@ func jsonMsgObj(c *gin.Context, msg string, obj any, err error) {
}
} else {
m.Success = false
ctx := requestErrorContext(c)
fail := I18nWeb(c, "fail")
errStr := err.Error()
if errStr != "" {
m.Msg = msg + " (" + errStr + ")"
logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err)
logger.Warningf("%s %s %s: %v", ctx, msg, fail, err)
} else if msg != "" {
m.Msg = msg
logger.Warning(msg + " " + I18nWeb(c, "fail"))
logger.Warningf("%s %s %s", ctx, msg, fail)
} else {
m.Msg = I18nWeb(c, "somethingWentWrong")
logger.Warning(I18nWeb(c, "somethingWentWrong") + " " + I18nWeb(c, "fail"))
logger.Warningf("%s %s %s", ctx, m.Msg, fail)
}
}
c.JSON(http.StatusOK, m)