All files / src/utils logger.js

0% Statements 0/30
0% Branches 0/14
0% Functions 0/9
0% Lines 0/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126                                                                                                                                                                                                                                                           
/**
 * ApplicationLoggerService - Structured JSON logging to stderr with log level support
 *
 * This service provides logging functions that output structured JSON exclusively to process.stderr.
 * It respects the LOG_LEVEL environment variable for filtering logs based on severity.
 */
 
// Log levels with numeric values for comparison
const LOG_LEVELS = {
  debug: 0,
  info: 1,
  warn: 2,
  error: 3,
};
 
// Get log level from environment or default to 'info'
const getCurrentLogLevel = () => {
  const logLevel = process.env.LOG_LEVEL?.toLowerCase() || "info";
  return LOG_LEVELS[logLevel] !== undefined ? logLevel : "info";
};
 
/**
 * Check if a given log level should be logged based on the current log level setting
 * @param {string} level - The log level to check
 * @returns {boolean} - Whether the log should be output
 */
const shouldLog = (level) => {
  const currentLevel = LOG_LEVELS[getCurrentLogLevel()];
  const targetLevel = LOG_LEVELS[level];
  return targetLevel >= currentLevel;
};
 
/**
 * Process message or error object to ensure proper serialization
 * @param {string|Error} message - Message string or Error object
 * @returns {Object} - Processed message object
 */
const processMessage = (message) => {
  if (message instanceof Error) {
    return {
      message: message.message,
      stack: message.stack,
    };
  }
  return { message };
};
 
/**
 * Process context object, handling Error objects specially
 * @param {Object|Error|undefined} context - Optional context object
 * @returns {Object|undefined} - Processed context
 */
const processContext = (context) => {
  if (!context) return undefined;
 
  if (context instanceof Error) {
    return {
      error: {
        message: context.message,
        stack: context.stack,
      },
    };
  }
 
  return context;
};
 
/**
 * Core logging function
 * @param {string} level - Log level
 * @param {string|Error} message - Log message or Error object
 * @param {Object} [context] - Optional context data
 */
const log = (level, message, context) => {
  if (!shouldLog(level)) return;
 
  const processedMessage = processMessage(message);
  const processedContext = processContext(context);
 
  const logObject = {
    timestamp: new Date().toISOString(),
    level,
    ...processedMessage,
    ...(processedContext ? { context: processedContext } : {}),
  };
 
  // Write to stderr as JSON with newline
  process.stderr.write(JSON.stringify(logObject) + "\n");
};
 
/**
 * Logger object with methods for different log levels
 */
const logger = {
  /**
   * Log debug message
   * @param {string|Error} message - Debug message or Error
   * @param {Object} [context] - Optional context
   */
  debug: (message, context) => log("debug", message, context),
 
  /**
   * Log informational message
   * @param {string|Error} message - Info message or Error
   * @param {Object} [context] - Optional context
   */
  info: (message, context) => log("info", message, context),
 
  /**
   * Log warning message
   * @param {string|Error} message - Warning message or Error
   * @param {Object} [context] - Optional context
   */
  warn: (message, context) => log("warn", message, context),
 
  /**
   * Log error message
   * @param {string|Error} message - Error message or Error object
   * @param {Object} [context] - Optional context
   */
  error: (message, context) => log("error", message, context),
};
 
// Export the logger instance
export default logger;