leshan-mcp-server
Version:
A standards-compliant MCP server for Leshan LwM2M, exposing Leshan as Model Context Protocol tools.
87 lines (72 loc) • 2.26 kB
JavaScript
import { createWriteStream } from "fs";
import { mkdir } from "fs/promises";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
import { env } from "../config/env.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
const LOG_DIR = join(__dirname, "../../logs");
class Logger {
constructor() {
this.logLevel = env.LOG_LEVEL;
this.enableFileLogging = env.ENABLE_FILE_LOGGING;
this.logStream = null;
this.levels = { debug: 0, info: 1, warn: 2, error: 3 };
this.initialized = false;
}
async init() {
if (this.initialized) return;
if (this.enableFileLogging) {
try {
await mkdir(LOG_DIR, { recursive: true });
this.logStream = createWriteStream(
join(LOG_DIR, `mcp-server-${new Date().toISOString().split('T')[0]}.log`),
{ flags: 'a' }
);
} catch (error) {
console.error("Failed to initialize file logging:", error.message);
}
}
this.initialized = true;
}
shouldLog(level) {
return this.levels[level] >= this.levels[this.logLevel];
}
formatMessage(level, message, meta = {}) {
const timestamp = new Date().toISOString();
const logEntry = {
timestamp,
level: level.toUpperCase(),
message,
pid: process.pid,
...meta
};
return JSON.stringify(logEntry);
}
log(level, message, meta = {}) {
if (!this.shouldLog(level)) return;
const formattedMessage = this.formatMessage(level, message, meta);
// Always log to stderr (MCP protocol uses stdout)
console.error(formattedMessage);
// Log to file if enabled
if (this.logStream) {
this.logStream.write(formattedMessage + '\n');
}
}
debug(message, meta) { this.log('debug', message, meta); }
info(message, meta) { this.log('info', message, meta); }
warn(message, meta) { this.log('warn', message, meta); }
error(message, meta) { this.log('error', message, meta); }
// Graceful shutdown
async close() {
if (this.logStream) {
return new Promise((resolve) => {
this.logStream.end(resolve);
});
}
}
}
const logger = new Logger();
export function configureLogger() {
return logger.init();
}
export default logger;