Merge "Log image dimensions"

This commit is contained in:
jenkins-bot 2014-09-30 15:15:54 +00:00 committed by Gerrit Code Review
commit 2203f89236
9 changed files with 216 additions and 28 deletions

View file

@ -45,6 +45,16 @@ if ( !isset( $wgMediaViewerAttributionLoggingSamplingFactor ) ) {
$wgMediaViewerAttributionLoggingSamplingFactor = false;
}
if ( !isset( $wgMediaViewerDimensionLoggingSamplingFactor ) ) {
/**
* If set, records whether image dimension data was available. A value of 1000 means there will be an
* 1:1000 chance to log the dimension event.
* False if unset.
* @var int|bool
*/
$wgMediaViewerDimensionLoggingSamplingFactor = false;
}
if ( !isset( $wgMediaViewerActionLoggingSamplingFactorMap ) ) {
/**
* If set, records user actions via EventLogging and applies a sampling factor according to the map. A "default" key in the map must be set.
@ -813,6 +823,7 @@ $wgResourceModules += array(
'mmv.provider',
'mmv.routing',
'mmv.logging.DurationLogger',
'mmv.logging.DimensionLogger',
'jquery.fullscreen',
'jquery.hidpi',
'jquery.scrollTo',
@ -902,6 +913,19 @@ $wgResourceModules += array(
),
),
'mmv.logging.DimensionLogger' => $wgMediaViewerResourceTemplate + array(
'scripts' => array(
'mmv/logging/mmv.logging.DimensionLogger.js',
),
'dependencies' => array(
'mmv.base',
'mmv.logging.Logger',
'oojs',
'jquery.hidpi',
),
),
'mmv.head' => $wgMediaViewerResourceTemplate + array(
'scripts' => array(
'mmv/mmv.head.js',
@ -936,10 +960,13 @@ $wgExtensionFunctions[] = function () {
$wgEventLoggingSchemas[ 'MultimediaViewerNetworkPerformance' ] = 7917896;
$wgEventLoggingSchemas[ 'MultimediaViewerDuration' ] = 8572641;
$wgEventLoggingSchemas[ 'MultimediaViewerAttribution' ] = 9758179;
$wgEventLoggingSchemas[ 'MultimediaViewerDimensions' ] = 10014238;
$wgResourceModules['mmv.logging.ActionLogger']['dependencies'][] = 'ext.eventLogging';
$wgResourceModules['mmv.logging.Performance']['dependencies'][] = 'ext.eventLogging';
$wgResourceModules['mmv.logging.DurationLogger']['dependencies'][] = 'ext.eventLogging';
$wgResourceModules['mmv.logging.AttributionLogger']['dependencies'][] = 'ext.eventLogging';
$wgResourceModules['mmv.logging.DimensionLogger']['dependencies'][] = 'ext.eventLogging';
}
};

View file

@ -139,8 +139,9 @@ class MultimediaViewerHooks {
* @return bool
*/
public static function resourceLoaderGetConfigVars( &$vars ) {
global $wgAPIPropModules, $wgMediaViewerActionLoggingSamplingFactorMap, $wgNetworkPerformanceSamplingFactor, $wgMediaViewerDurationLoggingSamplingFactor,
$wgMediaViewerAttributionLoggingSamplingFactor, $wgMediaViewerIsInBeta, $wgMediaViewerUseThumbnailGuessing;
global $wgMediaViewerActionLoggingSamplingFactorMap, $wgNetworkPerformanceSamplingFactor,
$wgMediaViewerDurationLoggingSamplingFactor, $wgMediaViewerAttributionLoggingSamplingFactor,
$wgMediaViewerDimensionLoggingSamplingFactor, $wgMediaViewerIsInBeta, $wgMediaViewerUseThumbnailGuessing;
$vars['wgMultimediaViewer'] = array(
'infoLink' => self::$infoLink,
'discussionLink' => self::$discussionLink,
@ -150,6 +151,7 @@ class MultimediaViewerHooks {
'networkPerformanceSamplingFactor' => $wgNetworkPerformanceSamplingFactor,
'actionLoggingSamplingFactorMap' => $wgMediaViewerActionLoggingSamplingFactorMap,
'attributionSamplingFactor' => $wgMediaViewerAttributionLoggingSamplingFactor,
'dimensionSamplingFactor' => $wgMediaViewerDimensionLoggingSamplingFactor,
'tooltipDelay' => 1000,
);
$vars['wgMediaViewer'] = true;
@ -192,6 +194,8 @@ class MultimediaViewerHooks {
'tests/qunit/mmv/logging/mmv.logging.DurationLogger.test.js',
'tests/qunit/mmv/logging/mmv.logging.Performance.test.js',
'tests/qunit/mmv/logging/mmv.logging.ActionLogger.test.js',
'tests/qunit/mmv/logging/mmv.logging.AttributionLogger.test.js',
'tests/qunit/mmv/logging/mmv.logging.DimensionLogger.test.js',
'tests/qunit/mmv/model/mmv.model.test.js',
'tests/qunit/mmv/model/mmv.model.IwTitle.test.js',
'tests/qunit/mmv/model/mmv.model.TaskQueue.test.js',

View file

@ -63,5 +63,6 @@
this.log( data );
};
mw.mmv.logging.AttributionLogger = AttributionLogger;
mw.mmv.attributionLogger = new AttributionLogger();
}( mediaWiki, jQuery, OO ) );

View file

@ -0,0 +1,76 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $, oo ) {
var DL;
/**
* Writes EventLogging entries for size measurements related to thumbnail size selection
* (bucket size vs. display size).
* @class mw.mmv.logging.DimensionLogger
* @extends mw.mmv.logging.Logger
* @constructor
*/
function DimensionLogger() {}
oo.inheritClass( DimensionLogger, mw.mmv.logging.Logger );
DL = DimensionLogger.prototype;
/**
* @override
* @inheritdoc
*/
DL.samplingFactor = mw.config.get( 'wgMultimediaViewer' ).dimensionSamplingFactor;
/**
* @override
* @inheritdoc
*/
DL.schema = 'MultimediaViewerDimensions';
/**
* Logs dimension data.
* @param {mw.mmv.model.ThumbnailWidth} imageWidths widths of the imagethat will be displayed
* @param {{width: Number, height: Number}} canvasDimensions canvas width and height in CSS pixels
* @param {string} context reason for requesting the image, one of 'show', 'resize', 'preload'
*/
DL.logDimensions = function ( imageWidths, canvasDimensions, context ) {
var data;
data = {
screenWidth: screen.width,
screenHeight: screen.height,
viewportWidth: $( window).width(),
viewportHeight: $( window).height(),
canvasWidth: canvasDimensions.width,
canvasHeight: canvasDimensions.height,
devicePixelRatio: $.devicePixelRatio(),
imgWidth: imageWidths.cssWidth,
imageAspectRatio: imageWidths.cssWidth / imageWidths.cssHeight,
thumbWidth: imageWidths.real,
context: context,
samplingFactor: this.samplingFactor
};
mw.log( 'mw.mmw.logger.DimensionLogger', data );
this.log( data );
};
mw.mmv.logging.DimensionLogger = DimensionLogger;
mw.mmv.dimensionLogger = new DimensionLogger();
}( mediaWiki, jQuery, OO ) );

View file

@ -179,14 +179,18 @@
* @param {mw.mmv.LightboxInterface} ui lightbox that got resized
*/
MMVP.resize = function ( ui ) {
var viewer = this,
image = this.thumbs[ this.currentIndex ].image,
imageWidths;
var imageWidths, canvasDimensions,
viewer = this,
image = this.thumbs[ this.currentIndex ].image;
this.preloadThumbnails();
if ( image ) {
imageWidths = ui.canvas.getCurrentImageWidths();
canvasDimensions = ui.canvas.getDimensions();
mw.mmv.dimensionLogger.logDimensions( imageWidths, canvasDimensions, 'resize' );
this.fetchThumbnailForLightboxImage(
image, imageWidths.real
).then( function( thumbnail, image ) {
@ -229,6 +233,7 @@
*/
MMVP.loadImage = function ( image, initialImage ) {
var imageWidths,
canvasDimensions,
imagePromise,
metadataPromise,
start,
@ -259,10 +264,11 @@
// this.preloadFullscreenThumbnail( image ); // disabled - #474
imageWidths = this.ui.canvas.getCurrentImageWidths();
canvasDimensions = this.ui.canvas.getDimensions();
start = $.now();
mw.mmv.dimensionLogger.logDimensions( imageWidths, canvasDimensions, 'show' );
imagePromise = this.fetchThumbnailForLightboxImage( image, imageWidths.real );
this.resetBlurredThumbnailStates();
@ -614,16 +620,20 @@
this.thumbnailPreloadQueue = this.pushLightboxImagesIntoQueue( function( lightboxImage ) {
return function() {
var imageWidths, canvasDimensions;
// viewer.ui.canvas.getLightboxImageWidths needs the viewer to be open
// because it needs to read the size of visible elements
if ( !viewer.isOpen ) {
return;
}
return viewer.fetchThumbnailForLightboxImage(
lightboxImage,
viewer.ui.canvas.getLightboxImageWidths( lightboxImage ).real
);
imageWidths = viewer.ui.canvas.getLightboxImageWidths( lightboxImage );
canvasDimensions = viewer.ui.canvas.getDimensions();
mw.mmv.dimensionLogger.logDimensions( imageWidths, canvasDimensions, 'preload' );
return viewer.fetchThumbnailForLightboxImage( lightboxImage, imageWidths.real );
};
} );
@ -634,10 +644,11 @@
* Preload the fullscreen size of the current image.
*/
MMVP.preloadFullscreenThumbnail = function( image ) {
this.fetchThumbnailForLightboxImage(
image,
this.ui.canvas.getLightboxImageWidthsForFullscreen( image ).real
);
var imageWidths = this.ui.canvas.getLightboxImageWidthsForFullscreen( image),
canvasDimensions = this.ui.canvas.getDimensions( true );
mw.mmv.dimensionLogger.logDimensions( imageWidths, canvasDimensions, 'preload' );
this.fetchThumbnailForLightboxImage( image, imageWidths.real );
};
/**

View file

@ -339,13 +339,13 @@
};
/**
* Gets the widths for a given lightbox image.
* @param {mw.mmv.LightboxImage} image
* @returns {mw.mmv.model.ThumbnailWidth}
* Returns width and height of the canvas area (i.e. the space available for the image).
* @param {boolean} forFullscreen if true, return size in fullscreen mode; otherwise, return current size
* (which might still be fullscreen mode).
* @return {{width: Number, height: Number}} width and height in CSS pixels
*/
C.getLightboxImageWidths = function ( image ) {
var thumb = image.thumbnail,
$window = $( window ),
C.getDimensions = function ( forFullscreen ) {
var $window = $( window ),
$aboveFold = $( '.mw-mmv-above-fold' ),
isFullscreened = !!$aboveFold.closest( '.jq-fullscreened' ).length,
// Don't rely on this.$imageWrapper's sizing because it's fragile.
@ -354,8 +354,30 @@
availableWidth = $window.width(),
availableHeight = $window.height() - ( isFullscreened ? 0 : $aboveFold.height() );
if ( forFullscreen ) {
return {
width: screen.width,
height: screen.height
};
} else {
return {
width: availableWidth,
height: availableHeight
};
}
};
/**
* Gets the widths for a given lightbox image.
* @param {mw.mmv.LightboxImage} image
* @returns {mw.mmv.model.ThumbnailWidth}
*/
C.getLightboxImageWidths = function ( image ) {
var thumb = image.thumbnail,
canvasDimensions = this.getDimensions();
return this.thumbnailWidthCalculator.calculateWidths(
availableWidth, availableHeight, thumb.width, thumb.height );
canvasDimensions.width, canvasDimensions.height, thumb.width, thumb.height );
};
/**
@ -366,10 +388,11 @@
* @returns {mw.mmv.model.ThumbnailWidth}
*/
C.getLightboxImageWidthsForFullscreen = function ( image ) {
var thumb = image.thumbnail;
var thumb = image.thumbnail,
canvasDimensions = this.getDimensions( true );
return this.thumbnailWidthCalculator.calculateWidths(
screen.width, screen.height, thumb.width, thumb.height );
canvasDimensions.width, canvasDimensions.height, thumb.width, thumb.height );
};
/**

View file

@ -0,0 +1,22 @@
( function ( mw, $ ) {
QUnit.module( 'mmv.logging.AttributionLogger', QUnit.newMwEnvironment() );
QUnit.test( 'log()', 2, function ( assert ) {
var fakeEventLog = { logEvent : this.sandbox.stub() },
logger = new mw.mmv.logging.AttributionLogger(),
image = { author: 'foo', source: 'bar', license: {} },
emptyImage = {};
this.sandbox.stub( logger, 'loadDependencies' ).returns( $.Deferred().resolve() );
this.sandbox.stub( mw, 'log' );
logger.samplingFactor = 1;
logger.setEventLog( fakeEventLog );
logger.logAttribution( image );
assert.ok( true, 'logDimensions() did not throw errors' );
logger.logAttribution( emptyImage );
assert.ok( true, 'logDimensions() did not throw errors for empty image' );
} );
}( mediaWiki, jQuery ) );

View file

@ -0,0 +1,17 @@
( function ( mw, $ ) {
QUnit.module( 'mmv.logging.DimensionLogger', QUnit.newMwEnvironment() );
QUnit.test( 'log()', 1, function ( assert ) {
var fakeEventLog = { logEvent : this.sandbox.stub() },
logger = new mw.mmv.logging.DimensionLogger();
this.sandbox.stub( logger, 'loadDependencies' ).returns( $.Deferred().resolve() );
this.sandbox.stub( mw, 'log' );
logger.samplingFactor = 1;
logger.setEventLog( fakeEventLog );
logger.logDimensions( 640, 480, 200, 'resize' );
assert.ok( true, 'logDimensions() did not throw errors' );
} );
}( mediaWiki, jQuery ) );

View file

@ -116,7 +116,9 @@
canvas: { set : $.noop,
unblurWithAnimation: $.noop,
unblur: $.noop,
getCurrentImageWidths: function () { return { real : 0 }; } },
getCurrentImageWidths: function () { return { real : 0 }; },
getDimensions: function () { return {}; }
},
panel: {
setImageInfo: $.noop,
scroller: {
@ -172,7 +174,9 @@
canvas : { set : $.noop,
unblurWithAnimation: $.noop,
unblur: $.noop,
getCurrentImageWidths : function () { return { real : 0 }; } },
getCurrentImageWidths : function () { return { real : 0 }; },
getDimensions: function () { return {}; }
},
panel : {
setImageInfo : $.noop,
scroller: {
@ -364,8 +368,11 @@
viewer.ui = {
setFileReuseData: $.noop,
setupForLoad : $.noop,
canvas : { set : $.noop,
getCurrentImageWidths : function () { return { real : 0 }; } },
canvas : {
set : $.noop,
getCurrentImageWidths : function () { return { real : 0 }; },
getDimensions: function () { return {}; }
},
panel : {
setImageInfo : this.sandbox.stub(),
scroller: {