Skip to content

Commit 03e1699

Browse files
authored
feat(api): added trace spans for asynchronous executions, modified api route naming convention (#154)
* improvement: added trace spans for asynchronous workflow executions, previously only appeared when workflow was executed manually * improvement: updated api/workflow route naming convention * improvement: updated api/schedules route naming convention * improvement(logs/ui): add differentiator in UI for different trigger types
1 parent c5d537f commit 03e1699

File tree

23 files changed

+340
-291
lines changed

23 files changed

+340
-291
lines changed

sim/app/api/marketplace/[id]/info/route.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { NextRequest } from 'next/server'
22
import { eq } from 'drizzle-orm'
33
import { createLogger } from '@/lib/logs/console-logger'
4+
import { validateWorkflowAccess } from '@/app/api/workflows/middleware'
5+
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
46
import { db } from '@/db'
57
import * as schema from '@/db/schema'
6-
import { validateWorkflowAccess } from '@/app/api/workflow/middleware'
7-
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflow/utils'
88

99
const logger = createLogger('MarketplaceInfoAPI')
1010

@@ -27,7 +27,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
2727
.from(schema.marketplace)
2828
.where(eq(schema.marketplace.workflowId, id))
2929
.limit(1)
30-
.then(rows => rows[0])
30+
.then((rows) => rows[0])
3131

3232
if (!marketplaceEntry) {
3333
logger.warn(`[${requestId}] No marketplace entry found for workflow: ${id}`)
@@ -48,7 +48,10 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
4848
updatedAt: marketplaceEntry.updatedAt,
4949
})
5050
} catch (error) {
51-
logger.error(`[${requestId}] Error getting marketplace info for workflow: ${(await params).id}`, error)
51+
logger.error(
52+
`[${requestId}] Error getting marketplace info for workflow: ${(await params).id}`,
53+
error
54+
)
5255
return createErrorResponse('Failed to get marketplace information', 500)
5356
}
54-
}
57+
}

sim/app/api/marketplace/[id]/star/route.ts

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { NextRequest } from 'next/server'
22
import { and, eq } from 'drizzle-orm'
33
import { getSession } from '@/lib/auth'
44
import { createLogger } from '@/lib/logs/console-logger'
5+
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
56
import { db } from '@/db'
67
import * as schema from '@/db/schema'
7-
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflow/utils'
88

99
const logger = createLogger('MarketplaceStarAPI')
1010

@@ -15,7 +15,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
1515
const { id } = await params
1616
const session = await getSession()
1717
const userId = session?.user?.id
18-
18+
1919
if (!userId) {
2020
return createErrorResponse('Unauthorized', 401)
2121
}
@@ -26,7 +26,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
2626
.from(schema.marketplace)
2727
.where(eq(schema.marketplace.id, id))
2828
.limit(1)
29-
.then(rows => rows[0])
29+
.then((rows) => rows[0])
3030

3131
if (!marketplaceEntry) {
3232
logger.warn(`[${requestId}] No marketplace entry found with ID: ${id}`)
@@ -37,28 +37,30 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
3737
const existingStar = await db
3838
.select()
3939
.from(schema.marketplaceStar)
40-
.where(and(
41-
eq(schema.marketplaceStar.marketplaceId, id),
42-
eq(schema.marketplaceStar.userId, userId)
43-
))
40+
.where(
41+
and(eq(schema.marketplaceStar.marketplaceId, id), eq(schema.marketplaceStar.userId, userId))
42+
)
4443
.limit(1)
45-
.then(rows => rows[0])
44+
.then((rows) => rows[0])
4645

4746
let action
4847
if (existingStar) {
4948
// User has already starred, so unstar it
50-
await db.delete(schema.marketplaceStar).where(
51-
and(
52-
eq(schema.marketplaceStar.marketplaceId, id),
53-
eq(schema.marketplaceStar.userId, userId)
49+
await db
50+
.delete(schema.marketplaceStar)
51+
.where(
52+
and(
53+
eq(schema.marketplaceStar.marketplaceId, id),
54+
eq(schema.marketplaceStar.userId, userId)
55+
)
5456
)
55-
)
56-
57+
5758
// Decrement the star count
58-
await db.update(schema.marketplace)
59+
await db
60+
.update(schema.marketplace)
5961
.set({ stars: marketplaceEntry.stars - 1 })
6062
.where(eq(schema.marketplace.id, id))
61-
63+
6264
action = 'unstarred'
6365
} else {
6466
// User hasn't starred yet, add a star
@@ -68,12 +70,13 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
6870
userId: userId,
6971
createdAt: new Date(),
7072
})
71-
73+
7274
// Increment the star count
73-
await db.update(schema.marketplace)
75+
await db
76+
.update(schema.marketplace)
7477
.set({ stars: marketplaceEntry.stars + 1 })
7578
.where(eq(schema.marketplace.id, id))
76-
79+
7780
action = 'starred'
7881
}
7982

@@ -107,12 +110,11 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
107110
const existingStar = await db
108111
.select()
109112
.from(schema.marketplaceStar)
110-
.where(and(
111-
eq(schema.marketplaceStar.marketplaceId, id),
112-
eq(schema.marketplaceStar.userId, userId)
113-
))
113+
.where(
114+
and(eq(schema.marketplaceStar.marketplaceId, id), eq(schema.marketplaceStar.userId, userId))
115+
)
114116
.limit(1)
115-
.then(rows => rows[0])
117+
.then((rows) => rows[0])
116118

117119
return createSuccessResponse({
118120
isStarred: !!existingStar,
@@ -121,4 +123,4 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
121123
logger.error(`[${requestId}] Error checking star status: ${(await params).id}`, error)
122124
return createErrorResponse('Failed to check star status', 500)
123125
}
124-
}
126+
}

sim/app/api/marketplace/[id]/unpublish/route.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { NextRequest } from 'next/server'
22
import { eq } from 'drizzle-orm'
33
import { createLogger } from '@/lib/logs/console-logger'
4+
import { validateWorkflowAccess } from '@/app/api/workflows/middleware'
5+
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
46
import { db } from '@/db'
57
import * as schema from '@/db/schema'
6-
import { validateWorkflowAccess } from '@/app/api/workflow/middleware'
7-
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflow/utils'
88

99
const logger = createLogger('MarketplaceUnpublishAPI')
1010

@@ -28,7 +28,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
2828
.from(schema.marketplace)
2929
.where(eq(schema.marketplace.workflowId, id))
3030
.limit(1)
31-
.then(rows => rows[0])
31+
.then((rows) => rows[0])
3232

3333
if (!marketplaceEntry) {
3434
logger.warn(`[${requestId}] No marketplace entry found for workflow: ${id}`)
@@ -51,4 +51,4 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
5151
logger.error(`[${requestId}] Error unpublishing workflow: ${(await params).id}`, error)
5252
return createErrorResponse('Failed to unpublish workflow', 500)
5353
}
54-
}
54+
}
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { v4 as uuidv4 } from 'uuid'
55
import { z } from 'zod'
66
import { createLogger } from '@/lib/logs/console-logger'
77
import { persistExecutionError, persistExecutionLogs } from '@/lib/logs/execution-logger'
8+
import { buildTraceSpans } from '@/lib/logs/trace-spans'
89
import { decryptSecret } from '@/lib/utils'
910
import { mergeSubblockState } from '@/stores/workflows/utils'
1011
import { BlockState, WorkflowState } from '@/stores/workflows/workflow/types'
@@ -325,8 +326,18 @@ export async function GET(req: NextRequest) {
325326
)
326327
const result = await executor.execute(schedule.workflowId)
327328

329+
// Build trace spans from execution logs
330+
const { traceSpans, totalDuration } = buildTraceSpans(result)
331+
332+
// Add trace spans to the execution result
333+
const enrichedResult = {
334+
...result,
335+
traceSpans,
336+
totalDuration,
337+
}
338+
328339
// Log each execution step and the final result
329-
await persistExecutionLogs(schedule.workflowId, executionId, result, 'schedule')
340+
await persistExecutionLogs(schedule.workflowId, executionId, enrichedResult, 'schedule')
330341

331342
// Only update next_run_at if execution was successful
332343
if (result.success) {

sim/app/api/webhooks/trigger/[path]/route.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { and, eq } from 'drizzle-orm'
33
import { v4 as uuidv4 } from 'uuid'
44
import { createLogger } from '@/lib/logs/console-logger'
55
import { persistExecutionError, persistExecutionLogs } from '@/lib/logs/execution-logger'
6+
import { buildTraceSpans } from '@/lib/logs/trace-spans'
67
import { closeRedisConnection, hasProcessedMessage, markMessageAsProcessed } from '@/lib/redis'
78
import { decryptSecret } from '@/lib/utils'
89
import { mergeSubblockStateAsync } from '@/stores/workflows/utils'
@@ -558,8 +559,18 @@ async function processWebhook(
558559
executionTime: result.metadata?.duration,
559560
})
560561

562+
// Build trace spans from execution logs
563+
const { traceSpans, totalDuration } = buildTraceSpans(result)
564+
565+
// Add trace spans to the execution result
566+
const enrichedResult = {
567+
...result,
568+
traceSpans,
569+
totalDuration,
570+
}
571+
561572
// Log each execution step and the final result
562-
await persistExecutionLogs(foundWorkflow.id, executionId, result, 'webhook')
573+
await persistExecutionLogs(foundWorkflow.id, executionId, enrichedResult, 'webhook')
563574

564575
// Return the execution result
565576
return NextResponse.json(result, { status: 200 })
File renamed without changes.

sim/app/api/workflow/[id]/execute/route.ts renamed to sim/app/api/workflows/[id]/execute/route.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { v4 as uuidv4 } from 'uuid'
44
import { z } from 'zod'
55
import { createLogger } from '@/lib/logs/console-logger'
66
import { persistExecutionError, persistExecutionLogs } from '@/lib/logs/execution-logger'
7+
import { buildTraceSpans } from '@/lib/logs/trace-spans'
78
import { decryptSecret } from '@/lib/utils'
89
import { mergeSubblockState } from '@/stores/workflows/utils'
910
import { WorkflowState } from '@/stores/workflows/workflow/types'
@@ -158,8 +159,18 @@ async function executeWorkflow(workflow: any, requestId: string, input?: any) {
158159
executionTime: result.metadata?.duration,
159160
})
160161

162+
// Build trace spans from execution logs
163+
const { traceSpans, totalDuration } = buildTraceSpans(result)
164+
165+
// Add trace spans to the execution result
166+
const enrichedResult = {
167+
...result,
168+
traceSpans,
169+
totalDuration,
170+
}
171+
161172
// Log each execution step and the final result
162-
await persistExecutionLogs(workflowId, executionId, result, 'api')
173+
await persistExecutionLogs(workflowId, executionId, enrichedResult, 'api')
163174

164175
return result
165176
} catch (error: any) {

0 commit comments

Comments
 (0)