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