Skip to content

Commit f254d70

Browse files
improvement(logs): cleanup code (#999)
1 parent 8748e1d commit f254d70

File tree

15 files changed

+6471
-329
lines changed

15 files changed

+6471
-329
lines changed

apps/sim/app/api/logs/[executionId]/frozen-canvas/route.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,7 @@ export async function GET(
4646
startedAt: workflowLog.startedAt.toISOString(),
4747
endedAt: workflowLog.endedAt?.toISOString(),
4848
totalDurationMs: workflowLog.totalDurationMs,
49-
blockStats: {
50-
total: workflowLog.blockCount,
51-
success: workflowLog.successCount,
52-
error: workflowLog.errorCount,
53-
skipped: workflowLog.skippedCount,
54-
},
55-
cost: {
56-
total: workflowLog.totalCost ? Number.parseFloat(workflowLog.totalCost) : null,
57-
input: workflowLog.totalInputCost ? Number.parseFloat(workflowLog.totalInputCost) : null,
58-
output: workflowLog.totalOutputCost
59-
? Number.parseFloat(workflowLog.totalOutputCost)
60-
: null,
61-
},
62-
totalTokens: workflowLog.totalTokens,
49+
cost: workflowLog.cost || null,
6350
},
6451
}
6552

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { and, eq } from 'drizzle-orm'
2+
import { type NextRequest, NextResponse } from 'next/server'
3+
import { getSession } from '@/lib/auth'
4+
import { createLogger } from '@/lib/logs/console/logger'
5+
import { db } from '@/db'
6+
import { permissions, workflow, workflowExecutionLogs } from '@/db/schema'
7+
8+
const logger = createLogger('LogDetailsByIdAPI')
9+
10+
export const revalidate = 0
11+
12+
export async function GET(_request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
13+
const requestId = crypto.randomUUID().slice(0, 8)
14+
15+
try {
16+
const session = await getSession()
17+
if (!session?.user?.id) {
18+
logger.warn(`[${requestId}] Unauthorized log details access attempt`)
19+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
20+
}
21+
22+
const userId = session.user.id
23+
const { id } = await params
24+
25+
const rows = await db
26+
.select({
27+
id: workflowExecutionLogs.id,
28+
workflowId: workflowExecutionLogs.workflowId,
29+
executionId: workflowExecutionLogs.executionId,
30+
stateSnapshotId: workflowExecutionLogs.stateSnapshotId,
31+
level: workflowExecutionLogs.level,
32+
trigger: workflowExecutionLogs.trigger,
33+
startedAt: workflowExecutionLogs.startedAt,
34+
endedAt: workflowExecutionLogs.endedAt,
35+
totalDurationMs: workflowExecutionLogs.totalDurationMs,
36+
executionData: workflowExecutionLogs.executionData,
37+
cost: workflowExecutionLogs.cost,
38+
files: workflowExecutionLogs.files,
39+
createdAt: workflowExecutionLogs.createdAt,
40+
workflowName: workflow.name,
41+
workflowDescription: workflow.description,
42+
workflowColor: workflow.color,
43+
workflowFolderId: workflow.folderId,
44+
workflowUserId: workflow.userId,
45+
workflowWorkspaceId: workflow.workspaceId,
46+
workflowCreatedAt: workflow.createdAt,
47+
workflowUpdatedAt: workflow.updatedAt,
48+
})
49+
.from(workflowExecutionLogs)
50+
.innerJoin(workflow, eq(workflowExecutionLogs.workflowId, workflow.id))
51+
.innerJoin(
52+
permissions,
53+
and(
54+
eq(permissions.entityType, 'workspace'),
55+
eq(permissions.entityId, workflow.workspaceId),
56+
eq(permissions.userId, userId)
57+
)
58+
)
59+
.where(eq(workflowExecutionLogs.id, id))
60+
.limit(1)
61+
62+
const log = rows[0]
63+
if (!log) {
64+
return NextResponse.json({ error: 'Not found' }, { status: 404 })
65+
}
66+
67+
const workflowSummary = {
68+
id: log.workflowId,
69+
name: log.workflowName,
70+
description: log.workflowDescription,
71+
color: log.workflowColor,
72+
folderId: log.workflowFolderId,
73+
userId: log.workflowUserId,
74+
workspaceId: log.workflowWorkspaceId,
75+
createdAt: log.workflowCreatedAt,
76+
updatedAt: log.workflowUpdatedAt,
77+
}
78+
79+
const response = {
80+
id: log.id,
81+
workflowId: log.workflowId,
82+
executionId: log.executionId,
83+
level: log.level,
84+
duration: log.totalDurationMs ? `${log.totalDurationMs}ms` : null,
85+
trigger: log.trigger,
86+
createdAt: log.startedAt.toISOString(),
87+
files: log.files || undefined,
88+
workflow: workflowSummary,
89+
executionData: {
90+
totalDuration: log.totalDurationMs,
91+
...(log.executionData as any),
92+
enhanced: true,
93+
},
94+
cost: log.cost as any,
95+
}
96+
97+
return NextResponse.json({ data: response })
98+
} catch (error: any) {
99+
logger.error(`[${requestId}] log details fetch error`, error)
100+
return NextResponse.json({ error: error.message }, { status: 500 })
101+
}
102+
}

apps/sim/app/api/logs/cleanup/route.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,13 @@ export async function GET(request: NextRequest) {
9999
executionId: workflowExecutionLogs.executionId,
100100
stateSnapshotId: workflowExecutionLogs.stateSnapshotId,
101101
level: workflowExecutionLogs.level,
102-
message: workflowExecutionLogs.message,
103102
trigger: workflowExecutionLogs.trigger,
104103
startedAt: workflowExecutionLogs.startedAt,
105104
endedAt: workflowExecutionLogs.endedAt,
106105
totalDurationMs: workflowExecutionLogs.totalDurationMs,
107-
blockCount: workflowExecutionLogs.blockCount,
108-
successCount: workflowExecutionLogs.successCount,
109-
errorCount: workflowExecutionLogs.errorCount,
110-
skippedCount: workflowExecutionLogs.skippedCount,
111-
totalCost: workflowExecutionLogs.totalCost,
112-
totalInputCost: workflowExecutionLogs.totalInputCost,
113-
totalOutputCost: workflowExecutionLogs.totalOutputCost,
114-
totalTokens: workflowExecutionLogs.totalTokens,
106+
executionData: workflowExecutionLogs.executionData,
107+
cost: workflowExecutionLogs.cost,
115108
files: workflowExecutionLogs.files,
116-
metadata: workflowExecutionLogs.metadata,
117109
createdAt: workflowExecutionLogs.createdAt,
118110
})
119111
.from(workflowExecutionLogs)

apps/sim/app/api/logs/route.ts

Lines changed: 29 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { and, desc, eq, gte, inArray, lte, or, type SQL, sql } from 'drizzle-orm'
1+
import { and, desc, eq, gte, inArray, lte, type SQL, sql } from 'drizzle-orm'
22
import { type NextRequest, NextResponse } from 'next/server'
33
import { z } from 'zod'
44
import { getSession } from '@/lib/auth'
@@ -44,8 +44,7 @@ function extractBlockExecutionsFromTraceSpans(traceSpans: any[]): any[] {
4444
export const revalidate = 0
4545

4646
const QueryParamsSchema = z.object({
47-
includeWorkflow: z.coerce.boolean().optional().default(false),
48-
includeBlocks: z.coerce.boolean().optional().default(false),
47+
details: z.enum(['basic', 'full']).optional().default('basic'),
4948
limit: z.coerce.number().optional().default(100),
5049
offset: z.coerce.number().optional().default(0),
5150
level: z.string().optional(),
@@ -81,20 +80,12 @@ export async function GET(request: NextRequest) {
8180
executionId: workflowExecutionLogs.executionId,
8281
stateSnapshotId: workflowExecutionLogs.stateSnapshotId,
8382
level: workflowExecutionLogs.level,
84-
message: workflowExecutionLogs.message,
8583
trigger: workflowExecutionLogs.trigger,
8684
startedAt: workflowExecutionLogs.startedAt,
8785
endedAt: workflowExecutionLogs.endedAt,
8886
totalDurationMs: workflowExecutionLogs.totalDurationMs,
89-
blockCount: workflowExecutionLogs.blockCount,
90-
successCount: workflowExecutionLogs.successCount,
91-
errorCount: workflowExecutionLogs.errorCount,
92-
skippedCount: workflowExecutionLogs.skippedCount,
93-
totalCost: workflowExecutionLogs.totalCost,
94-
totalInputCost: workflowExecutionLogs.totalInputCost,
95-
totalOutputCost: workflowExecutionLogs.totalOutputCost,
96-
totalTokens: workflowExecutionLogs.totalTokens,
97-
metadata: workflowExecutionLogs.metadata,
87+
executionData: workflowExecutionLogs.executionData,
88+
cost: workflowExecutionLogs.cost,
9889
files: workflowExecutionLogs.files,
9990
createdAt: workflowExecutionLogs.createdAt,
10091
workflowName: workflow.name,
@@ -163,13 +154,8 @@ export async function GET(request: NextRequest) {
163154
// Filter by search query
164155
if (params.search) {
165156
const searchTerm = `%${params.search}%`
166-
conditions = and(
167-
conditions,
168-
or(
169-
sql`${workflowExecutionLogs.message} ILIKE ${searchTerm}`,
170-
sql`${workflowExecutionLogs.executionId} ILIKE ${searchTerm}`
171-
)
172-
)
157+
// With message removed, restrict search to executionId only
158+
conditions = and(conditions, sql`${workflowExecutionLogs.executionId} ILIKE ${searchTerm}`)
173159
}
174160

175161
// Execute the query using the optimized join
@@ -290,31 +276,20 @@ export async function GET(request: NextRequest) {
290276
const enhancedLogs = logs.map((log) => {
291277
const blockExecutions = blockExecutionsByExecution[log.executionId] || []
292278

293-
// Use stored trace spans from metadata if available, otherwise create from block executions
294-
const storedTraceSpans = (log.metadata as any)?.traceSpans
279+
// Use stored trace spans if available, otherwise create from block executions
280+
const storedTraceSpans = (log.executionData as any)?.traceSpans
295281
const traceSpans =
296282
storedTraceSpans && Array.isArray(storedTraceSpans) && storedTraceSpans.length > 0
297283
? storedTraceSpans
298284
: createTraceSpans(blockExecutions)
299285

300-
// Use extracted cost summary if available, otherwise use stored values
286+
// Prefer stored cost JSON; otherwise synthesize from blocks
301287
const costSummary =
302-
blockExecutions.length > 0
303-
? extractCostSummary(blockExecutions)
304-
: {
305-
input: Number(log.totalInputCost) || 0,
306-
output: Number(log.totalOutputCost) || 0,
307-
total: Number(log.totalCost) || 0,
308-
tokens: {
309-
total: log.totalTokens || 0,
310-
prompt: (log.metadata as any)?.tokenBreakdown?.prompt || 0,
311-
completion: (log.metadata as any)?.tokenBreakdown?.completion || 0,
312-
},
313-
models: (log.metadata as any)?.models || {},
314-
}
288+
log.cost && Object.keys(log.cost as any).length > 0
289+
? (log.cost as any)
290+
: extractCostSummary(blockExecutions)
315291

316-
// Build workflow object from joined data
317-
const workflow = {
292+
const workflowSummary = {
318293
id: log.workflowId,
319294
name: log.workflowName,
320295
description: log.workflowDescription,
@@ -329,67 +304,28 @@ export async function GET(request: NextRequest) {
329304
return {
330305
id: log.id,
331306
workflowId: log.workflowId,
332-
executionId: log.executionId,
307+
executionId: params.details === 'full' ? log.executionId : undefined,
333308
level: log.level,
334-
message: log.message,
335309
duration: log.totalDurationMs ? `${log.totalDurationMs}ms` : null,
336310
trigger: log.trigger,
337311
createdAt: log.startedAt.toISOString(),
338-
files: log.files || undefined,
339-
workflow: params.includeWorkflow ? workflow : undefined,
340-
metadata: {
341-
totalDuration: log.totalDurationMs,
342-
cost: costSummary,
343-
blockStats: {
344-
total: log.blockCount,
345-
success: log.successCount,
346-
error: log.errorCount,
347-
skipped: log.skippedCount,
348-
},
349-
traceSpans,
350-
blockExecutions,
351-
enhanced: true,
352-
},
312+
files: params.details === 'full' ? log.files || undefined : undefined,
313+
workflow: workflowSummary,
314+
executionData:
315+
params.details === 'full'
316+
? {
317+
totalDuration: log.totalDurationMs,
318+
traceSpans,
319+
blockExecutions,
320+
enhanced: true,
321+
}
322+
: undefined,
323+
cost:
324+
params.details === 'full'
325+
? (costSummary as any)
326+
: { total: (costSummary as any)?.total || 0 },
353327
}
354328
})
355-
356-
// Include block execution data if requested
357-
if (params.includeBlocks) {
358-
// Block executions are now extracted from stored trace spans in metadata
359-
const blockLogsByExecution: Record<string, any[]> = {}
360-
361-
logs.forEach((log) => {
362-
const storedTraceSpans = (log.metadata as any)?.traceSpans
363-
if (storedTraceSpans && Array.isArray(storedTraceSpans)) {
364-
blockLogsByExecution[log.executionId] =
365-
extractBlockExecutionsFromTraceSpans(storedTraceSpans)
366-
} else {
367-
blockLogsByExecution[log.executionId] = []
368-
}
369-
})
370-
371-
// Add block logs to metadata
372-
const logsWithBlocks = enhancedLogs.map((log) => ({
373-
...log,
374-
metadata: {
375-
...log.metadata,
376-
blockExecutions: blockLogsByExecution[log.executionId] || [],
377-
},
378-
}))
379-
380-
return NextResponse.json(
381-
{
382-
data: logsWithBlocks,
383-
total: Number(count),
384-
page: Math.floor(params.offset / params.limit) + 1,
385-
pageSize: params.limit,
386-
totalPages: Math.ceil(Number(count) / params.limit),
387-
},
388-
{ status: 200 }
389-
)
390-
}
391-
392-
// Return basic logs
393329
return NextResponse.json(
394330
{
395331
data: enhancedLogs,

0 commit comments

Comments
 (0)