Skip to main content
Glama
logger.ts2.81 kB
import { appendFileSync, mkdirSync } from "node:fs"; import { join } from "node:path"; import { format as utilFormat } from "node:util"; type LogLevel = "info" | "warn" | "error" | "debug"; const LOG_DIR = join(process.cwd(), "log"); const LOG_FILE = createLogFilePath(); function createLogFilePath(): string { mkdirSync(LOG_DIR, { recursive: true }); const timestamp = new Date().toISOString().replaceAll(":", "-").replaceAll(".", "-"); return join(LOG_DIR, `${timestamp}.log`); } function formatMessage(level: LogLevel, message: unknown, ...rest: unknown[]): string { const time = new Date().toISOString(); const formatted = utilFormat(message as string, ...rest); return `[${time}] [${level.toUpperCase()}] ${formatted}`; } function writeToFile(line: string): void { appendFileSync(LOG_FILE, `${line}\n`); } export interface Logger { info(message: unknown, ...rest: unknown[]): void; warn(message: unknown, ...rest: unknown[]): void; error(message: unknown, ...rest: unknown[]): void; debug(message: unknown, ...rest: unknown[]): void; child(context: Record<string, unknown>): Logger; } class LoggerImpl implements Logger { constructor(private readonly context: Record<string, unknown> = {}) {} info(message: unknown, ...rest: unknown[]): void { this.log("info", message, ...rest); } warn(message: unknown, ...rest: unknown[]): void { this.log("warn", message, ...rest); } error(message: unknown, ...rest: unknown[]): void { this.log("error", message, ...rest); } debug(message: unknown, ...rest: unknown[]): void { if (process.env.NODE_ENV === "production" && process.env.DEEPSEARCH_LOG_LEVEL !== "debug") { return; } this.log("debug", message, ...rest); } child(context: Record<string, unknown>): Logger { return new LoggerImpl({ ...this.context, ...context }); } private log(level: LogLevel, message: unknown, ...rest: unknown[]): void { const contextPrefix = this.formatContext(); const fullMessage = contextPrefix ? `${contextPrefix} ${message}` : message; const line = formatMessage(level, fullMessage, ...rest); switch (level) { case "info": console.info(line); break; case "warn": console.warn(line); break; case "error": console.error(line); break; default: console.debug(line); break; } try { writeToFile(line); } catch (error) { console.error("写入日志文件失败", error); } } private formatContext(): string { const entries = Object.entries(this.context); if (entries.length === 0) { return ""; } return entries.map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(" "); } } export const logger: Logger = new LoggerImpl();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yuemingruoan/DeepSearch-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server