Source: lib/core/connection/logger.js

  1. 'use strict';
  2. var f = require('util').format,
  3. MongoError = require('../error').MongoError;
  4. // Filters for classes
  5. var classFilters = {};
  6. var filteredClasses = {};
  7. var level = null;
  8. // Save the process id
  9. var pid = process.pid;
  10. // current logger
  11. var currentLogger = null;
  12. /**
  13. * @callback Logger~loggerCallback
  14. * @param {string} msg message being logged
  15. * @param {object} state an object containing more metadata about the logging message
  16. */
  17. /**
  18. * Creates a new Logger instance
  19. * @class
  20. * @param {string} className The Class name associated with the logging instance
  21. * @param {object} [options=null] Optional settings.
  22. * @param {Logger~loggerCallback} [options.logger=null] Custom logger function;
  23. * @param {string} [options.loggerLevel=error] Override default global log level.
  24. */
  25. var Logger = function(className, options) {
  26. if (!(this instanceof Logger)) return new Logger(className, options);
  27. options = options || {};
  28. // Current reference
  29. this.className = className;
  30. // Current logger
  31. if (options.logger) {
  32. currentLogger = options.logger;
  33. } else if (currentLogger == null) {
  34. currentLogger = console.log;
  35. }
  36. // Set level of logging, default is error
  37. if (options.loggerLevel) {
  38. level = options.loggerLevel || 'error';
  39. }
  40. // Add all class names
  41. if (filteredClasses[this.className] == null) classFilters[this.className] = true;
  42. };
  43. /**
  44. * Log a message at the debug level
  45. * @method
  46. * @param {string} message The message to log
  47. * @param {object} object additional meta data to log
  48. * @return {null}
  49. */
  50. Logger.prototype.debug = function(message, object) {
  51. if (
  52. this.isDebug() &&
  53. ((Object.keys(filteredClasses).length > 0 && filteredClasses[this.className]) ||
  54. (Object.keys(filteredClasses).length === 0 && classFilters[this.className]))
  55. ) {
  56. var dateTime = new Date().getTime();
  57. var msg = f('[%s-%s:%s] %s %s', 'DEBUG', this.className, pid, dateTime, message);
  58. var state = {
  59. type: 'debug',
  60. message: message,
  61. className: this.className,
  62. pid: pid,
  63. date: dateTime
  64. };
  65. if (object) state.meta = object;
  66. currentLogger(msg, state);
  67. }
  68. };
  69. /**
  70. * Log a message at the warn level
  71. * @method
  72. * @param {string} message The message to log
  73. * @param {object} object additional meta data to log
  74. * @return {null}
  75. */
  76. (Logger.prototype.warn = function(message, object) {
  77. if (
  78. this.isWarn() &&
  79. ((Object.keys(filteredClasses).length > 0 && filteredClasses[this.className]) ||
  80. (Object.keys(filteredClasses).length === 0 && classFilters[this.className]))
  81. ) {
  82. var dateTime = new Date().getTime();
  83. var msg = f('[%s-%s:%s] %s %s', 'WARN', this.className, pid, dateTime, message);
  84. var state = {
  85. type: 'warn',
  86. message: message,
  87. className: this.className,
  88. pid: pid,
  89. date: dateTime
  90. };
  91. if (object) state.meta = object;
  92. currentLogger(msg, state);
  93. }
  94. }),
  95. /**
  96. * Log a message at the info level
  97. * @method
  98. * @param {string} message The message to log
  99. * @param {object} object additional meta data to log
  100. * @return {null}
  101. */
  102. (Logger.prototype.info = function(message, object) {
  103. if (
  104. this.isInfo() &&
  105. ((Object.keys(filteredClasses).length > 0 && filteredClasses[this.className]) ||
  106. (Object.keys(filteredClasses).length === 0 && classFilters[this.className]))
  107. ) {
  108. var dateTime = new Date().getTime();
  109. var msg = f('[%s-%s:%s] %s %s', 'INFO', this.className, pid, dateTime, message);
  110. var state = {
  111. type: 'info',
  112. message: message,
  113. className: this.className,
  114. pid: pid,
  115. date: dateTime
  116. };
  117. if (object) state.meta = object;
  118. currentLogger(msg, state);
  119. }
  120. }),
  121. /**
  122. * Log a message at the error level
  123. * @method
  124. * @param {string} message The message to log
  125. * @param {object} object additional meta data to log
  126. * @return {null}
  127. */
  128. (Logger.prototype.error = function(message, object) {
  129. if (
  130. this.isError() &&
  131. ((Object.keys(filteredClasses).length > 0 && filteredClasses[this.className]) ||
  132. (Object.keys(filteredClasses).length === 0 && classFilters[this.className]))
  133. ) {
  134. var dateTime = new Date().getTime();
  135. var msg = f('[%s-%s:%s] %s %s', 'ERROR', this.className, pid, dateTime, message);
  136. var state = {
  137. type: 'error',
  138. message: message,
  139. className: this.className,
  140. pid: pid,
  141. date: dateTime
  142. };
  143. if (object) state.meta = object;
  144. currentLogger(msg, state);
  145. }
  146. }),
  147. /**
  148. * Is the logger set at info level
  149. * @method
  150. * @return {boolean}
  151. */
  152. (Logger.prototype.isInfo = function() {
  153. return level === 'info' || level === 'debug';
  154. }),
  155. /**
  156. * Is the logger set at error level
  157. * @method
  158. * @return {boolean}
  159. */
  160. (Logger.prototype.isError = function() {
  161. return level === 'error' || level === 'info' || level === 'debug';
  162. }),
  163. /**
  164. * Is the logger set at error level
  165. * @method
  166. * @return {boolean}
  167. */
  168. (Logger.prototype.isWarn = function() {
  169. return level === 'error' || level === 'warn' || level === 'info' || level === 'debug';
  170. }),
  171. /**
  172. * Is the logger set at debug level
  173. * @method
  174. * @return {boolean}
  175. */
  176. (Logger.prototype.isDebug = function() {
  177. return level === 'debug';
  178. });
  179. /**
  180. * Resets the logger to default settings, error and no filtered classes
  181. * @method
  182. * @return {null}
  183. */
  184. Logger.reset = function() {
  185. level = 'error';
  186. filteredClasses = {};
  187. };
  188. /**
  189. * Get the current logger function
  190. * @method
  191. * @return {Logger~loggerCallback}
  192. */
  193. Logger.currentLogger = function() {
  194. return currentLogger;
  195. };
  196. /**
  197. * Set the current logger function
  198. * @method
  199. * @param {Logger~loggerCallback} logger Logger function.
  200. * @return {null}
  201. */
  202. Logger.setCurrentLogger = function(logger) {
  203. if (typeof logger !== 'function') throw new MongoError('current logger must be a function');
  204. currentLogger = logger;
  205. };
  206. /**
  207. * Set what classes to log.
  208. * @method
  209. * @param {string} type The type of filter (currently only class)
  210. * @param {string[]} values The filters to apply
  211. * @return {null}
  212. */
  213. Logger.filter = function(type, values) {
  214. if (type === 'class' && Array.isArray(values)) {
  215. filteredClasses = {};
  216. values.forEach(function(x) {
  217. filteredClasses[x] = true;
  218. });
  219. }
  220. };
  221. /**
  222. * Set the current log level
  223. * @method
  224. * @param {string} level Set current log level (debug, info, error)
  225. * @return {null}
  226. */
  227. Logger.setLevel = function(_level) {
  228. if (_level !== 'info' && _level !== 'error' && _level !== 'debug' && _level !== 'warn') {
  229. throw new Error(f('%s is an illegal logging level', _level));
  230. }
  231. level = _level;
  232. };
  233. module.exports = Logger;