log4js.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. 'use strict';
  2. /**
  3. * @fileoverview log4js is a library to log in JavaScript in similar manner
  4. * than in log4j for Java (but not really).
  5. *
  6. * <h3>Example:</h3>
  7. * <pre>
  8. * const logging = require('log4js');
  9. * const log = logging.getLogger('some-category');
  10. *
  11. * //call the log
  12. * log.trace('trace me' );
  13. * </pre>
  14. *
  15. * NOTE: the authors below are the original browser-based log4js authors
  16. * don't try to contact them about bugs in this version :)
  17. * @author Stephan Strittmatter - http://jroller.com/page/stritti
  18. * @author Seth Chisamore - http://www.chisamore.com
  19. * @since 2005-05-20
  20. * Website: http://log4js.berlios.de
  21. */
  22. const debug = require('debug')('log4js:main');
  23. const fs = require('fs');
  24. const CircularJSON = require('circular-json');
  25. const configuration = require('./configuration');
  26. const layouts = require('./layouts');
  27. const levels = require('./levels');
  28. const appenders = require('./appenders');
  29. const categories = require('./categories');
  30. const Logger = require('./logger');
  31. const clustering = require('./clustering');
  32. const connectLogger = require('./connect-logger');
  33. let enabled = false;
  34. function sendLogEventToAppender(logEvent) {
  35. if (!enabled) return;
  36. debug('Received log event ', logEvent);
  37. const categoryAppenders = categories.appendersForCategory(logEvent.categoryName);
  38. categoryAppenders.forEach((appender) => {
  39. appender(logEvent);
  40. });
  41. }
  42. function loadConfigurationFile(filename) {
  43. if (filename) {
  44. debug(`Loading configuration from ${filename}`);
  45. return JSON.parse(fs.readFileSync(filename, 'utf8'));
  46. }
  47. return filename;
  48. }
  49. function configure(configurationFileOrObject) {
  50. let configObject = configurationFileOrObject;
  51. if (typeof configObject === 'string') {
  52. configObject = loadConfigurationFile(configurationFileOrObject);
  53. }
  54. debug(`Configuration is ${configObject}`);
  55. // Fix for #743 - clone the config to avoid that is not writable in appenders
  56. // When the node-config module is used, config object becomes immutable.
  57. const clonedConfigObject = CircularJSON.parse(CircularJSON.stringify(configObject));
  58. configuration.configure(clonedConfigObject);
  59. clustering.onMessage(sendLogEventToAppender);
  60. enabled = true;
  61. return log4js;
  62. }
  63. /**
  64. * Shutdown all log appenders. This will first disable all writing to appenders
  65. * and then call the shutdown function each appender.
  66. *
  67. * @params {Function} cb - The callback to be invoked once all appenders have
  68. * shutdown. If an error occurs, the callback will be given the error object
  69. * as the first argument.
  70. */
  71. function shutdown(cb) {
  72. debug('Shutdown called. Disabling all log writing.');
  73. // First, disable all writing to appenders. This prevents appenders from
  74. // not being able to be drained because of run-away log writes.
  75. enabled = false;
  76. // Call each of the shutdown functions in parallel
  77. const appendersToCheck = Array.from(appenders.values());
  78. const shutdownFunctions = appendersToCheck.reduceRight((accum, next) => (next.shutdown ? accum + 1 : accum), 0);
  79. let completed = 0;
  80. let error;
  81. debug(`Found ${shutdownFunctions} appenders with shutdown functions.`);
  82. function complete(err) {
  83. error = error || err;
  84. completed += 1;
  85. debug(`Appender shutdowns complete: ${completed} / ${shutdownFunctions}`);
  86. if (completed >= shutdownFunctions) {
  87. debug('All shutdown functions completed.');
  88. cb(error);
  89. }
  90. }
  91. if (shutdownFunctions === 0) {
  92. debug('No appenders with shutdown functions found.');
  93. return cb();
  94. }
  95. appendersToCheck.filter(a => a.shutdown).forEach(a => a.shutdown(complete));
  96. return null;
  97. }
  98. /**
  99. * Get a logger instance.
  100. * @static
  101. * @param loggerCategoryName
  102. * @return {Logger} instance of logger for the category
  103. */
  104. function getLogger(category) {
  105. if (!enabled) {
  106. configure(process.env.LOG4JS_CONFIG || {
  107. appenders: { out: { type: 'stdout' } },
  108. categories: { default: { appenders: ['out'], level: 'OFF' } }
  109. });
  110. }
  111. return new Logger(category || 'default');
  112. }
  113. /**
  114. * @name log4js
  115. * @namespace Log4js
  116. * @property getLogger
  117. * @property configure
  118. * @property shutdown
  119. */
  120. const log4js = {
  121. getLogger,
  122. configure,
  123. shutdown,
  124. connectLogger,
  125. levels,
  126. addLayout: layouts.addLayout
  127. };
  128. module.exports = log4js;