Files
team-api/internal/logic/admin/error_log.go
T
2026-05-28 23:48:52 +08:00

186 lines
5.0 KiB
Go

package admin
import (
"context"
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
v1 "github.com/qianfree/team-api/api/admin/v1"
"github.com/qianfree/team-api/internal/dao"
"github.com/qianfree/team-api/internal/logic/common"
)
// ErrorLogList returns a paginated list of system error logs.
func (s *sAdmin) ErrorLogList(ctx context.Context, req *v1.ErrorLogListReq) (*v1.ErrorLogListRes, error) {
if err := common.ValidateDateParam(req.StartDate, "开始日期"); err != nil {
return nil, err
}
if err := common.ValidateDateParam(req.EndDate, "结束日期"); err != nil {
return nil, err
}
var conditions []string
var args []any
if req.Source != "" {
conditions = append(conditions, "source = ?")
args = append(args, req.Source)
}
if req.ErrorCode > 0 {
conditions = append(conditions, "error_code = ?")
args = append(args, req.ErrorCode)
}
if req.Resolved == "true" {
conditions = append(conditions, "resolved = true")
} else if req.Resolved == "false" {
conditions = append(conditions, "resolved = false")
}
if req.StartDate != "" {
conditions = append(conditions, "created_at >= ?")
args = append(args, req.StartDate)
}
if req.EndDate != "" {
conditions = append(conditions, "created_at <= ?")
args = append(args, req.EndDate+" 23:59:59")
}
if req.Keyword != "" {
conditions = append(conditions, "(error_message ILIKE ? OR request_path ILIKE ?)")
kw := "%" + req.Keyword + "%"
args = append(args, kw, kw)
}
where := strings.Join(conditions, " AND ")
items, total, err := queryPage(ctx,
"sys_error_logs", "*", where, "id DESC",
req.Page, req.PageSize, args...)
if err != nil {
return nil, err
}
if items == nil {
items = []map[string]any{}
}
return &v1.ErrorLogListRes{
List: items,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// ErrorLogDetail returns the detail of a single error log.
func (s *sAdmin) ErrorLogDetail(ctx context.Context, req *v1.ErrorLogDetailReq) (*v1.ErrorLogDetailRes, error) {
result, err := g.DB().Ctx(ctx).Query(ctx,
"SELECT * FROM sys_error_logs WHERE id = ?", req.Id)
if err != nil {
return nil, err
}
if len(result) == 0 {
return nil, common.NewNotFoundError("错误日志")
}
row := result[0]
data := make(map[string]any, len(row))
for k, v := range row {
data[k] = v.Val()
}
return &v1.ErrorLogDetailRes{Data: data}, nil
}
// ErrorLogResolve marks an error log as resolved.
func (s *sAdmin) ErrorLogResolve(ctx context.Context, req *v1.ErrorLogResolveReq) (*v1.ErrorLogResolveRes, error) {
count, err := dao.SysErrorLogs.Ctx(ctx).Where("id", req.Id).Count()
if err != nil {
return nil, err
}
if count == 0 {
return nil, common.NewNotFoundError("错误日志")
}
userID := common.GetCtxUserID(ctx)
_, err = dao.SysErrorLogs.Ctx(ctx).
Where("id", req.Id).
Data(g.Map{
"resolved": true,
"resolved_by": userID,
"resolved_at": gtime.Now(),
}).Update()
if err != nil {
return nil, err
}
return &v1.ErrorLogResolveRes{}, nil
}
// ErrorLogBatchResolve marks multiple error logs as resolved.
func (s *sAdmin) ErrorLogBatchResolve(ctx context.Context, req *v1.ErrorLogBatchResolveReq) (*v1.ErrorLogBatchResolveRes, error) {
userID := common.GetCtxUserID(ctx)
_, err := dao.SysErrorLogs.Ctx(ctx).
WhereIn("id", req.Ids).
Data(g.Map{
"resolved": true,
"resolved_by": userID,
"resolved_at": gtime.Now(),
}).Update()
if err != nil {
return nil, err
}
return &v1.ErrorLogBatchResolveRes{}, nil
}
// ErrorLogStats returns error log statistics.
func (s *sAdmin) ErrorLogStats(ctx context.Context, _ *v1.ErrorLogStatsReq) (*v1.ErrorLogStatsRes, error) {
// Total unresolved
unresolved, err := dao.SysErrorLogs.Ctx(ctx).Where("resolved", false).Count()
if err != nil {
return nil, err
}
// Total today
today := gtime.Now().Format("Y-m-d")
todayCount, err := dao.SysErrorLogs.Ctx(ctx).
Where("created_at >= ?", today).
Count()
if err != nil {
return nil, err
}
// By source (last 7 days)
bySourceResult, err := g.DB().Ctx(ctx).Query(ctx,
"SELECT source, COUNT(*) as count FROM sys_error_logs WHERE created_at >= NOW() - INTERVAL '7 days' GROUP BY source")
if err != nil {
return nil, err
}
bySource := make([]map[string]any, 0, len(bySourceResult))
for _, row := range bySourceResult {
m := make(map[string]any, len(row))
for k, v := range row {
m[k] = v.Val()
}
bySource = append(bySource, m)
}
// By error code (last 7 days, top 10)
byCodeResult, err := g.DB().Ctx(ctx).Query(ctx,
"SELECT error_code, COUNT(*) as count FROM sys_error_logs WHERE created_at >= NOW() - INTERVAL '7 days' GROUP BY error_code ORDER BY count DESC LIMIT 10")
if err != nil {
return nil, err
}
byCode := make([]map[string]any, 0, len(byCodeResult))
for _, row := range byCodeResult {
m := make(map[string]any, len(row))
for k, v := range row {
m[k] = v.Val()
}
byCode = append(byCode, m)
}
return &v1.ErrorLogStatsRes{
Data: map[string]any{
"unresolved": unresolved,
"today_count": todayCount,
"by_source": bySource,
"by_error_code": byCode,
},
}, nil
}