eventlogger module for ULS

Separating event logging out of ULS functionality. Event logging
is now loosely coupled with ULS. ULS core modules can emit an event
whenever EventLogging is required. The eventlogger module will act
on the event if configured.

Change-Id: I59dfcfb25c1acb85376b56239f2355ee7c4aff1e
This commit is contained in:
Santhosh Thottingal
2013-08-14 18:17:33 +05:30
committed by Amir E. Aharoni
parent 8defd1f4a8
commit 117cc5bf46
8 changed files with 215 additions and 98 deletions

View File

@@ -159,18 +159,17 @@
new mw.Api().parse( $.i18n( 'ext-uls-display-settings-anon-log-in-cta' ) )
.done( function ( parsedCta ) {
$loginCta.html( parsedCta );
// Because browsers navigate away when clicking a link,
// we are are overriding the normal click behavior to
// allow the event be logged first - currently there is no
// local queue for events. The timeout is there to make sure
// the user gets to the new page even if event logging is slow
// or fails.
$loginCta.find( 'a' ).click( function ( event ) {
event.preventDefault();
mw.uls.logEvent( { action: 'login-click' }, 500 )
.always( function () {
window.location.href = event.target.href;
} );
// Because browsers navigate away when clicking a link,
// we are are overriding the normal click behavior to
// allow the event be logged first - currently there is no
// local queue for events. The timeout is there to make sure
// the user gets to the new page even if event logging is slow
// or fails.
mw.hook( 'mw.uls.login.click' ).fire( function () {
window.location.href = event.target.href;
} );
} );
} );
@@ -323,10 +322,7 @@
$moreLanguagesButton.on( 'click', function () {
displaySettings.$parent.hide();
mw.uls.logEvent( {
action: 'more-languages-access',
context: 'interface'
} );
mw.hook( 'mw.uls.interface.morelanguages' ).fire();
} );
},

View File

@@ -0,0 +1,181 @@
/**
* ULS Event logger
*
* Copyright (C) 2012-2013 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon Harris,
* Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland and other
* contributors. See CREDITS for a list.
*
* UniversalLanguageSelector is dual licensed GPLv2 or later and MIT. You don't
* have to do anything special to choose one license or the other and you don't
* have to notify anyone which license you are using. You are free to use
* UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @file
* @ingroup Extensions
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
( function ( $, mw ) {
'use strict';
/**
* ULS Event logger
*
* @since 2013.08
* @see https://meta.wikimedia.org/wiki/Schema:UniversalLanguageSelector
*/
function ULSEventLogger() {
this.logEventQueue = $.Callbacks( 'memory once' );
this.init();
this.listen();
}
ULSEventLogger.prototype = {
init: function () {
var eventLogger = this;
// Set event defaults and make the
mw.eventLog.setDefaults( 'UniversalLanguageSelector', {
version: 1,
token: mw.user.id(),
contentLanguage: mw.config.get( 'wgContentLanguage' ),
interfaceLanguage: mw.config.get( 'wgUserLanguage' )
} );
eventLogger.logEventQueue.fire();
},
/**
* Local wrapper for 'mw.eventLog.logEvent' which handles default params
* and ensures the correct schema is loaded.
*
* @param {Object} event Event action and optional fields
* @param {int} [timeout] Fail the request if it is not completed within
* the specified timeout. Can be use for example to log actions that
* cause the browser to navigate to other pages.
* @return {jQuery.Promise} jQuery Promise object for the logging call
*/
log: function ( event, timeout ) {
// We need to create our own deferred for two reasons:
// - logEvent might not be executed immediately
// - we cannot reject a promise returned by it
// So we proxy the original promises status updates
// and register our timeout if requested (for links).
var deferred = $.Deferred();
this.logEventQueue.add( function () {
mw.eventLog.logEvent( 'UniversalLanguageSelector', event )
.done( deferred.resolve )
.fail( deferred.reject );
} );
if ( timeout !== undefined ) {
window.setTimeout( deferred.reject, timeout );
}
return deferred.promise();
},
/**
* Listen for event logging
*/
listen: function () {
// Register handlers for event logging triggers
mw.hook( 'mw.uls.settings.open' ).add( $.proxy( this.ulsSettingsOpen, this ) );
mw.hook( 'mw.uls.language.revert' ).add( $.proxy( this.ulsLanguageRevert, this ) );
mw.hook( 'mw.uls.ime.enable' ).add( $.proxy( this.enableIME, this ) );
mw.hook( 'mw.uls.ime.disable' ).add( $.proxy( this.disableIME, this ) );
mw.hook( 'mw.uls.login.click' ).add( $.proxy( this.loginClick, this ) );
mw.hook( 'mw.uls.ime.morelanguages' ).add( $.proxy( this.imeMoreLanguages, this ) );
mw.hook( 'mw.uls.interface.morelanguages' ).add( $.proxy( this.interfaceMoreLanguages, this ) );
mw.hook( 'mw.uls.interface.language.change' ).add( $.proxy( this.interfaceLanguageChange, this ) );
},
/**
* Log language settings open
* @param {Array} args
*/
ulsSettingsOpen: function ( args ) {
this.log( {
action: 'settings-open',
context: args
} );
},
/**
* Log language revert
*
* @param {Function} callback
*/
ulsLanguageRevert: function ( callback ) {
this.log( { action: 'ui-lang-revert' }, 500 ).always( callback );
},
/**
* Log IME disabling
*/
disableIME: function () {
this.log( { action: 'ime-disable' } );
},
/**
* Log IME enabling
*/
enableIME: function () {
this.log( { action: 'ime-enable' } );
},
/**
* Log login link click in display settings. Since this will navigate
* away from the current page, provide a callback option.
*
* If page is navigating away, event logging will fail because it is not
* yet completed. With the callback, the navigation can be executed in
* callback. The waiting for callback is not indefinite, but with a timeout.
*
* @param {Function} callback
*/
loginClick: function ( callback ) {
this.log( { action: 'login-click' }, 500 ).always( callback );
},
/**
* More languages item in IME menu is clicked
*/
imeMoreLanguages: function () {
this.log( {
action: 'more-languages-access',
context: 'ime'
} );
},
/**
* Log interface language change
*
* @param {string} language language code
* @param {Function} callback
*/
interfaceLanguageChange: function ( language, callback ) {
this.log( {
action: 'language-change',
context: 'interface',
interfaceLanguage: language
}, 500 ).always( callback );
},
/**
* More languages in display settings is clicked
*/
interfaceMoreLanguages: function () {
this.log( {
action: 'more-languages-access',
context: 'interface'
} );
}
};
mw.uls = mw.uls || {};
mw.uls.eventlogger= new ULSEventLogger();
}( jQuery, mediaWiki ) );

View File

@@ -81,13 +81,13 @@
disable: function () {
this.registry.isDirty = true;
this.registry.enable = false;
mw.uls.logEvent( { action: 'ime-disable' } );
mw.hook( 'mw.uls.ime.disable' ).fire();
},
enable: function () {
this.registry.isDirty = true;
this.registry.enable = true;
mw.uls.logEvent( { action: 'ime-enable' } );
mw.hook( 'mw.uls.ime.enable' ).fire();
},
isEnabled: function () {

View File

@@ -33,8 +33,7 @@
var jsonLoader = null,
initialized = false,
currentLang = mw.config.get( 'wgUserLanguage' ),
logEventQueue = $.Callbacks( 'memory once' );
currentLang = mw.config.get( 'wgUserLanguage' );
mw.uls = mw.uls || {};
mw.uls.previousLanguagesCookie = 'uls-previous-languages';
@@ -47,11 +46,7 @@
mw.uls.changeLanguage = function ( language ) {
var uri = new mw.Uri( window.location.href );
mw.uls.logEvent( {
action: 'language-change',
context: 'interface',
interfaceLanguage: language
}, 500 ).always( function () {
mw.hook( 'mw.uls.interface.language.change' ).fire( language, function () {
uri.extend( {
setlang: language
} );
@@ -170,39 +165,6 @@
return !$.client.test( blacklist, null, true );
}
/**
* Local wrapper for 'mw.eventLog.logEvent' which handles default params
* and ensures the correct schema is loaded.
*
* @param {Object} event Event action and optional fields
* @param {int} [timeout] Fail the request if it is not completed within
* the specified timeout. Can be use for example to log actions that
* cause the browser to navigate to other pages.
* @return {jQuery.Promise} jQuery Promise object for the logging call
* @since 2013.07
* @see https://meta.wikimedia.org/wiki/Schema:UniversalLanguageSelector
*/
mw.uls.logEvent = function ( event, timeout ) {
// We need to create our own deferred for two reasons:
// - logEvent might not be executed immediately
// - we cannot reject a promise returned by it
// So we proxy the original promises status updates
// and register our timeout if requested (for links).
var deferred = $.Deferred();
logEventQueue.add( function () {
mw.eventLog.logEvent( 'UniversalLanguageSelector', event )
.done( deferred.resolve )
.fail( deferred.reject );
} );
if ( timeout !== undefined ) {
window.setTimeout( deferred.reject, timeout );
}
return deferred.promise();
};
/**
* Initialize ULS front-end and its i18n.
*
@@ -224,20 +186,6 @@
return;
}
// If EventLogging integration is enabled, set event defaults and make the
// the function call event logging with correct schema.
if ( mw.config.get( 'wgULSEventLogging' ) ) {
mw.loader.using( 'schema.UniversalLanguageSelector', function () {
mw.eventLog.setDefaults( 'UniversalLanguageSelector', {
version: 1,
token: mw.user.id(),
contentLanguage: mw.config.get( 'wgContentLanguage' ),
interfaceLanguage: currentLang
} );
logEventQueue.fire();
} );
}
/*
* The 'als' is used in a non-standard way in MediaWiki -
* it may be used to represent the Allemanic language,

View File

@@ -391,10 +391,7 @@
$moreLanguagesButton.on( 'click', function () {
inputSettings.$parent.hide();
mw.uls.logEvent( {
action: 'more-languages-access',
context: 'ime'
} );
mw.hook( 'mw.uls.ime.morelanguages' ).fire();
} );
},

View File

@@ -91,7 +91,7 @@
.click();
} );
}
mw.hook( 'mw.uls.settings.open' ).fire( 'uls' );
uls.hide();
} );
}
@@ -121,11 +121,7 @@
} );
}
mw.uls.logEvent( {
action: 'settings-open',
context: 'uls'
} );
mw.hook( 'mw.uls.settings.open' ).fire( 'uls' );
uls.hide();
} );
}
@@ -252,10 +248,9 @@
// there wont be multiple event handlers bound to same click.
$( 'a.uls-prevlang-link' ).on( 'click.ulstipsy', function ( event ) {
event.preventDefault();
mw.uls.logEvent( { action: 'ui-lang-revert' }, 500 )
.always( function () {
mw.uls.changeLanguage( event.target.lang );
} );
mw.hook( 'mw.uls.language.revert' ).fire( function () {
mw.uls.changeLanguage( event.target.lang );
} );
} );
tipsyTimer = window.setTimeout( function () {
hideTipsy();
@@ -333,10 +328,7 @@
if ( languagesettings ) {
if ( !languagesettings.shown ) {
mw.uls.logEvent( {
action: 'settings-open',
context: eventParams && eventParams.source || 'interlanguage'
} );
mw.hook( 'mw.uls.settings.open' ).fire( eventParams && eventParams.source || 'interlanguage' );
}
} else {
// Initialize the Language settings window
@@ -385,10 +377,7 @@
if ( languagesettings ) {
if ( !languagesettings.shown ) {
mw.uls.logEvent( {
action: 'settings-open',
context: eventParams && eventParams.source || 'personal'
} );
mw.hook( 'mw.uls.settings.open' ).fire( eventParams && eventParams.source || 'personal' );
}
} else {
mw.loader.using( mw.uls.languageSettingsModules, function () {
@@ -407,10 +396,7 @@
if ( uls ) {
if ( !uls.shown ) {
mw.uls.logEvent( {
action: 'settings-open',
context: eventParams && eventParams.source || 'personal'
} );
mw.hook( 'mw.uls.settings.open' ).fire( eventParams && eventParams.source || 'personal' );
}
} else {
// ULS options that are common to all modes of showing