diff --git a/packages/core/src/tools/globalObject.ts b/packages/core/src/tools/globalObject.ts index ce9b637c02..14dc8724b3 100644 --- a/packages/core/src/tools/globalObject.ts +++ b/packages/core/src/tools/globalObject.ts @@ -48,4 +48,8 @@ export function getGlobalObject(): T { // eslint-disable-next-line local-rules/disallow-side-effects export const globalObject = getGlobalObject() +export const isBrowserEnvironment = 'document' in globalObject export const isWorkerEnvironment = 'WorkerGlobalScope' in globalObject +export const isNodeEnvironment = + // @ts-expect-error for Node.js-specific globals that are not present in browser environments + typeof process !== 'undefined' && process.versions !== null && !!process.versions.node diff --git a/packages/logs/src/boot/preStartLogs.ts b/packages/logs/src/boot/preStartLogs.ts index 257811bab0..a938a3b523 100644 --- a/packages/logs/src/boot/preStartLogs.ts +++ b/packages/logs/src/boot/preStartLogs.ts @@ -1,5 +1,6 @@ import type { TrackingConsentState } from '@datadog/browser-core' import { + isNodeEnvironment, createBoundedBuffer, canUseEventBridge, display, @@ -55,6 +56,10 @@ export function createPreStartStrategy( return { init(initConfiguration, errorStack) { + if (isNodeEnvironment) { + return + } + if (!initConfiguration) { display.error('Missing configuration') return diff --git a/packages/logs/src/boot/startLogs.ts b/packages/logs/src/boot/startLogs.ts index 929de4096f..e3028ee089 100644 --- a/packages/logs/src/boot/startLogs.ts +++ b/packages/logs/src/boot/startLogs.ts @@ -1,5 +1,6 @@ import type { TrackingConsentState, BufferedObservable, BufferedData, PageMayExitEvent } from '@datadog/browser-core' import { + isBrowserEnvironment, Observable, sendToExtension, createPageMayExitObservable, @@ -11,7 +12,6 @@ import { TelemetryService, createIdentityEncoder, startUserContext, - isWorkerEnvironment, } from '@datadog/browser-core' import { startLogsSessionManager, startLogsSessionManagerStub } from '../domain/logsSessionManager' import type { LogsConfiguration } from '../domain/configuration' @@ -55,7 +55,7 @@ export function startLogs( const reportError = startReportError(lifeCycle) // Page exit is not observable in worker environments (no window/document events) - const pageMayExitObservable = isWorkerEnvironment + const pageMayExitObservable = !isBrowserEnvironment ? new Observable() : createPageMayExitObservable(configuration) diff --git a/packages/logs/src/domain/networkError/networkErrorCollection.ts b/packages/logs/src/domain/networkError/networkErrorCollection.ts index d67ee301a9..683798c799 100644 --- a/packages/logs/src/domain/networkError/networkErrorCollection.ts +++ b/packages/logs/src/domain/networkError/networkErrorCollection.ts @@ -1,6 +1,6 @@ import type { FetchResolveContext, XhrCompleteContext } from '@datadog/browser-core' import { - isWorkerEnvironment, + isBrowserEnvironment, Observable, ErrorSource, initXhrObservable, @@ -28,7 +28,7 @@ export function startNetworkErrorCollection(configuration: LogsConfiguration, li // XHR is not available in web workers, so we use an empty observable that never emits const xhrSubscription = ( - isWorkerEnvironment ? new Observable() : initXhrObservable(configuration) + !isBrowserEnvironment ? new Observable() : initXhrObservable(configuration) ).subscribe((context) => { if (context.state === 'complete') { handleResponse(RequestType.XHR, context) diff --git a/packages/rum-core/src/boot/preStartRum.ts b/packages/rum-core/src/boot/preStartRum.ts index 0ea06776e4..5a8691dd48 100644 --- a/packages/rum-core/src/boot/preStartRum.ts +++ b/packages/rum-core/src/boot/preStartRum.ts @@ -1,5 +1,6 @@ import type { TrackingConsentState, DeflateWorker, Context, ContextManager, BoundedBuffer } from '@datadog/browser-core' import { + isNodeEnvironment, createBoundedBuffer, display, canUseEventBridge, @@ -100,6 +101,10 @@ export function createPreStartStrategy( } function doInit(initConfiguration: RumInitConfiguration, errorStack?: string) { + if (isNodeEnvironment) { + return + } + const eventBridgeAvailable = canUseEventBridge() if (eventBridgeAvailable) { initConfiguration = overrideInitConfigurationForBridge(initConfiguration) diff --git a/test/apps/vanilla/app.ts b/test/apps/vanilla/app.ts index c76bb788d2..23a4023fa9 100644 --- a/test/apps/vanilla/app.ts +++ b/test/apps/vanilla/app.ts @@ -17,8 +17,23 @@ if (typeof window !== 'undefined') { window.RUM_INIT() } } else { + // Document is always generated by the SSR environment + // @ts-ignore If document is mocked, the SDK executes further enough to throw an error + globalThis.document = {} + + // Check if the SDK sent any events + ;(globalThis as any).__ddBrowserSdkExtensionCallback = () => { + throw new Error('the SDK should not send events') + } + // compat test - datadogLogs.init({ clientToken: 'xxx', beforeSend: undefined }) - datadogRum.init({ clientToken: 'xxx', applicationId: 'xxx', beforeSend: undefined }) + + datadogLogs.init({ clientToken: 'xxx', beforeSend: undefined, telemetrySampleRate: 100 }) + datadogRum.init({ clientToken: 'xxx', applicationId: 'xxx', beforeSend: undefined, telemetrySampleRate: 100 }) datadogRum.setUser({ id: undefined }) + + // Check the SDK is not started + if (datadogLogs.getInternalContext() || datadogRum.getInternalContext()) { + throw new Error('SDK should not start on SSR environments') + } }