MCPcopy Index your code
hub / github.com/ChatLab/ChatLab / AppLogger

Class AppLogger

packages/node-runtime/src/logging/app-logger.ts:22–83  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

20const MAX_SIZE_BYTES = 10 * 1024 * 1024 // 10MB
21
22class AppLogger {
23 private logFile: string
24 private oldLogFile: string
25 private threshold: LogLevel
26
27 constructor(logsDir: string) {
28 this.logFile = path.join(logsDir, 'app.log')
29 this.oldLogFile = path.join(logsDir, 'app.old.log')
30 this.threshold = resolveThreshold()
31 }
32
33 debug(scope: string, message: string, data?: unknown): void {
34 this.write('DEBUG', scope, message, data)
35 }
36
37 info(scope: string, message: string, data?: unknown): void {
38 this.write('INFO', scope, message, data)
39 }
40
41 warn(scope: string, message: string, data?: unknown): void {
42 this.write('WARN', scope, message, data)
43 }
44
45 /** `data` may be an Error; its name/message/stack are extracted automatically. */
46 error(scope: string, message: string, data?: unknown): void {
47 this.write('ERROR', scope, message, data)
48 }
49
50 getLogPath(): string {
51 return this.logFile
52 }
53
54 private write(level: LogLevel, scope: string, message: string, data?: unknown): void {
55 if (LEVEL_ORDER[level] < LEVEL_ORDER[this.threshold]) return
56
57 let line = `[${new Date().toISOString()}] [${level}] [${scope}] ${message}`
58
59 try {
60 const tail = formatData(data)
61 if (tail) line += `\n${tail}`
62 line += '\n'
63 ensureDir(path.dirname(this.logFile))
64 this.rotateIfNeeded()
65 fs.appendFileSync(this.logFile, line, 'utf-8')
66 } catch (err) {
67 // Logging must never break the app; surface to console only.
68 console.error('[AppLogger] Failed to write log:', err)
69 }
70 }
71
72 // ponytail: rename-based rotation, atomic, no rewrite, ~20MB total ceiling
73 private rotateIfNeeded(): void {
74 let size = 0
75 try {
76 size = fs.statSync(this.logFile).size
77 } catch {
78 return // file doesn't exist yet
79 }

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected