log_tool
Query and filter logs by tool name, status, duration, and time range with pagination support for efficient log analysis and troubleshooting.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| endTime | No | End time (ISO8601) | |
| maxDuration | No | Maximum duration (ms) | |
| minDuration | No | Minimum duration (ms) | |
| page | Yes | Page number (>= 1) | |
| pageSize | Yes | Logs per page (1-100) | |
| startTime | No | Start time (ISO8601) | |
| status | No | Log status (success or error) | |
| toolName | No | Regex to match tool name |
Implementation Reference
- src/tools/log_tool.ts:60-121 (handler)Main handler function for log_tool: reads log file line-by-line, parses JSON entries, applies filters (toolName regex, status, duration range, time range), implements pagination (skip/take), returns formatted JSON or error.export default async (request: any): Promise<{ content: any[]; isError?: boolean }> => { try { const params = request.params.arguments; let { pageSize, page, toolName, status, minDuration, maxDuration, startTime, endTime } = params; // Parameter preprocessing pageSize = Math.min(pageSize || 10, 100); page = Math.max(page || 1, 1); const skip = (page - 1) * pageSize; const take = pageSize; const paginatedLogs: LogEntry[] = []; let matchedCount = 0; // Check if log file exists if (!fs.existsSync(logFile)) { return { content: [{ type: 'text', text: JSON.stringify([], null, 2) }] }; } const fileStream = fs.createReadStream(logFile); const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity, }); for await (const line of rl) { try { if (line.trim() === '') continue; const logEntry: LogEntry = JSON.parse(line); logEntry.tool = logEntry.tool || 'unknown'; // Apply filters if (toolName && !new RegExp(toolName).test(logEntry.tool)) continue; if (status && logEntry.stat !== status) continue; if (minDuration && logEntry.cost < minDuration) continue; if (maxDuration && logEntry.cost > maxDuration) continue; if (startTime && new Date(logEntry.ts) < new Date(startTime)) continue; if (endTime && new Date(logEntry.ts) > new Date(endTime)) continue; // If filters pass, check for pagination if (matchedCount >= skip) { paginatedLogs.push(logEntry); } matchedCount++; // If the page is full, stop reading if (paginatedLogs.length >= take) { rl.close(); fileStream.destroy(); break; } } catch (parseError) { // Ignore lines that are not valid JSON } } return { content: [{ type: 'text', text: JSON.stringify(paginatedLogs, null, 2) }] }; } catch (error: any) { return { content: [{ type: 'text', text: JSON.stringify(`Query failed: ${error.message}`, null, 2) }], isError: true }; } };
- src/tools/log_tool.ts:5-50 (schema)Input schema for log_tool defining optional parameters for pagination, filtering by tool name (regex), status, duration, and time range.export const schema = { name: 'log_tool', description: 'Query logs with filtering and pagination', type: 'object', properties: { pageSize: { type: 'number', description: 'Logs per page (1-100)', minimum: 1, maximum: 100, default: 10 }, page: { type: 'number', description: 'Page number (>= 1)', minimum: 1, default: 1 }, toolName: { type: 'string', description: 'Regex to match tool name', }, status: { type: 'string', description: 'Log status (success or error)', enum: ['success', 'error'], }, minDuration: { type: 'number', description: 'Minimum duration (ms)', }, maxDuration: { type: 'number', description: 'Maximum duration (ms)', }, startTime: { type: 'string', description: 'Start time (ISO8601)', }, endTime: { type: 'string', description: 'End time (ISO8601)', }, }, required: [] };
- src/handler/ToolHandler.ts:117-129 (registration)Dynamic tool registration in loadTools(): imports tool modules from src/tools/*.ts, extracts toolName from filename (e.g. log_tool.ts -> log_tool), registers schema, handler (default export), and destroy in global tools/handlers arrays.const { default: tool, schema, destroy } = await import(importPath); const toolName = path.parse(toolPath).name; // 注册工具 tools.push({ name: toolName, description: tool.description, inputSchema: schema, destroy: destroy }); // 注册处理函数 handlers[toolName] = async (request: ToolRequest) => { return await tool(request); };
- src/tools/log_tool.ts:124-127 (helper)Tool-specific destroy function for cleanup on reload/unload.export async function destroy() { // Release resources, stop timers, disconnect, etc. console.log("Destroy log_tool"); }