index.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /**
  2. * tFunk for colours/compiler
  3. */
  4. var tfunk = require("tfunk");
  5. /**
  6. * Lodash clonedeep & merge
  7. */
  8. var _ = require("./lodash.custom");
  9. /**
  10. * Default configuration.
  11. * Can be overridden in first constructor arg
  12. */
  13. var defaults = {
  14. /**
  15. * Initial log level
  16. */
  17. level: "info",
  18. /**
  19. * Prefix for logger
  20. */
  21. prefix: "",
  22. /**
  23. * Available levels and their score
  24. */
  25. levels: {
  26. "trace": 100,
  27. "debug": 200,
  28. "warn": 300,
  29. "info": 400,
  30. "error": 500
  31. },
  32. /**
  33. * Default prefixes
  34. */
  35. prefixes: {
  36. "trace": "[trace] ",
  37. "debug": "{yellow:[debug]} ",
  38. "info": "{cyan:[info]} ",
  39. "warn": "{magenta:[warn]} ",
  40. "error": "{red:[error]} "
  41. },
  42. /**
  43. * Should easy log statement be prefixed with the level?
  44. */
  45. useLevelPrefixes: false
  46. };
  47. /**
  48. * @param {Object} config
  49. * @constructor
  50. */
  51. var Logger = function(config) {
  52. if (!(this instanceof Logger)) {
  53. return new Logger(config);
  54. }
  55. config = config || {};
  56. this._mute = false;
  57. this.config = _.merge({}, defaults, config);
  58. this.addLevelMethods(this.config.levels);
  59. this.compiler = new tfunk.Compiler(this.config.custom || {}, this.config);
  60. this._memo = {};
  61. return this;
  62. };
  63. /**
  64. * Set an option once
  65. * @param path
  66. * @param value
  67. */
  68. Logger.prototype.setOnce = function (path, value) {
  69. if (typeof this.config[path] !== "undefined") {
  70. if (typeof this._memo[path] === "undefined") {
  71. this._memo[path] = this.config[path];
  72. }
  73. this.config[path] = value;
  74. }
  75. return this;
  76. };
  77. /**
  78. * Add convenience method such as
  79. * logger.warn("msg")
  80. * logger.error("msg")
  81. * logger.info("msg")
  82. *
  83. * instead of
  84. * logger.log("warn", "msg");
  85. * @param items
  86. */
  87. Logger.prototype.addLevelMethods = function (items) {
  88. Object.keys(items).forEach(function (item) {
  89. if (!this[item]) {
  90. this[item] = function () {
  91. var args = Array.prototype.slice.call(arguments);
  92. this.log.apply(this, args);
  93. return this;
  94. }.bind(this, item);
  95. }
  96. }, this);
  97. };
  98. /**
  99. * Reset the state of the logger.
  100. * @returns {Logger}
  101. */
  102. Logger.prototype.reset = function () {
  103. this.setLevel(defaults.level)
  104. .setLevelPrefixes(defaults.useLevelPrefixes)
  105. .mute(false);
  106. return this;
  107. };
  108. /**
  109. * @param {String} level
  110. * @returns {boolean}
  111. */
  112. Logger.prototype.canLog = function (level) {
  113. return this.config.levels[level] >= this.config.levels[this.config.level] && !this._mute;
  114. };
  115. /**
  116. * Log to the console with prefix
  117. * @param {String} level
  118. * @param {String} msg
  119. * @returns {Logger}
  120. */
  121. Logger.prototype.log = function (level, msg) {
  122. var args = Array.prototype.slice.call(arguments);
  123. this.logOne(args, msg, level);
  124. return this;
  125. };
  126. /**
  127. * Set the log level
  128. * @param {String} level
  129. * @returns {Logger}
  130. */
  131. Logger.prototype.setLevel = function (level) {
  132. this.config.level = level;
  133. return this;
  134. };
  135. /**
  136. * @param {boolean} state
  137. * @returns {Logger}
  138. */
  139. Logger.prototype.setLevelPrefixes = function (state) {
  140. this.config.useLevelPrefixes = state;
  141. return this;
  142. };
  143. /**
  144. * @param prefix
  145. */
  146. Logger.prototype.setPrefix = function (prefix) {
  147. if (typeof prefix === "string") {
  148. this.compiler.prefix = this.compiler.compile(prefix, true);
  149. }
  150. if (typeof prefix === "function") {
  151. this.compiler.prefix = prefix;
  152. }
  153. };
  154. /**
  155. * @param {String} level
  156. * @param {String} msg
  157. * @returns {Logger}
  158. */
  159. Logger.prototype.unprefixed = function (level, msg) {
  160. var args = Array.prototype.slice.call(arguments);
  161. this.logOne(args, msg, level, true);
  162. return this;
  163. };
  164. /**
  165. * @param {Array} args
  166. * @param {String} msg
  167. * @param {String} level
  168. * @param {boolean} [unprefixed]
  169. * @returns {Logger}
  170. */
  171. Logger.prototype.logOne = function (args, msg, level, unprefixed) {
  172. if (!this.canLog(level)) {
  173. return;
  174. }
  175. args = args.slice(2);
  176. if (this.config.useLevelPrefixes && !unprefixed) {
  177. msg = this.config.prefixes[level] + msg;
  178. }
  179. msg = this.compiler.compile(msg, unprefixed);
  180. args.unshift(msg);
  181. console.log.apply(console, args);
  182. this.resetTemps();
  183. return this;
  184. };
  185. /**
  186. * Reset any temporary value
  187. */
  188. Logger.prototype.resetTemps = function () {
  189. Object.keys(this._memo).forEach(function (key) {
  190. this.config[key] = this._memo[key];
  191. }, this);
  192. };
  193. /**
  194. * Mute the logger
  195. */
  196. Logger.prototype.mute = function (bool) {
  197. this._mute = bool;
  198. return this;
  199. };
  200. /**
  201. * Clone the instance to share setup
  202. * @param opts
  203. * @returns {Logger}
  204. */
  205. Logger.prototype.clone = function (opts) {
  206. var config = _.cloneDeep(this.config);
  207. if (typeof opts === "function") {
  208. config = opts(config) || {};
  209. } else {
  210. config = _.merge({}, config, opts || {});
  211. }
  212. return new Logger(config);
  213. };
  214. module.exports.Logger = Logger;
  215. module.exports.compile = tfunk;