From 39fcc04d785050a05b8c201ed3b25174f64419e7 Mon Sep 17 00:00:00 2001 From: Vaayne Date: Wed, 24 Sep 2025 21:57:02 +0800 Subject: [PATCH] refactor(logging): improve logging messages for clarity and consistency - Updated logging statements across various modules to provide more structured and detailed information. - Changed log levels from info to debug for less critical messages to reduce log clutter. - Enhanced error logging to include relevant context such as agentId, sessionId, and model details. - Standardized log messages to follow a consistent format, improving readability and maintainability. --- src/main/apiServer/app.ts | 7 +- src/main/apiServer/config.ts | 2 +- src/main/apiServer/middleware/error.ts | 2 +- src/main/apiServer/middleware/openapi.ts | 9 +- .../routes/agents/handlers/agents.ts | 65 +++++++------- .../routes/agents/handlers/messages.ts | 41 +++++---- .../routes/agents/handlers/sessions.ts | 87 +++++++++++-------- .../routes/agents/middleware/common.ts | 5 +- src/main/apiServer/routes/chat.ts | 12 +-- src/main/apiServer/routes/mcp.ts | 14 +-- src/main/apiServer/routes/messages.ts | 13 ++- src/main/apiServer/routes/models.ts | 20 ++--- src/main/apiServer/server.ts | 13 ++- .../apiServer/services/chat-completion.ts | 30 +++++-- src/main/apiServer/services/mcp.ts | 29 ++++--- src/main/apiServer/services/models.ts | 8 +- src/main/apiServer/utils/index.ts | 62 +++++++------ src/main/apiServer/utils/mcp.ts | 10 +-- 18 files changed, 245 insertions(+), 184 deletions(-) diff --git a/src/main/apiServer/app.ts b/src/main/apiServer/app.ts index 0c6615f1e8..3edbbe826e 100644 --- a/src/main/apiServer/app.ts +++ b/src/main/apiServer/app.ts @@ -26,7 +26,12 @@ app.use((req, res, next) => { const start = Date.now() res.on('finish', () => { const duration = Date.now() - start - logger.info(`${req.method} ${req.path} - ${res.statusCode} - ${duration}ms`) + logger.info('API request completed', { + method: req.method, + path: req.path, + statusCode: res.statusCode, + durationMs: duration + }) }) next() }) diff --git a/src/main/apiServer/config.ts b/src/main/apiServer/config.ts index 8bc4922968..c962726d24 100644 --- a/src/main/apiServer/config.ts +++ b/src/main/apiServer/config.ts @@ -36,7 +36,7 @@ class ConfigManager { } return this._config } catch (error: any) { - logger.warn('Failed to load config from Redux, using defaults:', error) + logger.warn('Failed to load config from Redux, using defaults', { error }) this._config = { enabled: false, port: defaultPort, diff --git a/src/main/apiServer/middleware/error.ts b/src/main/apiServer/middleware/error.ts index 6aa1819ddd..401a8cad84 100644 --- a/src/main/apiServer/middleware/error.ts +++ b/src/main/apiServer/middleware/error.ts @@ -6,7 +6,7 @@ const logger = loggerService.withContext('ApiServerErrorHandler') // oxlint-disable-next-line @typescript-eslint/no-unused-vars export const errorHandler = (err: Error, _req: Request, res: Response, _next: NextFunction) => { - logger.error('API Server Error:', err) + logger.error('API server error', { error: err }) // Don't expose internal errors in production const isDev = process.env.NODE_ENV === 'development' diff --git a/src/main/apiServer/middleware/openapi.ts b/src/main/apiServer/middleware/openapi.ts index 691bd8ec96..da3cfe0c4c 100644 --- a/src/main/apiServer/middleware/openapi.ts +++ b/src/main/apiServer/middleware/openapi.ts @@ -197,10 +197,11 @@ export function setupOpenAPIDocumentation(app: Express) { }) ) - logger.info('OpenAPI documentation setup complete') - logger.info('Documentation available at /api-docs') - logger.info('OpenAPI spec available at /api-docs.json') + logger.info('OpenAPI documentation ready', { + docsPath: '/api-docs', + specPath: '/api-docs.json' + }) } catch (error) { - logger.error('Failed to setup OpenAPI documentation:', error as Error) + logger.error('Failed to setup OpenAPI documentation', { error }) } } diff --git a/src/main/apiServer/routes/agents/handlers/agents.ts b/src/main/apiServer/routes/agents/handlers/agents.ts index dc9e4ecf52..1e772932e2 100644 --- a/src/main/apiServer/routes/agents/handlers/agents.ts +++ b/src/main/apiServer/routes/agents/handlers/agents.ts @@ -51,18 +51,18 @@ const modelValidationErrorBody = (error: AgentModelValidationError) => ({ */ export const createAgent = async (req: Request, res: Response): Promise => { try { - logger.info('Creating new agent') - logger.debug('Agent data:', req.body) + logger.debug('Creating agent') + logger.debug('Agent payload', { body: req.body }) const agent = await agentService.createAgent(req.body) try { - logger.info(`Agent created successfully: ${agent.id}`) - logger.info(`Creating default session for new agent: ${agent.id}`) + logger.info('Agent created', { agentId: agent.id }) + logger.debug('Creating default session for agent', { agentId: agent.id }) await sessionService.createSession(agent.id, {}) - logger.info(`Default session created for agent: ${agent.id}`) + logger.info('Default session created for agent', { agentId: agent.id }) return res.status(201).json(agent) } catch (sessionError: any) { logger.error('Failed to create default session for new agent, rolling back agent creation', { @@ -89,7 +89,7 @@ export const createAgent = async (req: Request, res: Response): Promise const limit = req.query.limit ? parseInt(req.query.limit as string) : 20 const offset = req.query.offset ? parseInt(req.query.offset as string) : 0 - logger.info(`Listing agents with limit=${limit}, offset=${offset}`) + logger.debug('Listing agents', { limit, offset }) const result = await agentService.listAgents({ limit, offset }) - logger.info(`Retrieved ${result.agents.length} agents (total: ${result.total})`) + logger.info('Agents listed', { + returned: result.agents.length, + total: result.total, + limit, + offset + }) return res.json({ data: result.agents, total: result.total, @@ -183,7 +188,7 @@ export const listAgents = async (req: Request, res: Response): Promise offset } satisfies ListAgentsResponse) } catch (error: any) { - logger.error('Error listing agents:', error) + logger.error('Error listing agents', { error }) return res.status(500).json({ error: { message: 'Failed to list agents', @@ -231,12 +236,12 @@ export const listAgents = async (req: Request, res: Response): Promise export const getAgent = async (req: Request, res: Response): Promise => { try { const { agentId } = req.params - logger.info(`Getting agent: ${agentId}`) + logger.debug('Getting agent', { agentId }) const agent = await agentService.getAgent(agentId) if (!agent) { - logger.warn(`Agent not found: ${agentId}`) + logger.warn('Agent not found', { agentId }) return res.status(404).json({ error: { message: 'Agent not found', @@ -246,10 +251,10 @@ export const getAgent = async (req: Request, res: Response): Promise = }) } - logger.info(`Agent retrieved successfully: ${agentId}`) + logger.info('Agent retrieved', { agentId }) return res.json(agent) } catch (error: any) { - logger.error('Error getting agent:', error) + logger.error('Error getting agent', { error, agentId: req.params.agentId }) return res.status(500).json({ error: { message: 'Failed to get agent', @@ -309,8 +314,8 @@ export const getAgent = async (req: Request, res: Response): Promise = export const updateAgent = async (req: Request, res: Response): Promise => { const { agentId } = req.params try { - logger.info(`Updating agent: ${agentId}`) - logger.debug('Update data:', req.body) + logger.debug('Updating agent', { agentId }) + logger.debug('Replace payload', { body: req.body }) const { validatedBody } = req as ValidationRequest const replacePayload = (validatedBody ?? {}) as ReplaceAgentRequest @@ -318,7 +323,7 @@ export const updateAgent = async (req: Request, res: Response): Promise => { const { agentId } = req.params try { - logger.info(`Partially updating agent: ${agentId}`) - logger.debug('Partial update data:', req.body) + logger.debug('Partially updating agent', { agentId }) + logger.debug('Patch payload', { body: req.body }) const { validatedBody } = req as ValidationRequest const updatePayload = (validatedBody ?? {}) as UpdateAgentRequest @@ -464,7 +469,7 @@ export const patchAgent = async (req: Request, res: Response): Promise const agent = await agentService.updateAgent(agentId, updatePayload) if (!agent) { - logger.warn(`Agent not found for partial update: ${agentId}`) + logger.warn('Agent not found for partial update', { agentId }) return res.status(404).json({ error: { message: 'Agent not found', @@ -474,11 +479,11 @@ export const patchAgent = async (req: Request, res: Response): Promise }) } - logger.info(`Agent partially updated successfully: ${agentId}`) + logger.info('Agent patched', { agentId }) return res.json(agent) } catch (error: any) { if (error instanceof AgentModelValidationError) { - logger.warn('Agent model validation error during partial update:', { + logger.warn('Agent model validation error during partial update', { agentId, agentType: error.context.agentType, field: error.context.field, @@ -488,7 +493,7 @@ export const patchAgent = async (req: Request, res: Response): Promise return res.status(400).json(modelValidationErrorBody(error)) } - logger.error('Error partially updating agent:', error) + logger.error('Error partially updating agent', { error, agentId }) return res.status(500).json({ error: { message: `Failed to partially update agent: ${error.message}`, @@ -532,12 +537,12 @@ export const patchAgent = async (req: Request, res: Response): Promise export const deleteAgent = async (req: Request, res: Response): Promise => { try { const { agentId } = req.params - logger.info(`Deleting agent: ${agentId}`) + logger.debug('Deleting agent', { agentId }) const deleted = await agentService.deleteAgent(agentId) if (!deleted) { - logger.warn(`Agent not found for deletion: ${agentId}`) + logger.warn('Agent not found for deletion', { agentId }) return res.status(404).json({ error: { message: 'Agent not found', @@ -547,10 +552,10 @@ export const deleteAgent = async (req: Request, res: Response): Promise const messageData = req.body - logger.info(`Creating streaming message for session: ${sessionId}`) - logger.debug('Streaming message data:', messageData) + logger.info('Creating streaming message', { agentId, sessionId }) + logger.debug('Streaming message payload', { messageData }) // Set SSE headers res.setHeader('Content-Type', 'text/event-stream') @@ -68,7 +68,7 @@ export const createMessage = async (req: Request, res: Response): Promise // res.write('data: {"type":"finish"}\n\n') res.write('data: [DONE]\n\n') } catch (writeError) { - logger.error('Error writing final sentinel to SSE stream:', { error: writeError as Error }) + logger.error('Error writing final sentinel to SSE stream', { error: writeError as Error }) } res.end() } @@ -94,7 +94,7 @@ export const createMessage = async (req: Request, res: Response): Promise */ const handleDisconnect = () => { if (responseEnded) return - logger.info(`Client disconnected from streaming message for session: ${sessionId}`) + logger.info('Streaming client disconnected', { agentId, sessionId }) responseEnded = true abortController.abort('Client disconnected') reader.cancel('Client disconnected').catch(() => {}) @@ -119,7 +119,7 @@ export const createMessage = async (req: Request, res: Response): Promise finalizeResponse() } catch (error) { if (responseEnded) return - logger.error('Error reading agent stream:', { error }) + logger.error('Error reading agent stream', { error }) try { res.write( `data: ${JSON.stringify({ @@ -132,7 +132,7 @@ export const createMessage = async (req: Request, res: Response): Promise })}\n\n` ) } catch (writeError) { - logger.error('Error writing stream error to SSE:', { error: writeError }) + logger.error('Error writing stream error to SSE', { error: writeError }) } responseEnded = true res.end() @@ -140,7 +140,7 @@ export const createMessage = async (req: Request, res: Response): Promise } pumpStream().catch((error) => { - logger.error('Pump stream failure:', { error }) + logger.error('Pump stream failure', { error }) }) completion @@ -150,7 +150,7 @@ export const createMessage = async (req: Request, res: Response): Promise }) .catch((error) => { if (responseEnded) return - logger.error(`Streaming message error for session: ${sessionId}:`, error) + logger.error('Streaming message error', { agentId, sessionId, error }) try { res.write( `data: ${JSON.stringify({ @@ -163,7 +163,7 @@ export const createMessage = async (req: Request, res: Response): Promise })}\n\n` ) } catch (writeError) { - logger.error('Error writing completion error to SSE stream:', { error: writeError }) + logger.error('Error writing completion error to SSE stream', { error: writeError }) } responseEnded = true res.end() @@ -173,7 +173,7 @@ export const createMessage = async (req: Request, res: Response): Promise const timeout = setTimeout( () => { if (!responseEnded) { - logger.error(`Streaming message timeout for session: ${sessionId}`) + logger.error('Streaming message timeout', { agentId, sessionId }) try { res.write( `data: ${JSON.stringify({ @@ -186,7 +186,7 @@ export const createMessage = async (req: Request, res: Response): Promise })}\n\n` ) } catch (writeError) { - logger.error('Error writing timeout to SSE stream:', { error: writeError }) + logger.error('Error writing timeout to SSE stream', { error: writeError }) } abortController.abort('stream timeout') reader.cancel('stream timeout').catch(() => {}) @@ -201,7 +201,11 @@ export const createMessage = async (req: Request, res: Response): Promise res.on('close', () => clearTimeout(timeout)) res.on('finish', () => clearTimeout(timeout)) } catch (error: any) { - logger.error('Error in streaming message handler:', error) + logger.error('Error in streaming message handler', { + error, + agentId: req.params.agentId, + sessionId: req.params.sessionId + }) // Send error as SSE if possible if (!res.headersSent) { @@ -222,7 +226,7 @@ export const createMessage = async (req: Request, res: Response): Promise res.write(`data: ${JSON.stringify(errorResponse)}\n\n`) } catch (writeError) { - logger.error('Error writing initial error to SSE stream:', { error: writeError }) + logger.error('Error writing initial error to SSE stream', { error: writeError }) } res.end() @@ -239,7 +243,7 @@ export const deleteMessage = async (req: Request, res: Response): Promise => { + const { agentId } = req.params try { - const { agentId } = req.params const limit = req.query.limit ? parseInt(req.query.limit as string) : 20 const offset = req.query.offset ? parseInt(req.query.offset as string) : 0 const status = req.query.status as any - logger.info(`Listing sessions for agent: ${agentId} with limit=${limit}, offset=${offset}, status=${status}`) + logger.debug('Listing agent sessions', { agentId, limit, offset, status }) const result = await sessionService.listSessions(agentId, { limit, offset }) - logger.info(`Retrieved ${result.sessions.length} sessions (total: ${result.total}) for agent: ${agentId}`) + logger.info('Agent sessions listed', { + agentId, + returned: result.sessions.length, + total: result.total, + limit, + offset + }) return res.json({ data: result.sessions, total: result.total, @@ -69,7 +75,7 @@ export const listSessions = async (req: Request, res: Response): Promise => { try { const { agentId, sessionId } = req.params - logger.info(`Getting session: ${sessionId} for agent: ${agentId}`) + logger.debug('Getting session', { agentId, sessionId }) const session = await sessionService.getSession(agentId, sessionId) if (!session) { - logger.warn(`Session not found: ${sessionId}`) + logger.warn('Session not found', { agentId, sessionId }) return res.status(404).json({ error: { message: 'Session not found', @@ -110,7 +116,7 @@ export const getSession = async (req: Request, res: Response): Promise // } // Fetch session messages - logger.info(`Fetching messages for session: ${sessionId}`) + logger.debug('Fetching session messages', { sessionId }) const { messages } = await sessionMessageService.listSessionMessages(sessionId) // Add messages to session @@ -119,10 +125,10 @@ export const getSession = async (req: Request, res: Response): Promise messages: messages } - logger.info(`Session retrieved successfully: ${sessionId} with ${messages.length} messages`) + logger.info('Session retrieved', { agentId, sessionId, messageCount: messages.length }) return res.json(sessionWithMessages) } catch (error: any) { - logger.error('Error getting session:', error) + logger.error('Error getting session', { error, agentId: req.params.agentId, sessionId: req.params.sessionId }) return res.status(500).json({ error: { message: 'Failed to get session', @@ -136,13 +142,13 @@ export const getSession = async (req: Request, res: Response): Promise export const updateSession = async (req: Request, res: Response): Promise => { const { agentId, sessionId } = req.params try { - logger.info(`Updating session: ${sessionId} for agent: ${agentId}`) - logger.debug('Update data:', req.body) + logger.debug('Updating session', { agentId, sessionId }) + logger.debug('Replace payload', { body: req.body }) // First check if session exists and belongs to agent const existingSession = await sessionService.getSession(agentId, sessionId) if (!existingSession || existingSession.agent_id !== agentId) { - logger.warn(`Session ${sessionId} not found for agent ${agentId}`) + logger.warn('Session not found for update', { agentId, sessionId }) return res.status(404).json({ error: { message: 'Session not found for this agent', @@ -158,7 +164,7 @@ export const updateSession = async (req: Request, res: Response): Promise => { const { agentId, sessionId } = req.params try { - logger.info(`Patching session: ${sessionId} for agent: ${agentId}`) - logger.debug('Patch data:', req.body) + logger.debug('Patching session', { agentId, sessionId }) + logger.debug('Patch payload', { body: req.body }) // First check if session exists and belongs to agent const existingSession = await sessionService.getSession(agentId, sessionId) if (!existingSession || existingSession.agent_id !== agentId) { - logger.warn(`Session ${sessionId} not found for agent ${agentId}`) + logger.warn('Session not found for patch', { agentId, sessionId }) return res.status(404).json({ error: { message: 'Session not found for this agent', @@ -217,7 +223,7 @@ export const patchSession = async (req: Request, res: Response): Promise => { try { const { agentId, sessionId } = req.params - logger.info(`Deleting session: ${sessionId} for agent: ${agentId}`) + logger.debug('Deleting session', { agentId, sessionId }) // First check if session exists and belongs to agent const existingSession = await sessionService.getSession(agentId, sessionId) if (!existingSession || existingSession.agent_id !== agentId) { - logger.warn(`Session ${sessionId} not found for agent ${agentId}`) + logger.warn('Session not found for deletion', { agentId, sessionId }) return res.status(404).json({ error: { message: 'Session not found for this agent', @@ -274,7 +280,7 @@ export const deleteSession = async (req: Request, res: Response): Promise { if (error instanceof ChatCompletionValidationError) { - logger.warn('Chat completion validation error:', { + logger.warn('Chat completion validation error', { errors: error.errors }) @@ -39,7 +39,7 @@ const mapChatCompletionError = (error: unknown): { status: number; body: ErrorRe } if (error instanceof ChatCompletionModelError) { - logger.warn('Chat completion model error:', error.error) + logger.warn('Chat completion model error', error.error) return { status: 400, @@ -72,7 +72,7 @@ const mapChatCompletionError = (error: unknown): { status: number; body: ErrorRe errorCode = 'upstream_error' } - logger.error('Chat completion error:', { error }) + logger.error('Chat completion error', { error }) return { status: statusCode, @@ -86,7 +86,7 @@ const mapChatCompletionError = (error: unknown): { status: number; body: ErrorRe } } - logger.error('Chat completion unknown error:', { error }) + logger.error('Chat completion unknown error', { error }) return { status: 500, @@ -193,7 +193,7 @@ router.post('/completions', async (req: Request, res: Response) => { }) } - logger.info('Chat completion request:', { + logger.debug('Chat completion request', { model: request.model, messageCount: request.messages?.length || 0, stream: request.stream, @@ -217,7 +217,7 @@ router.post('/completions', async (req: Request, res: Response) => { } res.write('data: [DONE]\n\n') } catch (streamError: any) { - logger.error('Stream error:', streamError) + logger.error('Stream error', { error: streamError }) res.write( `data: ${JSON.stringify({ error: { diff --git a/src/main/apiServer/routes/mcp.ts b/src/main/apiServer/routes/mcp.ts index 1e154ee583..6474194712 100644 --- a/src/main/apiServer/routes/mcp.ts +++ b/src/main/apiServer/routes/mcp.ts @@ -43,14 +43,14 @@ const router = express.Router() */ router.get('/', async (req: Request, res: Response) => { try { - logger.info('Get all MCP servers request received') + logger.debug('Listing MCP servers') const servers = await mcpApiService.getAllServers(req) return res.json({ success: true, data: servers }) } catch (error: any) { - logger.error('Error fetching MCP servers:', error) + logger.error('Error fetching MCP servers', { error }) return res.status(503).json({ success: false, error: { @@ -103,10 +103,12 @@ router.get('/', async (req: Request, res: Response) => { */ router.get('/:server_id', async (req: Request, res: Response) => { try { - logger.info('Get MCP server info request received') + logger.debug('Get MCP server info request received', { + serverId: req.params.server_id + }) const server = await mcpApiService.getServerInfo(req.params.server_id) if (!server) { - logger.warn('MCP server not found') + logger.warn('MCP server not found', { serverId: req.params.server_id }) return res.status(404).json({ success: false, error: { @@ -121,7 +123,7 @@ router.get('/:server_id', async (req: Request, res: Response) => { data: server }) } catch (error: any) { - logger.error('Error fetching MCP server info:', error) + logger.error('Error fetching MCP server info', { error, serverId: req.params.server_id }) return res.status(503).json({ success: false, error: { @@ -137,7 +139,7 @@ router.get('/:server_id', async (req: Request, res: Response) => { router.all('/:server_id/mcp', async (req: Request, res: Response) => { const server = await mcpApiService.getServerById(req.params.server_id) if (!server) { - logger.warn('MCP server not found') + logger.warn('MCP server not found', { serverId: req.params.server_id }) return res.status(404).json({ success: false, error: { diff --git a/src/main/apiServer/routes/messages.ts b/src/main/apiServer/routes/messages.ts index 65eb91b10b..c6d4644116 100644 --- a/src/main/apiServer/routes/messages.ts +++ b/src/main/apiServer/routes/messages.ts @@ -12,7 +12,9 @@ const providerRouter = express.Router({ mergeParams: true }) // Helper functions for shared logic async function validateRequestBody(req: Request): Promise<{ valid: boolean; error?: any }> { - logger.info('Validating request body', { body: req.body }) + logger.debug('Validating message request body', { + hasBody: Boolean(req.body) + }) const request: MessageCreateParams = req.body if (!request) { @@ -50,7 +52,7 @@ async function handleStreamingResponse( } res.write('data: [DONE]\n\n') } catch (streamError: any) { - logger.error('Stream error:', streamError) + logger.error('Stream error', { error: streamError }) res.write( `data: ${JSON.stringify({ type: 'error', @@ -66,7 +68,7 @@ async function handleStreamingResponse( } function handleErrorResponse(res: Response, error: any, logger: any): Response { - logger.error('Message processing error:', error) + logger.error('Message processing error', { error }) let statusCode = 500 let errorType = 'api_error' @@ -303,7 +305,10 @@ router.post('/', async (req: Request, res: Response) => { const modelValidation = await validateModelId(request.model) if (!modelValidation.valid) { const error = modelValidation.error! - logger.warn(`Model validation failed for '${request.model}':`, error) + logger.warn('Model validation failed', { + model: request.model, + error + }) return res.status(400).json({ type: 'error', error: { diff --git a/src/main/apiServer/routes/models.ts b/src/main/apiServer/routes/models.ts index 6694bf259b..ba965b3c80 100644 --- a/src/main/apiServer/routes/models.ts +++ b/src/main/apiServer/routes/models.ts @@ -75,13 +75,13 @@ const router = express */ .get('/', async (req: Request, res: Response) => { try { - logger.info('Models list request received', { query: req.query }) + logger.debug('Models list request received', { query: req.query }) // Validate query parameters using Zod schema const filterResult = ApiModelsFilterSchema.safeParse(req.query) if (!filterResult.success) { - logger.warn('Invalid query parameters:', filterResult.error.issues) + logger.warn('Invalid model query parameters', { issues: filterResult.error.issues }) return res.status(400).json({ error: { message: 'Invalid query parameters', @@ -99,24 +99,20 @@ const router = express const response = await modelsService.getModels(filter) if (response.data.length === 0) { - logger.warn( - 'No models available from providers. This may be because no OpenAI/Anthropic providers are configured or enabled.', - { filter } - ) + logger.warn('No models available from providers', { filter }) } - logger.info(`Returning ${response.data.length} models`, { + logger.info('Models response ready', { filter, total: response.total }) - logger.debug( - 'Model IDs:', - response.data.map((m) => m.id) - ) + logger.debug('Model IDs returned', { + modelIds: response.data.map((m) => m.id) + }) return res.json(response satisfies ApiModelsResponse) } catch (error: any) { - logger.error('Error fetching models:', error) + logger.error('Error fetching models', { error }) return res.status(503).json({ error: { message: 'Failed to retrieve models from available providers', diff --git a/src/main/apiServer/server.ts b/src/main/apiServer/server.ts index 1375320f06..61e8c291de 100644 --- a/src/main/apiServer/server.ts +++ b/src/main/apiServer/server.ts @@ -17,12 +17,12 @@ export class ApiServer { } // Load config - const { port, host, apiKey } = await config.load() + const { port, host } = await config.load() // Initialize AgentService - logger.info('Initializing AgentService...') + logger.info('Initializing AgentService') await agentService.initialize() - logger.info('AgentService initialized successfully') + logger.info('AgentService initialized') // Create server with Express app this.server = createServer(app) @@ -30,8 +30,7 @@ export class ApiServer { // Start server return new Promise((resolve, reject) => { this.server!.listen(port, host, () => { - logger.info(`API Server started at http://${host}:${port}`) - logger.info(`API Key: ${apiKey}`) + logger.info('API server started', { host, port }) resolve() }) @@ -44,7 +43,7 @@ export class ApiServer { return new Promise((resolve) => { this.server!.close(() => { - logger.info('API Server stopped') + logger.info('API server stopped') this.server = null resolve() }) @@ -62,7 +61,7 @@ export class ApiServer { const isListening = this.server?.listening || false const result = hasServer && isListening - logger.debug('isRunning check:', { hasServer, isListening, result }) + logger.debug('isRunning check', { hasServer, isListening, result }) return result } diff --git a/src/main/apiServer/services/chat-completion.ts b/src/main/apiServer/services/chat-completion.ts index a01592f25b..bc0e3bb23c 100644 --- a/src/main/apiServer/services/chat-completion.ts +++ b/src/main/apiServer/services/chat-completion.ts @@ -98,7 +98,7 @@ export class ChatCompletionService { const { provider, modelId, client } = providerContext - logger.info('Model validation successful:', { + logger.debug('Model validation successful', { provider: provider.id, providerType: provider.type, modelId, @@ -160,7 +160,7 @@ export class ChatCompletionService { response: OpenAI.Chat.Completions.ChatCompletion }> { try { - logger.info('Processing chat completion request:', { + logger.debug('Processing chat completion request', { model: request.model, messageCount: request.messages.length, stream: request.stream @@ -177,7 +177,7 @@ export class ChatCompletionService { const { provider, modelId, client, providerRequest } = preparation - logger.debug('Sending request to provider:', { + logger.debug('Sending request to provider', { provider: provider.id, model: modelId, apiHost: provider.apiHost @@ -185,14 +185,20 @@ export class ChatCompletionService { const response = (await client.chat.completions.create(providerRequest)) as OpenAI.Chat.Completions.ChatCompletion - logger.info('Successfully processed chat completion') + logger.info('Chat completion processed', { + modelId, + provider: provider.id + }) return { provider, modelId, response } } catch (error: any) { - logger.error('Error processing chat completion:', error) + logger.error('Error processing chat completion', { + error, + model: request.model + }) throw error } } @@ -203,7 +209,7 @@ export class ChatCompletionService { stream: AsyncIterable }> { try { - logger.info('Processing streaming chat completion request:', { + logger.debug('Processing streaming chat completion request', { model: request.model, messageCount: request.messages.length }) @@ -219,7 +225,7 @@ export class ChatCompletionService { const { provider, modelId, client, providerRequest } = preparation - logger.debug('Sending streaming request to provider:', { + logger.debug('Sending streaming request to provider', { provider: provider.id, model: modelId, apiHost: provider.apiHost @@ -230,14 +236,20 @@ export class ChatCompletionService { streamRequest )) as AsyncIterable - logger.info('Successfully started streaming chat completion') + logger.info('Streaming chat completion started', { + modelId, + provider: provider.id + }) return { provider, modelId, stream } } catch (error: any) { - logger.error('Error processing streaming chat completion:', error) + logger.error('Error processing streaming chat completion', { + error, + model: request.model + }) throw error } } diff --git a/src/main/apiServer/services/mcp.ts b/src/main/apiServer/services/mcp.ts index e5cff2e156..c03a90f930 100644 --- a/src/main/apiServer/services/mcp.ts +++ b/src/main/apiServer/services/mcp.ts @@ -49,7 +49,7 @@ class MCPApiService extends EventEmitter { constructor() { super() this.initMcpServer() - logger.silly('MCPApiService initialized') + logger.debug('MCPApiService initialized') } private initMcpServer() { @@ -60,7 +60,7 @@ class MCPApiService extends EventEmitter { async getAllServers(req: Request): Promise { try { const servers = await getMCPServersFromRedux() - logger.silly(`Returning ${servers.length} servers`) + logger.debug('Returning servers from Redux', { count: servers.length }) const resp: McpServersResp = { servers: {} } @@ -77,7 +77,7 @@ class MCPApiService extends EventEmitter { } return resp } catch (error: any) { - logger.error('Failed to get all servers:', error) + logger.error('Failed to get all servers', { error }) throw new Error('Failed to retrieve servers') } } @@ -85,17 +85,17 @@ class MCPApiService extends EventEmitter { // get server by id async getServerById(id: string): Promise { try { - logger.silly(`getServerById called with id: ${id}`) + logger.debug('getServerById called', { id }) const servers = await getMCPServersFromRedux() const server = servers.find((s) => s.id === id) if (!server) { - logger.warn(`Server with id ${id} not found`) + logger.warn('Server not found', { id }) return null } - logger.silly(`Returning server with id ${id}`) + logger.debug('Returning server', { id }) return server } catch (error: any) { - logger.error(`Failed to get server with id ${id}:`, error) + logger.error('Failed to get server', { id, error }) throw new Error('Failed to retrieve server') } } @@ -104,7 +104,7 @@ class MCPApiService extends EventEmitter { try { const server = await this.getServerById(id) if (!server) { - logger.warn(`Server with id ${id} not found`) + logger.warn('Server not found while fetching info', { id }) return null } @@ -118,14 +118,14 @@ class MCPApiService extends EventEmitter { tools: tools.tools } } catch (error: any) { - logger.error(`Failed to get server info with id ${id}:`, error) + logger.error('Failed to get server info', { id, error }) throw new Error('Failed to retrieve server info') } } async handleRequest(req: Request, res: Response, server: MCPServer) { const sessionId = req.headers['mcp-session-id'] as string | undefined - logger.silly(`Handling request for server with sessionId ${sessionId}`) + logger.debug('Handling MCP request', { sessionId, serverId: server.id }) let transport: StreamableHTTPServerTransport if (sessionId && transports[sessionId]) { transport = transports[sessionId] @@ -138,7 +138,7 @@ class MCPApiService extends EventEmitter { }) transport.onclose = () => { - logger.info(`Transport for sessionId ${sessionId} closed`) + logger.info('Transport closed', { sessionId }) if (transport.sessionId) { delete transports[transport.sessionId] } @@ -173,12 +173,15 @@ class MCPApiService extends EventEmitter { } } - logger.info(`Request body`, { rawBody: req.body, messages: JSON.stringify(messages) }) + logger.debug('Dispatching MCP request', { + sessionId: transport.sessionId ?? sessionId, + messageCount: messages.length + }) await transport.handleRequest(req as IncomingMessage, res as ServerResponse, messages) } private onMessage(message: JSONRPCMessage, extra?: MessageExtraInfo) { - logger.info(`Received message: ${JSON.stringify(message)}`, extra) + logger.debug('Received MCP message', { message, extra }) // Handle message here } } diff --git a/src/main/apiServer/services/models.ts b/src/main/apiServer/services/models.ts index 93a1bdb0e1..846687a77e 100644 --- a/src/main/apiServer/services/models.ts +++ b/src/main/apiServer/services/models.ts @@ -58,7 +58,11 @@ export class ModelsService { logger.debug(`Applied offset: offset=${offset}, showing ${modelData.length} of ${total} models`) } - logger.info(`Successfully retrieved ${modelData.length} models from ${models.length} total models`) + logger.info('Models retrieved', { + returned: modelData.length, + discovered: models.length, + filter + }) if (models.length > total) { logger.debug(`Filtered out ${models.length - total} models after deduplication and filtering`) @@ -80,7 +84,7 @@ export class ModelsService { return response } catch (error: any) { - logger.error('Error getting models:', error) + logger.error('Error getting models', { error, filter }) return { object: 'list', data: [] diff --git a/src/main/apiServer/utils/index.ts b/src/main/apiServer/utils/index.ts index 8f3f36a30b..6663918927 100644 --- a/src/main/apiServer/utils/index.ts +++ b/src/main/apiServer/utils/index.ts @@ -14,14 +14,16 @@ export async function getAvailableProviders(): Promise { // Try to get from cache first (faster) const cachedSupportedProviders = CacheService.get(PROVIDERS_CACHE_KEY) if (cachedSupportedProviders) { - logger.debug(`Found ${cachedSupportedProviders.length} supported providers (from cache)`) + logger.debug('Providers resolved from cache', { + count: cachedSupportedProviders.length + }) return cachedSupportedProviders } // If cache is not available, get fresh data from Redux const providers = await reduxService.select('state.llm.providers') if (!providers || !Array.isArray(providers)) { - logger.warn('No providers found in Redux store, returning empty array') + logger.warn('No providers found in Redux store') return [] } @@ -33,11 +35,14 @@ export async function getAvailableProviders(): Promise { // Cache the filtered results CacheService.set(PROVIDERS_CACHE_KEY, supportedProviders, PROVIDERS_CACHE_TTL) - logger.info(`Filtered to ${supportedProviders.length} supported providers from ${providers.length} total providers`) + logger.info('Providers filtered', { + supported: supportedProviders.length, + total: providers.length + }) return supportedProviders } catch (error: any) { - logger.error('Failed to get providers from Redux store:', error) + logger.error('Failed to get providers from Redux store', { error }) return [] } } @@ -47,7 +52,7 @@ export async function listAllAvailableModels(): Promise { const providers = await getAvailableProviders() return providers.map((p: Provider) => p.models || []).flat() } catch (error: any) { - logger.error('Failed to list available models:', error) + logger.error('Failed to list available models', { error }) return [] } } @@ -55,15 +60,13 @@ export async function listAllAvailableModels(): Promise { export async function getProviderByModel(model: string): Promise { try { if (!model || typeof model !== 'string') { - logger.warn(`Invalid model parameter: ${model}`) + logger.warn('Invalid model parameter', { model }) return undefined } // Validate model format first if (!model.includes(':')) { - logger.warn( - `Invalid model format, must contain ':' separator. Expected format "provider:model_id", got: ${model}` - ) + logger.warn('Invalid model format missing separator', { model }) return undefined } @@ -71,7 +74,7 @@ export async function getProviderByModel(model: string): Promise p.id === providerId) if (!provider) { - logger.warn( - `Provider '${providerId}' not found or not enabled. Available providers: ${providers.map((p) => p.id).join(', ')}` - ) + logger.warn('Provider not found for model', { + providerId, + available: providers.map((p) => p.id) + }) return undefined } - logger.debug(`Found provider '${providerId}' for model: ${model}`) + logger.debug('Provider resolved for model', { providerId, model }) return provider } catch (error: any) { - logger.error('Failed to get provider by model:', error) + logger.error('Failed to get provider by model', { error, model }) return undefined } } @@ -176,7 +180,7 @@ export async function validateModelId( modelId } } catch (error: any) { - logger.error('Error validating model ID:', error) + logger.error('Error validating model ID', { error, model }) return { valid: false, error: { @@ -207,7 +211,7 @@ export function transformModelToOpenAI(model: Model, providers: Provider[]): Api export async function getProviderById(providerId: string): Promise { try { if (!providerId || typeof providerId !== 'string') { - logger.warn(`Invalid provider ID parameter: ${providerId}`) + logger.warn('Invalid provider ID parameter', { providerId }) return undefined } @@ -215,16 +219,17 @@ export async function getProviderById(providerId: string): Promise p.id === providerId) if (!provider) { - logger.warn( - `Provider '${providerId}' not found or not enabled. Available providers: ${providers.map((p) => p.id).join(', ')}` - ) + logger.warn('Provider not found by ID', { + providerId, + available: providers.map((p) => p.id) + }) return undefined } - logger.debug(`Found provider '${providerId}'`) + logger.debug('Provider found by ID', { providerId }) return provider } catch (error: any) { - logger.error('Failed to get provider by ID:', error) + logger.error('Failed to get provider by ID', { error, providerId }) return undefined } } @@ -237,7 +242,7 @@ export function validateProvider(provider: Provider): boolean { // Check required fields if (!provider.id || !provider.type || !provider.apiKey || !provider.apiHost) { - logger.warn('Provider missing required fields:', { + logger.warn('Provider missing required fields', { id: !!provider.id, type: !!provider.type, apiKey: !!provider.apiKey, @@ -248,21 +253,22 @@ export function validateProvider(provider: Provider): boolean { // Check if provider is enabled if (!provider.enabled) { - logger.debug(`Provider is disabled: ${provider.id}`) + logger.debug('Provider is disabled', { providerId: provider.id }) return false } // Support OpenAI and Anthropic type providers if (provider.type !== 'openai' && provider.type !== 'anthropic') { - logger.debug( - `Provider type '${provider.type}' not supported, only 'openai' and 'anthropic' types are currently supported: ${provider.id}` - ) + logger.debug('Provider type not supported', { + providerId: provider.id, + providerType: provider.type + }) return false } return true } catch (error: any) { - logger.error('Error validating provider:', error) + logger.error('Error validating provider', { error, providerId: provider?.id }) return false } } diff --git a/src/main/apiServer/utils/mcp.ts b/src/main/apiServer/utils/mcp.ts index 380b8f1d99..40a9006528 100644 --- a/src/main/apiServer/utils/mcp.ts +++ b/src/main/apiServer/utils/mcp.ts @@ -47,12 +47,12 @@ async function getMcpServerConfigById(id: string): Promise { try { - logger.silly('Getting servers from Redux store') + logger.debug('Getting servers from Redux store') // Try to get from cache first (faster) const cachedServers = CacheService.get(MCP_SERVERS_CACHE_KEY) if (cachedServers) { - logger.silly(`Found ${cachedServers.length} servers (from cache)`) + logger.debug('MCP servers resolved from cache', { count: cachedServers.length }) return cachedServers } @@ -63,10 +63,10 @@ export async function getMCPServersFromRedux(): Promise { // Cache the results CacheService.set(MCP_SERVERS_CACHE_KEY, serverList, MCP_SERVERS_CACHE_TTL) - logger.silly(`Fetched ${serverList.length} servers from Redux store`) + logger.debug('Fetched servers from Redux store', { count: serverList.length }) return serverList } catch (error: any) { - logger.error('Failed to get servers from Redux:', error) + logger.error('Failed to get servers from Redux', { error }) return [] } } @@ -91,6 +91,6 @@ export async function getMcpServerById(id: string): Promise { cachedServers[id] = newServer return newServer } - logger.silly('getMcpServer ', { server: server }) + logger.debug('Returning cached MCP server', { id, hasHandlers: Boolean(server) }) return server }