Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improvement to logger #2396

Merged
merged 9 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]);
}
},
},
};
coderabbitai[bot] marked this conversation as resolved.
Show resolved Hide resolved

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
Loading