octocode-mcp
Version:
Model Context Protocol (MCP) server for advanced GitHub repository analysis, code discovery, and npm package exploration. Provides AI assistants with powerful tools to search, analyze, and understand codebases across GitHub and npm ecosystems.
3 lines (2 loc) • 3.06 kB
JavaScript
import{createHash as t}from"crypto";import{writeFileSync as e,existsSync as i,mkdirSync as s}from"fs";import{join as n}from"path";class r{static events=[];static initialized=!1;static logDirectory=process.env.AUDIT_LOG_DIR||"./logs/audit";static flushInterval=null;static MAX_BUFFER_SIZE=1e3;static FLUSH_INTERVAL_MS=3e5;static initialize(){this.initialized||(this.initialized=!0,"true"===process.env.AUDIT_ALL_ACCESS&&(this.setupFileLogging(),this.setupPeriodicFlush()),this.logEvent({action:"audit_logger_initialized",outcome:"success",source:"system",details:{fileLoggingEnabled:"true"===process.env.AUDIT_ALL_ACCESS,logDirectory:this.logDirectory}}))}static logEvent(t){const e={...t,eventId:this.generateEventId(),timestamp:new Date};if(this.events.push(e),"production"!==process.env.NODE_ENV){const t={outcome:e.outcome,userId:e.userId,organizationId:e.organizationId,source:e.source,eventId:e.eventId};try{process.stderr.write(`[AUDIT] ${e.action}: ${JSON.stringify(t)}\n`)}catch(t){}}this.events.length>=this.MAX_BUFFER_SIZE&&this.flushToDisk()}static flushToDisk(){if(this.initialized&&"true"===process.env.AUDIT_ALL_ACCESS&&0!==this.events.length)try{const t=(new Date).toISOString().split("T")[0],i=n(this.logDirectory,`audit-${t}.jsonl`),s=this.events.map(t=>this.serializeEvent(t)).map(t=>JSON.stringify(t)).join("\n")+"\n";e(i,s,{flag:"a",encoding:"utf8"});const r=this.events.length;if(this.events=[],"production"!==process.env.NODE_ENV)try{process.stderr.write(`[AUDIT] Flushed ${r} events to ${i}\n`)}catch(t){}}catch(t){try{process.stderr.write(`[AUDIT] Failed to flush events to disk: ${t instanceof Error?t.message:String(t)}\n`)}catch(t){}}}static getStats(){return{initialized:this.initialized,bufferedEvents:this.events.length,fileLoggingEnabled:"true"===process.env.AUDIT_ALL_ACCESS,logDirectory:this.logDirectory}}static clearBuffer(){this.events=[]}static shutdown(){this.initialized&&(this.flushToDisk(),this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=null),this.initialized=!1)}static setupFileLogging(){try{i(this.logDirectory)||s(this.logDirectory,{recursive:!0})}catch(t){try{process.stderr.write(`[AUDIT] Failed to create log directory: ${t instanceof Error?t.message:String(t)}\n`)}catch(t){}}}static setupPeriodicFlush(){this.flushInterval&&clearInterval(this.flushInterval),this.flushInterval=setInterval(()=>{this.flushToDisk()},this.FLUSH_INTERVAL_MS),process.once("exit",()=>{this.flushToDisk()}),process.once("SIGINT",()=>{this.shutdown()}),process.once("SIGTERM",()=>{this.shutdown()})}static generateEventId(){const e=Date.now().toString(),i=Math.random().toString(36).substring(2);return t("sha256").update(`${e}-${i}`).digest("hex").substring(0,16)}static serializeEvent(t){return{...t,timestamp:t.timestamp.toISOString()}}}function o(t,e,i){r.logEvent({action:`auth_${t}`,outcome:e,source:"token_manager",details:i})}function a(t,e,i){r.logEvent({action:`tool_${t}`,outcome:e,source:"tool_execution",details:i})}export{r as AuditLogger,o as logAuthEvent,a as logToolEvent};