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