diff --git a/src/logging.js b/src/logging.js index 3ed9d90a4f3977f8014589d6214d09a8c6f2270b..c6a99bcc57b1d2957e55e5a96251c8b54fd4ea42 100644 --- a/src/logging.js +++ b/src/logging.js @@ -1,11 +1,16 @@ /** * Custom logging to create more useful output. + * Simply include this file at the top of other files to get extra logging logic. */ // System Imports. const chalk = require('chalk'); +const fs = require('fs'); const path = require('path'); +// User Imports. +const getCurrentDate = require('./helper_functions.js'); + /** * Essentially "upgrades" default Javascript console output to be more informative. @@ -25,39 +30,159 @@ const path = require('path'); Error.prepareStackTrace = originalPrepareStackTrace; let relativeFileName = path.relative(process.cwd(), callee.getFileName()); - - // This is where we actually prepend to our provided log text. + // Generate and log our text to console/file. + let prefix = ''; + let console_string = ''; + let log_string = ''; if (methodName == 'debug') { - // Prepend text for DEBUG level. - var prefix = ` ${chalk.green('[DEBUG]')} [${relativeFileName} ${callee.getLineNumber()}] `; + // Handling for DEBUG level. + + // Generate and print Console text. + prefix = ` ${chalk.green('[DEBUG]')} [${relativeFileName} ${callee.getLineNumber()}] `; + console_string = prefix.concat(firstArgument, ...otherArguments); + originalLoggingMethod(console_string); + + // Generate and print Log File text. + prefix = `${getCurrentDate()} [DEBUG] [${relativeFileName} ${callee.getLineNumber()}] `; + log_string = prefix.concat(firstArgument, ...otherArguments, '\n'); + write_to_file(log_string, 'debug'); } else if (methodName == 'info') { - // Prepend text for INFO level. - var prefix = ` ${chalk.blue('[INFO]')} [${relativeFileName} ${callee.getLineNumber()}] `; + // Handling for INFO level. + + // Generate and print Console text. + prefix = ` ${chalk.blue('[INFO]')} [${relativeFileName} ${callee.getLineNumber()}] `; + console_string = prefix.concat(firstArgument, ...otherArguments); + originalLoggingMethod(console_string); + + // Generate and print Log File text. + prefix = `${getCurrentDate()} [INFO] [${relativeFileName} ${callee.getLineNumber()}] `; + log_string = prefix.concat(firstArgument, ...otherArguments, '\n'); + write_to_file(log_string, 'info'); } else if (methodName == 'warning' || methodName == 'warn') { - // Prepend text for WARNING level. - var prefix = ` ${chalk.yellow('[WARN]')} [${relativeFileName} ${callee.getLineNumber()}] `; + // Handling for WARNING level. + + // Generate and print Console text. + prefix = ` ${chalk.yellow('[WARN]')} [${relativeFileName} ${callee.getLineNumber()}] `; + console_string = prefix.concat(firstArgument, ...otherArguments); + originalLoggingMethod(console_string); + + // Generate and print Log File text. + prefix = `${getCurrentDate()} [WARN] [${relativeFileName} ${callee.getLineNumber()}] `; + log_string = prefix.concat(firstArgument, ...otherArguments, '\n'); + write_to_file(log_string, 'warn'); } else if (methodName == 'error' || methodName == 'err') { // Prepend text for ERROR level. - var prefix = ` ${chalk.red('[ERROR]')} [${relativeFileName} ${callee.getLineNumber()}] `; + + // Generate and print Console text. + prefix = ` ${chalk.red('[ERROR]')} [${relativeFileName} ${callee.getLineNumber()}] `; + console_string = prefix.concat(firstArgument, ...otherArguments); + originalLoggingMethod(console_string); + + // Generate and print Log File text. + prefix = `${getCurrentDate()} [ERROR] [${relativeFileName} ${callee.getLineNumber()}] `; + log_string = prefix.concat(firstArgument, ...otherArguments, '\n'); + write_to_file(log_string, 'error'); } else if (methodName == 'log') { // LOG level does not get prepend text. - var prefix = ' '; + prefix = ' '; + console_string = prefix.concat(firstArgument, ...otherArguments); + originalLoggingMethod(console_string); } else { // Fallback prepend text for all other cases. - var prefix = ` [${methodName}] [${relativeFileName} ${callee.getLineNumber()}] `; + prefix = ` [${methodName}] [${relativeFileName} ${callee.getLineNumber()}] `; + console_string = prefix.concat(firstArgument, ...otherArguments); + originalLoggingMethod(console_string); } - - // More magic to generate the console output. - if (typeof firstArgument === 'string') { - originalLoggingMethod(prefix + firstArgument, ...otherArguments); - } else { - originalLoggingMethod(prefix, firstArgument, ...otherArguments); - } }; }); + + +/** + * Writes provided string to log files. + */ +function write_to_file(log_string, level) { + let directory = './logging/'; + let file_location = './logging/info.log'; + let log_level = 0; + + // Get appropriate level of logger. Based off of Python log levels. + // https://docs.python.org/3/library/logging.html + if (level == 'error') { + log_level = 40; + } else if (level == 'warn') { + log_level = 30; + } else if (level == 'info') { + log_level = 20; + } else if (level == 'debug') { + log_level = 10; + } + console.log('Log Level: ' + log_level); + + // Attempt to create logging folder. + fs.mkdir(directory, err => { + // Ignore "dir already exists" errors. Raise all others. + if (err && err.code != 'EEXIST') { + throw err; + } + }); + + // Attempt to write to appropriate files, based on logging level. + if (log_level >= 40) { + // Error level logging or higher. + fs.appendFile(directory.concat('error.log'), log_string, (err) => { + if (err) { + console.log(err); + throw err; + } + }); + } + if (log_level >= 30) { + // Warning level logging or higher. + fs.appendFile(directory.concat('warn.log'), log_string, (err) => { + if (err) { + console.log(err); + throw err; + } + }); + } + if (log_level >= 20) { + // Info level logging or higher. + fs.appendFile(directory.concat('info.log'), log_string, (err) => { + if (err) { + console.log(err); + throw err; + } + }); + } + if (log_level >= 10) { + // Debug level logging or higher. + fs.appendFile(directory.concat('debug.log'), log_string, (err) => { + if (err) { + console.log(err); + throw err; + } + }); + } +} + + +/** + * Simple test to make sure all loging levels work as expected. + * Should convert this to a proper unit test at a later date. + */ +function testLogLevels() { + console.debug('Debug level test'); + console.info('Info level test.'); + console.warn('Warn level test.'); + console.error('Error level test.'); + console.log('Log/default level test.'); +} + + +module.exports = testLogLevels;