From 98248ddeeba232457a6f8c036fbf964a7197a07b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gerg=C5=91=20Tisza?= Date: Tue, 3 Feb 2015 22:49:40 +0000 Subject: [PATCH] mw.loader: Replace log() calls with mw.track events This allows other consumers (such as an error logging backend) to subscribe to these errors. Change-Id: I157e2fb5c6b4d77736fcaf0a87c624e76a833161 --- resources/src/mediawiki/mediawiki.js | 101 +++++++++++++++++---------- 1 file changed, 65 insertions(+), 36 deletions(-) diff --git a/resources/src/mediawiki/mediawiki.js b/resources/src/mediawiki/mediawiki.js index 2e78c1c7cd..17b06ce432 100644 --- a/resources/src/mediawiki/mediawiki.js +++ b/resources/src/mediawiki/mediawiki.js @@ -16,31 +16,6 @@ trackCallbacks = $.Callbacks( 'memory' ), trackQueue = []; - /** - * Log a message to window.console, if possible. - * - * Useful to force logging of some errors that are otherwise hard to detect (i.e., this logs - * also in production mode). Gets console references in each invocation instead of caching the - * reference, so that debugging tools loaded later are supported (e.g. Firebug Lite in IE). - * - * @private - * @method log_ - * @param {string} msg Text for the log entry. - * @param {Error} [e] - */ - function log( msg, e ) { - var console = window.console; - if ( console && console.log ) { - console.log( msg ); - // If we have an exception object, log it to the error channel to trigger a - // proper stacktraces in browsers that support it. No fallback as we have no browsers - // that don't support error(), but do support log(). - if ( e && console.error ) { - console.error( String( e ), e ); - } - } - } - /** * Create an object that can be read from or written to from methods that allow * interaction both with single and multiple properties at once. @@ -679,10 +654,25 @@ * error is not module-related or the module cannot be easily identified due to * batched handling. * @param {string} source Source of the error. Possible values: + * * - style: stylesheet error (only affects old IE where a special style loading method * is used) * - load-callback: exception thrown by user callback * - module-execute: exception thrown by module code + * - store-eval: could not evaluate module code cached in localStorage + * - store-localstorage-init: localStorage or JSON parse error in mw.loader.store.init + * - store-localstorage-json: JSON conversion error in mw.loader.store.set + * - store-localstorage-update: localStorage or JSON conversion error in mw.loader.store.update + */ + + /** + * Fired via mw.track on resource loading error conditions. + * + * @event resourceloader_assert + * @param {string} source Source of the error. Possible values: + * + * - bug-T59567: failed to cache script due to an Opera function -> string conversion + * bug; see for details */ /** @@ -868,7 +858,6 @@ try { styleEl.styleSheet.cssText += cssText; } catch ( e ) { - log( 'Stylesheet error', e ); mw.track( 'resourceloader.exception', { exception: e, source: 'stylesheet' } ); } } else { @@ -1132,9 +1121,7 @@ } catch ( e ) { // A user-defined callback raised an exception. // Swallow it to protect our state machine! - log( 'Exception thrown by user callback', e ); - mw.track( 'resourceloader.exception', - { exception: e, module: module, source: 'load-callback' } ); + mw.track( 'resourceloader.exception', { exception: e, module: module, source: 'load-callback' } ); } } } @@ -1260,7 +1247,6 @@ } catch ( e ) { // This needs to NOT use mw.log because these errors are common in production mode // and not in debug mode, such as when a symbol that should be global isn't exported - log( 'Exception thrown by ' + module, e ); registry[module].state = 'error'; mw.track( 'resourceloader.exception', { exception: e, module: module, source: 'module-execute' } ); handlePending( module ); @@ -1581,7 +1567,7 @@ // repopulate these modules to the cache. // This means that at most one module will be useless (the one that had // the error) instead of all of them. - log( 'Error while evaluating data from mw.loader.store', err ); + mw.track( 'resourceloader.exception', { exception: err, source: 'store-eval' } ); origBatch = $.grep( origBatch, function ( module ) { return registry[module].state === 'loading'; } ); @@ -2170,7 +2156,7 @@ return; } } catch ( e ) { - log( 'Storage error', e ); + mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-init' } ); } if ( raw === undefined ) { @@ -2243,14 +2229,14 @@ JSON.stringify( descriptor.messages ), JSON.stringify( descriptor.templates ) ]; - // Attempted workaround for a possible Opera bug (bug 57567). + // Attempted workaround for a possible Opera bug (bug T59567). // This regex should never match under sane conditions. if ( /^\s*\(/.test( args[1] ) ) { args[1] = 'function' + args[1]; - log( 'Detected malformed function stringification (bug 57567)' ); + mw.track( 'resourceloader.assert', { source: 'bug-T59567' } ); } } catch ( e ) { - log( 'Storage error', e ); + mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-json' } ); return; } @@ -2322,7 +2308,7 @@ data = JSON.stringify( mw.loader.store ); localStorage.setItem( key, data ); } catch ( e ) { - log( 'Storage error', e ); + mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-update' } ); } } @@ -2558,6 +2544,49 @@ // @deprecated since 1.23 Use $ or jQuery instead mw.log.deprecate( window, '$j', $, 'Use $ or jQuery instead.' ); + /** + * Log a message to window.console, if possible. + * + * Useful to force logging of some errors that are otherwise hard to detect (i.e., this logs + * also in production mode). Gets console references in each invocation instead of caching the + * reference, so that debugging tools loaded later are supported (e.g. Firebug Lite in IE). + * + * @private + * @method log_ + * @param {string} topic Stream name passed by mw.track + * @param {Object} data Data passed by mw.track + * @param {Error} [data.exception] + * @param {string} data.source Error source + * @param {string} [data.module] Name of module which caused the error + */ + function log( topic, data ) { + var msg, + e = data.exception, + source = data.source, + module = data.module, + console = window.console; + + if ( console && console.log ) { + msg = ( e ? 'Exception' : 'Error' ) + ' in ' + source; + if ( module ) { + msg += ' in module ' + module; + } + msg += ( e ? ':' : '.' ); + console.log( msg ); + + // If we have an exception object, log it to the error channel to trigger a + // proper stacktraces in browsers that support it. No fallback as we have no browsers + // that don't support error(), but do support log(). + if ( e && console.error ) { + console.error( String( e ), e ); + } + } + } + + // subscribe to error streams + mw.trackSubscribe( 'resourceloader.exception', log ); + mw.trackSubscribe( 'resourceloader.assert', log ); + // Attach to window and globally alias window.mw = window.mediaWiki = mw; }( jQuery ) ); -- 2.20.1