openEventsPlatformApp/plugins/cordova-plugin-console/www/logger.js
plugins/cordova-plugin-console/www/logger.jsRaw
1/*
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20*/
21
22//------------------------------------------------------------------------------
23// The logger module exports the following properties/functions:
24//
25// LOG - constant for the level LOG
26// ERROR - constant for the level ERROR
27// WARN - constant for the level WARN
28// INFO - constant for the level INFO
29// DEBUG - constant for the level DEBUG
30// logLevel() - returns current log level
31// logLevel(value) - sets and returns a new log level
32// useConsole() - returns whether logger is using console
33// useConsole(value) - sets and returns whether logger is using console
34// log(message,...) - logs a message at level LOG
35// error(message,...) - logs a message at level ERROR
36// warn(message,...) - logs a message at level WARN
37// info(message,...) - logs a message at level INFO
38// debug(message,...) - logs a message at level DEBUG
39// logLevel(level,message,...) - logs a message specified level
40//
41//------------------------------------------------------------------------------
42
43var logger = exports;
44
45var exec = require('cordova/exec');
46
47var UseConsole = false;
48var UseLogger = true;
49var Queued = [];
50var DeviceReady = false;
51var CurrentLevel;
52
53var originalConsole = console;
54
55/**
56 * Logging levels
57 */
58
59var Levels = [
60 "LOG",
61 "ERROR",
62 "WARN",
63 "INFO",
64 "DEBUG"
65];
66
67/*
68 * add the logging levels to the logger object and
69 * to a separate levelsMap object for testing
70 */
71
72var LevelsMap = {};
73for (var i=0; i<Levels.length; i++) {
74 var level = Levels[i];
75 LevelsMap[level] = i;
76 logger[level] = level;
77}
78
79CurrentLevel = LevelsMap.WARN;
80
81/**
82 * Getter/Setter for the logging level
83 *
84 * Returns the current logging level.
85 *
86 * When a value is passed, sets the logging level to that value.
87 * The values should be one of the following constants:
88 * logger.LOG
89 * logger.ERROR
90 * logger.WARN
91 * logger.INFO
92 * logger.DEBUG
93 *
94 * The value used determines which messages get printed. The logging
95 * values above are in order, and only messages logged at the logging
96 * level or above will actually be displayed to the user. E.g., the
97 * default level is WARN, so only messages logged with LOG, ERROR, or
98 * WARN will be displayed; INFO and DEBUG messages will be ignored.
99 */
100logger.level = function (value) {
101 if (arguments.length) {
102 if (LevelsMap[value] === null) {
103 throw new Error("invalid logging level: " + value);
104 }
105 CurrentLevel = LevelsMap[value];
106 }
107
108 return Levels[CurrentLevel];
109};
110
111/**
112 * Getter/Setter for the useConsole functionality
113 *
114 * When useConsole is true, the logger will log via the
115 * browser 'console' object.
116 */
117logger.useConsole = function (value) {
118 if (arguments.length) UseConsole = !!value;
119
120 if (UseConsole) {
121 if (typeof console == "undefined") {
122 throw new Error("global console object is not defined");
123 }
124
125 if (typeof console.log != "function") {
126 throw new Error("global console object does not have a log function");
127 }
128
129 if (typeof console.useLogger == "function") {
130 if (console.useLogger()) {
131 throw new Error("console and logger are too intertwingly");
132 }
133 }
134 }
135
136 return UseConsole;
137};
138
139/**
140 * Getter/Setter for the useLogger functionality
141 *
142 * When useLogger is true, the logger will log via the
143 * native Logger plugin.
144 */
145logger.useLogger = function (value) {
146 // Enforce boolean
147 if (arguments.length) UseLogger = !!value;
148 return UseLogger;
149};
150
151/**
152 * Logs a message at the LOG level.
153 *
154 * Parameters passed after message are used applied to
155 * the message with utils.format()
156 */
157logger.log = function(message) { logWithArgs("LOG", arguments); };
158
159/**
160 * Logs a message at the ERROR level.
161 *
162 * Parameters passed after message are used applied to
163 * the message with utils.format()
164 */
165logger.error = function(message) { logWithArgs("ERROR", arguments); };
166
167/**
168 * Logs a message at the WARN level.
169 *
170 * Parameters passed after message are used applied to
171 * the message with utils.format()
172 */
173logger.warn = function(message) { logWithArgs("WARN", arguments); };
174
175/**
176 * Logs a message at the INFO level.
177 *
178 * Parameters passed after message are used applied to
179 * the message with utils.format()
180 */
181logger.info = function(message) { logWithArgs("INFO", arguments); };
182
183/**
184 * Logs a message at the DEBUG level.
185 *
186 * Parameters passed after message are used applied to
187 * the message with utils.format()
188 */
189logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
190
191// log at the specified level with args
192function logWithArgs(level, args) {
193 args = [level].concat([].slice.call(args));
194 logger.logLevel.apply(logger, args);
195}
196
197// return the correct formatString for an object
198function formatStringForMessage(message) {
199 return (typeof message === "string") ? "" : "%o";
200}
201
202/**
203 * Logs a message at the specified level.
204 *
205 * Parameters passed after message are used applied to
206 * the message with utils.format()
207 */
208logger.logLevel = function(level /* , ... */) {
209 // format the message with the parameters
210 var formatArgs = [].slice.call(arguments, 1);
211 var fmtString = formatStringForMessage(formatArgs[0]);
212 if (fmtString.length > 0){
213 formatArgs.unshift(fmtString); // add formatString
214 }
215
216 var message = logger.format.apply(logger.format, formatArgs);
217
218 if (LevelsMap[level] === null) {
219 throw new Error("invalid logging level: " + level);
220 }
221
222 if (LevelsMap[level] > CurrentLevel) return;
223
224 // queue the message if not yet at deviceready
225 if (!DeviceReady && !UseConsole) {
226 Queued.push([level, message]);
227 return;
228 }
229
230 // Log using the native logger if that is enabled
231 if (UseLogger) {
232 exec(null, null, "Console", "logLevel", [level, message]);
233 }
234
235 // Log using the console if that is enabled
236 if (UseConsole) {
237 // make sure console is not using logger
238 if (console.useLogger()) {
239 throw new Error("console and logger are too intertwingly");
240 }
241
242 // log to the console
243 switch (level) {
244 case logger.LOG: originalConsole.log(message); break;
245 case logger.ERROR: originalConsole.log("ERROR: " + message); break;
246 case logger.WARN: originalConsole.log("WARN: " + message); break;
247 case logger.INFO: originalConsole.log("INFO: " + message); break;
248 case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
249 }
250 }
251};
252
253
254/**
255 * Formats a string and arguments following it ala console.log()
256 *
257 * Any remaining arguments will be appended to the formatted string.
258 *
259 * for rationale, see FireBug's Console API:
260 * http://getfirebug.com/wiki/index.php/Console_API
261 */
262logger.format = function(formatString, args) {
263 return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
264};
265
266
267//------------------------------------------------------------------------------
268/**
269 * Formats a string and arguments following it ala vsprintf()
270 *
271 * format chars:
272 * %j - format arg as JSON
273 * %o - format arg as JSON
274 * %c - format arg as ''
275 * %% - replace with '%'
276 * any other char following % will format it's
277 * arg via toString().
278 *
279 * Returns an array containing the formatted string and any remaining
280 * arguments.
281 */
282function __format(formatString, args) {
283 if (formatString === null || formatString === undefined) return [""];
284 if (arguments.length == 1) return [formatString.toString()];
285
286 if (typeof formatString != "string")
287 formatString = formatString.toString();
288
289 var pattern = /(.*?)%(.)(.*)/;
290 var rest = formatString;
291 var result = [];
292
293 while (args.length) {
294 var match = pattern.exec(rest);
295 if (!match) break;
296
297 var arg = args.shift();
298 rest = match[3];
299 result.push(match[1]);
300
301 if (match[2] == '%') {
302 result.push('%');
303 args.unshift(arg);
304 continue;
305 }
306
307 result.push(__formatted(arg, match[2]));
308 }
309
310 result.push(rest);
311
312 var remainingArgs = [].slice.call(args);
313 remainingArgs.unshift(result.join(''));
314 return remainingArgs;
315}
316
317function __formatted(object, formatChar) {
318
319 try {
320 switch(formatChar) {
321 case 'j':
322 case 'o': return JSON.stringify(object);
323 case 'c': return '';
324 }
325 }
326 catch (e) {
327 return "error JSON.stringify()ing argument: " + e;
328 }
329
330 if ((object === null) || (object === undefined)) {
331 return Object.prototype.toString.call(object);
332 }
333
334 return object.toString();
335}
336
337
338//------------------------------------------------------------------------------
339// when deviceready fires, log queued messages
340logger.__onDeviceReady = function() {
341 if (DeviceReady) return;
342
343 DeviceReady = true;
344
345 for (var i=0; i<Queued.length; i++) {
346 var messageArgs = Queued[i];
347 logger.logLevel(messageArgs[0], messageArgs[1]);
348 }
349
350 Queued = null;
351};
352
353// add a deviceready event to log queued messages
354document.addEventListener("deviceready", logger.__onDeviceReady, false);