sanket3280/code-execution
0
1const fs = require('fs').promises;2const path = require('path');3 4class ExecutionLogger {5 constructor() {6 this.logDir = path.join(__dirname, '../logs');7 this.currentSessionId = null;8 this.sessionStartTime = null;9 }10 11 async ensureLogDir() {12 try {13 await fs.mkdir(this.logDir, { recursive: true });14 } catch (error) {15 console.error('Failed to create log directory:', error);16 }17 }18 19 startSession(sessionId) {20 this.currentSessionId = sessionId;21 this.sessionStartTime = Date.now();22 }23 24 formatTime(ms) {25 if (ms < 1000) return `${ms}ms`;26 return `${(ms / 1000).toFixed(2)}s`;27 }28 29 formatMemory(kb) {30 if (kb < 1024) return `${kb}KB`;31 return `${(kb / 1024).toFixed(2)}MB`;32 }33 34 async logExecution({ 35 sessionId, 36 language, 37 executor, 38 totalTestCases, 39 testCaseResults, 40 totalTime, 41 summary 42 }) {43 await this.ensureLogDir();44 45 const timestamp = new Date().toISOString();46 const logFile = path.join(this.logDir, `execution-${timestamp.split('T')[0]}.log`);47 48 const separator = '='.repeat(80);49 const minorSep = '-'.repeat(80);50 51 let logContent = `\n${separator}\n`;52 logContent += `๐ CODE EXECUTION LOG\n`;53 logContent += `${separator}\n`;54 logContent += `๐
Timestamp: ${timestamp}\n`;55 logContent += `๐ Session ID: ${sessionId}\n`;56 logContent += `๐ป Language: ${language}\n`;57 logContent += `๐ณ Executor: ${executor}\n`;58 logContent += `โฑ๏ธ Total Execution Time: ${this.formatTime(totalTime)}\n`;59 logContent += `${separator}\n\n`;60 61 // Summary Section62 logContent += `๐ EXECUTION SUMMARY\n`;63 logContent += `${minorSep}\n`;64 logContent += `Total Test Cases: ${totalTestCases}\n`;65 logContent += `โ
Passed: ${summary.passed} (${((summary.passed / totalTestCases) * 100).toFixed(1)}%)\n`;66 logContent += `โ Failed: ${summary.failed} (${((summary.failed / totalTestCases) * 100).toFixed(1)}%)\n`;67 logContent += `โ ๏ธ Errors: ${summary.errors} (${((summary.errors / totalTestCases) * 100).toFixed(1)}%)\n`;68 logContent += `${minorSep}\n\n`;69 70 // Detailed Test Case Results71 logContent += `๐ DETAILED TEST CASE RESULTS\n`;72 logContent += `${minorSep}\n`;73 74 testCaseResults.forEach((testCase, index) => {75 const statusIcon = testCase.status === 'Pass' || testCase.pass ? 'โ
' : 76 testCase.status === 'Fail' ? 'โ' : 'โ ๏ธ';77 78 logContent += `\n${statusIcon} Test Case #${index + 1}\n`;79 logContent += ` Status: ${testCase.status}\n`;80 81 if (!testCase.isHidden) {82 logContent += ` Input: ${JSON.stringify(testCase.input).substring(0, 100)}${JSON.stringify(testCase.input).length > 100 ? '...' : ''}\n`;83 logContent += ` Expected: ${JSON.stringify(testCase.expected || testCase.expected_output).substring(0, 100)}\n`;84 logContent += ` Output: ${JSON.stringify(testCase.output).substring(0, 100)}${JSON.stringify(testCase.output).length > 100 ? '...' : ''}\n`;85 } else {86 logContent += ` [Hidden Test Case]\n`;87 }88 89 if (testCase.executionTime !== null && testCase.executionTime !== undefined) {90 logContent += ` โฑ๏ธ Time: ${this.formatTime(testCase.executionTime)}\n`;91 }92 93 if (testCase.memoryUsed !== null && testCase.memoryUsed !== undefined) {94 logContent += ` ๐พ Memory: ${this.formatMemory(testCase.memoryUsed)}\n`;95 }96 97 if (testCase.error) {98 logContent += ` โ ๏ธ Error: ${testCase.error.substring(0, 200)}${testCase.error.length > 200 ? '...' : ''}\n`;99 }100 });101 102 logContent += `\n${separator}\n\n`;103 104 // Console output105 this.printToConsole({ 106 sessionId, 107 language, 108 executor, 109 totalTestCases, 110 summary, 111 totalTime,112 testCaseResults 113 });114 115 // Write to file116 try {117 await fs.appendFile(logFile, logContent);118 } catch (error) {119 console.error('Failed to write log file:', error);120 }121 }122 123 printToConsole({ sessionId, language, executor, totalTestCases, summary, totalTime, testCaseResults }) {124 const separator = '='.repeat(80);125 const minorSep = '-'.repeat(80);126 127 console.log(`\n${separator}`);128 console.log(`๐ CODE EXECUTION REPORT`);129 console.log(`${separator}`);130 console.log(`๐ Session: ${sessionId}`);131 console.log(`๐ป Language: ${language}`);132 console.log(`๐ณ Executor: ${executor}`);133 console.log(`โฑ๏ธ Total Time: ${this.formatTime(totalTime)}`);134 console.log(`${separator}\n`);135 136 console.log(`๐ SUMMARY`);137 console.log(`${minorSep}`);138 console.log(`Total: ${totalTestCases} | โ
Pass: ${summary.passed} | โ Fail: ${summary.failed} | โ ๏ธ Error: ${summary.errors}`);139 console.log(`Success Rate: ${((summary.passed / totalTestCases) * 100).toFixed(1)}%`);140 console.log(`${minorSep}\n`);141 142 console.log(`๐ TEST CASES`);143 console.log(`${minorSep}`);144 145 testCaseResults.forEach((testCase, index) => {146 const statusIcon = testCase.status === 'Pass' || testCase.pass ? 'โ
' : 147 testCase.status === 'Fail' ? 'โ' : 'โ ๏ธ';148 const timeStr = testCase.executionTime ? ` (${this.formatTime(testCase.executionTime)})` : '';149 const hiddenStr = testCase.isHidden ? ' [HIDDEN]' : '';150 151 console.log(`${statusIcon} Test #${index + 1}: ${testCase.status}${timeStr}${hiddenStr}`);152 153 if (!testCase.isHidden && testCase.error) {154 console.log(` โ ๏ธ ${testCase.error.substring(0, 100)}${testCase.error.length > 100 ? '...' : ''}`);155 }156 });157 158 console.log(`${separator}\n`);159 }160 161 async logDockerExecution({ 162 executionId, 163 language, 164 dockerImage, 165 timeLimit, 166 memoryLimit, 167 result 168 }) {169 const timestamp = new Date().toISOString();170 const logFile = path.join(this.logDir, `docker-${timestamp.split('T')[0]}.log`);171 172 let logContent = `\n[${timestamp}] Docker Execution\n`;173 logContent += ` ID: ${executionId}\n`;174 logContent += ` Language: ${language}\n`;175 logContent += ` Image: ${dockerImage}\n`;176 logContent += ` Limits: ${timeLimit}s / ${memoryLimit}MB\n`;177 logContent += ` Status: ${result.status}\n`;178 logContent += ` Exit Code: ${result.success ? 0 : 1}\n`;179 logContent += ` Time: ${this.formatTime(result.executionTime)}\n`;180 181 if (result.error) {182 logContent += ` Error: ${result.error.substring(0, 200)}\n`;183 }184 185 logContent += `\n`;186 187 try {188 await this.ensureLogDir();189 await fs.appendFile(logFile, logContent);190 } catch (error) {191 console.error('Failed to write Docker log:', error);192 }193 }194 195 async logBatchExecution({ batchNumber, totalBatches, batchSize, results }) {196 console.log(`\n๐ฆ BATCH ${batchNumber}/${totalBatches}`);197 console.log(` Size: ${batchSize} test cases`);198 console.log(` โ
Pass: ${results.summary.passed} | โ Fail: ${results.summary.failed} | โ ๏ธ Error: ${results.summary.errors}`);199 }200}201 202module.exports = new ExecutionLogger();203 