jenkins-bot has submitted this change and it was merged. Change subject: Report error id and context ......................................................................
Report error id and context Bug: T89384 Change-Id: If9b2b0d798546e4ccf5f3de5821ad4e3db1aa2cd --- M Sentry.php M SentryHooks.php M resources/init.js A tests/qunit/init.test.js 4 files changed, 77 insertions(+), 7 deletions(-) Approvals: Gilles: Looks good to me, approved jenkins-bot: Verified diff --git a/Sentry.php b/Sentry.php index 1f3eb0e..6026e2f 100644 --- a/Sentry.php +++ b/Sentry.php @@ -29,6 +29,7 @@ $wgHooks['ResourceLoaderGetConfigVars'][] = 'SentryHooks::onResourceLoaderGetConfigVars'; $wgHooks['BeforePageDisplay'][] = 'SentryHooks::onBeforePageDisplay'; $wgHooks['UnitTestsList'][] = 'SentryHooks::onUnitTestsList'; +$wgHooks['ResourceLoaderTestModules'][] = 'SentryHooks::onResourceLoaderTestModules'; /** * Sentry DSN (http://raven.readthedocs.org/en/latest/config/#the-sentry-dsn) diff --git a/SentryHooks.php b/SentryHooks.php index 1751bb7..1ed5d2f 100644 --- a/SentryHooks.php +++ b/SentryHooks.php @@ -32,6 +32,15 @@ $paths[] = __DIR__ . '/tests'; } + public static function onResourceLoaderTestModules( array &$testModules, ResourceLoader &$resourceLoader ) { + $testModules['qunit']['sentry.test'] = array( + 'scripts' => array( 'init.test.js' ), + 'dependencies' => array( 'sentry' ), + 'localBasePath' => __DIR__ . '/tests/qunit', + 'remoteExtPath' => 'Sentry/tests/qunit', + ); + } + /** * For JS logging, the private key must be omitted from the DSN. * @param string $dsn diff --git a/resources/init.js b/resources/init.js index c3d9ab7..5982c28 100644 --- a/resources/init.js +++ b/resources/init.js @@ -1,4 +1,4 @@ -( function ( mw ) { +( function ( mw, $ ) { var raven; /** @@ -38,18 +38,33 @@ * @param {string} topic mw.track() queue name * @param {Object} data * @param {Mixed} data.exception The exception which has been caught + * @param {string} data.id An identifier for the exception * @param {string} data.source Describes what type of function caught the exception * @param {string} [data.module] Name of the module which threw the exception + * @param {Object} [data.context] Additional key-value pairs to be recorded as Sentry tags */ function report( topic, data ) { - initRaven().done( function ( raven ) { - raven.captureException( data.exception, { tags: { - source: data.source, - module: data.module - } } ); + mw.sentry.initRaven().done( function ( raven ) { + var tags = { source: data.source }, + log = window.console && ( console.warn || console.log ); + + if ( data.module ) { + tags.module = data.module; + } + $.extend( tags, data.context ); + + raven.captureException( data.exception, { tags: tags, event_id: data.id } ); + + if ( log ) { + log.call( console, 'MediaWiki error logging: reported an error with id ' + data.id ); + log.call( console, 'Please refer to this error id when reporting an error.' ); + } } ); } mw.trackSubscribe( 'errorLogging.exception', report ); mw.trackSubscribe( 'resourceloader.exception', report ); -} ) ( mediaWiki ); + + // make these available for unit tests + mw.sentry = { initRaven: initRaven, report: report }; +} ) ( mediaWiki, jQuery ); diff --git a/tests/qunit/init.test.js b/tests/qunit/init.test.js new file mode 100644 index 0000000..33ce559 --- /dev/null +++ b/tests/qunit/init.test.js @@ -0,0 +1,45 @@ +( function ( mw, $ ) { + QUnit.module( 'sentry', QUnit.newMwEnvironment() ); + + QUnit.test( 'initRaven()', 6, function ( assert ) { + var result; + + this.sandbox.stub( mw.loader, 'using' ).returns( $.Deferred().resolve() ); + this.sandbox.stub( Raven, 'config' ).returnsThis(); + this.sandbox.stub( Raven, 'install' ).returnsThis(); + + QUnit.stop(); + mw.sentry.initRaven().then( function ( raven ) { + assert.strictEqual( raven, Raven, 'initRaven() returns Raven as a promise' ); + assert.ok( Raven.config.called, 'Raven is configured' ); + assert.ok( Raven.install.called, 'Raven is installed' ); + + Raven.config.reset(); + Raven.install.reset(); + + return mw.sentry.initRaven(); + } ).then( function ( raven ) { + assert.strictEqual(raven, Raven, 'initRaven() returns Raven on second invocation' ); + assert.ok( !Raven.config.called, 'Raven is not configured twice' ); + assert.ok( !Raven.install.called, 'Raven is not installed twice' ); + QUnit.start(); + } ); + } ); + + QUnit.test( 'report()', 5, function ( assert ) { + var raven = { captureException: this.sandbox.stub() }; + + this.sandbox.stub( mw.sentry, 'initRaven' ).returns( $.Deferred().resolve( raven ) ); + + mw.sentry.report( 'some-topic', { exception: 42, source: 'Deep Thought', id: '123' } ); + assert.strictEqual( raven.captureException.lastCall.args[0], 42, 'Exception matches' ); + assert.strictEqual( raven.captureException.lastCall.args[1].event_id, '123', 'Event id matches' ); + assert.strictEqual( raven.captureException.lastCall.args[1].tags.source, 'Deep Thought', 'Source matches' ); + + mw.sentry.report( 'some-topic', { exception: 42, source: 'Deep Thought', module: 'foo', id: '123' } ); + assert.strictEqual( raven.captureException.lastCall.args[1].tags.module, 'foo', 'Module matches' ); + + mw.sentry.report( 'some-topic', { exception: 42, source: 'Deep Thought', id: '123', context: { foo: 'bar' } } ); + assert.strictEqual( raven.captureException.lastCall.args[1].tags.foo, 'bar', 'Custom context matches' ); + } ); +}( mediaWiki, jQuery ) ); -- To view, visit https://gerrit.wikimedia.org/r/192697 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If9b2b0d798546e4ccf5f3de5821ad4e3db1aa2cd Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Sentry Gerrit-Branch: master Gerrit-Owner: Gergő Tisza <gti...@wikimedia.org> Gerrit-Reviewer: Gilles <gdu...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits