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