Files
YMhut-box-C-/server/unified-management/internal/db/system_logs.go
T

85 lines
3.1 KiB
Go

package db
import "strings"
func (s *Store) ListSystemLogsPage(filters SystemLogFilters) (SystemLogPage, error) {
page := filters.Page
if page <= 0 {
page = 1
}
perPage := filters.PerPage
if perPage <= 0 {
perPage = 35
}
if perPage > 100 {
perPage = 100
}
base := systemLogUnionSQL()
where, args := systemLogWhere(filters)
var total int
if err := s.queryRow(`SELECT COUNT(*) FROM (`+base+`) system_logs`+where, args...).Scan(&total); err != nil {
return SystemLogPage{}, err
}
queryArgs := append(append([]any{}, args...), perPage, (page-1)*perPage)
rows, err := s.query(`SELECT id, category, type, target, status, message, detail, created_at
FROM (`+base+`) system_logs`+where+` ORDER BY created_at DESC, id DESC LIMIT ? OFFSET ?`, queryArgs...)
if err != nil {
return SystemLogPage{}, err
}
defer rows.Close()
items := []SystemLogItem{}
for rows.Next() {
var item SystemLogItem
if err := rows.Scan(&item.ID, &item.Category, &item.Type, &item.Target, &item.Status, &item.Message, &item.Detail, &item.CreatedAt); err != nil {
return SystemLogPage{}, err
}
items = append(items, item)
}
if err := rows.Err(); err != nil {
return SystemLogPage{}, err
}
return SystemLogPage{Items: items, Total: total, Page: page, PerPage: perPage}, nil
}
func systemLogUnionSQL() string {
return `SELECT id, 'operation' AS category, type, target,
COALESCE(NULLIF(actor, ''), 'system') AS status, message, user_agent AS detail, created_at
FROM audit_logs
UNION ALL
SELECT h.id, 'health' AS category, 'endpoint.health' AS type,
COALESCE(NULLIF(e.source_id, ''), 'unknown') AS target, h.status,
COALESCE(NULLIF(e.name, ''), 'unknown endpoint') AS message, h.error AS detail, h.checked_at AS created_at
FROM endpoint_health_checks h LEFT JOIN source_endpoints e ON e.id = h.source_db_id
UNION ALL
SELECT id, 'client' AS category, 'endpoint.call' AS type, source_id AS target,
status, error AS message, client AS detail, created_at
FROM endpoint_call_logs
UNION ALL
SELECT id, 'database_sync' AS category, direction AS type, direction AS target,
status, message, tables_json AS detail, COALESCE(NULLIF(finished_at, ''), started_at) AS created_at
FROM database_sync_jobs
UNION ALL
SELECT id, 'legacy_sync' AS category, 'legacy.sync' AS type, 'legacy' AS target,
status, summary AS message, stats_json AS detail, COALESCE(NULLIF(finished_at, ''), started_at) AS created_at
FROM legacy_sync_jobs`
}
func systemLogWhere(filters SystemLogFilters) (string, []any) {
clauses := []string{}
args := []any{}
if category := strings.TrimSpace(filters.Category); category != "" {
clauses = append(clauses, "category = ?")
args = append(args, sanitize(category))
}
if query := strings.TrimSpace(filters.Query); query != "" {
like := "%" + strings.ToLower(sanitize(query)) + "%"
clauses = append(clauses, `(LOWER(category) LIKE ? OR LOWER(type) LIKE ? OR LOWER(target) LIKE ? OR
LOWER(status) LIKE ? OR LOWER(message) LIKE ? OR LOWER(detail) LIKE ? OR LOWER(created_at) LIKE ?)`)
args = append(args, like, like, like, like, like, like, like)
}
if len(clauses) == 0 {
return "", args
}
return " WHERE " + strings.Join(clauses, " AND "), args
}