@baguskto/saham
Version:
MCP Server untuk data saham Indonesia (IDX) - Implementasi Node.js/TypeScript
132 lines • 4.92 kB
JavaScript
;
/**
* Logging utilities for IDX MCP Server
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logger = void 0;
const winston_1 = __importDefault(require("winston"));
const config_1 = require("../config");
// Safe JSON stringify that handles circular references and errors
function safeStringify(obj) {
try {
return JSON.stringify(obj, (_key, value) => {
// Handle errors by converting them to simple objects
if (value instanceof Error) {
return {
name: value.name,
message: value.message,
stack: value.stack
};
}
// Handle circular references
if (typeof value === 'object' && value !== null) {
if (value.constructor?.name === 'ClientRequest' ||
value.constructor?.name === 'IncomingMessage' ||
value.constructor?.name === 'Socket') {
return '[Circular Reference]';
}
}
return value;
});
}
catch (error) {
return `[Failed to stringify: ${error instanceof Error ? error.message : String(error)}]`;
}
}
class Logger {
static instance;
logger;
constructor() {
this.logger = this.createLogger();
}
static getInstance() {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
createLogger() {
const logConfig = config_1.config.getLogging();
const transports = [];
// Check if in MCP mode
const isMcpMode = process.env['IDX_MCP_LOG_LEVEL'] === 'error' || process.argv.includes('--mcp');
if (!isMcpMode) {
transports.push(new winston_1.default.transports.Console({
format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.timestamp(), winston_1.default.format.printf(({ timestamp, level, message, ...meta }) => {
let log = `${timestamp} [${level}]: ${message}`;
if (Object.keys(meta).length > 0) {
log += ` ${safeStringify(meta)}`;
}
return log;
}))
}));
}
else {
// In MCP mode, completely suppress console logging to avoid stdout pollution
// Only enable if log level is error and only to stderr
const logLevel = process.env['IDX_MCP_LOG_LEVEL'] || logConfig.level;
if (logLevel === 'error') {
transports.push(new winston_1.default.transports.Console({
stderrLevels: ['error'],
format: winston_1.default.format.combine(winston_1.default.format.printf(({ level, message, ...meta }) => {
let log = `[idx-mcp-server] [${level}] ${message}`;
if (Object.keys(meta).length > 0) {
log += ` ${safeStringify(meta)}`;
}
return log;
}))
}));
}
}
if (logConfig.file) {
transports.push(new winston_1.default.transports.File({
filename: logConfig.file,
format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.json()),
maxsize: 10 * 1024 * 1024, // 10MB
maxFiles: 5
}));
}
// Use environment log level if in MCP mode, otherwise use config
const logLevel = process.env['IDX_MCP_LOG_LEVEL'] || logConfig.level;
return winston_1.default.createLogger({
level: logLevel,
transports,
exitOnError: false
});
}
error(message, meta) {
this.logger.error(message, meta);
}
warn(message, meta) {
this.logger.warn(message, meta);
}
info(message, meta) {
this.logger.info(message, meta);
}
debug(message, meta) {
this.logger.debug(message, meta);
}
logMcpRequest(functionName, params, responseTime, error) {
const logData = {
functionName,
params,
responseTime,
success: !error,
error
};
if (error) {
this.error(`MCP Request Failed: ${functionName}`, logData);
}
else {
this.info(`MCP Request: ${functionName}`, logData);
}
}
logPerformanceMetrics(metrics) {
this.info('Performance Metrics', metrics);
}
}
exports.logger = Logger.getInstance();
//# sourceMappingURL=logger.js.map