sap-b1-mcp-server
Version:
SAP Business One Service Layer MCP Server
233 lines • 6.85 kB
JavaScript
export var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
LogLevel[LogLevel["WARN"] = 1] = "WARN";
LogLevel[LogLevel["INFO"] = 2] = "INFO";
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
})(LogLevel || (LogLevel = {}));
export class Logger {
level;
context;
constructor(level = LogLevel.INFO, context = {}) {
this.level = level;
this.context = context;
}
/**
* Create a child logger with additional context
*/
child(context) {
return new Logger(this.level, { ...this.context, ...context });
}
/**
* Log an error message
*/
error(message, error, context) {
if (this.level >= LogLevel.ERROR) {
this.log({
timestamp: new Date().toISOString(),
level: LogLevel.ERROR,
message,
context: { ...this.context, ...context },
error
});
}
}
/**
* Log a warning message
*/
warn(message, context) {
if (this.level >= LogLevel.WARN) {
this.log({
timestamp: new Date().toISOString(),
level: LogLevel.WARN,
message,
context: { ...this.context, ...context }
});
}
}
/**
* Log an info message
*/
info(message, context) {
if (this.level >= LogLevel.INFO) {
this.log({
timestamp: new Date().toISOString(),
level: LogLevel.INFO,
message,
context: { ...this.context, ...context }
});
}
}
/**
* Log a debug message
*/
debug(message, context) {
if (this.level >= LogLevel.DEBUG) {
this.log({
timestamp: new Date().toISOString(),
level: LogLevel.DEBUG,
message,
context: { ...this.context, ...context }
});
}
}
/**
* Log SAP API request
*/
logSAPRequest(method, endpoint, params) {
this.debug('SAP API Request', {
method,
endpoint,
params: params ? JSON.stringify(params) : undefined
});
}
/**
* Log SAP API response
*/
logSAPResponse(method, endpoint, status, responseTime) {
this.debug('SAP API Response', {
method,
endpoint,
status,
responseTime: responseTime ? `${responseTime}ms` : undefined
});
}
/**
* Log SAP API error
*/
logSAPError(method, endpoint, error, responseTime) {
this.error('SAP API Error', error, {
method,
endpoint,
responseTime: responseTime ? `${responseTime}ms` : undefined
});
}
/**
* Log MCP tool execution
*/
logToolExecution(toolName, args, success, duration) {
this.info('MCP Tool Execution', {
tool: toolName,
success,
duration: duration ? `${duration}ms` : undefined,
args: JSON.stringify(args, null, 2).substring(0, 500) // Truncate large arguments
});
}
/**
* Log session events
*/
logSessionEvent(event, sessionId) {
this.info('Session Event', {
event,
sessionId: sessionId ? `***${sessionId.slice(-8)}` : undefined // Mask session ID for security
});
}
/**
* Set log level
*/
setLevel(level) {
this.level = level;
}
/**
* Get current log level
*/
getLevel() {
return this.level;
}
/**
* Internal log method
*/
log(entry) {
const levelString = LogLevel[entry.level];
const contextString = entry.context && Object.keys(entry.context).length > 0
? ` ${JSON.stringify(entry.context)}`
: '';
const errorString = entry.error
? ` | Error: ${entry.error.message}${entry.error.stack ? `\n${entry.error.stack}` : ''}`
: '';
// Log to stderr so it doesn't interfere with STDIO transport
console.error(`[${entry.timestamp}] ${levelString}: ${entry.message}${contextString}${errorString}`);
}
/**
* Create logger from environment
*/
static fromEnvironment() {
const logLevelEnv = process.env.LOG_LEVEL?.toUpperCase();
let level = LogLevel.INFO;
switch (logLevelEnv) {
case 'ERROR':
level = LogLevel.ERROR;
break;
case 'WARN':
level = LogLevel.WARN;
break;
case 'INFO':
level = LogLevel.INFO;
break;
case 'DEBUG':
level = LogLevel.DEBUG;
break;
}
const context = {
service: 'SAP B1 MCP Server',
version: process.env.npm_package_version || '1.0.0',
nodeVersion: process.version,
pid: process.pid
};
return new Logger(level, context);
}
/**
* Format error for logging
*/
static formatError(error) {
if (error instanceof Error) {
return {
message: error.message,
stack: error.stack,
code: error.code
};
}
return {
message: String(error)
};
}
/**
* Sanitize sensitive data for logging
*/
static sanitize(data) {
if (typeof data !== 'object' || data === null) {
return data;
}
const sanitized = Array.isArray(data) ? [...data] : { ...data };
// List of sensitive field names to mask
const sensitiveFields = [
'password', 'token', 'secret', 'key', 'auth', 'authorization',
'sessionid', 'session_id', 'cookie', 'passwd', 'pwd'
];
const sanitizeValue = (obj) => {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(sanitizeValue);
}
const result = {};
for (const [key, value] of Object.entries(obj)) {
if (sensitiveFields.some(field => key.toLowerCase().includes(field))) {
result[key] = '***masked***';
}
else if (typeof value === 'object') {
result[key] = sanitizeValue(value);
}
else {
result[key] = value;
}
}
return result;
};
return sanitizeValue(sanitized);
}
}
// Export default logger instance
export const logger = Logger.fromEnvironment();
//# sourceMappingURL=logger.js.map