UNPKG

3.37 kBJavaScriptView Raw
1
2/* globals console,module,process */
3/* jshint -W097 */
4
5"use strict";
6
7var enableRe
8, currentLevel = 2
9, namespaces = log.namespaces = {}
10, slice = [].slice
11, date = new Date()
12, color = (process.stdout || /* c8 ignore next */ process).isTTY && process.argv.indexOf("--no-color") < 0
13, green = "\x1b[32m"
14, reset = "\x1b[0m"
15
16if (!color) green = reset = ""
17
18log.levels = {
19 "error": 0,
20 "warn": 1,
21 "info": 2,
22 "debug": 3
23}
24
25module.exports = log
26
27log.debug = debug
28log.level = level
29// expose nop for testing purpose
30log.nop = function nop() {}
31log.format = format
32
33log.rawStream = null
34log.prettyStream = process.stdout
35log.errorStream = process.stderr
36
37
38
39function log(name, enable) {
40 var binded = namespaces[name] || (namespaces[name] = function log() {
41 if (log.enabled === true) log.debug.apply(log, arguments)
42 })
43 binded.enabled = typeof enable === "boolean" ? enable : !!(enableRe && enableRe.test(name))
44 setLevels(name)
45 return binded
46}
47
48function level(newLevel) {
49 if (newLevel >= 0 && newLevel < Object.keys(log.levels).length) {
50 currentLevel = newLevel | 0
51 }
52 Object.keys(namespaces).forEach(setLevels)
53 return currentLevel
54}
55
56function setLevels(name) {
57 var level
58 , levels = log.levels
59 , binded = namespaces[name]
60 for (level in levels) {
61 binded[level] = (
62 binded.enabled || levels[level] <= currentLevel ?
63 Log.bind(binded, name, level) :
64 log.nop
65 )
66 }
67}
68
69function Log(name, level, msg) {
70 var args = arguments.length > 3 ? slice.call(arguments, 3) : null
71 , now = date.setTime(Date.now())
72 , tmp = now - (this.last || now)
73 , out = date.toISOString() + " " + name
74
75 if (log.rawStream) {
76 log.rawStream.write([now, name, level, msg, args])
77 }
78
79 if (msg instanceof Error) {
80 if (log.errorStream) {
81 log.errorStream.write(
82 date.toISOString() + " " + name + " " + msg.stack + "\n"
83 )
84 msg = msg.message
85 } else {
86 msg = msg.stack || msg.message
87 }
88 }
89
90 out += " " + (args === null ? msg : format(msg, args)) + green + " +" + (
91 tmp > 36e4 ? (tmp / 36e4).toFixed(1) + "h" :
92 tmp > 6e4 ? (tmp / 6e4).toFixed(1) + "m" :
93 tmp > 1e3 ? (tmp / 1e3 | 0) + "s" :
94 tmp + "ms"
95 ).replace(".0", "") + reset
96
97 if (log.prettyStream) {
98 log.prettyStream.write(out + "\n")
99 } else {
100 console.log(out)
101 }
102
103 this.last = now
104}
105
106function debug(filter) {
107
108 enableRe = filter && RegExp( // jshint ignore:line
109 "^(" +
110 filter
111 .replace(/[.+?^${}()|[\]\\]/g, "\\$&")
112 .replace(/\*/g, ".*?")
113 .replace(/[\s,]+/g, "|") +
114 ")$"
115 )
116 Object.keys(namespaces).forEach(log)
117}
118
119function format(msg, args) {
120 var tmp
121 , out = ""
122 , i = 0
123 , last = 0
124 , replaced = 0
125 , msgi = msg.length - 1
126 , argi = args.length
127
128 for (; i < msgi && replaced < argi; ) {
129 // 37=% 115=s 102=f 100=d 105=i 111=o
130 if (msg.charCodeAt(i++) === 37) {
131 tmp = msg.charCodeAt(i)
132 if (tmp === 115 || tmp === 100 || tmp === 102) {
133 out += msg.slice(last, i - 1) + args[replaced++]
134 last = ++i
135 } else if (tmp === 105) {
136 out += msg.slice(last, i - 1) + (args[replaced++]|0)
137 last = ++i
138 } else if (tmp === 111) {
139 out += msg.slice(last, i - 1) + JSON.stringify(args[replaced++])
140 last = ++i
141 } else if (tmp === 37) {
142 out += msg.slice(last, i)
143 last = ++i
144 }
145 }
146 }
147 if (last <= msgi) {
148 out += msg.slice(last)
149 }
150
151 if (replaced < argi) {
152 for (; replaced < argi; ) {
153 out += " " + args[replaced++]
154 }
155 }
156 return out
157}
158
159
160
161