init
This commit is contained in:
		
						commit
						4b00caf7d4
					
				
					 9 changed files with 187 additions and 0 deletions
				
			
		
							
								
								
									
										45
									
								
								Dispatch.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								Dispatch.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| import { statSync } from "node:fs"; | ||||
| import { IDispatch, IDispatchConfig } from "./IDispatch"; | ||||
| import { ILogItem } from "./ILogItem"; | ||||
| import { LogLevel } from "./LogLevel"; | ||||
| 
 | ||||
| export class Dispatch implements IDispatch { | ||||
|   private dispatches: IDispatch[] = []; | ||||
| 
 | ||||
|   constructor(config: IDispatchConfig = {}) {} | ||||
| 
 | ||||
|   trace(...args: any[]): void { | ||||
|     this.process({ timestamp: new Date(), level: LogLevel.Trace, data: args }); | ||||
|   } | ||||
| 
 | ||||
|   debug(...args: any[]): void { | ||||
|     this.process({ timestamp: new Date(), level: LogLevel.Debug, data: args }); | ||||
|   } | ||||
| 
 | ||||
|   info(...args: any[]): void { | ||||
|     this.process({ timestamp: new Date(), level: LogLevel.Info, data: args }); | ||||
|   } | ||||
| 
 | ||||
|   warn(...args: any[]): void { | ||||
|     this.process({ timestamp: new Date(), level: LogLevel.Warn, data: args }); | ||||
|   } | ||||
| 
 | ||||
|   error(...args: any[]): void { | ||||
|     this.process({ timestamp: new Date(), level: LogLevel.Error, data: args }); | ||||
|   } | ||||
| 
 | ||||
|   fatal(...args: any[]): void { | ||||
|     this.process({ timestamp: new Date(), level: LogLevel.Fatal, data: args }); | ||||
|   } | ||||
| 
 | ||||
|   process(item: ILogItem): void { | ||||
|     for (const dispatch of this.dispatches) { | ||||
|       dispatch.process(item); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   add(dispatch: IDispatch): Dispatch { | ||||
|     this.dispatches.push(dispatch); | ||||
|     return this; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										24
									
								
								FileDispatch.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								FileDispatch.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| import * as fs from "fs"; | ||||
| import { FormattedDispatch } from "./FormattedDispatch"; | ||||
| import { App } from "../App"; | ||||
| import { ILogItem } from "./ILogItem"; | ||||
| 
 | ||||
| export class FileDispatch extends FormattedDispatch { | ||||
|   path: string; | ||||
|   stream: fs.WriteStream; | ||||
| 
 | ||||
|   constructor(path: string) { | ||||
|     super(); | ||||
|     this.path = path; | ||||
|     this.stream = fs.createWriteStream(path, { flags: "a" }); | ||||
| 
 | ||||
|     this.stream.on("error", (err) => { | ||||
|       App.logger.error(`Error writing to file: ${this.path}`, err); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   process(item: ILogItem): void { | ||||
|     this.stream.write(this.format(item) + "\n"); | ||||
|     super.process(item); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										37
									
								
								FormattedDispatch.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								FormattedDispatch.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| import { Dispatch } from "./Dispatch"; | ||||
| import { ILogItem } from "./ILogItem"; | ||||
| import { LogLevel } from "./LogLevel"; | ||||
| 
 | ||||
| export class FormattedDispatch extends Dispatch { | ||||
|   private formatString: string = "%t %l <%o>: %m"; | ||||
| 
 | ||||
|   format(item: ILogItem): string { | ||||
|     return this.formatString | ||||
|       .replace("%t", item.timestamp.toISOString()) | ||||
|       .replace("%l", LogLevel[item.level]) | ||||
|       .replace("%o", item.origin || "") | ||||
|       .replace( | ||||
|         "%m", | ||||
|         item.data | ||||
|           .map((item: any) => { | ||||
|             switch (typeof item) { | ||||
|               case "string": | ||||
|               case "number": | ||||
|                 return item; | ||||
|               case "object": | ||||
|                 return JSON.stringify(item); | ||||
|               default: | ||||
|                 return item; | ||||
|             } | ||||
|           }) | ||||
|           .join(" "), | ||||
|       ); | ||||
|   } | ||||
| 
 | ||||
|   process(item: ILogItem): void { | ||||
|     super.process({ | ||||
|       ...item, | ||||
|       data: this.format(item), | ||||
|     }); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										7
									
								
								IDispatch.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								IDispatch.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| import { ILogItem } from "./ILogItem"; | ||||
| 
 | ||||
| export interface IDispatchConfig {} | ||||
| 
 | ||||
| export interface IDispatch { | ||||
|   process(item: ILogItem): void; | ||||
| } | ||||
							
								
								
									
										8
									
								
								ILogItem.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ILogItem.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| import { LogLevel } from "./LogLevel"; | ||||
| 
 | ||||
| export interface ILogItem { | ||||
|   timestamp: Date; | ||||
|   origin?: string; | ||||
|   level: LogLevel; | ||||
|   data: any; | ||||
| } | ||||
							
								
								
									
										8
									
								
								LogLevel.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								LogLevel.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| export enum LogLevel { | ||||
|     Trace, | ||||
|     Debug, | ||||
|     Info, | ||||
|     Warn, | ||||
|     Error, | ||||
|     Fatal | ||||
| } | ||||
							
								
								
									
										3
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| # s410 logger | ||||
| 
 | ||||
| Dispatch based logging, created by Didier a.k.a. s410 or s41uc0. | ||||
							
								
								
									
										44
									
								
								SmartDispatch.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								SmartDispatch.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| import { statSync } from "fs"; | ||||
| import { Dispatch } from "./Dispatch"; | ||||
| import { ILogItem } from "./ILogItem"; | ||||
| 
 | ||||
| export class SmartDispatch extends Dispatch { | ||||
|   process(item: ILogItem) { | ||||
|     let err = new Error(); | ||||
|     // we need to look through the stack and keep track of intermediate dispatches
 | ||||
|     let stack = err.stack!.split("\n"); | ||||
|     let i = 0; | ||||
|     while (!stack[i].includes("at SmartDispatch.process")) i++; | ||||
| 
 | ||||
|     let src = stack[i + 2].trim(); | ||||
|     let path = null; | ||||
| 
 | ||||
|     // now we need to format the src (at ...:..:.. or at App.<anonymous> ..., etc)
 | ||||
|     if (src.includes("at ")) src = src.split("at ")[1]; | ||||
|     if (src.includes(" (")) src = src.split(" (")[1]; | ||||
|     if (src.includes(")")) src = src.split(")")[0]; | ||||
| 
 | ||||
|     let file = { | ||||
|       path: src.split(":")[0], | ||||
|       line: src.split(":")[1], | ||||
|       column: src.split(":")[2], | ||||
|     }; | ||||
| 
 | ||||
|     try { | ||||
|       path = statSync(file.path).isFile() ? file.path : null; | ||||
|     } catch (e) { | ||||
|       path = null; | ||||
|     } | ||||
| 
 | ||||
|     if (path) { | ||||
|       // trim the path to the project root
 | ||||
|       if (path.startsWith(process.cwd())) | ||||
|         path = "." + path.slice(process.cwd().length); | ||||
|       src = `${path}:${file.line}:${file.column}`; | ||||
|     } | ||||
|     super.process({ | ||||
|       ...item, | ||||
|       origin: src, | ||||
|     }); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										11
									
								
								StdoutDispatch.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								StdoutDispatch.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| import { FormattedDispatch } from "./FormattedDispatch"; | ||||
| import { IDispatch } from "./IDispatch"; | ||||
| import { ILogItem } from "./ILogItem"; | ||||
| import { LogLevel } from "./LogLevel"; | ||||
| 
 | ||||
| export class StdoutDispatch extends FormattedDispatch { | ||||
|   process(item: ILogItem) { | ||||
|     process.stdout.write(this.format(item) + "\n"); | ||||
|     super.process(item); | ||||
|   } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue