Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

logger.js 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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. // The logger module exports the following properties/functions:
  23. //
  24. // LOG - constant for the level LOG
  25. // ERROR - constant for the level ERROR
  26. // WARN - constant for the level WARN
  27. // INFO - constant for the level INFO
  28. // DEBUG - constant for the level DEBUG
  29. // logLevel() - returns current log level
  30. // logLevel(value) - sets and returns a new log level
  31. // useConsole() - returns whether logger is using console
  32. // useConsole(value) - sets and returns whether logger is using console
  33. // log(message,...) - logs a message at level LOG
  34. // error(message,...) - logs a message at level ERROR
  35. // warn(message,...) - logs a message at level WARN
  36. // info(message,...) - logs a message at level INFO
  37. // debug(message,...) - logs a message at level DEBUG
  38. // logLevel(level,message,...) - logs a message specified level
  39. //
  40. // ------------------------------------------------------------------------------
  41. var logger = exports;
  42. var exec = require('cordova/exec');
  43. var UseConsole = false;
  44. var UseLogger = true;
  45. var Queued = [];
  46. var DeviceReady = false;
  47. var CurrentLevel;
  48. var originalConsole = console;
  49. /**
  50. * Logging levels
  51. */
  52. var Levels = [
  53. 'LOG',
  54. 'ERROR',
  55. 'WARN',
  56. 'INFO',
  57. 'DEBUG'
  58. ];
  59. /*
  60. * add the logging levels to the logger object and
  61. * to a separate levelsMap object for testing
  62. */
  63. var LevelsMap = {};
  64. for (var i = 0; i < Levels.length; i++) {
  65. var level = Levels[i];
  66. LevelsMap[level] = i;
  67. logger[level] = level;
  68. }
  69. CurrentLevel = LevelsMap.WARN;
  70. /**
  71. * Getter/Setter for the logging level
  72. *
  73. * Returns the current logging level.
  74. *
  75. * When a value is passed, sets the logging level to that value.
  76. * The values should be one of the following constants:
  77. * logger.LOG
  78. * logger.ERROR
  79. * logger.WARN
  80. * logger.INFO
  81. * logger.DEBUG
  82. *
  83. * The value used determines which messages get printed. The logging
  84. * values above are in order, and only messages logged at the logging
  85. * level or above will actually be displayed to the user. E.g., the
  86. * default level is WARN, so only messages logged with LOG, ERROR, or
  87. * WARN will be displayed; INFO and DEBUG messages will be ignored.
  88. */
  89. logger.level = function (value) {
  90. if (arguments.length) {
  91. if (LevelsMap[value] === null) {
  92. throw new Error('invalid logging level: ' + value);
  93. }
  94. CurrentLevel = LevelsMap[value];
  95. }
  96. return Levels[CurrentLevel];
  97. };
  98. /**
  99. * Getter/Setter for the useConsole functionality
  100. *
  101. * When useConsole is true, the logger will log via the
  102. * browser 'console' object.
  103. */
  104. logger.useConsole = function (value) {
  105. if (arguments.length) UseConsole = !!value;
  106. if (UseConsole) {
  107. if (typeof console === 'undefined') {
  108. throw new Error('global console object is not defined');
  109. }
  110. if (typeof console.log !== 'function') {
  111. throw new Error('global console object does not have a log function');
  112. }
  113. if (typeof console.useLogger === 'function') {
  114. if (console.useLogger()) {
  115. throw new Error('console and logger are too intertwingly');
  116. }
  117. }
  118. }
  119. return UseConsole;
  120. };
  121. /**
  122. * Getter/Setter for the useLogger functionality
  123. *
  124. * When useLogger is true, the logger will log via the
  125. * native Logger plugin.
  126. */
  127. logger.useLogger = function (value) {
  128. // Enforce boolean
  129. if (arguments.length) UseLogger = !!value;
  130. return UseLogger;
  131. };
  132. /**
  133. * Logs a message at the LOG level.
  134. *
  135. * Parameters passed after message are used applied to
  136. * the message with utils.format()
  137. */
  138. logger.log = function (message) { logWithArgs('LOG', arguments); };
  139. /**
  140. * Logs a message at the ERROR level.
  141. *
  142. * Parameters passed after message are used applied to
  143. * the message with utils.format()
  144. */
  145. logger.error = function (message) { logWithArgs('ERROR', arguments); };
  146. /**
  147. * Logs a message at the WARN level.
  148. *
  149. * Parameters passed after message are used applied to
  150. * the message with utils.format()
  151. */
  152. logger.warn = function (message) { logWithArgs('WARN', arguments); };
  153. /**
  154. * Logs a message at the INFO level.
  155. *
  156. * Parameters passed after message are used applied to
  157. * the message with utils.format()
  158. */
  159. logger.info = function (message) { logWithArgs('INFO', arguments); };
  160. /**
  161. * Logs a message at the DEBUG level.
  162. *
  163. * Parameters passed after message are used applied to
  164. * the message with utils.format()
  165. */
  166. logger.debug = function (message) { logWithArgs('DEBUG', arguments); };
  167. // log at the specified level with args
  168. function logWithArgs (level, args) {
  169. args = [level].concat([].slice.call(args));
  170. logger.logLevel.apply(logger, args);
  171. }
  172. // return the correct formatString for an object
  173. function formatStringForMessage (message) {
  174. return (typeof message === 'string') ? '' : '%o';
  175. }
  176. /**
  177. * Logs a message at the specified level.
  178. *
  179. * Parameters passed after message are used applied to
  180. * the message with utils.format()
  181. */
  182. logger.logLevel = function (level /* , ... */) {
  183. // format the message with the parameters
  184. var formatArgs = [].slice.call(arguments, 1);
  185. var fmtString = formatStringForMessage(formatArgs[0]);
  186. if (fmtString.length > 0) {
  187. formatArgs.unshift(fmtString); // add formatString
  188. }
  189. var message = logger.format.apply(logger.format, formatArgs);
  190. if (LevelsMap[level] === null) {
  191. throw new Error('invalid logging level: ' + level);
  192. }
  193. if (LevelsMap[level] > CurrentLevel) return;
  194. // queue the message if not yet at deviceready
  195. if (!DeviceReady && !UseConsole) {
  196. Queued.push([level, message]);
  197. return;
  198. }
  199. // Log using the native logger if that is enabled
  200. if (UseLogger) {
  201. exec(null, null, 'Console', 'logLevel', [level, message]);
  202. }
  203. // Log using the console if that is enabled
  204. if (UseConsole) {
  205. // make sure console is not using logger
  206. if (console.useLogger()) {
  207. throw new Error('console and logger are too intertwingly');
  208. }
  209. // log to the console
  210. switch (level) {
  211. case logger.LOG: originalConsole.log(message); break;
  212. case logger.ERROR: originalConsole.log('ERROR: ' + message); break;
  213. case logger.WARN: originalConsole.log('WARN: ' + message); break;
  214. case logger.INFO: originalConsole.log('INFO: ' + message); break;
  215. case logger.DEBUG: originalConsole.log('DEBUG: ' + message); break;
  216. }
  217. }
  218. };
  219. /**
  220. * Formats a string and arguments following it ala console.log()
  221. *
  222. * Any remaining arguments will be appended to the formatted string.
  223. *
  224. * for rationale, see FireBug's Console API:
  225. * http://getfirebug.com/wiki/index.php/Console_API
  226. */
  227. logger.format = function (formatString, args) {
  228. return __format(arguments[0], [].slice.call(arguments, 1)).join(' ');
  229. };
  230. // ------------------------------------------------------------------------------
  231. /**
  232. * Formats a string and arguments following it ala vsprintf()
  233. *
  234. * format chars:
  235. * %j - format arg as JSON
  236. * %o - format arg as JSON
  237. * %c - format arg as ''
  238. * %% - replace with '%'
  239. * any other char following % will format it's
  240. * arg via toString().
  241. *
  242. * Returns an array containing the formatted string and any remaining
  243. * arguments.
  244. */
  245. function __format (formatString, args) {
  246. if (formatString === null || formatString === undefined) return [''];
  247. if (arguments.length === 1) return [formatString.toString()];
  248. if (typeof formatString !== 'string') { formatString = formatString.toString(); }
  249. var pattern = /(.*?)%(.)(.*)/;
  250. var rest = formatString;
  251. var result = [];
  252. while (args.length) {
  253. var match = pattern.exec(rest);
  254. if (!match) break;
  255. var arg = args.shift();
  256. rest = match[3];
  257. result.push(match[1]);
  258. if (match[2] === '%') {
  259. result.push('%');
  260. args.unshift(arg);
  261. continue;
  262. }
  263. result.push(__formatted(arg, match[2]));
  264. }
  265. result.push(rest);
  266. var remainingArgs = [].slice.call(args);
  267. remainingArgs.unshift(result.join(''));
  268. return remainingArgs;
  269. }
  270. function __formatted (object, formatChar) {
  271. try {
  272. switch (formatChar) {
  273. case 'j':
  274. case 'o': return JSON.stringify(object);
  275. case 'c': return '';
  276. }
  277. } catch (e) {
  278. return 'error JSON.stringify()ing argument: ' + e;
  279. }
  280. if ((object === null) || (object === undefined)) {
  281. return Object.prototype.toString.call(object);
  282. }
  283. return object.toString();
  284. }
  285. // ------------------------------------------------------------------------------
  286. // when deviceready fires, log queued messages
  287. logger.__onDeviceReady = function () {
  288. if (DeviceReady) return;
  289. DeviceReady = true;
  290. for (var i = 0; i < Queued.length; i++) {
  291. var messageArgs = Queued[i];
  292. logger.logLevel(messageArgs[0], messageArgs[1]);
  293. }
  294. Queued = null;
  295. };
  296. // add a deviceready event to log queued messages
  297. document.addEventListener('deviceready', logger.__onDeviceReady, false);