@@ -21,6 +21,7 @@ export namespace Log {
2121  } 
2222
2323  export  type  Logger  =  { 
24+     log ( level : Level ,  message ?: any ,  extra ?: Record < string ,  any > ) : void , 
2425    debug ( message ?: any ,  extra ?: Record < string ,  any > ) : void 
2526    info ( message ?: any ,  extra ?: Record < string ,  any > ) : void 
2627    error ( message ?: any ,  extra ?: Record < string ,  any > ) : void 
@@ -34,6 +35,16 @@ export namespace Log {
3435      stop ( ) : void 
3536      [ Symbol . dispose ] ( ) : void 
3637    } 
38+     /** Clone the logger with the specified options. */ 
39+     opt ( options : LoggerOptions ) : Logger 
40+   } 
41+ 
42+   type  LoggerOptions  =  { 
43+     /** 
44+      * If true, the logger will print to stderr even if printing to stderr was not explicitly enabled. 
45+      * When undefined, error messages will be printed to stderr by default. 
46+      */ 
47+     important ?: boolean 
3748  } 
3849
3950  const  loggers  =  new  Map < string ,  Logger > ( ) 
@@ -51,22 +62,23 @@ export namespace Log {
5162    return  logpath 
5263  } 
5364
65+   let  printToStderr  =  false 
66+   let  logFileWriter : Bun . FileSink  |  null  =  null 
67+ 
5468  export  async  function  init ( options : Options )  { 
5569    if  ( options . level )  level  =  options . level 
5670    cleanup ( Global . Path . log ) 
57-     if  ( options . print )  return 
71+     if  ( options . print )  { 
72+        printToStderr  =  true 
73+        return 
74+     } 
5875    logpath  =  path . join ( 
5976      Global . Path . log , 
6077      options . dev  ? "dev.log"  : new  Date ( ) . toISOString ( ) . split ( "." ) [ 0 ] . replace ( / : / g,  "" )  +  ".log" , 
6178    ) 
6279    const  logfile  =  Bun . file ( logpath ) 
80+     logFileWriter  =  logfile . writer ( ) 
6381    await  fs . truncate ( logpath ) . catch ( ( )  =>  { } ) 
64-     const  writer  =  logfile . writer ( ) 
65-     process . stderr . write  =  ( msg )  =>  { 
66-       writer . write ( msg ) 
67-       writer . flush ( ) 
68-       return  true 
69-     } 
7082  } 
7183
7284  async  function  cleanup ( dir : string )  { 
@@ -120,26 +132,26 @@ export namespace Log {
120132      last  =  next . getTime ( ) 
121133      return  [ next . toISOString ( ) . split ( "." ) [ 0 ] ,  "+"  +  diff  +  "ms" ,  prefix ,  message ] . filter ( Boolean ) . join ( " " )  +  "\n" 
122134    } 
123-     const  result : Logger  =  { 
124-       debug ( message ?: any ,  extra ?: Record < string ,  any > )  { 
125-         if  ( shouldLog ( "DEBUG" ) )  { 
126-           process . stderr . write ( "DEBUG "  +  build ( message ,  extra ) ) 
135+     const  result : Logger  &  {  _options : LoggerOptions  }  =  { 
136+       _options : { 
137+         important : undefined , 
138+       } , 
139+       log ( level : Level ,  message ?: any ,  extra ?: Record < string ,  any > )  { 
140+         if  ( shouldLog ( level ) )  { 
141+           write ( level ,  level  +  " "  +  build ( message ,  extra ) ,  this . _options ) 
127142        } 
128143      } , 
144+       debug ( message ?: any ,  extra ?: Record < string ,  any > )  { 
145+         this . log ( "DEBUG" ,  message ,  extra ) 
146+       } , 
129147      info ( message ?: any ,  extra ?: Record < string ,  any > )  { 
130-         if  ( shouldLog ( "INFO" ) )  { 
131-           process . stderr . write ( "INFO  "  +  build ( message ,  extra ) ) 
132-         } 
148+         this . log ( "INFO" ,  message ,  extra ) 
133149      } , 
134150      error ( message ?: any ,  extra ?: Record < string ,  any > )  { 
135-         if  ( shouldLog ( "ERROR" ) )  { 
136-           process . stderr . write ( "ERROR "  +  build ( message ,  extra ) ) 
137-         } 
151+         this . log ( "ERROR" ,  message ,  extra ) 
138152      } , 
139153      warn ( message ?: any ,  extra ?: Record < string ,  any > )  { 
140-         if  ( shouldLog ( "WARN" ) )  { 
141-           process . stderr . write ( "WARN  "  +  build ( message ,  extra ) ) 
142-         } 
154+         this . log ( "WARN" ,  message ,  extra ) 
143155      } , 
144156      tag ( key : string ,  value : string )  { 
145157        if  ( tags )  tags [ key ]  =  value 
@@ -165,6 +177,11 @@ export namespace Log {
165177          } , 
166178        } 
167179      } , 
180+       opt ( options : LoggerOptions )  { 
181+         const  logger  =  this . clone ( )  as  Logger  &  {  _options : LoggerOptions  } 
182+         logger . _options  =  options 
183+         return  logger 
184+       } 
168185    } 
169186
170187    if  ( service  &&  typeof  service  ===  "string" )  { 
@@ -173,4 +190,38 @@ export namespace Log {
173190
174191    return  result 
175192  } 
193+ 
194+   let  messageQueue : {  level : Level ,  message : string  } [ ]  =  [ ] 
195+   let  backgroundMode  =  false 
196+ 
197+   function  write ( level : Level ,  message : string ,  options ?: {  ignoreFile ?: boolean ,  important ?: boolean  } )  { 
198+     const  shouldWriteToFile  =  ! options ?. ignoreFile  &&  ! printToStderr  &&  ! ! logFileWriter 
199+     const  isImportant  =  options ?. important  ??  ( levelPriority [ level ]  >=  levelPriority [ "ERROR" ] ) 
200+     const  shouldWriteToStderr  =  printToStderr  ||  isImportant 
201+     if  ( shouldWriteToFile )  { 
202+       logFileWriter ! . write ( message ) 
203+       logFileWriter ! . flush ( ) 
204+     } 
205+     if  ( shouldWriteToStderr )  { 
206+       if  ( backgroundMode )  messageQueue . push ( {  level,  message } ) 
207+       else  process . stderr . write ( message ) 
208+     } 
209+   } 
210+ 
211+   /** 
212+    * Collect log messages in the background, to be flushed to stderr on-demand later. 
213+    */ 
214+   export  function  setBackgroundMode ( value : boolean )  { 
215+     backgroundMode  =  value 
216+   } 
217+ 
218+   /** 
219+    * Flush collected background log messages to stderr. 
220+    */ 
221+   export  function  flushBackgroundLogs ( )  { 
222+     for  ( const  entry  of  messageQueue )  { 
223+       write ( entry . level ,  entry . message ,  {  ignoreFile : true  } ) 
224+     } 
225+     messageQueue  =  [ ] 
226+   } 
176227} 
0 commit comments