Skip to content

Commit

Permalink
feat: improvement to logger (#2396)
Browse files Browse the repository at this point in the history
* upd: initial updated logger

* upd: remove test case

* upd: improve some logs

* upd: resolved issues with mix of left and right json

* fix env and default mode

* Update pnpm-lock.yaml

---------

Co-authored-by: Sayo <[email protected]>
  • Loading branch information
JoeyKhd and wtfsayo authored Jan 17, 2025
1 parent 522481d commit e9e5608
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 270 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ SUPABASE_ANON_KEY=
# Comma separated list of remote character urls (optional)
REMOTE_CHARACTER_URLS=

# Logging
LOG_JSON_FORMAT= # Print everything in logger as json; false by default

###############################
#### Client Configurations ####
###############################
Expand Down
4 changes: 3 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"@ai-sdk/openai": "1.0.5",
"@anthropic-ai/sdk": "0.30.1",
"@fal-ai/client": "1.2.0",
"@tavily/core": "^0.0.2",
"@types/uuid": "10.0.0",
"ai": "3.4.33",
"anthropic-vertex-ai": "1.0.2",
Expand All @@ -85,7 +86,8 @@
"langchain": "0.3.6",
"ollama-ai-provider": "0.16.1",
"openai": "4.73.0",
"@tavily/core": "^0.0.2",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",
"tinyld": "1.3.4",
"together-ai": "0.7.0",
"unique-names-generator": "4.7.1",
Expand Down
319 changes: 57 additions & 262 deletions packages/core/src/logger.ts
Original file line number Diff line number Diff line change
@@ -1,271 +1,66 @@
class ElizaLogger {
constructor() {
// Check if we're in Node.js environment
this.isNode =
typeof process !== "undefined" &&
process.versions != null &&
process.versions.node != null;

// Set verbose based on environment
this.verbose = this.isNode ? process.env.VERBOSE === "true" : false;

// Add initialization logging
console.log(`[ElizaLogger] Initializing with:
isNode: ${this.isNode}
verbose: ${this.verbose}
VERBOSE env: ${process.env.VERBOSE}
NODE_ENV: ${process.env.NODE_ENV}
`);
}

private isNode: boolean;
verbose = false;
closeByNewLine = true;
useIcons = true;
logsTitle = "LOGS";
warningsTitle = "WARNINGS";
errorsTitle = "ERRORS";
informationsTitle = "INFORMATIONS";
successesTitle = "SUCCESS";
debugsTitle = "DEBUG";
assertsTitle = "ASSERT";

#getColor(foregroundColor = "", backgroundColor = "") {
if (!this.isNode) {
// Browser console styling
const colors: { [key: string]: string } = {
black: "#000000",
red: "#ff0000",
green: "#00ff00",
yellow: "#ffff00",
blue: "#0000ff",
magenta: "#ff00ff",
cyan: "#00ffff",
white: "#ffffff",
};

const fg = colors[foregroundColor.toLowerCase()] || colors.white;
const bg = colors[backgroundColor.toLowerCase()] || "transparent";
return `color: ${fg}; background: ${bg};`;
}

// Node.js console colors
let fgc = "\x1b[37m";
switch (foregroundColor.trim().toLowerCase()) {
case "black":
fgc = "\x1b[30m";
break;
case "red":
fgc = "\x1b[31m";
break;
case "green":
fgc = "\x1b[32m";
break;
case "yellow":
fgc = "\x1b[33m";
break;
case "blue":
fgc = "\x1b[34m";
break;
case "magenta":
fgc = "\x1b[35m";
break;
case "cyan":
fgc = "\x1b[36m";
break;
case "white":
fgc = "\x1b[37m";
break;
}

let bgc = "";
switch (backgroundColor.trim().toLowerCase()) {
case "black":
bgc = "\x1b[40m";
break;
case "red":
bgc = "\x1b[44m";
break;
case "green":
bgc = "\x1b[44m";
break;
case "yellow":
bgc = "\x1b[43m";
break;
case "blue":
bgc = "\x1b[44m";
break;
case "magenta":
bgc = "\x1b[45m";
break;
case "cyan":
bgc = "\x1b[46m";
break;
case "white":
bgc = "\x1b[47m";
break;
}

return `${fgc}${bgc}`;
}

#getColorReset() {
return this.isNode ? "\x1b[0m" : "";
}

clear() {
console.clear();
import pino, { LogFn } from "pino";
import pretty from "pino-pretty";

const customLevels: Record<string, number> = {
fatal: 60,
error: 50,
warn: 40,
info: 30,
log: 29,
progress: 28,
success: 27,
debug: 20,
trace: 10,
};

const raw = process?.env?.LOG_JSON_FORMAT || false;

const createStream = () => {
if (raw) {
return undefined;
}

print(foregroundColor = "white", backgroundColor = "black", ...strings) {
// Convert objects to strings
const processedStrings = strings.map((item) => {
if (typeof item === "object") {
return JSON.stringify(item, (key, value) =>
typeof value === "bigint" ? value.toString() : value
return pretty({
colorize: true,
translateTime: "yyyy-mm-dd HH:MM:ss",
ignore: "pid,hostname",
});
};

const options = {
customLevels,
hooks: {
logMethod(
inputArgs: [string | Record<string, unknown>, ...unknown[]],
method: LogFn
): void {
const [arg1, ...rest] = inputArgs;

if (typeof arg1 === "object") {
const messageParts = rest.map((arg) =>
typeof arg === "string" ? arg : JSON.stringify(arg)
);
}
return item;
});

if (this.isNode) {
const c = this.#getColor(foregroundColor, backgroundColor);
console.log(c, processedStrings.join(""), this.#getColorReset());
} else {
const style = this.#getColor(foregroundColor, backgroundColor);
console.log(`%c${processedStrings.join("")}`, style);
}

if (this.closeByNewLine) console.log("");
}

#logWithStyle(
strings: any[],
options: {
fg: string;
bg: string;
icon: string;
groupTitle: string;
}
) {
const { fg, bg, icon, groupTitle } = options;

if (strings.length > 1) {
if (this.isNode) {
const c = this.#getColor(fg, bg);
console.group(c, (this.useIcons ? icon : "") + groupTitle);
const message = messageParts.join(" ");
return method.apply(this, [arg1, message]);
} else {
const style = this.#getColor(fg, bg);
console.group(
`%c${this.useIcons ? icon : ""}${groupTitle}`,
style
const context = {};
const messageParts = [arg1, ...rest].map((arg) =>
typeof arg === "string" ? arg : arg
);
const message = messageParts
.filter((part) => typeof part === "string")
.join(" ");
const jsonParts = messageParts.filter(
(part) => typeof part === "object"
);
}

const nl = this.closeByNewLine;
this.closeByNewLine = false;
strings.forEach((item) => {
this.print(fg, bg, item);
});
this.closeByNewLine = nl;
console.groupEnd();
if (nl) console.log();
} else {
this.print(
fg,
bg,
strings.map((item) => {
return `${this.useIcons ? `${icon} ` : ""}${item}`;
})
);
}
}

log(...strings) {
this.#logWithStyle(strings, {
fg: "white",
bg: "",
icon: "\u25ce",
groupTitle: ` ${this.logsTitle}`,
});
}

warn(...strings) {
this.#logWithStyle(strings, {
fg: "yellow",
bg: "",
icon: "\u26a0",
groupTitle: ` ${this.warningsTitle}`,
});
}

error(...strings) {
this.#logWithStyle(strings, {
fg: "red",
bg: "",
icon: "\u26D4",
groupTitle: ` ${this.errorsTitle}`,
});
}

info(...strings) {
this.#logWithStyle(strings, {
fg: "blue",
bg: "",
icon: "\u2139",
groupTitle: ` ${this.informationsTitle}`,
});
}

debug(...strings) {
if (!this.verbose) {
// for diagnosing verbose logging issues
// console.log(
// "[ElizaLogger] Debug message suppressed (verbose=false):",
// ...strings
// );
return;
}
this.#logWithStyle(strings, {
fg: "magenta",
bg: "",
icon: "\u1367",
groupTitle: ` ${this.debugsTitle}`,
});
}

success(...strings) {
this.#logWithStyle(strings, {
fg: "green",
bg: "",
icon: "\u2713",
groupTitle: ` ${this.successesTitle}`,
});
}

assert(...strings) {
this.#logWithStyle(strings, {
fg: "cyan",
bg: "",
icon: "\u0021",
groupTitle: ` ${this.assertsTitle}`,
});
}
Object.assign(context, ...jsonParts);

progress(message: string) {
if (this.isNode) {
// Clear the current line and move cursor to beginning
process.stdout.clearLine(0);
process.stdout.cursorTo(0);
process.stdout.write(message);
} else {
console.log(message);
}
}
}
return method.apply(this, [context, message]);
}
},
},
};

export const elizaLogger = new ElizaLogger();
elizaLogger.closeByNewLine = true;
elizaLogger.useIcons = true;
export const elizaLogger = pino(options, createStream());

export default elizaLogger;
14 changes: 7 additions & 7 deletions packages/core/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,19 +371,19 @@ export class AgentRuntime implements IAgentRuntime {
this.imageModelProvider =
this.character.imageModelProvider ?? this.modelProvider;

elizaLogger.info("Selected model provider:", this.modelProvider);
elizaLogger.info(
"Selected image model provider:",
this.imageModelProvider
`Selected model provider: ${this.modelProvider}`
);

elizaLogger.info(
`Selected image model provider: ${this.imageModelProvider}`
);

this.imageVisionModelProvider =
this.character.imageVisionModelProvider ?? this.modelProvider;

// elizaLogger.info("Selected model provider:", this.modelProvider); duplicated log ln: 343
elizaLogger.info(
"Selected image vision model provider:",
this.imageVisionModelProvider
`Selected image vision model provider: ${this.imageVisionModelProvider}`
);

// Validate model provider
Expand Down Expand Up @@ -470,7 +470,7 @@ export class AgentRuntime implements IAgentRuntime {
this.character.knowledge.length > 0
) {
elizaLogger.info(
`[RAG Check] RAG Knowledge enabled: ${this.character.settings.ragKnowledge}`
`[RAG Check] RAG Knowledge enabled: ${this.character.settings.ragKnowledge ? true : false}`
);
elizaLogger.info(
`[RAG Check] Knowledge items:`,
Expand Down
Loading

0 comments on commit e9e5608

Please sign in to comment.