2014-10-29 01:19:52 +00:00
|
|
|
/*!
|
|
|
|
* VisualEditor MediaWiki event subscriber.
|
|
|
|
*
|
|
|
|
* Subscribes to ve.track() events and routes them to mw.track().
|
|
|
|
*
|
2015-01-08 23:54:03 +00:00
|
|
|
* @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
|
2014-10-29 01:19:52 +00:00
|
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
|
|
*/
|
|
|
|
|
|
|
|
( function () {
|
2015-02-21 02:41:33 +00:00
|
|
|
if ( mw.loader.getState( 'schema.Edit' ) === null ) {
|
|
|
|
// Only route any events into the Edit schema if the module is actually available.
|
|
|
|
// It won't be if EventLogging is installed but WikimediaEvents is not.
|
|
|
|
return;
|
|
|
|
}
|
2014-10-29 01:19:52 +00:00
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
var timing = {},
|
2014-10-29 01:19:52 +00:00
|
|
|
editingSessionId = mw.user.generateRandomSessionId();
|
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
function computeDuration( action, event, timeStamp ) {
|
|
|
|
if ( event.timing !== undefined ) {
|
|
|
|
return event.timing;
|
|
|
|
}
|
|
|
|
|
2014-10-29 01:19:52 +00:00
|
|
|
switch ( action ) {
|
|
|
|
case 'init':
|
|
|
|
// Account for second opening
|
2015-02-20 20:11:14 +00:00
|
|
|
return timeStamp - Math.max(
|
|
|
|
window.mediaWikiLoadStart,
|
|
|
|
timing.saveSuccess || 0,
|
|
|
|
timing.abort || 0
|
2014-10-29 01:19:52 +00:00
|
|
|
);
|
|
|
|
case 'ready':
|
2015-02-20 20:11:14 +00:00
|
|
|
return timeStamp - timing.init;
|
2014-10-29 01:19:52 +00:00
|
|
|
case 'saveIntent':
|
2015-02-20 20:11:14 +00:00
|
|
|
return timeStamp - timing.ready;
|
2014-10-29 01:19:52 +00:00
|
|
|
case 'saveAttempt':
|
2015-02-20 20:11:14 +00:00
|
|
|
return timeStamp - timing.saveIntent;
|
2014-10-29 01:19:52 +00:00
|
|
|
case 'saveSuccess':
|
|
|
|
case 'saveFailure':
|
|
|
|
// HERE BE DRAGONS: the caller must compute these themselves
|
|
|
|
// for sensible results. Deliberately sabotage any attempts to
|
|
|
|
// use the default by returning -1
|
|
|
|
mw.log.warn( 've.init.mw.trackSubscriber: Do not rely on default timing value for saveSuccess/saveFailure' );
|
|
|
|
return -1;
|
|
|
|
case 'abort':
|
2015-02-20 20:11:14 +00:00
|
|
|
switch ( event.type ) {
|
2014-10-29 01:19:52 +00:00
|
|
|
case 'preinit':
|
2015-02-20 20:11:14 +00:00
|
|
|
return timeStamp - timing.init;
|
2014-10-29 01:19:52 +00:00
|
|
|
case 'nochange':
|
|
|
|
case 'switchwith':
|
|
|
|
case 'switchwithout':
|
|
|
|
case 'abandon':
|
2015-02-20 20:11:14 +00:00
|
|
|
return timeStamp - timing.ready;
|
2014-10-29 01:19:52 +00:00
|
|
|
case 'abandonMidsave':
|
2015-02-20 20:11:14 +00:00
|
|
|
return timeStamp - timing.saveAttempt;
|
2014-10-29 01:19:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
mw.log.warn( 've.init.mw.trackSubscriber: Unrecognized action', action );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
ve.trackSubscribe( 'mwedit.', function ( topic, data, timeStamp ) {
|
|
|
|
var action = topic.split( '.' )[1],
|
|
|
|
event;
|
|
|
|
|
2015-02-21 21:02:08 +00:00
|
|
|
timeStamp = timeStamp || this.timeStamp; // I8e82acc12 back-compat
|
|
|
|
timing[action] = timeStamp;
|
2015-02-20 20:11:14 +00:00
|
|
|
|
|
|
|
if ( action === 'init' ) {
|
|
|
|
// Regenerate editingSessionId
|
|
|
|
editingSessionId = mw.user.generateRandomSessionId();
|
|
|
|
}
|
2014-12-06 19:11:02 +00:00
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
event = $.extend( {
|
2015-02-21 21:02:08 +00:00
|
|
|
version: 1,
|
|
|
|
action: action,
|
|
|
|
editor: 'visualeditor',
|
|
|
|
platform: 'desktop', // FIXME
|
|
|
|
integration: ve.init && ve.init.target && ve.init.target.constructor.static.integrationType || 'page',
|
|
|
|
'page.id': mw.config.get( 'wgArticleId' ),
|
|
|
|
'page.title': mw.config.get( 'wgPageName' ),
|
|
|
|
'page.ns': mw.config.get( 'wgNamespaceNumber' ),
|
|
|
|
'page.revid': mw.config.get( 'wgRevisionId' ),
|
|
|
|
'page.length': -1, // FIXME
|
|
|
|
editingSessionId: editingSessionId,
|
|
|
|
'user.id': mw.user.getId(),
|
|
|
|
'user.editCount': mw.config.get( 'wgUserEditCount', 0 ),
|
|
|
|
'mediawiki.version': mw.config.get( 'wgVersion' )
|
2015-02-20 20:11:14 +00:00
|
|
|
}, data );
|
2014-10-29 01:19:52 +00:00
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
if ( mw.user.isAnon() ) {
|
|
|
|
event['user.class'] = 'IP';
|
|
|
|
}
|
|
|
|
|
|
|
|
event['action.' + action + '.type'] = event.type;
|
|
|
|
event['action.' + action + '.mechanism'] = event.mechanism;
|
|
|
|
event['action.' + action + '.timing'] = Math.round( computeDuration( action, event, this.timeStamp ) );
|
2014-10-29 01:19:52 +00:00
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
// Remove renamed properties
|
|
|
|
delete event.type;
|
|
|
|
delete event.mechanism;
|
|
|
|
delete event.timing;
|
|
|
|
|
|
|
|
mw.track( 'event.Edit', event );
|
|
|
|
} );
|
2014-10-29 01:19:52 +00:00
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
ve.trackSubscribe( 'mwtiming.', function ( topic, data ) {
|
|
|
|
// Add type for save errors; not in the topic for stupid historical reasons
|
|
|
|
if ( topic === 'mwtiming.performance.user.saveError' ) {
|
|
|
|
topic = topic + '.' + data.type;
|
2014-10-29 01:19:52 +00:00
|
|
|
}
|
|
|
|
|
2015-02-20 20:11:14 +00:00
|
|
|
// Map mwtiming.foo --> timing.ve.foo.mobile
|
|
|
|
topic = topic.replace( /^mwtiming/, 'timing.ve.' + data.targetName );
|
|
|
|
mw.track( topic, data.duration );
|
2014-10-29 01:19:52 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
} )();
|