From 3d36830bd2b3523e5fe77257fc38aa76dda6b131 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 25 Sep 2025 17:10:19 +0800 Subject: [PATCH] fix: condition branch panic --- internal/workflow/dispatcher/dispatcher.go | 4 ++-- internal/workflow/engine/engine.go | 3 +++ internal/workflow/engine/state.go | 2 +- ui/src/App.tsx | 10 ++++++---- ui/src/components/workflow/WorkflowRunDetail.tsx | 15 +++++++++++++-- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/internal/workflow/dispatcher/dispatcher.go b/internal/workflow/dispatcher/dispatcher.go index ef4ad2e8f..566c0482f 100644 --- a/internal/workflow/dispatcher/dispatcher.go +++ b/internal/workflow/dispatcher/dispatcher.go @@ -200,8 +200,8 @@ func (wd *workflowDispatcher) tryExecuteAsync(task *taskInfo) { // 捕获 panic defer func() { if r := recover(); r != nil { - slog.Default().Warn(fmt.Sprintf("workflow dispatcher panic: %v, stack trace: %s", r, string(debug.Stack())), slog.Any("workflowId", task.WorkflowId), slog.Any("runId", task.RunId)) - wd.syslog.Error(fmt.Sprintf("workflow dispatcher panic: %v", r), slog.Any("workflowId", task.WorkflowId), slog.Any("runId", task.RunId)) + wd.syslog.Error(fmt.Sprintf("workflow dispatcher panic: %v", r), slog.String("workflowId", task.WorkflowId), slog.String("runId", task.RunId)) + slog.Default().Error(fmt.Sprintf("workflow dispatcher panic: %v, stack trace: %s", r, string(debug.Stack())), slog.String("workflowId", task.WorkflowId), slog.String("runId", task.RunId)) if workflowRun != nil { workflowRun.Status = domain.WorkflowRunStatusTypeFailed diff --git a/internal/workflow/engine/engine.go b/internal/workflow/engine/engine.go index 29a7525eb..aea61bfa4 100644 --- a/internal/workflow/engine/engine.go +++ b/internal/workflow/engine/engine.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "log/slog" + "runtime/debug" "sync" "github.com/samber/lo" @@ -58,6 +59,8 @@ func (we *workflowEngine) Invoke(ctx context.Context, execution WorkflowExecutio defer func() { if r := recover(); r != nil { we.fireOnErrorHooks(ctx, fmt.Errorf("workflow engine panic: %v", r)) + we.syslog.Error(fmt.Sprintf("workflow engine panic: %v", r), slog.String("workflowId", execution.WorkflowId), slog.String("runId", execution.RunId)) + slog.Default().Error(fmt.Sprintf("workflow engine panic: %v, stack trace: %s", r, string(debug.Stack())), slog.String("workflowId", execution.WorkflowId), slog.String("runId", execution.RunId)) } }() diff --git a/internal/workflow/engine/state.go b/internal/workflow/engine/state.go index 7005fefbc..f87aaa229 100644 --- a/internal/workflow/engine/state.go +++ b/internal/workflow/engine/state.go @@ -18,7 +18,7 @@ type VariableState struct { func (s VariableState) ValueString() string { switch s.ValueType { case "string": - return s.Value.(string) + return fmt.Sprintf("%s", s.Value) case "number": return fmt.Sprintf("%d", s.Value) case "boolean": diff --git a/ui/src/App.tsx b/ui/src/App.tsx index bbd03f147..794033cc0 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,7 +1,7 @@ import { useEffect, useLayoutEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { RouterProvider } from "react-router-dom"; -import { App, ConfigProvider, type ThemeConfig, theme } from "antd"; +import { Alert, App, ConfigProvider, type ThemeConfig, theme } from "antd"; import { type Locale } from "antd/es/locale"; import AntdLocaleEnUs from "antd/locale/en_US"; import AntdLocaleZhCN from "antd/locale/zh_CN"; @@ -107,9 +107,11 @@ const RootApp = () => { }, }} > - - - + + + + + ); }; diff --git a/ui/src/components/workflow/WorkflowRunDetail.tsx b/ui/src/components/workflow/WorkflowRunDetail.tsx index ac623495a..c74f61a3e 100644 --- a/ui/src/components/workflow/WorkflowRunDetail.tsx +++ b/ui/src/components/workflow/WorkflowRunDetail.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { EditorState, FlowLayoutDefault } from "@flowgram.ai/fixed-layout-editor"; -import { IconBrowserShare, IconCheck, IconDots, IconDownload, IconSettings2, IconTransferOut } from "@tabler/icons-react"; +import { IconBrowserShare, IconBug, IconCheck, IconDots, IconDownload, IconSettings2, IconTransferOut } from "@tabler/icons-react"; import { useRequest } from "ahooks"; import { Alert, App, Button, Card, Divider, Dropdown, Empty, Skeleton, Table, type TableProps, Tooltip, Typography, theme } from "antd"; import dayjs from "dayjs"; @@ -83,6 +83,14 @@ const WorkflowRunDetail = ({ className, style, ...props }: WorkflowRunDetailProp }[mergedData.status] ?? ("info" as const) } /> + {!!mergedData.error && ( + } + message={
{mergedData.error}
} + showIcon + /> + )}
{t("workflow_run.process")} @@ -228,6 +236,9 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin const [showWhitespace, setShowWhitespace] = useState(true); const renderLogRecord = (record: Log) => { + let timestamp = dayjs(record.timestamp).format("YYYY-MM-DD HH:mm:ss"); + timestamp = `[${timestamp}]`; + let message = <>{record.message}; if (record.data != null && Object.keys(record.data).length > 0) { message = ( @@ -245,7 +256,7 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin return (
- {showTimestamp ?
[{dayjs(record.timestamp).format("YYYY-MM-DD HH:mm:ss")}]
: <>} + {showTimestamp &&
{timestamp}
}