|
1 /*** |
|
2 |
|
3 MochiKit.Logging 1.4 |
|
4 |
|
5 See <http://mochikit.com/> for documentation, downloads, license, etc. |
|
6 |
|
7 (c) 2005 Bob Ippolito. All rights Reserved. |
|
8 |
|
9 ***/ |
|
10 |
|
11 if (typeof(dojo) != 'undefined') { |
|
12 dojo.provide('MochiKit.Logging'); |
|
13 dojo.require('MochiKit.Base'); |
|
14 } |
|
15 |
|
16 if (typeof(JSAN) != 'undefined') { |
|
17 JSAN.use("MochiKit.Base", []); |
|
18 } |
|
19 |
|
20 try { |
|
21 if (typeof(MochiKit.Base) == 'undefined') { |
|
22 throw ""; |
|
23 } |
|
24 } catch (e) { |
|
25 throw "MochiKit.Logging depends on MochiKit.Base!"; |
|
26 } |
|
27 |
|
28 if (typeof(MochiKit.Logging) == 'undefined') { |
|
29 MochiKit.Logging = {}; |
|
30 } |
|
31 |
|
32 MochiKit.Logging.NAME = "MochiKit.Logging"; |
|
33 MochiKit.Logging.VERSION = "1.4"; |
|
34 MochiKit.Logging.__repr__ = function () { |
|
35 return "[" + this.NAME + " " + this.VERSION + "]"; |
|
36 }; |
|
37 |
|
38 MochiKit.Logging.toString = function () { |
|
39 return this.__repr__(); |
|
40 }; |
|
41 |
|
42 |
|
43 MochiKit.Logging.EXPORT = [ |
|
44 "LogLevel", |
|
45 "LogMessage", |
|
46 "Logger", |
|
47 "alertListener", |
|
48 "logger", |
|
49 "log", |
|
50 "logError", |
|
51 "logDebug", |
|
52 "logFatal", |
|
53 "logWarning" |
|
54 ]; |
|
55 |
|
56 |
|
57 MochiKit.Logging.EXPORT_OK = [ |
|
58 "logLevelAtLeast", |
|
59 "isLogMessage", |
|
60 "compareLogMessage" |
|
61 ]; |
|
62 |
|
63 |
|
64 /** @id MochiKit.Logging.LogMessage */ |
|
65 MochiKit.Logging.LogMessage = function (num, level, info) { |
|
66 this.num = num; |
|
67 this.level = level; |
|
68 this.info = info; |
|
69 this.timestamp = new Date(); |
|
70 }; |
|
71 |
|
72 MochiKit.Logging.LogMessage.prototype = { |
|
73 /** @id MochiKit.Logging.LogMessage.prototype.repr */ |
|
74 repr: function () { |
|
75 var m = MochiKit.Base; |
|
76 return 'LogMessage(' + |
|
77 m.map( |
|
78 m.repr, |
|
79 [this.num, this.level, this.info] |
|
80 ).join(', ') + ')'; |
|
81 }, |
|
82 /** @id MochiKit.Logging.LogMessage.prototype.toString */ |
|
83 toString: MochiKit.Base.forwardCall("repr") |
|
84 }; |
|
85 |
|
86 MochiKit.Base.update(MochiKit.Logging, { |
|
87 /** @id MochiKit.Logging.logLevelAtLeast */ |
|
88 logLevelAtLeast: function (minLevel) { |
|
89 var self = MochiKit.Logging; |
|
90 if (typeof(minLevel) == 'string') { |
|
91 minLevel = self.LogLevel[minLevel]; |
|
92 } |
|
93 return function (msg) { |
|
94 var msgLevel = msg.level; |
|
95 if (typeof(msgLevel) == 'string') { |
|
96 msgLevel = self.LogLevel[msgLevel]; |
|
97 } |
|
98 return msgLevel >= minLevel; |
|
99 }; |
|
100 }, |
|
101 |
|
102 /** @id MochiKit.Logging.isLogMessage */ |
|
103 isLogMessage: function (/* ... */) { |
|
104 var LogMessage = MochiKit.Logging.LogMessage; |
|
105 for (var i = 0; i < arguments.length; i++) { |
|
106 if (!(arguments[i] instanceof LogMessage)) { |
|
107 return false; |
|
108 } |
|
109 } |
|
110 return true; |
|
111 }, |
|
112 |
|
113 /** @id MochiKit.Logging.compareLogMessage */ |
|
114 compareLogMessage: function (a, b) { |
|
115 return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]); |
|
116 }, |
|
117 |
|
118 /** @id MochiKit.Logging.alertListener */ |
|
119 alertListener: function (msg) { |
|
120 alert( |
|
121 "num: " + msg.num + |
|
122 "\nlevel: " + msg.level + |
|
123 "\ninfo: " + msg.info.join(" ") |
|
124 ); |
|
125 } |
|
126 |
|
127 }); |
|
128 |
|
129 /** @id MochiKit.Logging.Logger */ |
|
130 MochiKit.Logging.Logger = function (/* optional */maxSize) { |
|
131 this.counter = 0; |
|
132 if (typeof(maxSize) == 'undefined' || maxSize === null) { |
|
133 maxSize = -1; |
|
134 } |
|
135 this.maxSize = maxSize; |
|
136 this._messages = []; |
|
137 this.listeners = {}; |
|
138 this.useNativeConsole = false; |
|
139 }; |
|
140 |
|
141 MochiKit.Logging.Logger.prototype = { |
|
142 /** @id MochiKit.Logging.Logger.prototype.clear */ |
|
143 clear: function () { |
|
144 this._messages.splice(0, this._messages.length); |
|
145 }, |
|
146 |
|
147 /** @id MochiKit.Logging.Logger.prototype.logToConsole */ |
|
148 logToConsole: function (msg) { |
|
149 if (typeof(window) != "undefined" && window.console |
|
150 && window.console.log) { |
|
151 // Safari and FireBug 0.4 |
|
152 // Percent replacement is a workaround for cute Safari crashing bug |
|
153 window.console.log(msg.replace(/%/g, '\uFF05')); |
|
154 } else if (typeof(opera) != "undefined" && opera.postError) { |
|
155 // Opera |
|
156 opera.postError(msg); |
|
157 } else if (typeof(printfire) == "function") { |
|
158 // FireBug 0.3 and earlier |
|
159 printfire(msg); |
|
160 } else if (typeof(Debug) != "undefined" && Debug.writeln) { |
|
161 // IE Web Development Helper (?) |
|
162 // http://www.nikhilk.net/Entry.aspx?id=93 |
|
163 Debug.writeln(msg); |
|
164 } else if (typeof(debug) != "undefined" && debug.trace) { |
|
165 // Atlas framework (?) |
|
166 // http://www.nikhilk.net/Entry.aspx?id=93 |
|
167 debug.trace(msg); |
|
168 } |
|
169 }, |
|
170 |
|
171 /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */ |
|
172 dispatchListeners: function (msg) { |
|
173 for (var k in this.listeners) { |
|
174 var pair = this.listeners[k]; |
|
175 if (pair.ident != k || (pair[0] && !pair[0](msg))) { |
|
176 continue; |
|
177 } |
|
178 pair[1](msg); |
|
179 } |
|
180 }, |
|
181 |
|
182 /** @id MochiKit.Logging.Logger.prototype.addListener */ |
|
183 addListener: function (ident, filter, listener) { |
|
184 if (typeof(filter) == 'string') { |
|
185 filter = MochiKit.Logging.logLevelAtLeast(filter); |
|
186 } |
|
187 var entry = [filter, listener]; |
|
188 entry.ident = ident; |
|
189 this.listeners[ident] = entry; |
|
190 }, |
|
191 |
|
192 /** @id MochiKit.Logging.Logger.prototype.removeListener */ |
|
193 removeListener: function (ident) { |
|
194 delete this.listeners[ident]; |
|
195 }, |
|
196 |
|
197 /** @id MochiKit.Logging.Logger.prototype.baseLog */ |
|
198 baseLog: function (level, message/*, ...*/) { |
|
199 var msg = new MochiKit.Logging.LogMessage( |
|
200 this.counter, |
|
201 level, |
|
202 MochiKit.Base.extend(null, arguments, 1) |
|
203 ); |
|
204 this._messages.push(msg); |
|
205 this.dispatchListeners(msg); |
|
206 if (this.useNativeConsole) { |
|
207 this.logToConsole(msg.level + ": " + msg.info.join(" ")); |
|
208 } |
|
209 this.counter += 1; |
|
210 while (this.maxSize >= 0 && this._messages.length > this.maxSize) { |
|
211 this._messages.shift(); |
|
212 } |
|
213 }, |
|
214 |
|
215 /** @id MochiKit.Logging.Logger.prototype.getMessages */ |
|
216 getMessages: function (howMany) { |
|
217 var firstMsg = 0; |
|
218 if (!(typeof(howMany) == 'undefined' || howMany === null)) { |
|
219 firstMsg = Math.max(0, this._messages.length - howMany); |
|
220 } |
|
221 return this._messages.slice(firstMsg); |
|
222 }, |
|
223 |
|
224 /** @id MochiKit.Logging.Logger.prototype.getMessageText */ |
|
225 getMessageText: function (howMany) { |
|
226 if (typeof(howMany) == 'undefined' || howMany === null) { |
|
227 howMany = 30; |
|
228 } |
|
229 var messages = this.getMessages(howMany); |
|
230 if (messages.length) { |
|
231 var lst = map(function (m) { |
|
232 return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' '); |
|
233 }, messages); |
|
234 lst.unshift('LAST ' + messages.length + ' MESSAGES:'); |
|
235 return lst.join(''); |
|
236 } |
|
237 return ''; |
|
238 }, |
|
239 |
|
240 /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */ |
|
241 debuggingBookmarklet: function (inline) { |
|
242 if (typeof(MochiKit.LoggingPane) == "undefined") { |
|
243 alert(this.getMessageText()); |
|
244 } else { |
|
245 MochiKit.LoggingPane.createLoggingPane(inline || false); |
|
246 } |
|
247 } |
|
248 }; |
|
249 |
|
250 MochiKit.Logging.__new__ = function () { |
|
251 this.LogLevel = { |
|
252 ERROR: 40, |
|
253 FATAL: 50, |
|
254 WARNING: 30, |
|
255 INFO: 20, |
|
256 DEBUG: 10 |
|
257 }; |
|
258 |
|
259 var m = MochiKit.Base; |
|
260 m.registerComparator("LogMessage", |
|
261 this.isLogMessage, |
|
262 this.compareLogMessage |
|
263 ); |
|
264 |
|
265 var partial = m.partial; |
|
266 |
|
267 var Logger = this.Logger; |
|
268 var baseLog = Logger.prototype.baseLog; |
|
269 m.update(this.Logger.prototype, { |
|
270 debug: partial(baseLog, 'DEBUG'), |
|
271 log: partial(baseLog, 'INFO'), |
|
272 error: partial(baseLog, 'ERROR'), |
|
273 fatal: partial(baseLog, 'FATAL'), |
|
274 warning: partial(baseLog, 'WARNING') |
|
275 }); |
|
276 |
|
277 // indirectly find logger so it can be replaced |
|
278 var self = this; |
|
279 var connectLog = function (name) { |
|
280 return function () { |
|
281 self.logger[name].apply(self.logger, arguments); |
|
282 }; |
|
283 }; |
|
284 |
|
285 /** @id MochiKit.Logging.log */ |
|
286 this.log = connectLog('log'); |
|
287 /** @id MochiKit.Logging.logError */ |
|
288 this.logError = connectLog('error'); |
|
289 /** @id MochiKit.Logging.logDebug */ |
|
290 this.logDebug = connectLog('debug'); |
|
291 /** @id MochiKit.Logging.logFatal */ |
|
292 this.logFatal = connectLog('fatal'); |
|
293 /** @id MochiKit.Logging.logWarning */ |
|
294 this.logWarning = connectLog('warning'); |
|
295 this.logger = new Logger(); |
|
296 this.logger.useNativeConsole = true; |
|
297 |
|
298 this.EXPORT_TAGS = { |
|
299 ":common": this.EXPORT, |
|
300 ":all": m.concat(this.EXPORT, this.EXPORT_OK) |
|
301 }; |
|
302 |
|
303 m.nameFunctions(this); |
|
304 |
|
305 }; |
|
306 |
|
307 if (typeof(printfire) == "undefined" && |
|
308 typeof(document) != "undefined" && document.createEvent && |
|
309 typeof(dispatchEvent) != "undefined") { |
|
310 // FireBug really should be less lame about this global function |
|
311 printfire = function () { |
|
312 printfire.args = arguments; |
|
313 var ev = document.createEvent("Events"); |
|
314 ev.initEvent("printfire", false, true); |
|
315 dispatchEvent(ev); |
|
316 }; |
|
317 } |
|
318 |
|
319 MochiKit.Logging.__new__(); |
|
320 |
|
321 MochiKit.Base._exportSymbols(this, MochiKit.Logging); |