Skip to content

Commit 3b82e7d

Browse files
committed
improvement(providers): added enhanced error logging
1 parent ca6884c commit 3b82e7d

File tree

2 files changed

+141
-6
lines changed

2 files changed

+141
-6
lines changed

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

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@ export const dynamic = 'force-dynamic'
1212
* Server-side proxy for provider requests
1313
*/
1414
export async function POST(request: NextRequest) {
15+
const requestId = crypto.randomUUID().slice(0, 8)
16+
const startTime = Date.now()
17+
1518
try {
19+
logger.info(`[${requestId}] Provider API request started`, {
20+
timestamp: new Date().toISOString(),
21+
userAgent: request.headers.get('User-Agent'),
22+
contentType: request.headers.get('Content-Type'),
23+
})
24+
1625
const body = await request.json()
1726
const {
1827
provider,
@@ -29,17 +38,44 @@ export async function POST(request: NextRequest) {
2938
messages,
3039
} = body
3140

41+
logger.info(`[${requestId}] Provider request details`, {
42+
provider,
43+
model,
44+
hasSystemPrompt: !!systemPrompt,
45+
hasContext: !!context,
46+
hasTools: !!tools?.length,
47+
toolCount: tools?.length || 0,
48+
hasApiKey: !!apiKey,
49+
hasResponseFormat: !!responseFormat,
50+
workflowId,
51+
stream: !!stream,
52+
hasMessages: !!messages?.length,
53+
messageCount: messages?.length || 0,
54+
})
55+
3256
let finalApiKey: string
3357
try {
3458
finalApiKey = getApiKey(provider, model, apiKey)
3559
} catch (error) {
36-
logger.error('Failed to get API key:', error)
60+
logger.error(`[${requestId}] Failed to get API key:`, {
61+
provider,
62+
model,
63+
error: error instanceof Error ? error.message : String(error),
64+
hasProvidedApiKey: !!apiKey,
65+
})
3766
return NextResponse.json(
3867
{ error: error instanceof Error ? error.message : 'API key error' },
3968
{ status: 400 }
4069
)
4170
}
4271

72+
logger.info(`[${requestId}] Executing provider request`, {
73+
provider,
74+
model,
75+
workflowId,
76+
hasApiKey: !!finalApiKey,
77+
})
78+
4379
// Execute provider request directly with the managed key
4480
const response = await executeProviderRequest(provider, {
4581
model,
@@ -55,6 +91,20 @@ export async function POST(request: NextRequest) {
5591
messages,
5692
})
5793

94+
const executionTime = Date.now() - startTime
95+
logger.info(`[${requestId}] Provider request completed successfully`, {
96+
provider,
97+
model,
98+
workflowId,
99+
executionTime,
100+
responseType:
101+
response instanceof ReadableStream
102+
? 'stream'
103+
: response && typeof response === 'object' && 'stream' in response
104+
? 'streaming-execution'
105+
: 'json',
106+
})
107+
58108
// Check if the response is a StreamingExecution
59109
if (
60110
response &&
@@ -63,7 +113,7 @@ export async function POST(request: NextRequest) {
63113
'execution' in response
64114
) {
65115
const streamingExec = response as StreamingExecution
66-
logger.info('Received StreamingExecution from provider')
116+
logger.info(`[${requestId}] Received StreamingExecution from provider`)
67117

68118
// Extract the stream and execution data
69119
const stream = streamingExec.stream
@@ -110,7 +160,7 @@ export async function POST(request: NextRequest) {
110160
}
111161
executionDataHeader = JSON.stringify(safeExecutionData)
112162
} catch (error) {
113-
logger.error('Failed to serialize execution data:', error)
163+
logger.error(`[${requestId}] Failed to serialize execution data:`, error)
114164
executionDataHeader = JSON.stringify({
115165
success: executionData.success,
116166
error: 'Failed to serialize full execution data',
@@ -130,7 +180,7 @@ export async function POST(request: NextRequest) {
130180

131181
// Check if the response is a ReadableStream for streaming
132182
if (response instanceof ReadableStream) {
133-
logger.info('Streaming response from provider')
183+
logger.info(`[${requestId}] Streaming response from provider`)
134184
return new Response(response, {
135185
headers: {
136186
'Content-Type': 'text/event-stream',
@@ -143,7 +193,15 @@ export async function POST(request: NextRequest) {
143193
// Return regular JSON response for non-streaming
144194
return NextResponse.json(response)
145195
} catch (error) {
146-
logger.error('Provider request failed:', error)
196+
const executionTime = Date.now() - startTime
197+
logger.error(`[${requestId}] Provider request failed:`, {
198+
error: error instanceof Error ? error.message : String(error),
199+
errorName: error instanceof Error ? error.name : 'Unknown',
200+
errorStack: error instanceof Error ? error.stack : undefined,
201+
executionTime,
202+
timestamp: new Date().toISOString(),
203+
})
204+
147205
return NextResponse.json(
148206
{ error: error instanceof Error ? error.message : String(error) },
149207
{ status: 500 }

apps/sim/executor/handlers/agent/agent-handler.ts

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,25 +344,58 @@ export class AgentBlockHandler implements BlockHandler {
344344
const url = new URL('/api/providers', baseUrl)
345345

346346
try {
347+
logger.info(`Making provider request to: ${url.toString()}`, {
348+
workflowId: context.workflowId,
349+
blockId: block.id,
350+
provider: providerId,
351+
model,
352+
timestamp: new Date().toISOString(),
353+
})
354+
347355
const response = await fetch(url.toString(), {
348356
method: 'POST',
349357
headers: {
350358
'Content-Type': 'application/json',
351359
},
352360
body: JSON.stringify(providerRequest),
361+
// Add timeout and signal for better error handling
362+
signal: AbortSignal.timeout(120000), // 2 minute timeout
353363
})
354364

355365
if (!response.ok) {
356366
// Try to extract a helpful error message
357367
let errorMessage = `Provider API request failed with status ${response.status}`
368+
let errorDetails = null
369+
358370
try {
359371
const errorData = await response.json()
360372
if (errorData.error) {
361373
errorMessage = errorData.error
374+
errorDetails = errorData
362375
}
363376
} catch (_e) {
364-
// If JSON parsing fails, use the original error message
377+
// If JSON parsing fails, try to get text response
378+
try {
379+
const textError = await response.text()
380+
if (textError) {
381+
errorDetails = { textResponse: textError }
382+
}
383+
} catch (_textError) {
384+
// If text parsing also fails, use the original error message
385+
}
365386
}
387+
388+
logger.error('Provider API request failed', {
389+
workflowId: context.workflowId,
390+
blockId: block.id,
391+
status: response.status,
392+
statusText: response.statusText,
393+
url: url.toString(),
394+
errorMessage,
395+
errorDetails,
396+
headers: Object.fromEntries(response.headers.entries()),
397+
})
398+
366399
throw new Error(errorMessage)
367400
}
368401

@@ -579,6 +612,50 @@ export class AgentBlockHandler implements BlockHandler {
579612
}
580613
} catch (error) {
581614
logger.error('Error executing provider request:', { error })
615+
616+
// Enhanced error logging for different error types
617+
if (error instanceof Error) {
618+
logger.error('Provider request error details', {
619+
workflowId: context.workflowId,
620+
blockId: block.id,
621+
errorName: error.name,
622+
errorMessage: error.message,
623+
errorStack: error.stack,
624+
url: url.toString(),
625+
timestamp: new Date().toISOString(),
626+
})
627+
628+
// Check for specific error types
629+
if (error.name === 'AbortError') {
630+
logger.error('Request timed out after 2 minutes', {
631+
workflowId: context.workflowId,
632+
blockId: block.id,
633+
url: url.toString(),
634+
})
635+
throw new Error('Provider request timed out - the API took too long to respond')
636+
}
637+
if (error.name === 'TypeError' && error.message.includes('fetch')) {
638+
logger.error('Network fetch error - possible connectivity issue', {
639+
workflowId: context.workflowId,
640+
blockId: block.id,
641+
url: url.toString(),
642+
errorMessage: error.message,
643+
})
644+
throw new Error(
645+
'Network error - unable to connect to provider API. Please check your internet connection.'
646+
)
647+
}
648+
if (error.message.includes('ENOTFOUND') || error.message.includes('ECONNREFUSED')) {
649+
logger.error('DNS/Connection error', {
650+
workflowId: context.workflowId,
651+
blockId: block.id,
652+
url: url.toString(),
653+
errorMessage: error.message,
654+
})
655+
throw new Error('Unable to connect to server - DNS or connection issue')
656+
}
657+
}
658+
582659
throw error
583660
}
584661
}

0 commit comments

Comments
 (0)