|
1 |
| -class ElizaLogger { |
2 |
| - constructor() { |
3 |
| - // Check if we're in Node.js environment |
4 |
| - this.isNode = |
5 |
| - typeof process !== "undefined" && |
6 |
| - process.versions != null && |
7 |
| - process.versions.node != null; |
8 |
| - |
9 |
| - // Set verbose based on environment |
10 |
| - this.verbose = this.isNode ? process.env.VERBOSE === "true" : false; |
11 |
| - |
12 |
| - // Add initialization logging |
13 |
| - console.log(`[ElizaLogger] Initializing with: |
14 |
| - isNode: ${this.isNode} |
15 |
| - verbose: ${this.verbose} |
16 |
| - VERBOSE env: ${process.env.VERBOSE} |
17 |
| - NODE_ENV: ${process.env.NODE_ENV} |
18 |
| - `); |
19 |
| - } |
20 |
| - |
21 |
| - private isNode: boolean; |
22 |
| - verbose = false; |
23 |
| - closeByNewLine = true; |
24 |
| - useIcons = true; |
25 |
| - logsTitle = "LOGS"; |
26 |
| - warningsTitle = "WARNINGS"; |
27 |
| - errorsTitle = "ERRORS"; |
28 |
| - informationsTitle = "INFORMATIONS"; |
29 |
| - successesTitle = "SUCCESS"; |
30 |
| - debugsTitle = "DEBUG"; |
31 |
| - assertsTitle = "ASSERT"; |
32 |
| - |
33 |
| - #getColor(foregroundColor = "", backgroundColor = "") { |
34 |
| - if (!this.isNode) { |
35 |
| - // Browser console styling |
36 |
| - const colors: { [key: string]: string } = { |
37 |
| - black: "#000000", |
38 |
| - red: "#ff0000", |
39 |
| - green: "#00ff00", |
40 |
| - yellow: "#ffff00", |
41 |
| - blue: "#0000ff", |
42 |
| - magenta: "#ff00ff", |
43 |
| - cyan: "#00ffff", |
44 |
| - white: "#ffffff", |
45 |
| - }; |
46 |
| - |
47 |
| - const fg = colors[foregroundColor.toLowerCase()] || colors.white; |
48 |
| - const bg = colors[backgroundColor.toLowerCase()] || "transparent"; |
49 |
| - return `color: ${fg}; background: ${bg};`; |
50 |
| - } |
51 |
| - |
52 |
| - // Node.js console colors |
53 |
| - let fgc = "\x1b[37m"; |
54 |
| - switch (foregroundColor.trim().toLowerCase()) { |
55 |
| - case "black": |
56 |
| - fgc = "\x1b[30m"; |
57 |
| - break; |
58 |
| - case "red": |
59 |
| - fgc = "\x1b[31m"; |
60 |
| - break; |
61 |
| - case "green": |
62 |
| - fgc = "\x1b[32m"; |
63 |
| - break; |
64 |
| - case "yellow": |
65 |
| - fgc = "\x1b[33m"; |
66 |
| - break; |
67 |
| - case "blue": |
68 |
| - fgc = "\x1b[34m"; |
69 |
| - break; |
70 |
| - case "magenta": |
71 |
| - fgc = "\x1b[35m"; |
72 |
| - break; |
73 |
| - case "cyan": |
74 |
| - fgc = "\x1b[36m"; |
75 |
| - break; |
76 |
| - case "white": |
77 |
| - fgc = "\x1b[37m"; |
78 |
| - break; |
79 |
| - } |
80 |
| - |
81 |
| - let bgc = ""; |
82 |
| - switch (backgroundColor.trim().toLowerCase()) { |
83 |
| - case "black": |
84 |
| - bgc = "\x1b[40m"; |
85 |
| - break; |
86 |
| - case "red": |
87 |
| - bgc = "\x1b[44m"; |
88 |
| - break; |
89 |
| - case "green": |
90 |
| - bgc = "\x1b[44m"; |
91 |
| - break; |
92 |
| - case "yellow": |
93 |
| - bgc = "\x1b[43m"; |
94 |
| - break; |
95 |
| - case "blue": |
96 |
| - bgc = "\x1b[44m"; |
97 |
| - break; |
98 |
| - case "magenta": |
99 |
| - bgc = "\x1b[45m"; |
100 |
| - break; |
101 |
| - case "cyan": |
102 |
| - bgc = "\x1b[46m"; |
103 |
| - break; |
104 |
| - case "white": |
105 |
| - bgc = "\x1b[47m"; |
106 |
| - break; |
107 |
| - } |
108 |
| - |
109 |
| - return `${fgc}${bgc}`; |
110 |
| - } |
111 |
| - |
112 |
| - #getColorReset() { |
113 |
| - return this.isNode ? "\x1b[0m" : ""; |
114 |
| - } |
115 |
| - |
116 |
| - clear() { |
117 |
| - console.clear(); |
| 1 | +import pino, { LogFn } from "pino"; |
| 2 | +import pretty from "pino-pretty"; |
| 3 | + |
| 4 | +const customLevels: Record<string, number> = { |
| 5 | + fatal: 60, |
| 6 | + error: 50, |
| 7 | + warn: 40, |
| 8 | + info: 30, |
| 9 | + log: 29, |
| 10 | + progress: 28, |
| 11 | + success: 27, |
| 12 | + debug: 20, |
| 13 | + trace: 10, |
| 14 | +}; |
| 15 | + |
| 16 | +const raw = process?.env?.LOG_JSON_FORMAT || false; |
| 17 | + |
| 18 | +const createStream = () => { |
| 19 | + if (raw) { |
| 20 | + return undefined; |
118 | 21 | }
|
119 |
| - |
120 |
| - print(foregroundColor = "white", backgroundColor = "black", ...strings) { |
121 |
| - // Convert objects to strings |
122 |
| - const processedStrings = strings.map((item) => { |
123 |
| - if (typeof item === "object") { |
124 |
| - return JSON.stringify(item, (key, value) => |
125 |
| - typeof value === "bigint" ? value.toString() : value |
| 22 | + return pretty({ |
| 23 | + colorize: true, |
| 24 | + translateTime: "yyyy-mm-dd HH:MM:ss", |
| 25 | + ignore: "pid,hostname", |
| 26 | + }); |
| 27 | +}; |
| 28 | + |
| 29 | +const options = { |
| 30 | + customLevels, |
| 31 | + hooks: { |
| 32 | + logMethod( |
| 33 | + inputArgs: [string | Record<string, unknown>, ...unknown[]], |
| 34 | + method: LogFn |
| 35 | + ): void { |
| 36 | + const [arg1, ...rest] = inputArgs; |
| 37 | + |
| 38 | + if (typeof arg1 === "object") { |
| 39 | + const messageParts = rest.map((arg) => |
| 40 | + typeof arg === "string" ? arg : JSON.stringify(arg) |
126 | 41 | );
|
127 |
| - } |
128 |
| - return item; |
129 |
| - }); |
130 |
| - |
131 |
| - if (this.isNode) { |
132 |
| - const c = this.#getColor(foregroundColor, backgroundColor); |
133 |
| - console.log(c, processedStrings.join(""), this.#getColorReset()); |
134 |
| - } else { |
135 |
| - const style = this.#getColor(foregroundColor, backgroundColor); |
136 |
| - console.log(`%c${processedStrings.join("")}`, style); |
137 |
| - } |
138 |
| - |
139 |
| - if (this.closeByNewLine) console.log(""); |
140 |
| - } |
141 |
| - |
142 |
| - #logWithStyle( |
143 |
| - strings: any[], |
144 |
| - options: { |
145 |
| - fg: string; |
146 |
| - bg: string; |
147 |
| - icon: string; |
148 |
| - groupTitle: string; |
149 |
| - } |
150 |
| - ) { |
151 |
| - const { fg, bg, icon, groupTitle } = options; |
152 |
| - |
153 |
| - if (strings.length > 1) { |
154 |
| - if (this.isNode) { |
155 |
| - const c = this.#getColor(fg, bg); |
156 |
| - console.group(c, (this.useIcons ? icon : "") + groupTitle); |
| 42 | + const message = messageParts.join(" "); |
| 43 | + return method.apply(this, [arg1, message]); |
157 | 44 | } else {
|
158 |
| - const style = this.#getColor(fg, bg); |
159 |
| - console.group( |
160 |
| - `%c${this.useIcons ? icon : ""}${groupTitle}`, |
161 |
| - style |
| 45 | + const context = {}; |
| 46 | + const messageParts = [arg1, ...rest].map((arg) => |
| 47 | + typeof arg === "string" ? arg : arg |
| 48 | + ); |
| 49 | + const message = messageParts |
| 50 | + .filter((part) => typeof part === "string") |
| 51 | + .join(" "); |
| 52 | + const jsonParts = messageParts.filter( |
| 53 | + (part) => typeof part === "object" |
162 | 54 | );
|
163 |
| - } |
164 |
| - |
165 |
| - const nl = this.closeByNewLine; |
166 |
| - this.closeByNewLine = false; |
167 |
| - strings.forEach((item) => { |
168 |
| - this.print(fg, bg, item); |
169 |
| - }); |
170 |
| - this.closeByNewLine = nl; |
171 |
| - console.groupEnd(); |
172 |
| - if (nl) console.log(); |
173 |
| - } else { |
174 |
| - this.print( |
175 |
| - fg, |
176 |
| - bg, |
177 |
| - strings.map((item) => { |
178 |
| - return `${this.useIcons ? `${icon} ` : ""}${item}`; |
179 |
| - }) |
180 |
| - ); |
181 |
| - } |
182 |
| - } |
183 |
| - |
184 |
| - log(...strings) { |
185 |
| - this.#logWithStyle(strings, { |
186 |
| - fg: "white", |
187 |
| - bg: "", |
188 |
| - icon: "\u25ce", |
189 |
| - groupTitle: ` ${this.logsTitle}`, |
190 |
| - }); |
191 |
| - } |
192 |
| - |
193 |
| - warn(...strings) { |
194 |
| - this.#logWithStyle(strings, { |
195 |
| - fg: "yellow", |
196 |
| - bg: "", |
197 |
| - icon: "\u26a0", |
198 |
| - groupTitle: ` ${this.warningsTitle}`, |
199 |
| - }); |
200 |
| - } |
201 |
| - |
202 |
| - error(...strings) { |
203 |
| - this.#logWithStyle(strings, { |
204 |
| - fg: "red", |
205 |
| - bg: "", |
206 |
| - icon: "\u26D4", |
207 |
| - groupTitle: ` ${this.errorsTitle}`, |
208 |
| - }); |
209 |
| - } |
210 |
| - |
211 |
| - info(...strings) { |
212 |
| - this.#logWithStyle(strings, { |
213 |
| - fg: "blue", |
214 |
| - bg: "", |
215 |
| - icon: "\u2139", |
216 |
| - groupTitle: ` ${this.informationsTitle}`, |
217 |
| - }); |
218 |
| - } |
219 |
| - |
220 |
| - debug(...strings) { |
221 |
| - if (!this.verbose) { |
222 |
| - // for diagnosing verbose logging issues |
223 |
| - // console.log( |
224 |
| - // "[ElizaLogger] Debug message suppressed (verbose=false):", |
225 |
| - // ...strings |
226 |
| - // ); |
227 |
| - return; |
228 |
| - } |
229 |
| - this.#logWithStyle(strings, { |
230 |
| - fg: "magenta", |
231 |
| - bg: "", |
232 |
| - icon: "\u1367", |
233 |
| - groupTitle: ` ${this.debugsTitle}`, |
234 |
| - }); |
235 |
| - } |
236 |
| - |
237 |
| - success(...strings) { |
238 |
| - this.#logWithStyle(strings, { |
239 |
| - fg: "green", |
240 |
| - bg: "", |
241 |
| - icon: "\u2713", |
242 |
| - groupTitle: ` ${this.successesTitle}`, |
243 |
| - }); |
244 |
| - } |
245 | 55 |
|
246 |
| - assert(...strings) { |
247 |
| - this.#logWithStyle(strings, { |
248 |
| - fg: "cyan", |
249 |
| - bg: "", |
250 |
| - icon: "\u0021", |
251 |
| - groupTitle: ` ${this.assertsTitle}`, |
252 |
| - }); |
253 |
| - } |
| 56 | + Object.assign(context, ...jsonParts); |
254 | 57 |
|
255 |
| - progress(message: string) { |
256 |
| - if (this.isNode) { |
257 |
| - // Clear the current line and move cursor to beginning |
258 |
| - process.stdout.clearLine(0); |
259 |
| - process.stdout.cursorTo(0); |
260 |
| - process.stdout.write(message); |
261 |
| - } else { |
262 |
| - console.log(message); |
263 |
| - } |
264 |
| - } |
265 |
| -} |
| 58 | + return method.apply(this, [context, message]); |
| 59 | + } |
| 60 | + }, |
| 61 | + }, |
| 62 | +}; |
266 | 63 |
|
267 |
| -export const elizaLogger = new ElizaLogger(); |
268 |
| -elizaLogger.closeByNewLine = true; |
269 |
| -elizaLogger.useIcons = true; |
| 64 | +export const elizaLogger = pino(options, createStream()); |
270 | 65 |
|
271 | 66 | export default elizaLogger;
|
0 commit comments