From f8820805052c7a1a59b8d7c07b8d6624cee6fffd Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Tue, 7 Oct 2025 09:58:33 +0200 Subject: [PATCH 01/10] fix: block logs in node --- packages/logs/src/boot/preStartLogs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/logs/src/boot/preStartLogs.ts b/packages/logs/src/boot/preStartLogs.ts index 257811bab0..88025ec285 100644 --- a/packages/logs/src/boot/preStartLogs.ts +++ b/packages/logs/src/boot/preStartLogs.ts @@ -43,7 +43,7 @@ export function createPreStartStrategy( const trackingConsentStateSubscription = trackingConsentState.observable.subscribe(tryStartLogs) function tryStartLogs() { - if (!cachedConfiguration || !cachedInitConfiguration || !trackingConsentState.isGranted()) { + if (isNodeEnvironment || !cachedConfiguration || !cachedInitConfiguration || !trackingConsentState.isGranted()) { return } From bd913a5b9f8affc01e54a0ef799efb47fabcb373 Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Thu, 9 Oct 2025 11:00:16 +0200 Subject: [PATCH 02/10] fix: compatibility test --- test/apps/vanilla/app.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/apps/vanilla/app.ts b/test/apps/vanilla/app.ts index c76bb788d2..8cd981f62c 100644 --- a/test/apps/vanilla/app.ts +++ b/test/apps/vanilla/app.ts @@ -18,6 +18,7 @@ if (typeof window !== 'undefined') { } } else { // compat test + datadogLogs.init({ clientToken: 'xxx', beforeSend: undefined }) datadogRum.init({ clientToken: 'xxx', applicationId: 'xxx', beforeSend: undefined }) datadogRum.setUser({ id: undefined }) From fbee29c4107ddab319aedd6a51b6e8da98434179 Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Thu, 9 Oct 2025 12:21:14 +0200 Subject: [PATCH 03/10] fix: super weird linter fix --- test/apps/vanilla/app.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/apps/vanilla/app.ts b/test/apps/vanilla/app.ts index 8cd981f62c..495e1cc96c 100644 --- a/test/apps/vanilla/app.ts +++ b/test/apps/vanilla/app.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ + import { datadogLogs } from '@datadog/browser-logs' import { datadogRum } from '@datadog/browser-rum' From c4811f1d14b7599c6b988f0bff97be20000972fd Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Fri, 10 Oct 2025 10:19:17 +0200 Subject: [PATCH 04/10] fix: throw the error --- packages/logs/src/boot/preStartLogs.ts | 2 +- test/apps/vanilla/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/logs/src/boot/preStartLogs.ts b/packages/logs/src/boot/preStartLogs.ts index 88025ec285..257811bab0 100644 --- a/packages/logs/src/boot/preStartLogs.ts +++ b/packages/logs/src/boot/preStartLogs.ts @@ -43,7 +43,7 @@ export function createPreStartStrategy( const trackingConsentStateSubscription = trackingConsentState.observable.subscribe(tryStartLogs) function tryStartLogs() { - if (isNodeEnvironment || !cachedConfiguration || !cachedInitConfiguration || !trackingConsentState.isGranted()) { + if (!cachedConfiguration || !cachedInitConfiguration || !trackingConsentState.isGranted()) { return } diff --git a/test/apps/vanilla/package.json b/test/apps/vanilla/package.json index 756bb58d4c..4e61420080 100644 --- a/test/apps/vanilla/package.json +++ b/test/apps/vanilla/package.json @@ -4,7 +4,7 @@ "scripts": { "build": "webpack --config ./webpack.web.js", "compat:tsc": "tsc -p tsconfig.json", - "compat:ssr": "webpack --config ./webpack.ssr.js && node dist/app.js" + "compat:ssr": "webpack --config ./webpack.ssr.js && output=$(node dist/app.js 2>&1) && [ -z \"$output\" ] || (echo \"Node output detected: $output\" && exit 1)" }, "dependencies": { "@datadog/browser-logs": "file:../../../packages/logs/package.tgz", From d4ddd96c1af525a3027b59d0aad43cb26bb7651b Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Tue, 14 Oct 2025 09:40:58 +0200 Subject: [PATCH 05/10] =?UTF-8?q?=F0=9F=90=9B=20replace=20isworker=20by=20?= =?UTF-8?q?due=20to=20multiple=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/apps/vanilla/app.ts | 3 --- test/apps/vanilla/package.json | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/test/apps/vanilla/app.ts b/test/apps/vanilla/app.ts index 495e1cc96c..c76bb788d2 100644 --- a/test/apps/vanilla/app.ts +++ b/test/apps/vanilla/app.ts @@ -1,5 +1,3 @@ -/* eslint-disable */ - import { datadogLogs } from '@datadog/browser-logs' import { datadogRum } from '@datadog/browser-rum' @@ -20,7 +18,6 @@ if (typeof window !== 'undefined') { } } else { // compat test - datadogLogs.init({ clientToken: 'xxx', beforeSend: undefined }) datadogRum.init({ clientToken: 'xxx', applicationId: 'xxx', beforeSend: undefined }) datadogRum.setUser({ id: undefined }) diff --git a/test/apps/vanilla/package.json b/test/apps/vanilla/package.json index 4e61420080..756bb58d4c 100644 --- a/test/apps/vanilla/package.json +++ b/test/apps/vanilla/package.json @@ -4,7 +4,7 @@ "scripts": { "build": "webpack --config ./webpack.web.js", "compat:tsc": "tsc -p tsconfig.json", - "compat:ssr": "webpack --config ./webpack.ssr.js && output=$(node dist/app.js 2>&1) && [ -z \"$output\" ] || (echo \"Node output detected: $output\" && exit 1)" + "compat:ssr": "webpack --config ./webpack.ssr.js && node dist/app.js" }, "dependencies": { "@datadog/browser-logs": "file:../../../packages/logs/package.tgz", From 146369322f43eb287dfb2e106b0ce5a67f48b81e Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Fri, 17 Oct 2025 09:52:11 +0200 Subject: [PATCH 06/10] =?UTF-8?q?=F0=9F=90=9B=20improve=20check=20on=20nod?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/tools/globalObject.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/src/tools/globalObject.ts b/packages/core/src/tools/globalObject.ts index ce9b637c02..c8fb0c0dec 100644 --- a/packages/core/src/tools/globalObject.ts +++ b/packages/core/src/tools/globalObject.ts @@ -49,3 +49,5 @@ export function getGlobalObject(): T { export const globalObject = getGlobalObject() export const isWorkerEnvironment = 'WorkerGlobalScope' in globalObject +// @ts-expect-error module is undefined outside of Node. +export const isNodeEnvironment = typeof module !== 'undefined' && module.exports From 505d3b7ad1e7510a843837061d7799652502d92d Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Fri, 17 Oct 2025 09:52:44 +0200 Subject: [PATCH 07/10] =?UTF-8?q?=F0=9F=91=B7=20add=20source=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/tools/globalObject.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/tools/globalObject.ts b/packages/core/src/tools/globalObject.ts index c8fb0c0dec..5b8ea1c5cd 100644 --- a/packages/core/src/tools/globalObject.ts +++ b/packages/core/src/tools/globalObject.ts @@ -49,5 +49,6 @@ export function getGlobalObject(): T { export const globalObject = getGlobalObject() export const isWorkerEnvironment = 'WorkerGlobalScope' in globalObject +// @see https://stackoverflow.com/questions/4224606/how-to-check-whether-a-script-is-running-under-node-js // @ts-expect-error module is undefined outside of Node. export const isNodeEnvironment = typeof module !== 'undefined' && module.exports From c4f60e955e2d9794653f6a88ac6434f0c6e09c5d Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Fri, 17 Oct 2025 13:01:16 +0200 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=91=B7=20improve=20node=20detection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/tools/globalObject.ts | 6 +++--- test/apps/vanilla/app.ts | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/core/src/tools/globalObject.ts b/packages/core/src/tools/globalObject.ts index 5b8ea1c5cd..1cb699dd41 100644 --- a/packages/core/src/tools/globalObject.ts +++ b/packages/core/src/tools/globalObject.ts @@ -49,6 +49,6 @@ export function getGlobalObject(): T { export const globalObject = getGlobalObject() export const isWorkerEnvironment = 'WorkerGlobalScope' in globalObject -// @see https://stackoverflow.com/questions/4224606/how-to-check-whether-a-script-is-running-under-node-js -// @ts-expect-error module is undefined outside of Node. -export const isNodeEnvironment = typeof module !== 'undefined' && module.exports +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 !== null 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') + } } From b117b268f546ce15f6b10fab33b154a2147b224a Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Mon, 20 Oct 2025 09:50:48 +0200 Subject: [PATCH 09/10] =?UTF-8?q?=F0=9F=91=B7=20conflicts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/tools/globalObject.ts | 1 + packages/logs/src/boot/preStartLogs.ts | 5 +++++ packages/logs/src/boot/startLogs.ts | 4 ++-- .../logs/src/domain/networkError/networkErrorCollection.ts | 4 ++-- packages/rum-core/src/boot/preStartRum.ts | 5 +++++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/core/src/tools/globalObject.ts b/packages/core/src/tools/globalObject.ts index 1cb699dd41..70b3399b76 100644 --- a/packages/core/src/tools/globalObject.ts +++ b/packages/core/src/tools/globalObject.ts @@ -48,6 +48,7 @@ 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 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) From 1c287af28b3fda3ba393f581764a762a7f153b51 Mon Sep 17 00:00:00 2001 From: Adrian de la Rosa Date: Tue, 21 Oct 2025 14:15:59 +0200 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=90=9B=20web-ui=20not=20null=20node?= =?UTF-8?q?=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/tools/globalObject.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/tools/globalObject.ts b/packages/core/src/tools/globalObject.ts index 70b3399b76..14dc8724b3 100644 --- a/packages/core/src/tools/globalObject.ts +++ b/packages/core/src/tools/globalObject.ts @@ -52,4 +52,4 @@ 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 !== null + typeof process !== 'undefined' && process.versions !== null && !!process.versions.node