PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/js/yii/logging/CLogger.js

http://github.com/phpnode/YiiJS
JavaScript | 339 lines | 200 code | 6 blank | 133 comment | 52 complexity | 04c6c3ae30c3ae412449de058faeacc0 MD5 | raw file
  1. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  2. /**
  3. * CLogger records log messages in memory.
  4. *
  5. * CLogger implements the methods to retrieve the messages with
  6. * various filter conditions, including log levels and log categories.
  7. *
  8. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  9. * @version $Id: CLogger.php 3137 2011-03-28 11:08:06Z mdomba $
  10. * @package system.logging
  11. * @since 1.0
  12. * @author Charles Pick
  13. * @class
  14. * @extends Yii.CComponent
  15. */
  16. Yii.CLogger = function() {
  17. };
  18. Yii.CLogger.prototype = new Yii.CComponent();
  19. Yii.CLogger.prototype.constructor = Yii.CLogger;
  20. /**
  21. * @const
  22. */
  23. Yii.CLogger.prototype.LEVEL_TRACE = 'trace';
  24. /**
  25. * @const
  26. */
  27. Yii.CLogger.prototype.LEVEL_WARNING = 'warning';
  28. /**
  29. * @const
  30. */
  31. Yii.CLogger.prototype.LEVEL_ERROR = 'error';
  32. /**
  33. * @const
  34. */
  35. Yii.CLogger.prototype.LEVEL_INFO = 'info';
  36. /**
  37. * @const
  38. */
  39. Yii.CLogger.prototype.LEVEL_PROFILE = 'profile';
  40. /**
  41. * @var {Integer} how many messages should be logged before they are flushed to destinations.
  42. * Defaults to 10,000, meaning for every 10,000 messages, the {@link flush} method will be
  43. * automatically invoked once. If this is 0, it means messages will never be flushed automatically.
  44. * @since 1.1.0
  45. */
  46. Yii.CLogger.prototype.autoFlush = 10000;
  47. /**
  48. * @var {Array} log messages
  49. */
  50. Yii.CLogger.prototype._logs = [];
  51. /**
  52. * @var {Integer} number of log messages
  53. */
  54. Yii.CLogger.prototype._logCount = 0;
  55. /**
  56. * @var {Array} log levels for filtering (used when filtering)
  57. */
  58. Yii.CLogger.prototype._levels = null;
  59. /**
  60. * @var {Array} log categories for filtering (used when filtering)
  61. */
  62. Yii.CLogger.prototype._categories = null;
  63. /**
  64. * @var {Array} the profiling results (category, token => time in seconds)
  65. * @since 1.0.6
  66. */
  67. Yii.CLogger.prototype._timings = null;
  68. /**
  69. * Logs a message.
  70. * Messages logged by this method may be retrieved back via {@link getLogs}.
  71. * @param {String} message message to be logged
  72. * @param {String} level level of the message (e.g. 'Trace', 'Warning', 'Error'). It is case-insensitive.
  73. * @param {String} category category of the message (e.g. 'system.web'). It is case-insensitive.
  74. * @see getLogs
  75. */
  76. Yii.CLogger.prototype.log = function (message, level, category) {
  77. if (level === undefined) {
  78. level = 'info';
  79. }
  80. if (category === undefined) {
  81. category = 'application';
  82. }
  83. this._logs.push([message,level,category,php.microtime(true)]);
  84. this._logCount++;
  85. if(this.autoFlush>0 && this._logCount>=this.autoFlush) {
  86. this.flush();
  87. }
  88. };
  89. /**
  90. * Retrieves log messages.
  91. *
  92. * Messages may be filtered by log levels and/or categories.
  93. * A level filter is specified by a list of levels separated by comma or space
  94. * (e.g. 'trace, error'). A category filter is similar to level filter
  95. * (e.g. 'system, system.web'). A difference is that in category filter
  96. * you can use pattern like 'system.*' to indicate all categories starting
  97. * with 'system'.
  98. *
  99. * If you do not specify level filter, it will bring back logs at all levels.
  100. * The same applies to category filter.
  101. *
  102. * Level filter and category filter are combinational, i.e., only messages
  103. * satisfying both filter conditions will be returned.
  104. *
  105. * @param {String} levels level filter
  106. * @param {String} categories category filter
  107. * @returns {Array} list of messages. Each array elements represents one message
  108. * with the following structure:
  109. * array(
  110. * [0] => message (string)
  111. * [1] => level (string)
  112. * [2] => category (string)
  113. * [3] => timestamp (float, obtained by microtime(true));
  114. */
  115. Yii.CLogger.prototype.getLogs = function (levels, categories) {
  116. var ret, self;
  117. if (levels === undefined) {
  118. levels = '';
  119. this._levels = [];
  120. }
  121. else {
  122. this._levels=levels.toLowerCase().split(/[\s,]+/);
  123. }
  124. if (categories === undefined) {
  125. categories = '';
  126. this._categories = [];
  127. }
  128. else {
  129. this._categories=categories.toLowerCase().split(/[\s,]+/);
  130. }
  131. self = this;
  132. if(php.empty(levels) && php.empty(categories)) {
  133. return this._logs;
  134. }
  135. else if(php.empty(levels)) {
  136. return Yii.filter(this._logs,function(value, k, arr) {
  137. var matched = false, cat = value[2].toLowerCase(), c;
  138. Yii.forEach(self._categories, function(i, category) {
  139. if(cat===category || ((c=php.rtrim(category,'.*'))!==category && php.strpos(cat,c)===0)) {
  140. matched = true;
  141. return false;
  142. }
  143. });
  144. return matched ? value : false;
  145. });
  146. }
  147. else if(php.empty(categories)) {
  148. return Yii.filter(this._logs,function(value, k, arr) {
  149. var matched = false, matchLevel = value[1].toLowerCase();
  150. Yii.forEach(self._levels, function(i, level) {
  151. if (level === matchLevel) {
  152. matched = true;
  153. return false;
  154. }
  155. });
  156. return matched ? value : false;
  157. });
  158. }
  159. else {
  160. return Yii.filter(Yii.filter(this._logs,function(value, k, arr) {
  161. var matched = false, cat = value[2].toLowerCase(), c;
  162. Yii.forEach(self._categories, function(i, category) {
  163. if(cat===category || ((c=php.rtrim(category,'.*'))!==category && php.strpos(cat,c)===0)) {
  164. matched = true;
  165. return false;
  166. }
  167. });
  168. return matched ? value : false;
  169. }), function(value, k, arr) {
  170. var matched = false, matchLevel = value[1].toLowerCase();
  171. Yii.forEach(self._levels, function(i, level) {
  172. if (level === matchLevel) {
  173. matched = true;
  174. return false;
  175. }
  176. });
  177. return matched ? value : false;
  178. });
  179. }
  180. };
  181. /**
  182. * Filter function used by {@link getLogs}
  183. * @param {Array} value element to be filtered
  184. * @returns {Array} valid log, false if not.
  185. */
  186. Yii.CLogger.prototype.filterByCategory = function (value) {
  187. var i, cat, category, c;
  188. for (i in this._categories) {
  189. if (this._categories.hasOwnProperty(i)) {
  190. category = this._categories[i];
  191. cat=value[2].toLowerCase();
  192. if(cat===category || ((c=php.rtrim(category,'.*'))!==category && php.strpos(cat,c)===0)) {
  193. return value;
  194. }
  195. }
  196. }
  197. return false;
  198. };
  199. /**
  200. * Filter function used by {@link getLogs}
  201. * @param {Array} value element to be filtered
  202. * @returns {Array} valid log, false if not.
  203. */
  204. Yii.CLogger.prototype.filterByLevel = function (value) {
  205. var matched = false, matchLevel = value[1].toLowerCase();
  206. Yii.forEach(this._levels, function(i, level) {
  207. console.log(level);
  208. if (level === matchLevel) {
  209. matched = true;
  210. return false;
  211. }
  212. });
  213. return matched ? value : false;
  214. };
  215. /**
  216. * Returns the total time for serving the current request.
  217. * This method calculates the difference between now and the timestamp
  218. * defined by constant YII_BEGIN_TIME.
  219. * To estimate the execution time more accurately, the constant should
  220. * be defined as early as possible (best at the beginning of the entry script.)
  221. * @returns {Float} the total time for serving the current request.
  222. */
  223. Yii.CLogger.prototype.getExecutionTime = function () {
  224. return php.microtime(true)-YII_BEGIN_TIME;
  225. };
  226. /**
  227. * Not Available in JavaScript, always returns 0
  228. * @returns {Integer} memory usage of the application (in bytes).
  229. */
  230. Yii.CLogger.prototype.getMemoryUsage = function () {
  231. return 0;
  232. };
  233. /**
  234. * Returns the profiling results.
  235. * The results may be filtered by token and/or category.
  236. * If no filter is specified, the returned results would be an array with each element
  237. * being array($token,$category,$time).
  238. * If a filter is specified, the results would be an array of timings.
  239. * @param {String} token token filter. Defaults to null, meaning not filtered by token.
  240. * @param {String} category category filter. Defaults to null, meaning not filtered by category.
  241. * @param {Boolean} refresh whether to refresh the internal timing calculations. If false,
  242. * only the first time calling this method will the timings be calculated internally.
  243. * @returns {Array} the profiling results.
  244. * @since 1.0.6
  245. */
  246. Yii.CLogger.prototype.getProfilingResults = function (token, category, refresh) {
  247. var results, i, timing;
  248. if (token === undefined) {
  249. token = null;
  250. }
  251. if (category === undefined) {
  252. category = null;
  253. }
  254. if (refresh === undefined) {
  255. refresh = false;
  256. }
  257. if(this._timings===null || refresh) {
  258. this.calculateTimings();
  259. }
  260. if(token===null && category===null) {
  261. return this._timings;
  262. }
  263. results=[];
  264. for (i in this._timings) {
  265. if (this._timings.hasOwnProperty(i)) {
  266. timing = this._timings[i];
  267. if((category===null || timing[1]===category) && (token===null || timing[0]===token)) {
  268. results.push(timing[2]);
  269. }
  270. }
  271. }
  272. return results;
  273. };
  274. Yii.CLogger.prototype.calculateTimings = function () {
  275. var stack, i, log, message, level, category, timestamp, token, last, delta, now;
  276. this._timings=[];
  277. stack=[];
  278. for (i in this._logs) {
  279. if (this._logs.hasOwnProperty(i)) {
  280. log = this._logs[i];
  281. if(log[1]!==Yii.CLogger.prototype.LEVEL_PROFILE) {
  282. continue;
  283. }
  284. message = log[0];
  285. level = log[1];
  286. category = log[2];
  287. timestamp = log[3];
  288. if(!php.strncasecmp(message,'begin:',6)) {
  289. log[0]=message.slice(6);
  290. stack.push(log);
  291. }
  292. else if(!php.strncasecmp(message,'end:',4)) {
  293. token=message.slice(4);
  294. if((last=php.array_pop(stack))!==null && last[0]===token) {
  295. delta=log[3]-last[3];
  296. this._timings.push([message,category,delta]);
  297. }
  298. else {
  299. throw new Yii.CException(Yii.t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
  300. {'{token}':token}));
  301. }
  302. }
  303. }
  304. }
  305. now=php.microtime(true);
  306. while((last=php.array_pop(stack))!==null) {
  307. delta=now-last[3];
  308. this._timings.push([last[0],last[2],delta]);
  309. }
  310. };
  311. /**
  312. * Removes all recorded messages from the memory.
  313. * This method will raise an {@link onFlush} event.
  314. * The attached event handlers can process the log messages before they are removed.
  315. * @param {Boolean} dumpLogs whether to process the logs
  316. * @since 1.1.0
  317. */
  318. Yii.CLogger.prototype.flush = function (dumpLogs) {
  319. if (dumpLogs === undefined) {
  320. dumpLogs = false;
  321. }
  322. this.onFlush(new Yii.CEvent(this, {'dumpLogs':dumpLogs}));
  323. this._logs=[];
  324. this._logCount=0;
  325. };
  326. /**
  327. * Raises an <code>onFlush</code> event.
  328. * @param {Yii.CEvent} event the event parameter
  329. * @since 1.1.0
  330. */
  331. Yii.CLogger.prototype.onFlush = function (event) {
  332. this.raiseEvent('onFlush', event);
  333. }