diff --git a/src/lib/Preview.js b/src/lib/Preview.js index 2d212516a..e0402f42e 100644 --- a/src/lib/Preview.js +++ b/src/lib/Preview.js @@ -1054,6 +1054,7 @@ class Preview extends EventEmitter { // Node requires listener attached to 'error' this.viewer.addListener('error', this.triggerError); this.viewer.addListener(VIEWER_EVENT.default, this.handleViewerEvents); + this.viewer.addListener(VIEWER_EVENT.metric, this.handleViewerMetrics); } /** @@ -1101,6 +1102,23 @@ class Preview extends EventEmitter { } } + /** + * Handle metrics emitted by the viewer + * + * @private + * @param {Object} [data] - Viewer metric data + * @return {void} + */ + handleViewerMetrics(data) { + const formattedEvent = { + event_name: data.event, + value: data.data, + ...this.createLogEvent() + }; + + this.emit(PREVIEW_METRIC, formattedEvent); + } + /** * Finish loading a viewer - display the appropriate control buttons, re-emit the 'load' event, log * the preview, and prefetch the next few files. diff --git a/src/lib/__tests__/Preview-test.js b/src/lib/__tests__/Preview-test.js index 3edff480f..36ad3cc1c 100644 --- a/src/lib/__tests__/Preview-test.js +++ b/src/lib/__tests__/Preview-test.js @@ -1511,6 +1511,7 @@ describe('lib/Preview', () => { preview.attachViewerListeners(); expect(preview.viewer.addListener).to.be.calledWith('error', sinon.match.func); expect(preview.viewer.addListener).to.be.calledWith(VIEWER_EVENT.default, sinon.match.func); + expect(preview.viewer.addListener).to.be.calledWith(VIEWER_EVENT.metric, sinon.match.func); }); }); @@ -1591,6 +1592,24 @@ describe('lib/Preview', () => { }); }); + describe('handleViewerMetrics()', () => { + it('should create a formatted event and emit a preview_metric', () => { + sandbox.stub(preview, 'createLogEvent'); + sandbox.stub(preview, 'emit'); + const fakeEvent = { + event: 'test', + data: 7 + } + + const fakeLog = { + event_name: fakeEvent.event, + value: fakeEvent.data + } + preview.handleViewerMetrics(fakeEvent); + expect(preview.emit).to.be.calledWith(PREVIEW_METRIC, fakeLog); + }); + }); + describe('finishLoading()', () => { beforeEach(() => { stubs.checkPermission = sandbox.stub(file, 'checkPermission'); diff --git a/src/lib/events.js b/src/lib/events.js index 5eb67ec4e..695e156ca 100644 --- a/src/lib/events.js +++ b/src/lib/events.js @@ -8,8 +8,9 @@ export const VIEWER_EVENT = { notificationShow: 'notificationshow', // Show notification modal. notificationHide: 'notificationhide', // Hide notification modal. mediaEndAutoplay: 'mediaendautoplay', // Media playback has completed, with autoplay enabled. - error: 'error', // When an error occurs - default: 'viewerevent' // The default viewer event + error: 'error', // When an error occurs. + default: 'viewerevent', // The default viewer event. + metric: 'viewermetric' // A viewer metric. }; // Error codes logged by preview with "preview_error" events diff --git a/src/lib/viewers/BaseViewer.js b/src/lib/viewers/BaseViewer.js index 4afedf816..9f2a20a8f 100644 --- a/src/lib/viewers/BaseViewer.js +++ b/src/lib/viewers/BaseViewer.js @@ -499,6 +499,22 @@ class BaseViewer extends EventEmitter { }); } + /** + * Emits a viewer metric + * + * @protected + * @emits metric + * @param {string} event - Event name + * @param {Object} data - Event data + * @return {void} + */ + emitMetric(event, data) { + super.emit(VIEWER_EVENT.metric, { + event, + data + }); + } + /** * Handles the beginning of a pinch to zoom event on mobile. * Although W3 strongly discourages the prevention of pinch to zoom,