From 90ee7fe201dc87cabbc67545650739a897d3c80d Mon Sep 17 00:00:00 2001 From: JzoNg Date: Sat, 9 Mar 2024 12:48:14 +0800 Subject: [PATCH] tracing --- .../components/app/workflow-log/detail.tsx | 2 +- web/app/components/workflow/run/index.tsx | 5 +- web/app/components/workflow/run/node.tsx | 17 +--- web/app/components/workflow/run/tracing.tsx | 77 ++++++++++++++----- web/service/log.ts | 5 ++ web/types/workflow.ts | 32 ++++++++ 6 files changed, 103 insertions(+), 35 deletions(-) diff --git a/web/app/components/app/workflow-log/detail.tsx b/web/app/components/app/workflow-log/detail.tsx index 9478a51b75..111aaeda60 100644 --- a/web/app/components/app/workflow-log/detail.tsx +++ b/web/app/components/app/workflow-log/detail.tsx @@ -18,7 +18,7 @@ const DetailPanel: FC = ({ runID, onClose }) => {

{t('appLog.runDetail.workflowTitle')}

- + ) } diff --git a/web/app/components/workflow/run/index.tsx b/web/app/components/workflow/run/index.tsx index 4f3d9318a6..b379a804a7 100644 --- a/web/app/components/workflow/run/index.tsx +++ b/web/app/components/workflow/run/index.tsx @@ -5,14 +5,13 @@ import { useTranslation } from 'react-i18next' import cn from 'classnames' import Result from './result' import Tracing from './tracing' -// import type { App } from '@/types/app' type RunProps = { - activeTab: 'RESULT' | 'TRACING' + activeTab?: 'RESULT' | 'TRACING' runID: string } -const RunPanel: FC = ({ activeTab, runID }) => { +const RunPanel: FC = ({ activeTab = 'RESULT', runID }) => { const { t } = useTranslation() const [currentTab, setCurrentTab] = useState(activeTab) diff --git a/web/app/components/workflow/run/node.tsx b/web/app/components/workflow/run/node.tsx index 181adbca1e..2090002007 100644 --- a/web/app/components/workflow/run/node.tsx +++ b/web/app/components/workflow/run/node.tsx @@ -3,24 +3,15 @@ import { useTranslation } from 'react-i18next' import type { FC } from 'react' import cn from 'classnames' import BlockIcon from '../block-icon' -import type { BlockEnum } from '../types' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' import { AlertCircle, AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' import { CheckCircle, Loading02 } from '@/app/components/base/icons/src/vender/line/general' import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' - -export type NodeInfo = { - type: BlockEnum - title: string - time: number - tokens: number - status: string - error?: string -} +import type { NodeTracing } from '@/types/workflow' type Props = { - nodeInfo: NodeInfo + nodeInfo: NodeTracing collapsed: boolean collapseHandle: () => void } @@ -60,9 +51,9 @@ const NodePanel: FC = ({ nodeInfo, collapsed, collapseHandle }) => { !collapsed && 'rotate-90', )} /> - +
{nodeInfo.title}
-
{`${getTime(nodeInfo.time)} · ${getTokenCount(nodeInfo.tokens)} tokens`}
+
{`${getTime(nodeInfo.elapsed_time)} · ${getTokenCount(nodeInfo.execution_metadata.total_tokens)} tokens`}
{nodeInfo.status === 'succeeded' && ( )} diff --git a/web/app/components/workflow/run/tracing.tsx b/web/app/components/workflow/run/tracing.tsx index 21185447d7..d1c1dbcbc8 100644 --- a/web/app/components/workflow/run/tracing.tsx +++ b/web/app/components/workflow/run/tracing.tsx @@ -1,35 +1,76 @@ 'use client' import type { FC } from 'react' -import React, { useState } from 'react' -// import { useTranslation } from 'react-i18next' -// import cn from 'classnames' -import { BlockEnum } from '../types' +import React, { useCallback, useEffect, useState } from 'react' +import { useContext } from 'use-context-selector' +import produce from 'immer' import NodePanel from './node' +import Loading from '@/app/components/base/loading' +import { fetchTracingList } from '@/service/log' +import { useStore as useAppStore } from '@/app/components/app/store' +import type { NodeTracing } from '@/types/workflow' +import { ToastContext } from '@/app/components/base/toast' type TracingProps = { runID: string } -const nodeInfoFake = { - type: BlockEnum.Start, - title: 'START', - time: 67.349, - tokens: 2708, - status: 'failed', - error: 'lvlvlvlv', -} - const Tracing: FC = ({ runID }) => { - // const { t } = useTranslation() - const [nodeCollapsed, setCurrentTab] = useState(false) + const { notify } = useContext(ToastContext) + const { appDetail } = useAppStore() + const [loading, setLoading] = useState(true) + const [list, setList] = useState([]) + const [collapseState, setCollapseState] = useState([]) - const collapseStateChange = () => { - setCurrentTab(!nodeCollapsed) + const getTracingList = useCallback(async (appID: string, runID: string) => { + setLoading(true) + try { + const { data: nodeList } = await fetchTracingList({ + url: `/apps/${appID}/workflow-runs/${runID}/node-executions`, + }) + const collapseState = nodeList.map(node => node.status === 'succeeded') + setList(nodeList) + setCollapseState(collapseState) + setLoading(false) + } + catch (err) { + notify({ + type: 'error', + message: `${err}`, + }) + setLoading(false) + } + }, [notify]) + + useEffect(() => { + if (appDetail && runID) + getTracingList(appDetail.id, runID) + }, [appDetail, getTracingList, runID]) + + const collapseStateChange = (index: number) => { + const newCollapseState = produce(collapseState, (draft: boolean[]) => { + draft[index] = !draft[index] + }) + setCollapseState(newCollapseState) + } + + if (loading) { + return ( +
+ +
+ ) } return (
- + {list.map((node, index) => ( + collapseStateChange(index)} + /> + ))}
) } diff --git a/web/service/log.ts b/web/service/log.ts index 413374b676..50ef0c6bc9 100644 --- a/web/service/log.ts +++ b/web/service/log.ts @@ -19,6 +19,7 @@ import type { WorkflowLogsResponse, WorkflowRunDetailResponse, } from '@/models/log' +import type { NodeTracingListResponse } from '@/types/workflow' export const fetchConversationList: Fetcher }> = ({ appId, params }) => { return get(`/console/api/apps/${appId}/messages`, params) @@ -68,3 +69,7 @@ export const fetchWorkflowLogs: Fetcher { return get(`/apps/${appID}/workflow-run/${runID}`) } + +export const fetchTracingList: Fetcher = ({ url }) => { + return get(url) +} diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 79ed73f455..900921bbf9 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -1,9 +1,37 @@ import type { Viewport } from 'reactflow' import type { + BlockEnum, Edge, Node, } from '@/app/components/workflow/types' +export type NodeTracing = { + id: string + index: number + predecessor_node_id: string + node_id: string + node_type: BlockEnum + title: string + inputs: any + process_data: any + outputs?: any + status: string + error?: string + elapsed_time: number + execution_metadata: { + total_tokens: number + total_price: number + currency: string + } + created_at: number + created_by: { + id: string + name: string + email: string + } + finished_at: number +} + export type FetchWorkflowDraftResponse = { id: string graph: { @@ -14,3 +42,7 @@ export type FetchWorkflowDraftResponse = { features?: any updated_at: number } + +export type NodeTracingListResponse = { + data: NodeTracing[] +}