From 82f0792e68bd7abe3725f6065c4056ac0b35d971 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Tue, 11 Oct 2022 13:12:20 +0100 Subject: [PATCH] Merge pull request #9935 from overleaf/revert-9901-as-td-cm6-perf-editing-sessions Revert "Connect CM6 perf measurement to editing sessions" GitOrigin-RevId: b9793b47d6965a5026c0f770105abb9e07a09a59 --- .../Features/Analytics/AnalyticsController.js | 16 +++- services/web/frontend/js/ide.js | 29 +------ .../js/infrastructure/cm6-performance.ts | 84 ------------------- services/web/frontend/js/main/event.js | 14 ++-- 4 files changed, 25 insertions(+), 118 deletions(-) delete mode 100644 services/web/frontend/js/infrastructure/cm6-performance.ts diff --git a/services/web/app/src/Features/Analytics/AnalyticsController.js b/services/web/app/src/Features/Analytics/AnalyticsController.js index 079441db94..40bb834109 100644 --- a/services/web/app/src/Features/Analytics/AnalyticsController.js +++ b/services/web/app/src/Features/Analytics/AnalyticsController.js @@ -10,7 +10,7 @@ async function updateEditingSession(req, res, next) { } const userId = SessionManager.getLoggedInUserId(req.session) const { projectId } = req.params - const segmentation = req.body.segmentation || {} + const segmentation = _getSegmentation(req) let countryCode = null if (userId) { @@ -45,6 +45,20 @@ function recordEvent(req, res, next) { res.sendStatus(202) } +function _getSegmentation(req) { + const segmentation = req.body ? req.body.segmentation : null + const cleanedSegmentation = {} + if ( + segmentation && + segmentation.editorType && + typeof segmentation.editorType === 'string' && + segmentation.editorType.length < 100 + ) { + cleanedSegmentation.editorType = segmentation.editorType + } + return cleanedSegmentation +} + module.exports = { updateEditingSession, recordEvent, diff --git a/services/web/frontend/js/ide.js b/services/web/frontend/js/ide.js index 2bc448c4a8..54982c5d1f 100644 --- a/services/web/frontend/js/ide.js +++ b/services/web/frontend/js/ide.js @@ -66,7 +66,6 @@ import './features/share-project-modal/controllers/react-share-project-modal-con import './features/source-editor/controllers/editor-switch-controller' import getMeta from './utils/meta' import { cleanupServiceWorker } from './utils/service-worker-cleanup' -import { reportCM6Perf } from './infrastructure/cm6-performance' App.controller( 'IdeController', @@ -257,30 +256,10 @@ If the project has been renamed please look in your project list for a new proje }) ide.editingSessionHeartbeat = () => { - eventTracking.editingSessionHeartbeat(() => { - const editorType = ide.editorManager.getEditorType() - - const segmentation = { - editorType, - } - - if (editorType === 'cm6') { - const cm6PerfData = reportCM6Perf() - - // Ignore if no typing has happened - if (cm6PerfData.numberOfEntries > 0) { - segmentation.cm6PerfMax = cm6PerfData.max - segmentation.cm6PerfMean = cm6PerfData.mean - segmentation.cm6PerfMedian = cm6PerfData.median - segmentation.cm6PerfNinetyFifthPercentile = - cm6PerfData.ninetyFifthPercentile - segmentation.cm6PerfDocLength = cm6PerfData.docLength - segmentation.cm6PerfNumberOfEntries = cm6PerfData.numberOfEntries - } - } - - return segmentation - }) + const segmentation = { + editorType: ide.editorManager.getEditorType(), + } + eventTracking.editingSessionHeartbeat(segmentation) } $scope.$on('cursor:editor:update', () => { diff --git a/services/web/frontend/js/infrastructure/cm6-performance.ts b/services/web/frontend/js/infrastructure/cm6-performance.ts deleted file mode 100644 index 631b952c90..0000000000 --- a/services/web/frontend/js/infrastructure/cm6-performance.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Transaction } from '@codemirror/state' - -const TIMER_START_NAME = 'CM6-BeforeUpdate' -const TIMER_END_NAME = 'CM6-AfterUpdate' -const TIMER_MEASURE_NAME = 'CM6-Update' - -let latestDocLength = 0 - -export function timedDispatch(dispatchFn: (tr: Transaction) => void) { - return (tr: Transaction) => { - performance.mark(TIMER_START_NAME) - - dispatchFn(tr) - - performance.mark(TIMER_END_NAME) - performance.measure(TIMER_MEASURE_NAME, { - start: TIMER_START_NAME, - end: TIMER_END_NAME, - detail: { - isInputUserEvent: tr.isUserEvent('input'), - }, - }) - - latestDocLength = tr.state.doc.length - } -} - -function calculateMean(durations: number[]) { - if (durations.length === 0) return 0 - - const sum = durations.reduce((acc, entry) => acc + entry, 0) - return sum / durations.length -} - -function calculateMedian(sortedDurations: number[]) { - if (sortedDurations.length === 0) return 0 - - const middle = Math.floor(sortedDurations.length / 2) - - if (sortedDurations.length % 2 === 0) { - return (sortedDurations[middle - 1] + sortedDurations[middle]) / 2 - } - return sortedDurations[middle] -} - -function calculate95thPercentile(sortedDurations: number[]) { - if (sortedDurations.length === 0) return 0 - - const index = Math.round((sortedDurations.length - 1) * 0.95) - return sortedDurations[index] -} - -export function reportCM6Perf() { - // Get entries triggered by keystrokes - const cm6Entries = performance.getEntriesByName( - TIMER_MEASURE_NAME, - 'measure' - ) as PerformanceMeasure[] - - const inputDurations = cm6Entries - .filter(entry => entry.detail?.isInputUserEvent) - .map(({ duration }) => duration) - .sort((a, b) => a - b) - - const max = inputDurations.reduce((a, b) => Math.max(a, b), 0) - const mean = calculateMean(inputDurations) - const median = calculateMedian(inputDurations) - const ninetyFifthPercentile = calculate95thPercentile(inputDurations) - - performance.clearMeasures(TIMER_MEASURE_NAME) - - return { - max, - mean, - median, - ninetyFifthPercentile, - docLength: latestDocLength, - numberOfEntries: inputDurations.length, - } -} - -window._reportCM6Perf = () => { - console.log(reportCM6Perf()) -} diff --git a/services/web/frontend/js/main/event.js b/services/web/frontend/js/main/event.js index d06391fcf1..748fb1183b 100644 --- a/services/web/frontend/js/main/event.js +++ b/services/web/frontend/js/main/event.js @@ -70,13 +70,11 @@ App.factory('eventTracking', function ($http, localStorage) { } }, - editingSessionHeartbeat(segmentationCb = () => {}) { - sl_console.log('[Event] heartbeat trigger') - - // If the next heartbeat is in the future, stop - if (nextHeartbeat > new Date()) return - - const segmentation = segmentationCb() + editingSessionHeartbeat(segmentation) { + sl_console.log('[Event] heartbeat trigger', segmentation) + if (!(nextHeartbeat <= new Date())) { + return + } sl_console.log('[Event] send heartbeat request', segmentation) _sendEditingSessionHeartbeat(segmentation) @@ -92,7 +90,7 @@ App.factory('eventTracking', function ($http, localStorage) { ? (heartbeatsSent - 2) * 60 : 300 - nextHeartbeat = moment().add(backoffSecs, 'seconds').toDate() + return (nextHeartbeat = moment().add(backoffSecs, 'seconds').toDate()) }, sendMB,