diff --git a/backend/internal/handler/admin/ops_handler.go b/backend/internal/handler/admin/ops_handler.go index 822f7d62..44accc8f 100644 --- a/backend/internal/handler/admin/ops_handler.go +++ b/backend/internal/handler/admin/ops_handler.go @@ -111,6 +111,7 @@ func (h *OpsHandler) GetErrorLogs(c *gin.Context) { filter.Owner = strings.TrimSpace(c.Query("error_owner")) filter.Source = strings.TrimSpace(c.Query("error_source")) filter.Query = strings.TrimSpace(c.Query("q")) + filter.UserQuery = strings.TrimSpace(c.Query("user_query")) // Force request errors: client-visible status >= 400. // buildOpsErrorLogsWhere already applies this for non-upstream phase. @@ -211,6 +212,7 @@ func (h *OpsHandler) ListRequestErrors(c *gin.Context) { filter.Owner = strings.TrimSpace(c.Query("error_owner")) filter.Source = strings.TrimSpace(c.Query("error_source")) filter.Query = strings.TrimSpace(c.Query("q")) + filter.UserQuery = strings.TrimSpace(c.Query("user_query")) // Force request errors: client-visible status >= 400. // buildOpsErrorLogsWhere already applies this for non-upstream phase. diff --git a/backend/internal/repository/ops_repo.go b/backend/internal/repository/ops_repo.go index d889269f..613c5bd5 100644 --- a/backend/internal/repository/ops_repo.go +++ b/backend/internal/repository/ops_repo.go @@ -326,6 +326,7 @@ SELECT COALESCE(e.upstream_errors::text, ''), e.is_business_limited, e.user_id, + COALESCE(u.email, ''), e.api_key_id, e.account_id, COALESCE(a.name, ''), @@ -345,6 +346,7 @@ SELECT e.request_body_bytes, COALESCE(e.request_headers::text, '') FROM ops_error_logs e +LEFT JOIN users u ON e.user_id = u.id LEFT JOIN accounts a ON e.account_id = a.id LEFT JOIN groups g ON e.group_id = g.id WHERE e.id = $1 @@ -395,6 +397,7 @@ LIMIT 1` &out.UpstreamErrors, &out.IsBusinessLimited, &userID, + &out.UserEmail, &apiKeyID, &accountID, &out.AccountName, @@ -1033,6 +1036,13 @@ func buildOpsErrorLogsWhere(filter *service.OpsErrorLogFilter) (string, []any) { clauses = append(clauses, "(request_id ILIKE $"+n+" OR client_request_id ILIKE $"+n+" OR error_message ILIKE $"+n+")") } + if userQuery := strings.TrimSpace(filter.UserQuery); userQuery != "" { + like := "%" + userQuery + "%" + args = append(args, like) + n := itoa(len(args)) + clauses = append(clauses, "u.email ILIKE $"+n) + } + return "WHERE " + strings.Join(clauses, " AND "), args } diff --git a/backend/internal/service/ops_models.go b/backend/internal/service/ops_models.go index c7666e92..347cd52b 100644 --- a/backend/internal/service/ops_models.go +++ b/backend/internal/service/ops_models.go @@ -93,6 +93,7 @@ type OpsErrorLogFilter struct { Source string Resolved *bool Query string + UserQuery string // Search by user email // Optional correlation keys for exact matching. RequestID string