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