mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
improve logging ui
This commit is contained in:
@@ -3,12 +3,15 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import {
|
||||
AlertCircle,
|
||||
ChevronDown,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
ChevronUp,
|
||||
Clock,
|
||||
DollarSign,
|
||||
Hash,
|
||||
Loader2,
|
||||
Maximize2,
|
||||
X,
|
||||
Zap,
|
||||
} from 'lucide-react'
|
||||
@@ -21,6 +24,69 @@ import type { WorkflowState } from '@/stores/workflows/workflow/types'
|
||||
|
||||
const logger = createLogger('FrozenCanvas')
|
||||
|
||||
function ExpandableDataSection({ title, data }: { title: string; data: any }) {
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
|
||||
const jsonString = JSON.stringify(data, null, 2)
|
||||
const isLargeData = jsonString.length > 500 || jsonString.split('\n').length > 10
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div className='mb-2 flex items-center justify-between'>
|
||||
<h4 className='font-medium text-foreground text-sm'>{title}</h4>
|
||||
<div className='flex items-center gap-1'>
|
||||
{isLargeData && (
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className='rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground'
|
||||
title="Expand in modal"
|
||||
>
|
||||
<Maximize2 className='h-3 w-3' />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
className='rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground'
|
||||
>
|
||||
{isExpanded ? <ChevronUp className='h-3 w-3' /> : <ChevronDown className='h-3 w-3' />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'overflow-y-auto rounded bg-muted p-3 font-mono text-xs transition-all duration-200',
|
||||
isExpanded ? 'max-h-96' : 'max-h-32'
|
||||
)}
|
||||
>
|
||||
<pre className='whitespace-pre-wrap break-words text-foreground'>{jsonString}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Modal for large data */}
|
||||
{isModalOpen && (
|
||||
<div className='fixed inset-0 z-[200] flex items-center justify-center bg-black/50'>
|
||||
<div className='mx-4 h-[80vh] w-full max-w-4xl rounded-lg border bg-background shadow-lg'>
|
||||
<div className='flex items-center justify-between border-b p-4'>
|
||||
<h3 className='font-medium text-foreground text-lg'>{title}</h3>
|
||||
<button
|
||||
onClick={() => setIsModalOpen(false)}
|
||||
className='rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground'
|
||||
>
|
||||
<X className='h-4 w-4' />
|
||||
</button>
|
||||
</div>
|
||||
<div className='h-[calc(80vh-4rem)] overflow-auto p-4'>
|
||||
<pre className='whitespace-pre-wrap break-words font-mono text-foreground text-sm'>{jsonString}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function formatExecutionData(executionData: any) {
|
||||
const {
|
||||
inputData,
|
||||
@@ -160,14 +226,14 @@ function PinnedLogs({ executionData, onClose }: { executionData: any; onClose: (
|
||||
<span className='text-foreground text-sm'>{formatted.duration}</span>
|
||||
</div>
|
||||
|
||||
{formatted.cost && (
|
||||
{formatted.cost && formatted.cost.total > 0 && (
|
||||
<div className='flex items-center gap-2'>
|
||||
<DollarSign className='h-4 w-4 text-muted-foreground' />
|
||||
<span className='text-foreground text-sm'>${formatted.cost.total.toFixed(5)}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{formatted.tokens && (
|
||||
{formatted.tokens && formatted.tokens.total > 0 && (
|
||||
<div className='flex items-center gap-2'>
|
||||
<Hash className='h-4 w-4 text-muted-foreground' />
|
||||
<span className='text-foreground text-sm'>{formatted.tokens.total} tokens</span>
|
||||
@@ -175,21 +241,17 @@ function PinnedLogs({ executionData, onClose }: { executionData: any; onClose: (
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className='mb-2 font-medium text-foreground text-sm'>Input</h4>
|
||||
<div className='max-h-32 overflow-y-auto rounded bg-muted p-3 font-mono text-xs'>
|
||||
<pre className='text-foreground'>{JSON.stringify(formatted.input, null, 2)}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<ExpandableDataSection
|
||||
title="Input"
|
||||
data={formatted.input}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<h4 className='mb-2 font-medium text-foreground text-sm'>Output</h4>
|
||||
<div className='max-h-32 overflow-y-auto rounded bg-muted p-3 font-mono text-xs'>
|
||||
<pre className='text-foreground'>{JSON.stringify(formatted.output, null, 2)}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<ExpandableDataSection
|
||||
title="Output"
|
||||
data={formatted.output}
|
||||
/>
|
||||
|
||||
{formatted.cost && (
|
||||
{formatted.cost && formatted.cost.total > 0 && (
|
||||
<div>
|
||||
<h4 className='mb-2 font-medium text-foreground text-sm'>Cost Breakdown</h4>
|
||||
<div className='space-y-1 text-sm'>
|
||||
@@ -209,7 +271,7 @@ function PinnedLogs({ executionData, onClose }: { executionData: any; onClose: (
|
||||
</div>
|
||||
)}
|
||||
|
||||
{formatted.tokens && (
|
||||
{formatted.tokens && formatted.tokens.total > 0 && (
|
||||
<div>
|
||||
<h4 className='mb-2 font-medium text-foreground text-sm'>Token Usage</h4>
|
||||
<div className='space-y-1 text-sm'>
|
||||
@@ -242,12 +304,7 @@ interface FrozenCanvasData {
|
||||
startedAt: string
|
||||
endedAt?: string
|
||||
totalDurationMs?: number
|
||||
blockStats: {
|
||||
total: number
|
||||
success: number
|
||||
error: number
|
||||
skipped: number
|
||||
}
|
||||
|
||||
cost: {
|
||||
total: number | null
|
||||
input: number | null
|
||||
|
||||
@@ -494,42 +494,7 @@ export function Sidebar({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Enhanced Stats - only show for enhanced logs */}
|
||||
{log.metadata?.enhanced && log.metadata?.blockStats && (
|
||||
<div>
|
||||
<h3 className='mb-1 font-medium text-muted-foreground text-xs'>
|
||||
Block Execution Stats
|
||||
</h3>
|
||||
<div className='space-y-1 text-sm'>
|
||||
<div className='flex justify-between'>
|
||||
<span>Total Blocks:</span>
|
||||
<span className='font-medium'>{log.metadata.blockStats.total}</span>
|
||||
</div>
|
||||
<div className='flex justify-between'>
|
||||
<span>Successful:</span>
|
||||
<span className='font-medium text-green-600'>
|
||||
{log.metadata.blockStats.success}
|
||||
</span>
|
||||
</div>
|
||||
{log.metadata.blockStats.error > 0 && (
|
||||
<div className='flex justify-between'>
|
||||
<span>Failed:</span>
|
||||
<span className='font-medium text-red-600'>
|
||||
{log.metadata.blockStats.error}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{log.metadata.blockStats.skipped > 0 && (
|
||||
<div className='flex justify-between'>
|
||||
<span>Skipped:</span>
|
||||
<span className='font-medium text-yellow-600'>
|
||||
{log.metadata.blockStats.skipped}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{/* Enhanced Cost - only show for enhanced logs with actual cost data */}
|
||||
{log.metadata?.enhanced && hasCostInfo && (
|
||||
@@ -583,7 +548,7 @@ export function Sidebar({
|
||||
className='w-full justify-start gap-2'
|
||||
>
|
||||
<Eye className='h-4 w-4' />
|
||||
View Frozen Canvas
|
||||
View Snapshot
|
||||
</Button>
|
||||
<p className='mt-1 text-muted-foreground text-xs'>
|
||||
See the exact workflow state and block inputs/outputs at execution time
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
ChevronDown,
|
||||
ChevronDownSquare,
|
||||
ChevronRight,
|
||||
ChevronUpSquare,
|
||||
Code,
|
||||
Cpu,
|
||||
ExternalLink,
|
||||
@@ -203,39 +201,16 @@ export function TraceSpansDisplay({
|
||||
// Keep track of expanded spans
|
||||
const [expandedSpans, setExpandedSpans] = useState<Set<string>>(new Set())
|
||||
|
||||
// Function to collect all span IDs recursively (for expand all functionality)
|
||||
const collectAllSpanIds = (spans: TraceSpan[]): string[] => {
|
||||
const ids: string[] = []
|
||||
|
||||
const collectIds = (span: TraceSpan) => {
|
||||
const spanId = span.id || `span-${span.name}-${span.startTime}`
|
||||
ids.push(spanId)
|
||||
|
||||
// Process children
|
||||
if (span.children && span.children.length > 0) {
|
||||
span.children.forEach(collectIds)
|
||||
}
|
||||
}
|
||||
|
||||
spans.forEach(collectIds)
|
||||
return ids
|
||||
}
|
||||
|
||||
const allSpanIds = useMemo(() => {
|
||||
if (!traceSpans || traceSpans.length === 0) return []
|
||||
return collectAllSpanIds(traceSpans)
|
||||
}, [traceSpans])
|
||||
|
||||
// Early return after all hooks
|
||||
if (!traceSpans || traceSpans.length === 0) {
|
||||
return <div className='text-muted-foreground text-sm'>No trace data available</div>
|
||||
}
|
||||
|
||||
// Format total duration for better readability
|
||||
const _formatTotalDuration = (ms: number) => {
|
||||
if (ms < 1000) return `${ms}ms`
|
||||
return `${(ms / 1000).toFixed(2)}s (${ms}ms)`
|
||||
}
|
||||
|
||||
|
||||
// Find the earliest start time among all spans to be the workflow start time
|
||||
const workflowStartTime = traceSpans.reduce((earliest, span) => {
|
||||
@@ -269,48 +244,12 @@ export function TraceSpansDisplay({
|
||||
}
|
||||
}
|
||||
|
||||
// Handle expand all / collapse all
|
||||
const handleExpandAll = () => {
|
||||
const newExpandedSpans = new Set(allSpanIds)
|
||||
setExpandedSpans(newExpandedSpans)
|
||||
|
||||
if (onExpansionChange) {
|
||||
onExpansionChange(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleCollapseAll = () => {
|
||||
setExpandedSpans(new Set())
|
||||
|
||||
if (onExpansionChange) {
|
||||
onExpansionChange(false)
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if all spans are currently expanded
|
||||
const allExpanded = allSpanIds.length > 0 && allSpanIds.every((id) => expandedSpans.has(id))
|
||||
|
||||
return (
|
||||
<div className='w-full'>
|
||||
<div className='mb-2 flex items-center justify-between'>
|
||||
<div className='font-medium text-muted-foreground text-xs'>Trace Spans</div>
|
||||
<button
|
||||
onClick={allExpanded ? handleCollapseAll : handleExpandAll}
|
||||
className='flex items-center gap-1 text-muted-foreground text-xs transition-colors hover:text-foreground'
|
||||
title={allExpanded ? 'Collapse all spans' : 'Expand all spans'}
|
||||
>
|
||||
{allExpanded ? (
|
||||
<>
|
||||
<ChevronUpSquare className='h-3.5 w-3.5' />
|
||||
<span>Collapse</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ChevronDownSquare className='h-3.5 w-3.5' />
|
||||
<span>Expand</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
<div className='font-medium text-muted-foreground text-xs'>Workflow Execution</div>
|
||||
</div>
|
||||
<div className='w-full overflow-hidden rounded-md border shadow-sm'>
|
||||
{traceSpans.map((span, index) => {
|
||||
@@ -369,7 +308,8 @@ function TraceSpanItem({
|
||||
const expanded = expandedSpans.has(spanId)
|
||||
const hasChildren = span.children && span.children.length > 0
|
||||
const hasToolCalls = span.toolCalls && span.toolCalls.length > 0
|
||||
const hasNestedItems = hasChildren || hasToolCalls
|
||||
const hasInputOutput = Boolean(span.input || span.output)
|
||||
const hasNestedItems = hasChildren || hasToolCalls || hasInputOutput
|
||||
|
||||
// Calculate timing information
|
||||
const spanStartTime = new Date(span.startTime).getTime()
|
||||
@@ -389,8 +329,7 @@ function TraceSpanItem({
|
||||
const safeStartPercent = Math.min(100, Math.max(0, relativeStartPercent))
|
||||
const safeWidthPercent = Math.max(2, Math.min(100 - safeStartPercent, actualDurationPercent))
|
||||
|
||||
// For parent-relative timing display
|
||||
const _startOffsetPercentage = totalDuration > 0 ? (startOffset / totalDuration) * 100 : 0
|
||||
|
||||
|
||||
// Handle click to expand/collapse this span
|
||||
const handleSpanClick = () => {
|
||||
@@ -605,17 +544,17 @@ function TraceSpanItem({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Children and tool calls */}
|
||||
{/* Expanded content */}
|
||||
{expanded && (
|
||||
<div>
|
||||
{/* Block Input/Output Data */}
|
||||
{(span.input || span.output) && (
|
||||
<div className='mt-2 ml-8 space-y-3 overflow-hidden'>
|
||||
<div className='mt-2 ml-8 mr-4 mb-4 space-y-3 overflow-hidden'>
|
||||
{/* Input Data */}
|
||||
{span.input && (
|
||||
<div>
|
||||
<h4 className='mb-2 font-medium text-muted-foreground text-xs'>Input</h4>
|
||||
<div className='overflow-hidden rounded-md bg-secondary/30 p-3'>
|
||||
<div className='overflow-hidden rounded-md bg-secondary/30 p-3 mb-2'>
|
||||
<BlockDataDisplay data={span.input} blockType={span.type} isInput={true} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -627,7 +566,7 @@ function TraceSpanItem({
|
||||
<h4 className='mb-2 font-medium text-muted-foreground text-xs'>
|
||||
{span.status === 'error' ? 'Error Details' : 'Output'}
|
||||
</h4>
|
||||
<div className='overflow-hidden rounded-md bg-secondary/30 p-3'>
|
||||
<div className='overflow-hidden rounded-md bg-secondary/30 p-3 mb-2'>
|
||||
<BlockDataDisplay
|
||||
data={span.output}
|
||||
blockType={span.type}
|
||||
@@ -639,12 +578,8 @@ function TraceSpanItem({
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Children and tool calls */}
|
||||
{expanded && (
|
||||
<div>
|
||||
{/* Children and tool calls */}
|
||||
{/* Render child spans */}
|
||||
{hasChildren && (
|
||||
<div>
|
||||
|
||||
@@ -308,14 +308,16 @@ export default function Logs() {
|
||||
{/* Table with fixed layout */}
|
||||
<div className='w-full min-w-[800px]'>
|
||||
{/* Header */}
|
||||
<div className='border-border/50 border-b'>
|
||||
<div className='grid grid-cols-[160px_100px_1fr_120px_100px_100px] gap-4 px-4 py-3 font-medium text-muted-foreground text-xs'>
|
||||
<div>Time</div>
|
||||
<div>Status</div>
|
||||
<div>Workflow</div>
|
||||
<div className='hidden lg:block'>Trigger</div>
|
||||
<div className='hidden xl:block'>Cost</div>
|
||||
<div>Duration</div>
|
||||
<div className='px-4 py-4'>
|
||||
<div className='rounded-lg border border-border/30 bg-muted/30'>
|
||||
<div className='grid grid-cols-[160px_100px_1fr_120px_100px_100px] gap-4 px-4 py-3'>
|
||||
<div className='font-medium text-muted-foreground text-xs'>Time</div>
|
||||
<div className='font-medium text-muted-foreground text-xs'>Status</div>
|
||||
<div className='font-medium text-muted-foreground text-xs'>Workflow</div>
|
||||
<div className='hidden lg:block font-medium text-muted-foreground text-xs'>Trigger</div>
|
||||
<div className='hidden xl:block font-medium text-muted-foreground text-xs'>Cost</div>
|
||||
<div className='font-medium text-muted-foreground text-xs'>Duration</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -344,7 +346,7 @@ export default function Logs() {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className='space-y-1 p-4'>
|
||||
<div className='space-y-1 px-4 pb-4'>
|
||||
{logs.map((log) => {
|
||||
const formattedDate = formatDate(log.createdAt)
|
||||
const isSelected = selectedLog?.id === log.id
|
||||
@@ -360,7 +362,7 @@ export default function Logs() {
|
||||
}`}
|
||||
onClick={() => handleLogClick(log)}
|
||||
>
|
||||
<div className='grid grid-cols-[160px_100px_1fr_120px_100px_100px] gap-4 p-4'>
|
||||
<div className='grid grid-cols-[160px_100px_1fr_120px_100px_100px] gap-4 px-4 py-4'>
|
||||
{/* Time */}
|
||||
<div>
|
||||
<div className='font-medium text-sm'>{formattedDate.formatted}</div>
|
||||
@@ -403,13 +405,13 @@ export default function Logs() {
|
||||
|
||||
{/* Cost */}
|
||||
<div className='hidden xl:block'>
|
||||
<div className='text-xs'>
|
||||
<div className='text-xs text-muted-foreground'>
|
||||
{log.metadata?.enhanced && log.metadata?.cost?.total ? (
|
||||
<span className='text-muted-foreground'>
|
||||
<span>
|
||||
${log.metadata.cost.total.toFixed(4)}
|
||||
</span>
|
||||
) : (
|
||||
<span className='text-muted-foreground'>—</span>
|
||||
<span className='pl-0.5'>—</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -84,12 +84,7 @@ export interface WorkflowLog {
|
||||
cost?: CostMetadata
|
||||
blockInput?: Record<string, any>
|
||||
enhanced?: boolean
|
||||
blockStats?: {
|
||||
total: number
|
||||
success: number
|
||||
error: number
|
||||
skipped: number
|
||||
}
|
||||
|
||||
blockExecutions?: Array<{
|
||||
id: string
|
||||
blockId: string
|
||||
|
||||
@@ -194,12 +194,6 @@ export class EnhancedExecutionLogger implements IExecutionLoggerService {
|
||||
executionId: string
|
||||
endedAt: string
|
||||
totalDurationMs: number
|
||||
blockStats: {
|
||||
total: number
|
||||
success: number
|
||||
error: number
|
||||
skipped: number
|
||||
}
|
||||
costSummary: {
|
||||
totalCost: number
|
||||
totalInputCost: number
|
||||
@@ -224,7 +218,6 @@ export class EnhancedExecutionLogger implements IExecutionLoggerService {
|
||||
executionId,
|
||||
endedAt,
|
||||
totalDurationMs,
|
||||
blockStats,
|
||||
costSummary,
|
||||
finalOutput,
|
||||
traceSpans,
|
||||
@@ -232,11 +225,8 @@ export class EnhancedExecutionLogger implements IExecutionLoggerService {
|
||||
|
||||
logger.debug(`Completing workflow execution ${executionId}`)
|
||||
|
||||
const level = blockStats.error > 0 ? 'error' : 'info'
|
||||
const message =
|
||||
blockStats.error > 0
|
||||
? `Workflow execution failed: ${blockStats.error} error(s), ${blockStats.success} success(es)`
|
||||
: `Workflow execution completed: ${blockStats.success} block(s) executed successfully`
|
||||
const level = 'info'
|
||||
const message = `Workflow execution completed`
|
||||
|
||||
const [updatedLog] = await db
|
||||
.update(workflowExecutionLogs)
|
||||
@@ -245,10 +235,10 @@ export class EnhancedExecutionLogger implements IExecutionLoggerService {
|
||||
message,
|
||||
endedAt: new Date(endedAt),
|
||||
totalDurationMs,
|
||||
blockCount: blockStats.total,
|
||||
successCount: blockStats.success,
|
||||
errorCount: blockStats.error,
|
||||
skippedCount: blockStats.skipped,
|
||||
blockCount: 0,
|
||||
successCount: 0,
|
||||
errorCount: 0,
|
||||
skippedCount: 0,
|
||||
totalCost: costSummary.totalCost.toString(),
|
||||
totalInputCost: costSummary.totalInputCost.toString(),
|
||||
totalOutputCost: costSummary.totalOutputCost.toString(),
|
||||
|
||||
@@ -46,50 +46,7 @@ export async function loadWorkflowStateForExecution(workflowId: string): Promise
|
||||
}
|
||||
}
|
||||
|
||||
export function calculateBlockStats(traceSpans: any[]): {
|
||||
total: number
|
||||
success: number
|
||||
error: number
|
||||
skipped: number
|
||||
} {
|
||||
if (!traceSpans || traceSpans.length === 0) {
|
||||
return { total: 0, success: 0, error: 0, skipped: 0 }
|
||||
}
|
||||
|
||||
// Recursively collect all block spans from the trace span tree
|
||||
const collectBlockSpans = (spans: any[]): any[] => {
|
||||
const blocks: any[] = []
|
||||
|
||||
for (const span of spans) {
|
||||
// Check if this span is an actual workflow block
|
||||
if (
|
||||
span.type &&
|
||||
span.type !== 'workflow' &&
|
||||
span.type !== 'provider' &&
|
||||
span.type !== 'model' &&
|
||||
span.blockId
|
||||
) {
|
||||
blocks.push(span)
|
||||
}
|
||||
|
||||
// Recursively check children
|
||||
if (span.children && Array.isArray(span.children)) {
|
||||
blocks.push(...collectBlockSpans(span.children))
|
||||
}
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
const blockSpans = collectBlockSpans(traceSpans)
|
||||
|
||||
const total = blockSpans.length
|
||||
const success = blockSpans.filter((span) => span.status === 'success').length
|
||||
const error = blockSpans.filter((span) => span.status === 'error').length
|
||||
const skipped = blockSpans.filter((span) => span.status === 'skipped').length
|
||||
|
||||
return { total, success, error, skipped }
|
||||
}
|
||||
|
||||
export function calculateCostSummary(traceSpans: any[]): {
|
||||
totalCost: number
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { enhancedExecutionLogger } from './enhanced-execution-logger'
|
||||
import {
|
||||
calculateBlockStats,
|
||||
calculateCostSummary,
|
||||
createEnvironmentObject,
|
||||
createTriggerObject,
|
||||
@@ -99,14 +98,12 @@ export class EnhancedLoggingSession {
|
||||
const { endedAt, totalDurationMs, finalOutput, traceSpans } = params
|
||||
|
||||
try {
|
||||
const blockStats = calculateBlockStats(traceSpans || [])
|
||||
const costSummary = calculateCostSummary(traceSpans || [])
|
||||
|
||||
await enhancedExecutionLogger.completeWorkflowExecution({
|
||||
executionId: this.executionId,
|
||||
endedAt: endedAt || new Date().toISOString(),
|
||||
totalDurationMs: totalDurationMs || 0,
|
||||
blockStats,
|
||||
costSummary,
|
||||
finalOutput: finalOutput || {},
|
||||
traceSpans: traceSpans || [],
|
||||
@@ -126,7 +123,6 @@ export class EnhancedLoggingSession {
|
||||
|
||||
async completeWithError(error?: any): Promise<void> {
|
||||
try {
|
||||
const blockStats = { total: 0, success: 0, error: 1, skipped: 0 }
|
||||
const costSummary = {
|
||||
totalCost: 0,
|
||||
totalInputCost: 0,
|
||||
@@ -141,7 +137,6 @@ export class EnhancedLoggingSession {
|
||||
executionId: this.executionId,
|
||||
endedAt: new Date().toISOString(),
|
||||
totalDurationMs: 0,
|
||||
blockStats,
|
||||
costSummary,
|
||||
finalOutput: null,
|
||||
traceSpans: [],
|
||||
|
||||
@@ -169,12 +169,7 @@ export interface WorkflowExecutionSummary {
|
||||
startedAt: string
|
||||
endedAt: string
|
||||
durationMs: number
|
||||
blockStats: {
|
||||
total: number
|
||||
success: number
|
||||
error: number
|
||||
skipped: number
|
||||
}
|
||||
|
||||
costSummary: {
|
||||
total: number
|
||||
inputCost: number
|
||||
@@ -360,12 +355,7 @@ export interface ExecutionLoggerService {
|
||||
executionId: string
|
||||
endedAt: string
|
||||
totalDurationMs: number
|
||||
blockStats: {
|
||||
total: number
|
||||
success: number
|
||||
error: number
|
||||
skipped: number
|
||||
}
|
||||
|
||||
costSummary: {
|
||||
totalCost: number
|
||||
totalInputCost: number
|
||||
|
||||
Reference in New Issue
Block a user