From 4506cb819d3e0aff30c7e183835ed4e89a35ecff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Thu, 23 Feb 2023 16:46:08 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20[RUMF-1505]=20introduce=20?= =?UTF-8?q?a=20safe=20`setInterval`=20helper=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eslint-local-rules/disallowZoneJsPatchedValues.js | 5 +++++ packages/core/src/browser/timer.ts | 8 ++++++++ packages/core/src/domain/session/sessionManager.ts | 6 +++--- packages/core/src/domain/session/sessionStore.ts | 4 ++-- packages/core/src/tools/contextHistory.ts | 1 + .../domain/rumEventsCollection/view/trackViews.ts | 12 +++++------- .../src/domain/startCustomerDataTelemetry.ts | 4 ++-- 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/eslint-local-rules/disallowZoneJsPatchedValues.js b/eslint-local-rules/disallowZoneJsPatchedValues.js index 8da66fab4e..e7c75ffd4d 100644 --- a/eslint-local-rules/disallowZoneJsPatchedValues.js +++ b/eslint-local-rules/disallowZoneJsPatchedValues.js @@ -8,6 +8,11 @@ const PROBLEMATIC_IDENTIFIERS = { setTimeout: 'Use `setTimeout` from @datadog/browser-core instead', clearTimeout: 'Use `clearTimeout` from @datadog/browser-core instead', + // We didn't stumble on cases where using the patched `setInterval` from Zone.js is problematic + // yet, but still consider it problematic in prevention and to unify its usages with `setTimeout`. + setInterval: 'Use `setInterval` from @datadog/browser-core instead', + clearInterval: 'Use `clearInterval` from @datadog/browser-core instead', + // TODO: disallow addEventListener, removeEventListener } diff --git a/packages/core/src/browser/timer.ts b/packages/core/src/browser/timer.ts index 3851487376..6874ac2b64 100644 --- a/packages/core/src/browser/timer.ts +++ b/packages/core/src/browser/timer.ts @@ -10,3 +10,11 @@ export function setTimeout(callback: () => void, delay?: number): TimeoutId { export function clearTimeout(timeoutId: TimeoutId | undefined) { getZoneJsOriginalValue(window, 'clearTimeout')(timeoutId) } + +export function setInterval(callback: () => void, delay?: number): TimeoutId { + return getZoneJsOriginalValue(window, 'setInterval')(monitor(callback), delay) +} + +export function clearInterval(timeoutId: TimeoutId | undefined) { + getZoneJsOriginalValue(window, 'clearInterval')(timeoutId) +} diff --git a/packages/core/src/domain/session/sessionManager.ts b/packages/core/src/domain/session/sessionManager.ts index bc651f427e..0600cb58e8 100644 --- a/packages/core/src/domain/session/sessionManager.ts +++ b/packages/core/src/domain/session/sessionManager.ts @@ -5,8 +5,8 @@ import type { Context } from '../../tools/context' import { ContextHistory } from '../../tools/contextHistory' import type { RelativeTime } from '../../tools/timeUtils' import { relativeNow, clocksOrigin } from '../../tools/timeUtils' -import { monitor } from '../../tools/monitor' import { DOM_EVENT, addEventListener, addEventListeners } from '../../browser/addEventListener' +import { clearInterval, setInterval } from '../../browser/timer' import { tryOldCookiesMigration } from './oldCookiesMigration' import { startSessionStore } from './sessionStore' import { SESSION_TIME_OUT_DELAY } from './sessionConstants' @@ -81,11 +81,11 @@ function trackActivity(expandOrRenewSession: () => void) { } function trackVisibility(expandSession: () => void) { - const expandSessionWhenVisible = monitor(() => { + const expandSessionWhenVisible = () => { if (document.visibilityState === 'visible') { expandSession() } - }) + } const { stop } = addEventListener(document, DOM_EVENT.VISIBILITY_CHANGE, expandSessionWhenVisible) stopCallbacks.push(stop) diff --git a/packages/core/src/domain/session/sessionStore.ts b/packages/core/src/domain/session/sessionStore.ts index bcd67a004e..6fca8774b8 100644 --- a/packages/core/src/domain/session/sessionStore.ts +++ b/packages/core/src/domain/session/sessionStore.ts @@ -1,6 +1,6 @@ import type { CookieOptions } from '../../browser/cookie' import { COOKIE_ACCESS_DELAY } from '../../browser/cookie' -import { monitor } from '../../tools/monitor' +import { clearInterval, setInterval } from '../../browser/timer' import { Observable } from '../../tools/observable' import { dateNow } from '../../tools/timeUtils' import * as utils from '../../tools/utils' @@ -39,7 +39,7 @@ export function startSessionStore( const renewObservable = new Observable() const expireObservable = new Observable() - const watchSessionTimeoutId = setInterval(monitor(watchSession), COOKIE_ACCESS_DELAY) + const watchSessionTimeoutId = setInterval(watchSession, COOKIE_ACCESS_DELAY) let sessionCache: SessionState = retrieveActiveSession() function expandOrRenewSession() { diff --git a/packages/core/src/tools/contextHistory.ts b/packages/core/src/tools/contextHistory.ts index 4c8d885f0d..e61b33ff46 100644 --- a/packages/core/src/tools/contextHistory.ts +++ b/packages/core/src/tools/contextHistory.ts @@ -1,3 +1,4 @@ +import { setInterval, clearInterval } from '../browser/timer' import type { TimeoutId } from '../browser/timer' import type { RelativeTime } from './timeUtils' import { relativeNow } from './timeUtils' diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts b/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts index 88c24e682f..bc530531c5 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts @@ -5,7 +5,6 @@ import { assign, elapsed, generateUUID, - monitor, ONE_MINUTE, throttle, clocksNow, @@ -13,6 +12,8 @@ import { timeStampNow, display, looksLikeRelativeTime, + setInterval, + clearInterval, } from '@datadog/browser-core' import type { ViewCustomTimings } from '../../../rawRumEvent.types' @@ -136,12 +137,9 @@ export function trackViews( }) // Session keep alive - const keepAliveInterval = window.setInterval( - monitor(() => { - currentView.triggerUpdate() - }), - SESSION_KEEP_ALIVE_INTERVAL - ) + const keepAliveInterval = setInterval(() => { + currentView.triggerUpdate() + }, SESSION_KEEP_ALIVE_INTERVAL) return { stop: () => { diff --git a/packages/rum-core/src/domain/startCustomerDataTelemetry.ts b/packages/rum-core/src/domain/startCustomerDataTelemetry.ts index a0fb8b4c8d..49352bea18 100644 --- a/packages/rum-core/src/domain/startCustomerDataTelemetry.ts +++ b/packages/rum-core/src/domain/startCustomerDataTelemetry.ts @@ -1,5 +1,5 @@ import type { BatchFlushEvent, Context, ContextManager, Observable, Telemetry } from '@datadog/browser-core' -import { isEmptyObject, includes, performDraw, ONE_SECOND, addTelemetryDebug, monitor } from '@datadog/browser-core' +import { isEmptyObject, includes, performDraw, ONE_SECOND, addTelemetryDebug, setInterval } from '@datadog/browser-core' import { RumEventType } from '../rawRumEvent.types' import type { RumEvent } from '../rumEvent.types' import type { RumConfiguration } from './configuration' @@ -91,7 +91,7 @@ export function startCustomerDataTelemetry( initCurrentBatchMeasures() }) - setInterval(monitor(sendCurrentPeriodMeasures), MEASURES_PERIOD_DURATION) + setInterval(sendCurrentPeriodMeasures, MEASURES_PERIOD_DURATION) } function sendCurrentPeriodMeasures() {