@incubrain/logger
Version:
A modern, format-agnostic logging library for Node.js and browser environments, built on top of Consola with additional features for enterprise applications.
7 lines (6 loc) • 17 kB
JavaScript
var se=Object.defineProperty;var U=(t,e)=>()=>(t&&(e=t(t=0)),e);var q=(t,e)=>{for(var r in e)se(t,r,{get:e[r],enumerable:!0})};function ce(){return typeof window<"u"&&typeof window.document<"u"?"client":"server"}function Q(){return ce()==="client"}var X=U(()=>{"use strict"});var Z={};q(Z,{getEnvVar:()=>w,getRuntime:()=>j,getRuntimeContext:()=>p,setupErrorHandlers:()=>fe});function j(){return k||(k=Q()?new J:new B),k}function w(t){return j().getEnvVar(t)}function p(){return j().getContext()}function fe(t){return j().setupErrorHandlers(t)}var B,J,k,b=U(()=>{"use strict";X();B=class{getContext(){return{runtime:"server",isFileSystemAvailable:!0,isProcessAvailable:!0,environment:process.env.NODE_ENV||"development"}}getEnvVar(e){return process.env[e]}setupErrorHandlers(e){if(typeof process<"u"){process.on("uncaughtException",o=>{e.fatal("Uncaught Exception:",o),process.exit(1)}),process.on("unhandledRejection",(o,n)=>{e.error("Unhandled Rejection at:",n,"reason:",o)});let r=["SIGTERM","SIGINT","SIGUSR2"];for(let o of r)process.once(o,async()=>{e.info(`Received ${o}, shutting down...`),await e.end?.(),process.exit(0)})}}},J=class{getContext(){return{runtime:"client",isFileSystemAvailable:!1,isProcessAvailable:!1,environment:process.env?.MODE||"development"}}getEnvVar(e){return process.env?.[e]}setupErrorHandlers(e){typeof window<"u"&&(window.addEventListener("unhandledrejection",r=>{e.error("Unhandled Rejection:",r.reason)}),window.addEventListener("error",r=>{e.fatal("Uncaught Error:",r.error)}))}}});var ie={};q(ie,{FileLogger:()=>T,FileReporter:()=>E,closeAllFileLoggers:()=>oe,createFileLogger:()=>C,logFile:()=>ne,setupErrorLogger:()=>xe,setupLoggerCleanup:()=>K});import{createWriteStream as ve,existsSync as M,mkdirSync as re,statSync as Ee}from"fs";import z from"path";function C(t,e={},r=t){try{let o=z.join(process.cwd(),"logs");M(o)||re(o,{recursive:!0});let n=z.join(o,t),s=`${n}-${r}`;return A[s]||(A[s]=new T(n,e,r)),A[s]}catch(o){console.error("Error creating logger:",o);let n=z.join(process.cwd(),"logs","emergency");return new T(n,e,"emergency")}}async function oe(){await Promise.all(Object.values(A).map(t=>t.close()))}async function ne(t,e,r={}){let o=C(t,r);await o.write(e),process.env.NODE_ENV==="test"&&await o.flush()}function xe(t={}){return new E("error",{...t,format:"jsonsl"})}function K(){let t=async()=>{await oe()};return["SIGINT","SIGTERM","SIGUSR2"].forEach(e=>{process.listeners(e).forEach(n=>{n.name==="cleanupLoggers"&&process.removeListener(e,n)});let o=async function(){await t(),process.exit(0)};process.once(e,o)}),t}var P,T,A,E,D=U(()=>{"use strict";P={maxFileSize:5*1024*1024,maxFiles:5,pretty:!1,rotateOnLimit:!0,timestamp:!0,format:"json",bufferSize:64*1024,flushInterval:1e3},T=class{constructor(e,r={},o="default"){this.baseFilePath=e;this.logName=o,this.options={...P,...r};let n=z.dirname(e);M(n)||re(n,{recursive:!0}),this.initStream(),this.setupFlushInterval()}currentFile=0;writeStream=null;currentSize=0;isRotating=!1;buffer=[];bufferSize=0;flushTimer=null;isClosed=!1;logName;options;async flush(){if(this.buffer.length===0||this.isClosed)return;let e=[...this.buffer],r=this.bufferSize;this.buffer=[],this.bufferSize=0;try{if(this.options.rotateOnLimit&&this.currentSize+r>(this.options.maxFileSize||P.maxFileSize)&&await this.rotateFiles(),this.writeStream&&!this.isRotating&&!this.isClosed){let o=e.join("");return new Promise((n,s)=>{if(!this.writeStream)return this.buffer=[...e,...this.buffer],this.bufferSize+=r,s(new Error("Write stream is null"));this.writeStream.write(o,g=>{g?(this.buffer=[...e,...this.buffer],this.bufferSize+=r,s(g)):(this.currentSize+=r,n())})||this.writeStream.once("drain",()=>n())})}}catch(o){throw this.buffer=[...e,...this.buffer],this.bufferSize+=r,o}}async write(e,r="info"){if(!(!e||this.isClosed))try{let o=this.normalizeEntries(e);for(let n of o){let s=typeof n=="object"&&n!==null?{...n,level:r}:{message:String(n),level:r},a=this.formatLogEntry(s),g=Buffer.from(a).length;this.buffer.push(a),this.bufferSize+=g}this.bufferSize>=(this.options.bufferSize||P.bufferSize)&&await this.flush(),process.env.NODE_ENV==="test"&&await this.flush()}catch(o){console.error(`Error writing log entry [${this.logName}]:`,o)}}async close(){if(!this.isClosed){if(this.isClosed=!0,this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.buffer.length>0)try{await this.flush()}catch(e){console.error(`Error during final flush [${this.logName}]:`,e)}if(this.writeStream)return new Promise(e=>{if(!this.writeStream)return e();this.writeStream.end(()=>{this.writeStream&&(this.writeStream.destroy(),this.writeStream=null),e()})})}}getCurrentFilePath(){return`${this.baseFilePath}.${this.currentFile}.log`}initStream(){try{let e=this.getCurrentFilePath();if(this.writeStream=ve(e,{flags:"a"}),M(e)){let o=Ee(e);this.currentSize=o.size}else this.currentSize=0;this.writeStream.on("error",o=>{console.error(`Error writing to log file [${this.logName}]:`,o)});let r=()=>{this.close().catch(o=>{console.error(`Error closing logger during exit [${this.logName}]:`,o)})};process.removeListener("beforeExit",r),process.once("beforeExit",r)}catch(e){console.error(`Failed to initialize log stream [${this.logName}]:`,e)}}setupFlushInterval(){this.flushTimer&&clearInterval(this.flushTimer);let e=this.options.flushInterval||P.flushInterval,r=()=>{if(this.isClosed){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null);return}this.flush().catch(o=>{console.error(`Error flushing log buffer [${this.logName}]:`,o)})};this.flushTimer=setInterval(r,e),this.flushTimer.unref&&this.flushTimer.unref()}async rotateFiles(){if(!(this.isRotating||this.isClosed)){this.isRotating=!0;try{this.writeStream&&await new Promise((e,r)=>{if(!this.writeStream)return e();this.writeStream.end(o=>{o?r(o):(this.writeStream=null,e())})}),this.currentFile=(this.currentFile+1)%(this.options.maxFiles||P.maxFiles),this.initStream(),this.currentSize=0}catch(e){console.error(`Error rotating log files [${this.logName}]:`,e)}finally{this.isRotating=!1}}}formatLogEntry(e){let r={...e,...this.options.timestamp&&{timestamp:new Date().toISOString()},logger:this.logName};try{return this.options.format==="jsonsl"?JSON.stringify(r)+`
`:this.options.pretty?JSON.stringify(r,null,2)+`
`:JSON.stringify(r)+`
`}catch{return`${new Date().toISOString()} ERROR_FORMATTING_LOG [${this.logName}]: ${String(e)}
`}}normalizeEntries(e){switch(typeof e){case"string":case"number":case"bigint":case"boolean":return[{message:String(e)}];case"object":return e===null?[{message:"null"}]:Array.isArray(e)?e:e instanceof Error?[{message:e.message,name:e.name,stack:e.stack}]:[e];default:return[{message:`[${typeof e}]`}]}}async info(e){return this.write(e,"info")}async warn(e){return this.write(e,"warn")}async error(e){return this.write(e,"error")}async debug(e){return this.write(e,"debug")}},A={};E=class{fileLogger;constructor(e,r={}){this.fileLogger=C(e,r,z.basename(e))}log(e){let r=l=>{let S=new Set;return JSON.stringify(l,(Y,h)=>{if(typeof h=="object"&&h!==null){if(S.has(h))return"[Circular]";S.add(h)}return h})},{args:o=[],date:n,tag:s,type:a,message:g}=e,m=o.find(l=>l instanceof Error),f={type:a,message:g||(o[0]&&typeof o[0]=="string"?o[0]:void 0),timestamp:n instanceof Date?n.toISOString():new Date().toISOString(),...s&&{tag:s},...m&&{error:{name:m.name,message:m.message,stack:m.stack}},...o.length>0&&{args:o.map(l=>{if(l instanceof Error)return{name:l.name,message:l.message,stack:l.stack};if(typeof l=="object"&&l!==null)try{return JSON.parse(r(l))}catch{return String(l)}return l})}},x=this.mapTypeToLevel(a);Promise.resolve().then(async()=>{try{await this.fileLogger.write(f,x),process.env.NODE_ENV==="test"&&await this.fileLogger.flush()}catch(l){console.error("Error writing to file logger:",l)}})}mapTypeToLevel(e){switch(e){case"error":case"fatal":return"error";case"warn":return"warn";case"debug":case"trace":return"debug";default:return"info"}}async end(){try{await this.fileLogger.flush(),await this.fileLogger.close()}catch(e){console.error("Error ending file reporter:",e)}}}});var i={SILENT:-999,VERBOSE:999,FATAL:0,ERROR:0,WARN:1,LOG:2,INFO:3,SUCCESS:3,READY:3,START:3,DEBUG:4,TRACE:5},ae={log:(t,e)=>{let{args:r=[],date:o,type:n,tag:s}=t,a,g=[...r];typeof t.message=="string"&&t.message.length>0?(a=t.message,r.length>0&&r[0]===a&&(g=r.slice(1))):r.length>0&&typeof r[0]=="string"?(a=r[0],g=r.slice(1)):a="[No message]";let m=r.find(G=>G instanceof Error),f=m?` Error: ${m.message}`:"",x=g.filter(G=>!(G instanceof Error)),l=o instanceof Date?o.toISOString():new Date().toISOString(),S=s?`[${s}] `:"",Y=n==="error"||n==="fatal"?"error":n==="warn"?"warn":n==="info"||n==="success"?"info":n==="debug"||n==="trace"?"debug":"log",h="";if(x.length>0)try{h=" "+JSON.stringify(x.length===1?x[0]:x)}catch{h=" [Cannot stringify metadata]"}console[Y](`[${l}] [${n.toUpperCase()}] ${S}${a}${f}${h}`)}},u={level:3,reporters:[ae],formatOptions:{date:!0,colors:!0,compact:!1}},d={development:"development",production:"production",test:"test"};var I=class extends Error{constructor(r,o){super(r);this.cause=o;this.name="LoggerError"}},H=class extends I{constructor(e,r){super(`Stream Error: ${e}`,r),this.name="StreamError"}},_=class extends I{constructor(r,o,n){super(`Serialization Error: ${r}`,n);this.data=o;this.name="SerializationError"}},y=class extends I{constructor(e,r){super(`Configuration Error: ${e}`,r),this.name="ConfigurationError"}},Ne=t=>{if(console.debug("[DEBUG] defaultErrorHandler received error:",{error:t}),console.error(`[LOGGER ERROR] ${t.name}:`,{message:t.message,cause:t.cause,stack:t.stack}),process.env.NODE_ENV==="development"){if(!(t instanceof _))throw t}else if(t instanceof H||t instanceof y)throw t};import{createConsola as le}from"consola";var ge=process.env.DEBUG==="true"&&process.env.NODE_ENV==="development";function O(...t){ge&&console.log("[LOGGER_DEBUG]",...t)}var L=class t{static instance;consola;reporters=[];options;constructor(e={},r){try{this.consola=r||le({level:e.level??u.level,reporters:e.reporters||u.reporters,formatOptions:{...u.formatOptions,...e.formatOptions}}),this.options={...u,...e,context:e.context||{}}}catch(o){throw new y("Failed to initialize logger",o instanceof Error?o:void 0)}}shouldLog(e){let r=i[e],o=this.consola.level;return o===i.SILENT?!1:o===i.VERBOSE?!0:r<=o}static getInstance(e){return O("getInstance called with options:",e),t.instance?O("Returning existing Logger instance"):(O("Creating new Logger instance"),t.instance=new t(e)),t.instance}withContext(e){O(`withContext called with: ${JSON.stringify(e)}`),O("Creating new logger with merged context");let r={level:this.options.level,formatOptions:{...this.options.formatOptions},context:{...this.options.context,...e}},o=new t(r);return O(`Setting reporters on new logger: ${JSON.stringify(this.reporters)}`),o.reporters=this.reporters,o}setLevel(e){this.consola.level=e,this.options.level=e}async end(){await Promise.all(this.reporters.map(e=>e.end?.()).filter(Boolean))}prompt(e,r){return this.consola.prompt(e,r)}debug(e,...r){this.shouldLog("DEBUG")&&(typeof e=="string"&&r.length===0?this.consola.debug(e):this.consola.debug(e,...r))}info(e,...r){this.shouldLog("INFO")&&(typeof e=="string"&&r.length===0?this.consola.info(e):this.consola.info(e,...r))}success(e,...r){this.shouldLog("SUCCESS")&&(typeof e=="string"&&r.length===0?this.consola.success(e):this.consola.success(e,...r))}warn(e,...r){this.shouldLog("WARN")&&(typeof e=="string"&&r.length===0?this.consola.warn(e):this.consola.warn(e,...r))}error(e,...r){this.shouldLog("ERROR")&&(typeof e=="string"&&r.length===0?this.consola.error(e):this.consola.error(e,...r))}fatal(e,...r){this.shouldLog("FATAL")&&(typeof e=="string"&&r.length===0?this.consola.fatal(e):this.consola.fatal(e,...r))}trace(e,...r){this.shouldLog("TRACE")&&(typeof e=="string"&&r.length===0?this.consola.trace(e):this.consola.trace(e,...r))}log(e,...r){this.shouldLog("LOG")&&(typeof e=="string"&&r.length===0?this.consola.log(e):this.consola.log(e,...r))}};b();var ue=process.env.NODE_ENV==="development.js";function c(...t){ue&&console.log("[INIT_DEBUG]",...t)}var v=null;function pe(t){if(t.level!==void 0&&(t.level<0||t.level>5))throw new y("Log level must be between 0 and 5")}function F(t){try{let e=new WeakSet;return JSON.stringify(t,(r,o)=>{if(typeof o=="object"&&o!==null){if(e.has(o))return"[Circular].js";e.add(o)}return typeof o=="function"?"[Function].js":o},2)}catch(e){return`[Cannot stringify: ${e.message}]`}}function V(t={}){c("initLogger called with options:",F(t)),pe(t);let e=p();c("Runtime context:",F(e)),t.serviceName&&(!t.context||!t.context.serviceName)&&(t.context={...t.context||{},serviceName:t.serviceName},c("Added serviceName to context:",F(t.context)));let r={environment:e.environment,runtime:e.runtime,serviceName:"default-service"};c("Default context:",F(r));let o={...u,...t,context:{...r,...t.context},formatOptions:{...u.formatOptions,...t.formatOptions}};if(c("Merged options:",F(o)),t.reporters&&(c("Setting reporters from options:",typeof t.reporters),o.reporters=t.reporters),c("Final reporters count:",o.reporters?.length),c("Creating logger instance"),v=L.getInstance(o),!v)throw new Error("Failed to create logger instance");let n=t.level??he();return c("Setting log level:",n),v.setLevel(n),c("Logger instance created successfully"),v}function R(){return c("getLogger called, loggerInstance exists:",!!v),v||V()}function me(t){return c("createLogger called with context:",F(t)),R().withContext(t)}function he(){let t=w("LOG_LEVEL");if(t&&t in i)return i[t];switch(p().environment){case d.production:return i.INFO;case d.test:return i.ERROR;case d.development:default:return i.DEBUG}}b();b();var W=p(),de={environment:W.environment,runtime:W.runtime},Le={...u,context:de},ee=L.getInstance(Le);function te(t){return ee.withContext(t)}function ye(){let t=w("LOG_LEVEL");if(t&&t in i)return i[t];switch(W.environment){case d.production:return i.INFO;case d.test:return i.ERROR;case d.development:default:return i.DEBUG}}ee.setLevel(ye());D();D();b();var N=class{constructor(e={}){this.options=e;let o=p().environment==="development";this.logLevel=e.level??(o?i.DEBUG:i.WARN);let n=e.filePath||"error";this.fileLogger=C(n,{maxFileSize:e.maxFileSize||10*1024*1024,maxFiles:e.maxFiles||5,format:"jsonsl",timestamp:!0},"error-reporter")}fileLogger;logLevel;log(e){let{type:r,args:o=[],message:n,date:s}=e;if(this.getTypeLevel(r)>this.logLevel)return;let g=o.find(f=>f instanceof Error),m={level:r,message:n||(o[0]&&typeof o[0]=="string"?o[0]:void 0)||`[${r}]`,timestamp:s instanceof Date?s.toISOString():new Date().toISOString(),...g&&{error:{name:g.name,message:g.message,stack:g.stack}},...o.length>0&&{args:o.map(f=>f instanceof Error?{name:f.name,message:f.message,stack:f.stack}:this.sanitizeForJson(f))}};this.fileLogger.write(m),process.env.NODE_ENV==="test"&&this.fileLogger.flush()}sanitizeForJson(e){if(e==null||typeof e!="object")return e;try{let r=new WeakSet;return JSON.parse(JSON.stringify(e,(o,n)=>{if(typeof n=="object"&&n!==null){if(r.has(n))return"[Circular]";r.add(n)}return n}))}catch{return String(e)}}getTypeLevel(e){switch(e){case"fatal":return i.FATAL;case"error":return i.ERROR;case"warn":return i.WARN;case"log":return i.LOG;case"info":case"success":case"ready":case"start":return i.INFO;case"debug":return i.DEBUG;case"trace":return i.TRACE;default:return i.INFO}}async end(){await this.fileLogger.close()}};function Se(t={}){return new N(t)}var $=null;async function Oe(t={}){let e=p(),r=e.environment==="development",o=[...t.reporters||[]];if(t.fileLogging?.enabled){let a=new E(t.fileLogging.filePath||"app",{maxFileSize:t.fileLogging.maxFileSize,maxFiles:t.fileLogging.maxFiles,format:t.fileLogging.format,pretty:t.fileLogging.pretty,bufferSize:t.fileLogging.bufferSize,flushInterval:t.fileLogging.flushInterval});o.push(a)}if(r||t.errorLogging?.enabled){let a=new N({filePath:t.errorLogging?.filePath||"error",maxFileSize:t.errorLogging?.maxFileSize,maxFiles:t.errorLogging?.maxFiles,level:t.errorLogging?.level||i.WARN});o.push(a)}let n={...t,reporters:o.length>0?o:t.reporters},s=V({...n,context:{...t.context,environment:e.environment}});if(t.setupErrorHandlers){let{setupErrorHandlers:a}=await Promise.resolve().then(()=>(b(),Z));a(s)}return $||($=K()),s}function we(t){return{provide:{logger:t?te(t):R()}}}async function be(){$&&await $()}async function Fe(t,e,r={}){let{logFile:o}=await Promise.resolve().then(()=>(D(),ie));return o(t,e,r)}D();var dt=R();export{y as ConfigurationError,u as DEFAULT_OPTIONS,d as ENV,N as ErrorReporter,E as FileReporter,i as LOG_LEVELS,L as Logger,I as LoggerError,_ as SerializationError,H as StreamError,be as cleanupLoggers,Se as createErrorReporter,C as createFileLogger,me as createLogger,we as createNuxtPlugin,Ne as defaultErrorHandler,R as getLogger,V as initLogger,ne as logFile,Fe as logToFile,dt as logger,Oe as setupLogger};
//# sourceMappingURL=index.js.map