Phuedx has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/325337

Change subject: WIP: Log events
......................................................................

WIP: Log events

Bug: T152225
Change-Id: I02eeb6a981107fa2c643b158f87529612d5240fd
---
M extension.json
M resources/ext.popups/actions.js
M resources/ext.popups/boot.js
A resources/ext.popups/changeListeners/eventLogging.js
M resources/ext.popups/reducers.js
A resources/ext.popups/schema.js
A tests/qunit/ext.popups/changeListeners/eventLogging.test.js
M tests/qunit/ext.popups/reducers.eventLogging.test.js
A tests/qunit/ext.popups/schema.test.js
9 files changed, 252 insertions(+), 4 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Popups 
refs/changes/37/325337/1

diff --git a/extension.json b/extension.json
index 055ac17..828993b 100644
--- a/extension.json
+++ b/extension.json
@@ -68,10 +68,12 @@
                                "resources/ext.popups/reducers.js",
                                "resources/ext.popups/changeListener.js",
                                "resources/ext.popups/renderer.js",
+                               "resources/ext.popups/schema.js",
                                
"resources/ext.popups/changeListeners/footerLink.js",
                                
"resources/ext.popups/changeListeners/linkTitle.js",
                                
"resources/ext.popups/changeListeners/render.js",
                                
"resources/ext.popups/changeListeners/previewCount.js",
+                               
"resources/ext.popups/changeListeners/eventLogging.js",
                                "resources/ext.popups/boot.js"
                        ],
                        "templates": {
diff --git a/resources/ext.popups/actions.js b/resources/ext.popups/actions.js
index 966379b..c90e9a3 100644
--- a/resources/ext.popups/actions.js
+++ b/resources/ext.popups/actions.js
@@ -19,7 +19,8 @@
                        PREVIEW_CLICK: 'PREVIEW_CLICK',
                        COG_CLICK: 'COG_CLICK',
                        SETTINGS_DIALOG_RENDERED: 'SETTINGS_DIALOG_RENDERED',
-                       SETTINGS_DIALOG_CLOSED: 'SETTINGS_DIALOG_CLOSED'
+                       SETTINGS_DIALOG_CLOSED: 'SETTINGS_DIALOG_CLOSED',
+                       EVENT_LOGGING_QUEUE_DRAINED: 
'EVENT_LOGGING_QUEUE_DRAINED'
                },
                FETCH_START_DELAY = 500, // ms.
                ABANDON_END_DELAY = 300; // ms.
@@ -232,6 +233,18 @@
                };
        };
 
+       /**
+        * Represents the Event Logging queue being drained by the
+        * `mw.popups.changeListeners.eventLogging` change listener.
+        *
+        * @return {Object}
+        */
+       actions.eventLoggingQueueDrained = function () {
+               return {
+                       type: types.EVENT_LOGGING_QUEUE_DRAINED
+               };
+       };
+
        mw.popups.actions = actions;
        mw.popups.actionTypes = types;
 
diff --git a/resources/ext.popups/boot.js b/resources/ext.popups/boot.js
index 6729599..a09c67e 100644
--- a/resources/ext.popups/boot.js
+++ b/resources/ext.popups/boot.js
@@ -30,8 +30,9 @@
         * @param {Redux.Store} store
         * @param {Object} actions
         * @param {ext.popups.UserSettings} userSettings
+        * @param {mw.eventLog.Schema} schema
         */
-       function registerChangeListeners( store, actions, userSettings ) {
+       function registerChangeListeners( store, actions, userSettings, schema 
) {
 
                // Sugar.
                var changeListeners = mw.popups.changeListeners,
@@ -41,6 +42,10 @@
                registerChangeListener( store, changeListeners.linkTitle() );
                registerChangeListener( store, changeListeners.render( actions 
) );
                registerChangeListener( store, changeListeners.previewCount( 
userSettings ) );
+
+               if ( window.QUnit === undefined ) {
+                       registerChangeListener( store, 
changeListeners.eventLogging( actions, schema ) );
+               }
        }
 
        /**
@@ -74,9 +79,12 @@
                        generateToken = mw.user.generateRandomSessionId,
                        gateway = createGateway(),
                        userSettings = mw.popups.createUserSettings( 
mw.storage, mw.user ),
-                       isUserInCondition;
+                       isUserInCondition,
+                       schema;
 
                isUserInCondition = mw.popups.createExperiment( mw.config, 
mw.user, userSettings );
+
+               schema = mw.popups.createSchema( mw.config, window.navigator );
 
                // If debug mode is enabled, then enable Redux DevTools.
                if ( mw.config.get( 'debug' ) === true ) {
@@ -90,7 +98,7 @@
                        ) )
                );
                actions = createBoundActions( store );
-               registerChangeListeners( store, actions, userSettings );
+               registerChangeListeners( store, actions, userSettings, schema );
 
                actions.boot(
                        isUserInCondition,
diff --git a/resources/ext.popups/changeListeners/eventLogging.js 
b/resources/ext.popups/changeListeners/eventLogging.js
new file mode 100644
index 0000000..19adc2d
--- /dev/null
+++ b/resources/ext.popups/changeListeners/eventLogging.js
@@ -0,0 +1,24 @@
+( function ( mw, $ ) {
+
+       /**
+        *
+        * @param {Object} boundActions
+        * @param {mw.eventLog.Schema} schema
+        * @return {ext.popups.ChangeListener}
+        */
+       mw.popups.changeListeners.eventLogging = function ( boundActions, 
schema ) {
+               return function ( _, state ) {
+                       var queue = state.eventLogging.queue,
+                               baseData = state.eventLogging.baseData;
+
+                       if ( queue.length ) {
+                               $.each( queue, function ( _, data ) {
+                                       schema.log( $.extend( true, {}, 
baseData, data ) );
+                               } );
+
+                               boundActions.eventLoggingQueueDrained();
+                       }
+               };
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/ext.popups/reducers.js b/resources/ext.popups/reducers.js
index c8f28d5..d91e0ed 100644
--- a/resources/ext.popups/reducers.js
+++ b/resources/ext.popups/reducers.js
@@ -172,6 +172,11 @@
                                        } )
                                } );
 
+                       case mw.popups.actionTypes.EVENT_LOGGING_QUEUE_DRAINED:
+                               return nextState( state, {
+                                       queue: []
+                               } );
+
                        default:
                                return state;
                }
diff --git a/resources/ext.popups/schema.js b/resources/ext.popups/schema.js
new file mode 100644
index 0000000..88c41b3
--- /dev/null
+++ b/resources/ext.popups/schema.js
@@ -0,0 +1,18 @@
+( function ( mw, $ ) {
+
+       /**
+        * @param {mw.Map} config
+        * @param {Navigator} navigator
+        * @return {mw.eventLog.Schema}
+        */
+       mw.popups.createSchema = function ( config, navigator ) {
+               var samplingRate = config.get( 
'wgPopupsSchemaPopupsSamplingRate', 0 );
+
+               if ( !navigator || !$.isFunction( navigator.sendBeacon ) ) {
+                       samplingRate = 0;
+               }
+
+               return new mw.eventLog.Schema( 'Popups', samplingRate );
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/tests/qunit/ext.popups/changeListeners/eventLogging.test.js 
b/tests/qunit/ext.popups/changeListeners/eventLogging.test.js
new file mode 100644
index 0000000..d4f5767
--- /dev/null
+++ b/tests/qunit/ext.popups/changeListeners/eventLogging.test.js
@@ -0,0 +1,92 @@
+( function ( mw ) {
+
+       QUnit.module( 'ext.popups/changeListeners/eventLogging', {
+               setup: function () {
+                       this.boundActions = {
+                               eventLoggingQueueDrained: this.sandbox.spy()
+                       };
+
+                       this.schema = {
+                               log: this.sandbox.spy()
+                       };
+
+                       this.changeListener = 
mw.popups.changeListeners.eventLogging(
+                               this.boundActions,
+                               this.schema
+                       );
+               }
+       } );
+
+       QUnit.test( 'it should log all the queued events individually', 
function ( assert ) {
+               var baseData,
+                       state;
+
+               assert.expect( 2 );
+
+               baseData = {
+                       foo: 'bar',
+                       baz: 'qux'
+               };
+
+               state = {
+                       eventLogging: {
+                               baseData: baseData,
+                               queue: [
+                                       {
+                                               action: 'pageLoaded'
+                                       },
+                                       {
+                                               action: 'opened'
+                                       }
+                               ]
+                       }
+               };
+
+               this.changeListener( undefined, state );
+
+               assert.ok(
+                       this.schema.log.calledWith( {
+                               foo: 'bar',
+                               baz: 'qux',
+                               action: 'pageLoaded'
+                       } ),
+                       'It should merge the event data and the accumulated 
base data.'
+               );
+
+               assert.ok( this.schema.log.calledWith( {
+                       foo: 'bar',
+                       baz: 'qux',
+                       action: 'opened'
+               } ) );
+       } );
+
+       QUnit.test(
+               'it should call the eventLoggingQueueDrained bound action 
creator',
+               function ( assert ) {
+                       var state = {
+                               eventLogging: {
+                                       baseData: {},
+                                       queue: []
+                               }
+                       };
+
+                       this.changeListener( undefined, state );
+
+                       assert.notOk(
+                               
this.boundActions.eventLoggingQueueDrained.called,
+                               'It shouldn\'t call the 
eventLoggingQueueDrained bound action creator if the queue is empty.'
+                       );
+
+                       // ---
+
+                       state.eventLogging.queue.push( {
+                               action: 'pageLoaded'
+                       } );
+
+                       this.changeListener( undefined, state );
+
+                       assert.ok( 
this.boundActions.eventLoggingQueueDrained.called );
+               }
+       );
+
+}( mediaWiki ) );
diff --git a/tests/qunit/ext.popups/reducers.eventLogging.test.js 
b/tests/qunit/ext.popups/reducers.eventLogging.test.js
index 2a3a7d0..8190a4a 100644
--- a/tests/qunit/ext.popups/reducers.eventLogging.test.js
+++ b/tests/qunit/ext.popups/reducers.eventLogging.test.js
@@ -88,4 +88,32 @@
                );
        } );
 
+       QUnit.test( 'EVENT_LOGGING_QUEUE_DRAINED', function ( assert ) {
+               var state,
+                       action;
+
+               state = {
+                       queue: [
+                               {
+                                       action: 'pageLoaded'
+                               },
+                               {
+                                       action: 'opened'
+                               }
+                       ]
+               };
+
+               action = {
+                       type: 'EVENT_LOGGING_QUEUE_DRAINED'
+               };
+
+               assert.deepEqual(
+                       mw.popups.reducers.eventLogging( state, action ),
+                       {
+                               queue: []
+                       },
+                       'It resets the queue.'
+               );
+       } );
+
 }( mediaWiki ) );
diff --git a/tests/qunit/ext.popups/schema.test.js 
b/tests/qunit/ext.popups/schema.test.js
new file mode 100644
index 0000000..2989700
--- /dev/null
+++ b/tests/qunit/ext.popups/schema.test.js
@@ -0,0 +1,58 @@
+( function ( mw ) {
+
+       QUnit.module( 'ext.popups/schema', {
+               setup: function () {
+                       this.config = new mw.Map();
+                       this.config.set( 'wgPopupsSchemaPopupsSamplingRate', 1 
);
+
+                       this.navigator = {
+                               sendBeacon: function () {}
+                       };
+
+                       // Stub out the mw.eventLog.Schema constructor function.
+                       this.sandbox.stub( mw.eventLog, 'Schema', function () 
{} );
+               }
+       } );
+
+       QUnit.test( 'it should use $wgPopupsSchemaPopupsSamplingRate as the 
sampling rate', function ( assert ) {
+               assert.expect( 2 );
+
+               mw.popups.createSchema( this.config, this.navigator );
+
+               assert.ok( mw.eventLog.Schema.calledWith( 'Popups', 1 ) );
+
+               // ---
+
+               mw.popups.createSchema( new mw.Map(), this.navigator );
+
+               assert.ok(
+                       mw.eventLog.Schema.calledWith( 'Popups', 0 ),
+                       'If $wgPopupsSchemaPopupsSamplingRate isn\'t set, then 
the sampling rate should be 0.'
+               );
+       } );
+
+       QUnit.test( 'it should use a 0 sampling rate when sendBeacon isn\'t 
supported', function ( assert ) {
+               var expectedArgs = [ 'Popups', 0 ];
+
+               assert.expect( 3 );
+
+               mw.popups.createSchema( this.config, undefined );
+
+               assert.deepEqual( mw.eventLog.Schema.getCall( 0 ).args, 
expectedArgs );
+
+               // ---
+
+               mw.popups.createSchema( this.config, { } );
+
+               assert.deepEqual( mw.eventLog.Schema.getCall( 1 ).args, 
expectedArgs );
+
+               // ---
+
+               mw.popups.createSchema( this.config, {
+                       sendBeacon: 'NOT A FUNCTION'
+               } );
+
+               assert.deepEqual( mw.eventLog.Schema.getCall( 1 ).args, 
expectedArgs );
+       } );
+
+}( mediaWiki ) );

-- 
To view, visit https://gerrit.wikimedia.org/r/325337
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I02eeb6a981107fa2c643b158f87529612d5240fd
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Popups
Gerrit-Branch: mpga
Gerrit-Owner: Phuedx <samsm...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to