@0xobelisk/graphql-server
Version:
Tookit for interacting with dubhe graphql server
230 lines • 9.23 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logGraphQLQuery = exports.logWebSocketEvent = exports.logDatabaseOperation = exports.logExpress = exports.logPerformance = exports.createComponentLogger = exports.perfLogger = exports.authLogger = exports.systemLogger = exports.subscriptionLogger = exports.gqlLogger = exports.wsLogger = exports.httpLogger = exports.serverLogger = exports.dbLogger = exports.Logger = void 0;
const pino_1 = __importDefault(require("pino"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
/**
* High-performance logging system based on Pino
*/
class Logger {
pinoInstance;
config;
constructor(config = {}) {
this.config = {
level: config.level || process.env.LOG_LEVEL || 'info',
service: config.service || 'dubhe-graphql-server',
component: config.component || 'default',
enableFileLogging: config.enableFileLogging !== false,
logsDir: config.logsDir || path_1.default.join(process.cwd(), 'logs')
};
this.ensureLogsDirectory();
this.pinoInstance = this.createPinoInstance();
this.setupExceptionHandlers();
}
/**
* Ensure logs directory exists
*/
ensureLogsDirectory() {
if (this.config.enableFileLogging && !fs_1.default.existsSync(this.config.logsDir)) {
fs_1.default.mkdirSync(this.config.logsDir, { recursive: true });
}
}
/**
* Create Pino instance
*/
createPinoInstance() {
const pinoOptions = {
level: this.config.level,
base: {
service: this.config.service,
pid: process.pid
},
timestamp: pino_1.default.stdTimeFunctions.isoTime,
formatters: {
level(label) {
return { level: label };
}
},
serializers: {
error: pino_1.default.stdSerializers.err
}
};
// If file logging is enabled, use multistream
if (this.config.enableFileLogging) {
const streams = [
// Pretty print to console
{
stream: pino_1.default.transport({
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'yyyy-mm-dd HH:MM:ss.l',
ignore: 'pid,hostname,service,component',
messageFormat: '[{component}]: {msg}',
singleLine: true,
hideObject: false
}
})
},
// JSON format to file
{
stream: pino_1.default.destination({
dest: path_1.default.join(this.config.logsDir, 'combined.log'),
sync: false
})
}
];
return (0, pino_1.default)(pinoOptions, pino_1.default.multistream(streams));
}
// Only output to console in pretty format
return (0, pino_1.default)({
...pinoOptions,
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'yyyy-mm-dd HH:MM:ss.l',
ignore: 'pid,hostname,service',
messageFormat: '[{component}]: {msg}',
singleLine: true,
hideObject: false
}
}
});
}
/**
* Setup exception handlers
*/
setupExceptionHandlers() {
process.on('uncaughtException', (error) => {
this.pinoInstance.fatal({ error }, 'Uncaught Exception');
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
this.pinoInstance.fatal({ reason, promise }, 'Unhandled Promise Rejection');
process.exit(1);
});
}
/**
* Create component logger with context
*/
createComponentLogger(component) {
const componentLogger = this.pinoInstance.child({ component });
return {
debug: (message, meta) => componentLogger.debug(meta || {}, message),
info: (message, meta) => componentLogger.info(meta || {}, message),
warn: (message, meta) => componentLogger.warn(meta || {}, message),
error: (message, error, meta) => {
const errorData = error instanceof Error
? {
error: {
message: error.message,
stack: error.stack,
name: error.name
},
...meta
}
: { error, ...meta };
componentLogger.error(errorData, message);
}
};
}
/**
* Get raw Pino instance
*/
getPinoInstance() {
return this.pinoInstance;
}
/**
* Log performance metrics
*/
logPerformance(operation, startTime, meta) {
const duration = Date.now() - startTime;
const perfLogger = this.createComponentLogger('performance');
perfLogger.info(operation, {
duration: `${duration}ms`,
...meta
});
}
/**
* Log Express HTTP requests
*/
logExpress(method, path, statusCode, startTime, meta) {
const duration = Date.now() - startTime;
const httpLogger = this.createComponentLogger('express');
const message = `${method} ${path} - ${statusCode} (${duration}ms)`;
// Choose log level based on status code
if (statusCode >= 500) {
httpLogger.error(message, meta);
}
else if (statusCode >= 400) {
httpLogger.warn(message, meta);
}
else {
httpLogger.info(message, meta);
}
}
/**
* Log database operations
*/
logDatabaseOperation(operation, table, meta) {
const dbLogger = this.createComponentLogger('database');
dbLogger.info(`Database operation: ${operation}`, {
table,
...meta
});
}
/**
* Log WebSocket events
*/
logWebSocketEvent(event, clientCount, meta) {
const wsLogger = this.createComponentLogger('websocket');
wsLogger.info(`WebSocket event: ${event}`, {
clientCount,
...meta
});
}
/**
* Log GraphQL queries
*/
logGraphQLQuery(operation, query, variables) {
const gqlLogger = this.createComponentLogger('graphql');
gqlLogger.info(`GraphQL ${operation}`, {
query: query?.substring(0, 200) + (query && query.length > 200 ? '...' : ''),
variableCount: variables ? Object.keys(variables).length : 0
});
}
}
exports.Logger = Logger;
// Create default logger instance
const defaultLogger = new Logger();
// Export predefined component loggers (maintain backward compatibility)
exports.dbLogger = defaultLogger.createComponentLogger('database');
exports.serverLogger = defaultLogger.createComponentLogger('server');
exports.httpLogger = defaultLogger.createComponentLogger('express');
exports.wsLogger = defaultLogger.createComponentLogger('websocket');
exports.gqlLogger = defaultLogger.createComponentLogger('graphql');
exports.subscriptionLogger = defaultLogger.createComponentLogger('subscription');
exports.systemLogger = defaultLogger.createComponentLogger('system');
exports.authLogger = defaultLogger.createComponentLogger('auth');
exports.perfLogger = defaultLogger.createComponentLogger('performance');
// Export utility functions (maintain backward compatibility)
const createComponentLogger = (component) => defaultLogger.createComponentLogger(component);
exports.createComponentLogger = createComponentLogger;
const logPerformance = (operation, startTime, meta) => defaultLogger.logPerformance(operation, startTime, meta);
exports.logPerformance = logPerformance;
const logExpress = (method, path, statusCode, startTime, meta) => defaultLogger.logExpress(method, path, statusCode, startTime, meta);
exports.logExpress = logExpress;
const logDatabaseOperation = (operation, table, meta) => defaultLogger.logDatabaseOperation(operation, table, meta);
exports.logDatabaseOperation = logDatabaseOperation;
const logWebSocketEvent = (event, clientCount, meta) => defaultLogger.logWebSocketEvent(event, clientCount, meta);
exports.logWebSocketEvent = logWebSocketEvent;
const logGraphQLQuery = (operation, query, variables) => defaultLogger.logGraphQLQuery(operation, query, variables);
exports.logGraphQLQuery = logGraphQLQuery;
// Default export (maintain backward compatibility)
exports.default = defaultLogger.getPinoInstance();
//# sourceMappingURL=index.js.map