From 6838b23c577b86b900af410ca1fd3c637e5cf696 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Thu, 23 Oct 2025 11:21:00 +0200 Subject: [PATCH 01/62] Lock actions to specific commit hash --- .github/workflows/publish.yml | 6 +++--- .github/workflows/stale.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e4a4faf8d..ea9c9ba7d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,12 +9,12 @@ jobs: runs-on: ubuntu-latest environment: Production steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '18.x' - run: yarn config set npmAuthToken $NPM_PUBLISH_TOKEN --home # Uses --home to avoid updating the project's .yarnrc.yml env: NPM_PUBLISH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} - run: yarn - - run: yarn run lerna publish from-package + - run: yarn run lerna publish from-package --yes diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index cb4caf9bb..d1a506cbe 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: | From ed535ce9088db3f7d32a4239cad52670617abf6d Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Tue, 28 Oct 2025 12:03:14 +0100 Subject: [PATCH 02/62] Remove NPM_TOKEN and set dry-run to test --- .github/workflows/publish.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ea9c9ba7d..2586decb1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,13 +8,12 @@ jobs: build: runs-on: ubuntu-latest environment: Production + permissions: + id-token: write steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: '18.x' - - run: yarn config set npmAuthToken $NPM_PUBLISH_TOKEN --home # Uses --home to avoid updating the project's .yarnrc.yml - env: - NPM_PUBLISH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} + node-version: '24.x' - run: yarn - - run: yarn run lerna publish from-package --yes + - run: yarn run lerna publish from-package --dry-run From 42f9b44ac3dccfc158ef214b56f191375364f9e5 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Tue, 28 Oct 2025 12:10:15 +0100 Subject: [PATCH 03/62] Add --yes parameter to lerna publish --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2586decb1..5782404bd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,4 +16,4 @@ jobs: with: node-version: '24.x' - run: yarn - - run: yarn run lerna publish from-package --dry-run + - run: yarn run lerna publish from-package --yes --dry-run From 3289037930836f91c835795d30fb114d2fcb9f49 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Tue, 28 Oct 2025 12:29:14 +0100 Subject: [PATCH 04/62] Set publish action to automatically accept prompts --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5782404bd..312010054 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,4 +16,4 @@ jobs: with: node-version: '24.x' - run: yarn - - run: yarn run lerna publish from-package --yes --dry-run + - run: yarn run lerna publish from-package --yes From 02a539a57134b2891da456dca57c9af5f3143154 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Wed, 15 Oct 2025 13:12:52 +0200 Subject: [PATCH 05/62] Preserve user baggage header when setting session ID --- .../distributedTracing/distributedTracing.tsx | 2 + .../distributedTracingHeaders.ts | 15 +++++- .../requestProxy/XHRProxy/XHRProxy.ts | 13 ++++- .../XHRProxy/__tests__/XHRProxy.test.ts | 49 +++++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx index e529f3cd1..c8d54d32a 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx @@ -26,12 +26,14 @@ export type DdRumResourceTracingAttributes = rulePsr: number; propagatorTypes: PropagatorType[]; rumSessionId?: string; + baggageHeaders?: Set; } | { tracingStrategy: 'DISCARD'; traceId?: void; spanId?: void; samplingPriorityHeader: '0'; + baggageHeaders?: Set; }; const DISCARDED_TRACE_ATTRIBUTES: DdRumResourceTracingAttributes = { diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts index f4decf2ac..3559c30d1 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts @@ -138,9 +138,22 @@ export const getTracingHeadersFromAttributes = ( } } if (tracingAttributes.rumSessionId) { + if (!tracingAttributes.baggageHeaders) { + tracingAttributes.baggageHeaders = new Set(); + } + + tracingAttributes.baggageHeaders?.add( + `${DD_RUM_SESSION_ID_TAG}=${tracingAttributes.rumSessionId}` + ); + } + + const baggageHeader = tracingAttributes.baggageHeaders + ? Array.from(tracingAttributes.baggageHeaders).join(', ') + : null; + if (baggageHeader) { headers.push({ header: BAGGAGE_HEADER_KEY, - value: `${DD_RUM_SESSION_ID_TAG}=${tracingAttributes.rumSessionId}` + value: baggageHeader }); } }); diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts index e81c8014f..11966d39a 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts @@ -6,7 +6,10 @@ import { Timer } from '../../../../../utils/Timer'; import { getCachedSessionId } from '../../../../sessionId/sessionIdHelper'; -import { getTracingHeadersFromAttributes } from '../../distributedTracing/distributedTracingHeaders'; +import { + BAGGAGE_HEADER_KEY, + getTracingHeadersFromAttributes +} from '../../distributedTracing/distributedTracingHeaders'; import type { DdRumResourceTracingAttributes } from '../../distributedTracing/distributedTracing'; import { getTracingAttributes } from '../../distributedTracing/distributedTracing'; import { @@ -226,6 +229,14 @@ const proxySetRequestHeader = (providers: XHRProxyProviders): void => { } } + if (header.toLowerCase() === BAGGAGE_HEADER_KEY) { + if (!this._datadog_xhr.tracingAttributes.baggageHeaders) { + this._datadog_xhr.tracingAttributes.baggageHeaders = new Set(); + } + + this._datadog_xhr.tracingAttributes.baggageHeaders?.add(value); + } + // eslint-disable-next-line prefer-rest-params return originalXhrSetRequestHeader.apply(this, arguments as any); }; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts index 907bfe57a..c6fb8c4fb 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts @@ -839,6 +839,55 @@ describe('XHRProxy', () => { // THEN expect(xhr.requestHeaders[BAGGAGE_HEADER_KEY]).toBeUndefined(); }); + + it('rum session id does not overwrite existing baggage headers', async () => { + // GIVEN + const method = 'GET'; + const url = 'https://api.example.com:443/v2/user'; + xhrProxy.onTrackingStart({ + tracingSamplingRate: 100, + firstPartyHostsRegexMap: firstPartyHostsRegexMapBuilder([ + { + match: 'api.example.com', + propagatorTypes: [ + PropagatorType.DATADOG, + PropagatorType.TRACECONTEXT + ] + }, + { + match: 'example.com', + propagatorTypes: [ + PropagatorType.B3, + PropagatorType.B3MULTI + ] + } + ]) + }); + + setCachedSessionId('TEST-SESSION-ID'); + + // WHEN + const xhr = new XMLHttpRequestMock(); + xhr.open(method, url); + xhr.setRequestHeader('baggage', 'existing.key=existing-value'); + xhr.send(); + xhr.notifyResponseArrived(); + xhr.complete(200, 'ok'); + await flushPromises(); + + // THEN + expect(xhr.requestHeaders[BAGGAGE_HEADER_KEY]).not.toBeUndefined(); + expect(xhr.requestHeaders[BAGGAGE_HEADER_KEY]).toContain( + 'existing.key=existing-value' + ); + + const values = xhr.requestHeaders[BAGGAGE_HEADER_KEY].split( + ', ' + ).sort(); + + expect(values[0]).toBe('existing.key=existing-value'); + expect(values[1]).toBe('session.id=TEST-SESSION-ID'); + }); }); describe('DdRum.startResource calls', () => { From 6007a26ffc8c564e5b6e82c77c7bc1879b7e52f0 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Tue, 28 Oct 2025 11:25:10 +0100 Subject: [PATCH 06/62] Enforced W3 specification for 'baggage' header --- .../__tests__/headers.test.ts | 14 ++ .../distributedTracing/distributedTracing.tsx | 2 - .../distributedTracingHeaders.ts | 26 +-- .../graphql/__tests__/graphqlHeaders.test.ts | 10 +- .../graphql/graphqlHeaders.ts | 9 +- .../resourceTracking/headers.ts | 12 ++ .../requestProxy/XHRProxy/XHRProxy.ts | 72 +++++--- .../XHRProxy/__tests__/XHRProxy.test.ts | 2 +- .../__tests__/baggageHeaderUtils.test.ts | 106 +++++++++++ .../XHRProxy/baggageHeaderUtils.ts | 172 ++++++++++++++++++ 10 files changed, 362 insertions(+), 63 deletions(-) create mode 100644 packages/core/src/rum/instrumentation/resourceTracking/__tests__/headers.test.ts create mode 100644 packages/core/src/rum/instrumentation/resourceTracking/headers.ts create mode 100644 packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts create mode 100644 packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts diff --git a/packages/core/src/rum/instrumentation/resourceTracking/__tests__/headers.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/__tests__/headers.test.ts new file mode 100644 index 000000000..dbb18b89b --- /dev/null +++ b/packages/core/src/rum/instrumentation/resourceTracking/__tests__/headers.test.ts @@ -0,0 +1,14 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ +import { isDatadogCustomHeader } from '../headers'; + +describe('headers', () => { + describe('isDatadogCustomHeader', () => { + it('returns false for non-custom headers', () => { + expect(isDatadogCustomHeader('non-custom-header')).toBeFalsy(); + }); + }); +}); diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx index c8d54d32a..e529f3cd1 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx @@ -26,14 +26,12 @@ export type DdRumResourceTracingAttributes = rulePsr: number; propagatorTypes: PropagatorType[]; rumSessionId?: string; - baggageHeaders?: Set; } | { tracingStrategy: 'DISCARD'; traceId?: void; spanId?: void; samplingPriorityHeader: '0'; - baggageHeaders?: Set; }; const DISCARDED_TRACE_ATTRIBUTES: DdRumResourceTracingAttributes = { diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts index 3559c30d1..5c0e1435d 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts @@ -137,27 +137,15 @@ export const getTracingHeadersFromAttributes = ( ); } } - if (tracingAttributes.rumSessionId) { - if (!tracingAttributes.baggageHeaders) { - tracingAttributes.baggageHeaders = new Set(); - } - - tracingAttributes.baggageHeaders?.add( - `${DD_RUM_SESSION_ID_TAG}=${tracingAttributes.rumSessionId}` - ); - } - - const baggageHeader = tracingAttributes.baggageHeaders - ? Array.from(tracingAttributes.baggageHeaders).join(', ') - : null; - if (baggageHeader) { - headers.push({ - header: BAGGAGE_HEADER_KEY, - value: baggageHeader - }); - } }); + if (tracingAttributes.rumSessionId) { + headers.push({ + header: BAGGAGE_HEADER_KEY, + value: `${DD_RUM_SESSION_ID_TAG}=${tracingAttributes.rumSessionId}` + }); + } + return headers; }; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/graphql/__tests__/graphqlHeaders.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/graphql/__tests__/graphqlHeaders.test.ts index b7d7dfa10..78c0f3b88 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/graphql/__tests__/graphqlHeaders.test.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/graphql/__tests__/graphqlHeaders.test.ts @@ -4,11 +4,11 @@ * Copyright 2016-Present Datadog, Inc. */ +import { isDatadogCustomHeader } from '../../headers'; import { DATADOG_GRAPH_QL_OPERATION_NAME_HEADER, DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER, - DATADOG_GRAPH_QL_VARIABLES_HEADER, - isDatadogCustomHeader + DATADOG_GRAPH_QL_VARIABLES_HEADER } from '../graphqlHeaders'; describe('GraphQL custom headers', () => { @@ -19,10 +19,4 @@ describe('GraphQL custom headers', () => { ])('%s matches the custom header pattern', header => { expect(isDatadogCustomHeader(header)).toBeTruthy(); }); - - describe('isDatadogCustomHeader', () => { - it('returns false for non-custom headers', () => { - expect(isDatadogCustomHeader('non-custom-header')).toBeFalsy(); - }); - }); }); diff --git a/packages/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.ts b/packages/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.ts index 87c79e65e..730b1c468 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.ts @@ -1,15 +1,10 @@ +import { DATADOG_CUSTOM_HEADER_PREFIX } from '../headers'; + /* * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. * This product includes software developed at Datadog (https://www.datadoghq.com/). * Copyright 2016-Present Datadog, Inc. */ - -const DATADOG_CUSTOM_HEADER_PREFIX = '_dd-custom-header'; - export const DATADOG_GRAPH_QL_OPERATION_NAME_HEADER = `${DATADOG_CUSTOM_HEADER_PREFIX}-graph-ql-operation-name`; export const DATADOG_GRAPH_QL_VARIABLES_HEADER = `${DATADOG_CUSTOM_HEADER_PREFIX}-graph-ql-variables`; export const DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER = `${DATADOG_CUSTOM_HEADER_PREFIX}-graph-ql-operation-type`; - -export const isDatadogCustomHeader = (header: string) => { - return header.match(new RegExp(`^${DATADOG_CUSTOM_HEADER_PREFIX}`)); -}; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/headers.ts b/packages/core/src/rum/instrumentation/resourceTracking/headers.ts new file mode 100644 index 000000000..6ecdd37ae --- /dev/null +++ b/packages/core/src/rum/instrumentation/resourceTracking/headers.ts @@ -0,0 +1,12 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +export const DATADOG_CUSTOM_HEADER_PREFIX = '_dd-custom-header'; +export const DATADOG_BAGGAGE_HEADER = `${DATADOG_CUSTOM_HEADER_PREFIX}-baggage`; + +export const isDatadogCustomHeader = (header: string) => { + return header.match(new RegExp(`^${DATADOG_CUSTOM_HEADER_PREFIX}`)); +}; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts index 11966d39a..d48c4f01a 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts @@ -15,14 +15,15 @@ import { getTracingAttributes } from '../../distributedTracing/distributedTracin import { DATADOG_GRAPH_QL_OPERATION_NAME_HEADER, DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER, - DATADOG_GRAPH_QL_VARIABLES_HEADER, - isDatadogCustomHeader + DATADOG_GRAPH_QL_VARIABLES_HEADER } from '../../graphql/graphqlHeaders'; +import { DATADOG_BAGGAGE_HEADER, isDatadogCustomHeader } from '../../headers'; import type { RequestProxyOptions } from '../interfaces/RequestProxy'; import { RequestProxy } from '../interfaces/RequestProxy'; import type { ResourceReporter } from './DatadogRumResource/ResourceReporter'; import { URLHostParser } from './URLHostParser'; +import { formatBaggageHeader } from './baggageHeaderUtils'; import { calculateResponseSize } from './responseSize'; const RESPONSE_START_LABEL = 'response_start'; @@ -42,6 +43,7 @@ interface DdRumXhrContext { reported: boolean; timer: Timer; tracingAttributes: DdRumResourceTracingAttributes; + baggageHeaderEntries: Set; } interface XHRProxyProviders { @@ -114,7 +116,8 @@ const proxyOpen = ( firstPartyHostsRegexMap, tracingSamplingRate, rumSessionId: getCachedSessionId() - }) + }), + baggageHeaderEntries: new Set() }; // eslint-disable-next-line prefer-rest-params return originalXhrOpen.apply(this, arguments as any); @@ -130,12 +133,22 @@ const proxySend = (providers: XHRProxyProviders): void => { // keep track of start time this._datadog_xhr.timer.start(); + // Tracing Headers const tracingHeaders = getTracingHeadersFromAttributes( this._datadog_xhr.tracingAttributes ); + tracingHeaders.forEach(({ header, value }) => { this.setRequestHeader(header, value); }); + + // Join all baggage header entries + const baggageHeader = formatBaggageHeader( + this._datadog_xhr.baggageHeaderEntries + ); + if (baggageHeader) { + this.setRequestHeader(DATADOG_BAGGAGE_HEADER, baggageHeader); + } } proxyOnReadyStateChange(this, providers); @@ -214,30 +227,37 @@ const proxySetRequestHeader = (providers: XHRProxyProviders): void => { header: string, value: string ) { - if (isDatadogCustomHeader(header)) { - if (header === DATADOG_GRAPH_QL_OPERATION_NAME_HEADER) { - this._datadog_xhr.graphql.operationName = value; - return; + const key = header.toLowerCase(); + if (isDatadogCustomHeader(key)) { + switch (key) { + case DATADOG_GRAPH_QL_OPERATION_NAME_HEADER: + this._datadog_xhr.graphql.operationName = value; + break; + case DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER: + this._datadog_xhr.graphql.operationType = value; + break; + case DATADOG_GRAPH_QL_VARIABLES_HEADER: + this._datadog_xhr.graphql.variables = value; + break; + case DATADOG_BAGGAGE_HEADER: + // Apply Baggage Header only if pre-processed by Datadog + return originalXhrSetRequestHeader.apply(this, [ + BAGGAGE_HEADER_KEY, + value + ]); + default: + return originalXhrSetRequestHeader.apply( + this, + // eslint-disable-next-line prefer-rest-params + arguments as any + ); } - if (header === DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER) { - this._datadog_xhr.graphql.operationType = value; - return; - } - if (header === DATADOG_GRAPH_QL_VARIABLES_HEADER) { - this._datadog_xhr.graphql.variables = value; - return; - } - } - - if (header.toLowerCase() === BAGGAGE_HEADER_KEY) { - if (!this._datadog_xhr.tracingAttributes.baggageHeaders) { - this._datadog_xhr.tracingAttributes.baggageHeaders = new Set(); - } - - this._datadog_xhr.tracingAttributes.baggageHeaders?.add(value); + } else if (key === BAGGAGE_HEADER_KEY) { + // Intercept User Baggage Header entries to apply them later + this._datadog_xhr.baggageHeaderEntries?.add(value); + } else { + // eslint-disable-next-line prefer-rest-params + return originalXhrSetRequestHeader.apply(this, arguments as any); } - - // eslint-disable-next-line prefer-rest-params - return originalXhrSetRequestHeader.apply(this, arguments as any); }; }; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts index c6fb8c4fb..af6cb2a47 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts @@ -882,7 +882,7 @@ describe('XHRProxy', () => { ); const values = xhr.requestHeaders[BAGGAGE_HEADER_KEY].split( - ', ' + ',' ).sort(); expect(values[0]).toBe('existing.key=existing-value'); diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts new file mode 100644 index 000000000..6c6943674 --- /dev/null +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts @@ -0,0 +1,106 @@ +import { InternalLog } from '../../../../../../InternalLog'; +import { SdkVerbosity } from '../../../../../../SdkVerbosity'; +import { formatBaggageHeader } from '../baggageHeaderUtils'; + +describe('formatBaggageHeader', () => { + let logSpy: jest.SpyInstance; + + beforeEach(() => { + logSpy = jest.spyOn(InternalLog, 'log').mockImplementation(() => {}); + }); + + afterEach(() => { + logSpy.mockRestore(); + }); + + it('should format simple key=value entries correctly', () => { + const entries = new Set(['userId=alice', 'isProduction=false']); + const result = formatBaggageHeader(entries); + expect(result).toBe('userId=alice,isProduction=false'); + expect(logSpy).not.toHaveBeenCalled(); + }); + + it('should percent-encode spaces and non-ASCII characters in values', () => { + const entries = new Set(['user=Amélie', 'region=us east']); + const result = formatBaggageHeader(entries); + expect(result).toBe('user=Am%C3%A9lie,region=us%20east'); + }); + + it('should support properties with and without values', () => { + const entries = new Set(['traceId=abc123;sampled=true;debug']); + const result = formatBaggageHeader(entries); + expect(result).toBe('traceId=abc123;sampled=true;debug'); + }); + + it('should trim whitespace around keys, values, and properties', () => { + const entries = new Set([' foo = bar ; p1 = one ; p2 ']); + const result = formatBaggageHeader(entries); + expect(result).toBe('foo=bar;p1=one;p2'); + }); + + it('should skip invalid entries without crashing', () => { + const entries = new Set(['valid=ok', 'invalidEntry']); + const result = formatBaggageHeader(entries); + expect(result).toBe('valid=ok'); + expect(logSpy).toHaveBeenCalledWith( + expect.stringContaining('Dropped invalid baggage header entry'), + SdkVerbosity.WARN + ); + }); + + it('should skip entries with invalid key (non-token)', () => { + const entries = new Set(['in valid=value', 'user=ok']); + const result = formatBaggageHeader(entries); + expect(result).toBe('user=ok'); + expect(logSpy).toHaveBeenCalledWith( + expect.stringContaining('key not compliant'), + SdkVerbosity.WARN + ); + }); + + it('should skip invalid properties (bad property key)', () => { + const entries = new Set(['user=ok;invalid key=value;good=yes']); + const result = formatBaggageHeader(entries); + expect(result).toBe('user=ok;good=yes'); + expect(logSpy).toHaveBeenCalledWith( + expect.stringContaining('property key not compliant'), + SdkVerbosity.WARN + ); + }); + + it('should log warning when too many members (>64)', () => { + const entries = new Set(); + for (let i = 0; i < 70; i++) { + entries.add(`k${i}=v${i}`); + } + const result = formatBaggageHeader(entries); + expect(result?.startsWith('k0=v0')).toBe(true); + expect(logSpy).toHaveBeenCalledWith( + expect.stringContaining('Too many baggage members'), + SdkVerbosity.WARN + ); + }); + + it('should log warning when header exceeds byte limit', () => { + const bigValue = 'x'.repeat(9000); + const entries = new Set([`large=${bigValue}`]); + const result = formatBaggageHeader(entries); + expect(result).toContain('large='); + expect(logSpy).toHaveBeenCalledWith( + expect.stringContaining('Baggage header too large'), + SdkVerbosity.WARN + ); + }); + + it('should return null if all entries are invalid', () => { + const entries = new Set(['badEntry', 'stillBad']); + const result = formatBaggageHeader(entries); + expect(result).toBeNull(); + }); + + it('should preserve insertion order', () => { + const entries = new Set(['first=1', 'second=2', 'third=3']); + const result = formatBaggageHeader(entries); + expect(result).toBe('first=1,second=2,third=3'); + }); +}); diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts new file mode 100644 index 000000000..bcacfc411 --- /dev/null +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts @@ -0,0 +1,172 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import { InternalLog } from '../../../../../InternalLog'; +import { SdkVerbosity } from '../../../../../SdkVerbosity'; + +// The resulting baggage-string should contain 64 list-members or less (https://www.w3.org/TR/baggage/#limits) +const MAX_MEMBERS = 64; + +// The resulting baggage-string should be of size 8192 bytes or less (https://www.w3.org/TR/baggage/#limits) +const MAX_BYTES = 8192; + +// The keys must follow RFC 7230 token grammar (https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6) +const TOKEN_REGEX = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; + +/** + * Lazy property for {@link getBaggageHeaderSafeChars}. + */ +let baggageHeaderSafeChars: Set | undefined; + +/** + * Transform a Set of baggage entries (strings like "key=value;prop1=foo;prop2") + * into a compliant baggage header value per W3C Baggage spec. + */ +export function formatBaggageHeader(entries: Set): string | null { + const formattedParts: string[] = []; + + for (const rawEntry of entries) { + if (!rawEntry.includes('=')) { + InternalLog.log( + 'XHRProxy: Dropped invalid baggage header entry - expected format "key=value".', + SdkVerbosity.WARN + ); + continue; + } + + // Split first key=value from properties (properties are after first ';') + const [mainPart, ...rawProperties] = rawEntry.split(';'); + const idx = mainPart.indexOf('='); + if (idx <= 0) { + InternalLog.log( + "XHRProxy: Dropped invalid baggage header entry - no '=' or empty key", + SdkVerbosity.WARN + ); + continue; + } + + const rawKey = mainPart.slice(0, idx).trim(); + const rawValue = mainPart.slice(idx + 1).trim(); + + if (!TOKEN_REGEX.test(rawKey)) { + InternalLog.log( + 'XHRProxy: Dropped invalid baggage header entry - key not compliant to RFC 7230 token grammar', + SdkVerbosity.WARN + ); + continue; + } + + const encodedValue = encodeValue(rawValue); + + // Handle properties + const properties: string[] = []; + for (const rawProperty of rawProperties) { + const trimmed = rawProperty.trim(); + if (!trimmed) { + continue; + } + + const eqIdx = trimmed.indexOf('='); + if (eqIdx === -1) { + // Property with no value (key1=value1;prop1; ... ) + const propKey = trimmed.trim(); + if (!TOKEN_REGEX.test(propKey)) { + InternalLog.log( + 'XHRProxy: Dropped invalid baggage header entry - property key not compliant to RFC 7230 token grammar', + SdkVerbosity.WARN + ); + continue; + } + properties.push(propKey); + } else { + // Property in key-value format (key1=value1;prop1=propValue1; ... ) + const propKey = trimmed.slice(0, eqIdx).trim(); + const propVal = trimmed.slice(eqIdx + 1).trim(); + if (!TOKEN_REGEX.test(propKey)) { + InternalLog.log( + 'XHRProxy: Dropped invalid baggage header entry - key-value property key not compliant to RFC 7230 token grammar', + SdkVerbosity.WARN + ); + continue; + } + properties.push(`${propKey}=${encodeValue(propVal)}`); + } + } + + const joinedProps = properties.length ? `;${properties.join(';')}` : ''; + formattedParts.push(`${rawKey}=${encodedValue}${joinedProps}`); + } + + if (formattedParts.length > MAX_MEMBERS) { + InternalLog.log( + `XHRProxy: Too many baggage members: ${formattedParts.length} > ${MAX_MEMBERS} - entries might be dropped (https://www.w3.org/TR/baggage/#limits)`, + SdkVerbosity.WARN + ); + } else if (formattedParts.length === 0) { + return null; + } + + const headerValue = formattedParts.join(','); + const byteLength = Buffer.byteLength(headerValue, 'utf8'); + + if (byteLength > MAX_BYTES) { + InternalLog.log( + `Baggage header too large: ${byteLength} bytes > ${MAX_BYTES} - entries might be dropped (https://www.w3.org/TR/baggage/#limits)`, + SdkVerbosity.WARN + ); + } + + return headerValue; +} + +/** + * Returns a set of valid baggage header characters. + */ +function getBaggageHeaderSafeChars(): Set { + if (baggageHeaderSafeChars) { + return baggageHeaderSafeChars; + } + + const safeChars = new Set(); + for (let c = 0x21; c <= 0x7e; c++) { + if ( + c === 0x22 || + c === 0x2c || + c === 0x3b || + c === 0x5c || + c === 0x20 + ) { + continue; + } + safeChars.add(String.fromCharCode(c)); + } + + baggageHeaderSafeChars = safeChars; + + return safeChars; +} + +/* + * Percent-encode all characters outside baggage-octet range. + */ +function encodeValue(raw: string): string { + const safeChars = getBaggageHeaderSafeChars(); + let result = ''; + for (const ch of Array.from(raw)) { + if (safeChars.has(ch)) { + result += ch; + } else { + const utf8Bytes = Buffer.from(ch, 'utf8'); + for (const value of utf8Bytes) { + result += `%${value + .toString(16) + .toUpperCase() + .padStart(2, '0')}`; + } + } + } + return result; +} From 943c9d2163cef444d8df55c3897885a71ca7eea1 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Wed, 29 Oct 2025 12:15:59 +0100 Subject: [PATCH 07/62] Session Replay Scenario tweaks --- benchmarks/src/scenario/SessionReplay/component/TextViews.tsx | 4 ++++ .../src/scenario/SessionReplay/sessionReplayScenario.tsx | 1 + 2 files changed, 5 insertions(+) diff --git a/benchmarks/src/scenario/SessionReplay/component/TextViews.tsx b/benchmarks/src/scenario/SessionReplay/component/TextViews.tsx index ca2fc90b0..129c6f148 100644 --- a/benchmarks/src/scenario/SessionReplay/component/TextViews.tsx +++ b/benchmarks/src/scenario/SessionReplay/component/TextViews.tsx @@ -13,6 +13,10 @@ function TextViews(): React.JSX.Element { Borkdrive doggo he made many woofs many pats tungg shibe you are doing me the shock heckin good boys shoob, h*ck wow such tempt porgo sub woofer floofs shoober doge borkf smol, blep dat tungg tho ur givin me a spook very taste wow most angery pupper I have ever seen length boy woofer. Super chub big ol pupper floofs blep doggo pupper such treat shooberino, adorable doggo borkdrive he made many woofs heck long water shoob h*ck, wrinkler lotsa pats dat tungg tho fat boi much ruin diet most angery pupper I have ever seen. Adorable doggo waggy wags maximum borkdrive smol long doggo mlem bork, fluffer ur givin me a spook doggorino puggorino. + + Ellipsized doggo waggy wags maximum borkdrive smol long doggo mlem bork, fluffer ur givin me a spook doggorino puggorino, fluffer ur givin me a spook doggorino puggorino, fluffer ur givin me a spook doggorino puggorino. + Ellipsized doggo waggy wags maximum borkdrive smol long doggo mlem bork, fluffer ur givin me a spook doggorino puggorino. + ) }; diff --git a/benchmarks/src/scenario/SessionReplay/sessionReplayScenario.tsx b/benchmarks/src/scenario/SessionReplay/sessionReplayScenario.tsx index 4a7a50094..6d72cd601 100644 --- a/benchmarks/src/scenario/SessionReplay/sessionReplayScenario.tsx +++ b/benchmarks/src/scenario/SessionReplay/sessionReplayScenario.tsx @@ -18,6 +18,7 @@ function SessionReplayScenario(props: SessionReplayScenarioProps): React.JSX.Ele if (props.testConfig?.runType !== RunType.BASELINE) { instrument().then(() => { SessionReplay.enable({ + replaySampleRate: 100, textAndInputPrivacyLevel: TextAndInputPrivacyLevel.MASK_SENSITIVE_INPUTS, imagePrivacyLevel: ImagePrivacyLevel.MASK_NONE, touchPrivacyLevel: TouchPrivacyLevel.SHOW, From c06f455e1d07e5ed5c7a14f2e8414a00f4263c74 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Mon, 3 Nov 2025 08:37:28 +0100 Subject: [PATCH 08/62] Only inject Session ID header if propagator=Datadog|W3C --- .../distributedTracingHeaders.ts | 6 ++- .../XHRProxy/__tests__/XHRProxy.test.ts | 38 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts index 5c0e1435d..8bfaec669 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts @@ -48,9 +48,12 @@ export const getTracingHeadersFromAttributes = ( if (tracingAttributes.tracingStrategy === 'DISCARD') { return headers; } + + let hasDatadogOrW3CPropagator = false; tracingAttributes.propagatorTypes.forEach(propagator => { switch (propagator) { case PropagatorType.DATADOG: { + hasDatadogOrW3CPropagator = true; headers.push( { header: ORIGIN_HEADER_KEY, @@ -82,6 +85,7 @@ export const getTracingHeadersFromAttributes = ( break; } case PropagatorType.TRACECONTEXT: { + hasDatadogOrW3CPropagator = true; const isSampled = tracingAttributes.samplingPriorityHeader === '1'; headers.push( @@ -139,7 +143,7 @@ export const getTracingHeadersFromAttributes = ( } }); - if (tracingAttributes.rumSessionId) { + if (hasDatadogOrW3CPropagator && tracingAttributes.rumSessionId) { headers.push({ header: BAGGAGE_HEADER_KEY, value: `${DD_RUM_SESSION_ID_TAG}=${tracingAttributes.rumSessionId}` diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts index af6cb2a47..cfc5e0178 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts @@ -840,6 +840,44 @@ describe('XHRProxy', () => { expect(xhr.requestHeaders[BAGGAGE_HEADER_KEY]).toBeUndefined(); }); + it('does not add rum session id to baggage headers when propagator type is not datadog or w3c', async () => { + // GIVEN + const method = 'GET'; + const url = 'https://example.com'; + xhrProxy.onTrackingStart({ + tracingSamplingRate: 100, + firstPartyHostsRegexMap: firstPartyHostsRegexMapBuilder([ + { + match: 'api.example.com', + propagatorTypes: [ + PropagatorType.DATADOG, + PropagatorType.TRACECONTEXT + ] + }, + { + match: 'example.com', // <-- no datadog or tracecontext here + propagatorTypes: [ + PropagatorType.B3, + PropagatorType.B3MULTI + ] + } + ]) + }); + + setCachedSessionId('TEST-SESSION-ID'); + + // WHEN + const xhr = new XMLHttpRequestMock(); + xhr.open(method, url); + xhr.send(); + xhr.notifyResponseArrived(); + xhr.complete(200, 'ok'); + await flushPromises(); + + // THEN + expect(xhr.requestHeaders[BAGGAGE_HEADER_KEY]).toBeUndefined(); + }); + it('rum session id does not overwrite existing baggage headers', async () => { // GIVEN const method = 'GET'; From 920e3e028442e889113847cae182ad6cedddedef Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Mon, 3 Nov 2025 13:38:39 +0000 Subject: [PATCH 09/62] Conditionally remove webview tracking from tvOS builds --- packages/core/ios/Sources/DatadogSDKWrapper.swift | 8 +++++++- packages/core/ios/Sources/DdSdk.mm | 2 ++ packages/core/ios/Sources/DdSdkImplementation.swift | 10 +++++++++- .../core/ios/Sources/DdSdkNativeInitialization.swift | 7 ++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/core/ios/Sources/DatadogSDKWrapper.swift b/packages/core/ios/Sources/DatadogSDKWrapper.swift index 842ee5d89..9cbac3bd8 100644 --- a/packages/core/ios/Sources/DatadogSDKWrapper.swift +++ b/packages/core/ios/Sources/DatadogSDKWrapper.swift @@ -10,10 +10,13 @@ import DatadogRUM import DatadogLogs import DatadogTrace import DatadogCrashReporting -import DatadogWebViewTracking import DatadogInternal import Foundation +#if os(iOS) +import DatadogWebViewTracking +#endif + public typealias OnCoreInitializedListener = (DatadogCoreProtocol) -> Void /// Wrapper around the Datadog SDK. Use DatadogSDKWrapper.shared to access the instance. @@ -156,6 +159,8 @@ public class DatadogSDKWrapper { ) } + +#if os(iOS) // Webview private var webviewMessageEmitter: InternalExtension.AbstractMessageEmitter? @@ -170,6 +175,7 @@ public class DatadogSDKWrapper { internal func sendWebviewMessage(body: NSString) throws { try self.webviewMessageEmitter?.send(body: body) } +#endif } diff --git a/packages/core/ios/Sources/DdSdk.mm b/packages/core/ios/Sources/DdSdk.mm index 663da0a79..590452c86 100644 --- a/packages/core/ios/Sources/DdSdk.mm +++ b/packages/core/ios/Sources/DdSdk.mm @@ -128,9 +128,11 @@ - (dispatch_queue_t)methodQueue { return [RNQueue getSharedQueue]; } +#if TARGET_OS_IOS - (void)consumeWebviewEvent:(NSString *)message resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { [self.ddSdkImplementation consumeWebviewEventWithMessage:message resolve:resolve reject:reject]; } +#endif - (void)initialize:(NSDictionary *)configuration resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { [self.ddSdkImplementation initializeWithConfiguration:configuration resolve:resolve reject:reject]; diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 6d060dc31..b4ddc59fd 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -10,10 +10,13 @@ import DatadogRUM import DatadogLogs import DatadogTrace import DatadogCrashReporting -import DatadogWebViewTracking import DatadogInternal import React +#if os(iOS) +import DatadogWebViewTracking +#endif + func getDefaultAppVersion() -> String { let bundleShortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String let bundleVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String @@ -27,7 +30,10 @@ public class DdSdkImplementation: NSObject { let mainDispatchQueue: DispatchQueueType let RUMMonitorProvider: () -> RUMMonitorProtocol let RUMMonitorInternalProvider: () -> RUMMonitorInternalProtocol? + +#if os(iOS) var webviewMessageEmitter: InternalExtension.AbstractMessageEmitter? +#endif private let jsLongTaskThresholdInSeconds: TimeInterval = 0.1; @@ -149,6 +155,7 @@ public class DdSdkImplementation: NSObject { resolve(nil) } +#if os(iOS) @objc public func consumeWebviewEvent(message: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { do{ @@ -158,6 +165,7 @@ public class DdSdkImplementation: NSObject { } resolve(nil) } +#endif @objc public func clearAllData(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { diff --git a/packages/core/ios/Sources/DdSdkNativeInitialization.swift b/packages/core/ios/Sources/DdSdkNativeInitialization.swift index d68d89d06..dec3cbcb2 100644 --- a/packages/core/ios/Sources/DdSdkNativeInitialization.swift +++ b/packages/core/ios/Sources/DdSdkNativeInitialization.swift @@ -10,10 +10,13 @@ import DatadogRUM import DatadogLogs import DatadogTrace import DatadogCrashReporting -import DatadogWebViewTracking import DatadogInternal import React +#if os(iOS) +import DatadogWebViewTracking +#endif + @objc public class DdSdkNativeInitialization: NSObject { let jsonFileReader: ResourceFileReader @@ -90,7 +93,9 @@ public class DdSdkNativeInitialization: NSObject { DatadogSDKWrapper.shared.enableCrashReporting() } +#if os(iOS) DatadogSDKWrapper.shared.enableWebviewTracking() +#endif } func buildSDKConfiguration(configuration: DdSdkConfiguration, defaultAppVersion: String = getDefaultAppVersion()) -> Datadog.Configuration { From 9533fc43d52c81f67278cc9767fd84d44feb1606 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Tue, 4 Nov 2025 09:08:43 +0100 Subject: [PATCH 10/62] Clear cached RUM Session ID on stopSession --- packages/core/src/rum/DdRum.ts | 2 ++ packages/core/src/rum/sessionId/sessionIdHelper.ts | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/packages/core/src/rum/DdRum.ts b/packages/core/src/rum/DdRum.ts index 8943ed5b0..cbd06f4fe 100644 --- a/packages/core/src/rum/DdRum.ts +++ b/packages/core/src/rum/DdRum.ts @@ -31,6 +31,7 @@ import { getTracingContextForPropagators } from './instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders'; import { + clearCachedSessionId, getCachedSessionId, setCachedSessionId } from './sessionId/sessionIdHelper'; @@ -295,6 +296,7 @@ class DdRumWrapper implements DdRumType { stopSession = (): Promise => { InternalLog.log('Stopping RUM Session', SdkVerbosity.DEBUG); + clearCachedSessionId(); return bufferVoidNativeCall(() => this.nativeRum.stopSession()); }; diff --git a/packages/core/src/rum/sessionId/sessionIdHelper.ts b/packages/core/src/rum/sessionId/sessionIdHelper.ts index 64e56fecb..887b75984 100644 --- a/packages/core/src/rum/sessionId/sessionIdHelper.ts +++ b/packages/core/src/rum/sessionId/sessionIdHelper.ts @@ -12,3 +12,7 @@ export const getCachedSessionId = () => { export const setCachedSessionId = (sessionId: string) => { _cachedSessionId = sessionId; }; + +export const clearCachedSessionId = () => { + _cachedSessionId = undefined; +}; From 32d7885a9bd9d74570ceea0c3a4ca657780dc110 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Tue, 4 Nov 2025 09:29:39 +0100 Subject: [PATCH 11/62] Additional test for baggage header and minor warn message improvement --- .../XHRProxy/__tests__/baggageHeaderUtils.test.ts | 11 +++++++++++ .../requestProxy/XHRProxy/baggageHeaderUtils.ts | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts index 6c6943674..eee59838f 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts @@ -103,4 +103,15 @@ describe('formatBaggageHeader', () => { const result = formatBaggageHeader(entries); expect(result).toBe('first=1,second=2,third=3'); }); + + it('should trim keys and values', () => { + const entries = new Set([ + 'traceId=abc123;sampled=true;debug', + 'test1 = this is a test' + ]); + const result = formatBaggageHeader(entries); + expect(result).toBe( + 'traceId=abc123;sampled=true;debug,test1=this%20is%20a%20test' + ); + }); }); diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts index bcacfc411..7094ec4e8 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts @@ -102,7 +102,7 @@ export function formatBaggageHeader(entries: Set): string | null { if (formattedParts.length > MAX_MEMBERS) { InternalLog.log( - `XHRProxy: Too many baggage members: ${formattedParts.length} > ${MAX_MEMBERS} - entries might be dropped (https://www.w3.org/TR/baggage/#limits)`, + `XHRProxy: Too many baggage members: ${formattedParts.length} > ${MAX_MEMBERS} - entries may be dropped (https://www.w3.org/TR/baggage/#limits)`, SdkVerbosity.WARN ); } else if (formattedParts.length === 0) { @@ -114,7 +114,7 @@ export function formatBaggageHeader(entries: Set): string | null { if (byteLength > MAX_BYTES) { InternalLog.log( - `Baggage header too large: ${byteLength} bytes > ${MAX_BYTES} - entries might be dropped (https://www.w3.org/TR/baggage/#limits)`, + `Baggage header too large: ${byteLength} bytes > ${MAX_BYTES} - entries may be dropped (https://www.w3.org/TR/baggage/#limits)`, SdkVerbosity.WARN ); } From d8453a1e9c02d9a7628ad397d4ecade73e42546a Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Tue, 4 Nov 2025 16:20:53 +0100 Subject: [PATCH 12/62] Bump to version 2.13.1 --- NATIVE_SDK_VERSIONS.md | 1 + benchmarks/ios/Podfile.lock | 116 ++++++++--------- example-new-architecture/ios/Podfile.lock | 92 +++++++------- example/ios/Podfile.lock | 118 +++++++++--------- lerna.json | 2 +- packages/codepush/package.json | 2 +- .../com/datadog/reactnative/SdkVersion.kt | 2 +- packages/core/ios/Sources/SdkVersion.swift | 2 +- packages/core/package.json | 2 +- packages/core/release-content.txt | 16 +++ packages/core/src/version.ts | 2 +- packages/internal-testing-tools/package.json | 2 +- .../react-native-apollo-client/package.json | 2 +- .../release-content.txt | 4 + .../react-native-babel-plugin/package.json | 2 +- packages/react-native-navigation/package.json | 4 +- .../release-content.txt | 4 + .../react-native-session-replay/package.json | 2 +- packages/react-native-webview/package.json | 2 +- packages/react-navigation/package.json | 4 +- packages/react-navigation/release-content.txt | 4 + yarn.lock | 6 +- 22 files changed, 210 insertions(+), 181 deletions(-) diff --git a/NATIVE_SDK_VERSIONS.md b/NATIVE_SDK_VERSIONS.md index a1014ecf2..0c19e3c82 100644 --- a/NATIVE_SDK_VERSIONS.md +++ b/NATIVE_SDK_VERSIONS.md @@ -1,5 +1,6 @@ | React Native | iOS Bridge / iOS SDK | Android Bridge / Android SDK | |-------------|---------------------|-----------------------------| +| 2.13.1 | 2.30.2 | 2.26.2 | | 2.13.0 | 2.30.2 | 2.26.2 | | 2.12.4 | 2.30.0 | 2.25.0 | | 2.12.3 | 2.30.0 | 2.25.0 | diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 71cd768ba..3b1d0b0cc 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 2.30.2) - DatadogRUM (2.30.2): - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.0): + - DatadogSDKReactNative (2.13.1): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -37,7 +37,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeSessionReplay (2.13.0): + - DatadogSDKReactNativeSessionReplay (2.13.1): - DatadogSDKReactNative - DatadogSessionReplay (= 2.30.2) - DoubleConversion @@ -60,7 +60,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.0): + - DatadogSDKReactNativeWebView (2.13.1): - DatadogInternal (= 2.30.2) - DatadogSDKReactNative - DatadogWebViewTracking (= 2.30.2) @@ -2075,9 +2075,9 @@ SPEC CHECKSUMS: DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 6da208fd44e9eef09a17eb54826f65a58731186b - DatadogSDKReactNativeSessionReplay: 96194d4014b4bee544b75589ef7c5f0954a24aae - DatadogSDKReactNativeWebView: e9b6c83bbd6eea15a97bad45ed007e7b24f0da63 + DatadogSDKReactNative: 40ac2d99dc3110c21fc2a670a8c6cd915ddc0d2c + DatadogSDKReactNativeSessionReplay: 679968d631841592a930122220c906eca487fd7e + DatadogSDKReactNativeWebView: 78d1a2ddc52c528d78b7559ce04973193c90f1dc DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be @@ -2089,70 +2089,70 @@ SPEC CHECKSUMS: hermes-engine: 2771b98fb813fdc6f92edd7c9c0035ecabf9fee7 OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 - RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 + RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 RCTDeprecation: be794de7dc6ed8f9f7fbf525f86e7651b8b68746 RCTRequired: a83787b092ec554c2eb6019ff3f5b8d125472b3b RCTTypeSafety: 48ad3c858926b1c46f46a81a58822b476e178e2c React: 3b5754191f1b65f1dbc52fbea7959c3d2d9e39c9 React-callinvoker: 6beeaf4c7db11b6cc953fac45f2c76e3fb125013 - React-Core: 8a10ac9de53373a3ecb5dfcbcf56df1d3dad0861 - React-CoreModules: af6999b35c7c01b0e12b59d27f3e054e13da43b1 - React-cxxreact: 833f00155ce8c2fda17f6d286f8eaeff2ececc69 + React-Core: 88e817c42de035378cc71e009193b9a044d3f595 + React-CoreModules: dcf764d71efb4f75d38fcae8d4513b6729f49360 + React-cxxreact: 8cdcc937c5fbc406fe843a381102fd69440ca78a React-debug: 440175830c448e7e53e61ebb8d8468c3256b645e - React-defaultsnativemodule: a970effe18fe50bdbbb7115c3297f873b666d0d4 - React-domnativemodule: 45f886342a724e61531b18fba1859bb6782e5d62 - React-Fabric: 69f1881f2177a8512304a64157943548ab6df0cf - React-FabricComponents: f54111c8e2439fc273ab07483e3a7054ca1e75af - React-FabricImage: 9ad2619dfe8c386d79e8aaa87da6e8f018ab9592 + React-defaultsnativemodule: 4824bcd7b96ee2d75c28b1ca21f58976867f5535 + React-domnativemodule: a421118b475618961cf282e8ea85347cc9bb453c + React-Fabric: 6ac7de06009eb96b609a770b17abba6e460b5f45 + React-FabricComponents: e3bc2680a5a9a4917ff0c8d7f390688c30ef753c + React-FabricImage: 8bad558dec7478077974caa96acc79692d6b71f5 React-featureflags: b9cf9b35baca1c7f20c06a104ffc325a02752faa - React-featureflagsnativemodule: 7f1bc76d1d2c5bede5e753b8d188dbde7c59b12f - React-graphics: 069e0d0b31ed1e80feb023ad4f7e97f00e84f7b9 - React-hermes: 63df5ac5a944889c8758a6213b39ed825863adb7 - React-idlecallbacksnativemodule: 4c700bd7c0012adf904929075a79418b828b5ffc - React-ImageManager: 5d1ba8a7bae44ebba43fc93da64937c713d42941 - React-jserrorhandler: 0defd58f8bb797cdd0a820f733bf42d8bee708ce - React-jsi: 99d6207ec802ad73473a0dad3c9ad48cd98463f6 - React-jsiexecutor: 8c8097b4ba7e7f480582d6e6238b01be5dcc01c0 - React-jsinspector: ea148ec45bc7ff830e443383ea715f9780c15934 - React-jsinspectortracing: 46bb2841982f01e7b63eaab98140fa1de5b2a1db - React-jsitracing: c1063fc2233960d1c8322291e74bca51d25c10d7 - React-logger: 763728cf4eebc9c5dc9bfc3649e22295784f69f3 - React-Mapbuffer: 63278529b5cf531a7eaf8fc71244fabb062ca90c - React-microtasksnativemodule: 6a39463c32ce831c4c2aa8469273114d894b6be9 - react-native-config: 644074ab88db883fcfaa584f03520ec29589d7df - react-native-safe-area-context: afcc2e2b3e78ae8ef90d81e658aacee34ebc27ea - react-native-slider: 310d3f89edd6ca8344a974bfe83a29a3fbb60e5a - react-native-webview: 80ef603d1df42e24fdde765686fbb9b8a6ecd554 - React-NativeModulesApple: fd0545efbb7f936f78edd15a6564a72d2c34bb32 - React-perflogger: 5f8fa36a8e168fb355efe72099efe77213bc2ac6 - React-performancetimeline: 8c0ecfa1ae459cc5678a65f95ac3bf85644d6feb + React-featureflagsnativemodule: dc93d81da9f41f7132e24455ec8b4b60802fd5b0 + React-graphics: aaa5a38bea15d7b895b210d95d554af45a07002a + React-hermes: 08ad9fb832d1b9faef391be17309aa6a69fad23b + React-idlecallbacksnativemodule: aacea33ef6c511a9781f9286cc7cdf93f39bba14 + React-ImageManager: c596c3b658c9c14607f9183ed0f635c8dd77987c + React-jserrorhandler: 987609b2f16b7d79d63fcd621bf0110dd7400b35 + React-jsi: afa286d7e0c102c2478dc420d4f8935e13c973fc + React-jsiexecutor: 08f5b512b4db9e2f147416d60a0a797576b9cfef + React-jsinspector: 5a94bcae66e3637711c4d96a00038ab9ec935bf5 + React-jsinspectortracing: a12589a0adbb2703cbc4380dabe9a58800810923 + React-jsitracing: 0b1a403d7757cec66b7dd8b308d04db85eef75f3 + React-logger: 304814ae37503c8eb54359851cc55bd4f936b39c + React-Mapbuffer: b588d1ca18d2ce626f868f04ab12d8b1f004f12c + React-microtasksnativemodule: 11831d070aa47755bb5739069eb04ec621fec548 + react-native-config: 3367df9c1f25bb96197007ec531c7087ed4554c3 + react-native-safe-area-context: 9b169299f9dc95f1d7fe1dd266fde53bd899cd0c + react-native-slider: 27263d134d55db948a4706f1e47d0ec88fb354dd + react-native-webview: be9957759cb73cb64f2ed5359e32a85f1f5bdff8 + React-NativeModulesApple: 79a4404ac301b40bec3b367879c5e9a9ce81683c + React-perflogger: 0ea25c109dba33d47dec36b2634bf7ea67c1a555 + React-performancetimeline: f74480de6efbcd8541c34317c0baedb433f27296 React-RCTActionSheet: 2ef95837e89b9b154f13cd8401f9054fc3076aff - React-RCTAnimation: 46abefd5acfda7e6629f9e153646deecc70babd2 - React-RCTAppDelegate: 7e58e0299e304cceee3f7019fa77bc6990f66b22 - React-RCTBlob: f68c63a801ef1d27e83c4011e3b083cc86a200d7 - React-RCTFabric: c59f41d0c4edbaac8baa232731ca09925ae4dda7 - React-RCTFBReactNativeSpec: 3240b9b8d792aa4be0fb85c9898fc183125ba8de - React-RCTImage: 34e0bba1507e55f1c614bd759eb91d9be48c8c5b - React-RCTLinking: a0b6c9f4871c18b0b81ea952f43e752718bd5f1d - React-RCTNetwork: bdafd661ac2b20d23b779e45bf7ac3e4c8bd1b60 - React-RCTSettings: 98aa5163796f43789314787b584a84eba47787a9 - React-RCTText: 424a274fc9015b29de89cf3cbcdf4dd85dd69f83 - React-RCTVibration: 92d9875a955b0adb34b4b773528fdbbbc5addd6c + React-RCTAnimation: 33d960d7f58a81779eea6dea47ad0364c67e1517 + React-RCTAppDelegate: 85c13403fd6f6b6cc630428d52bd8bd76a670dc9 + React-RCTBlob: 74c986a02d951931d2f6ed0e07ed5a7eb385bfc0 + React-RCTFabric: 384a8fea4f22fc0f21299d771971862883ba630a + React-RCTFBReactNativeSpec: eb1c3ec5149f76133593a516ff9d5efe32ebcecd + React-RCTImage: 2c58b5ddeb3c65e52f942bbe13ff9c59bd649b09 + React-RCTLinking: b6b14f8a3e62c02fc627ac4f3fb0c7bd941f907c + React-RCTNetwork: 1d050f2466c1541b339587d46f78d5eee218d626 + React-RCTSettings: 8148f6be0ccc0cfe6e313417ebf8a479caaa2146 + React-RCTText: 64114531ad1359e4e02a4a8af60df606dbbabc25 + React-RCTVibration: f4859417a7dd859b6bf18b1aba897e52beb72ef6 React-rendererconsistency: 5ac4164ec18cfdd76ed5f864dbfdc56a5a948bc9 - React-rendererdebug: 710dbd7990e355852c786aa6bc7753f6028f357a + React-rendererdebug: 3dc1d97bbee0c0c13191e501a96ed9325bbd920e React-rncore: 0bace3b991d8843bb5b57c5f2301ec6e9c94718b - React-RuntimeApple: 701ec44a8b5d863ee9b6a2b2447b6a26bb6805a1 - React-RuntimeCore: a82767065b9a936b05e209dc6987bc1ea9eb5d2d + React-RuntimeApple: 1e1e0a0c6086bc8c3b07e8f1a2f6ca99b50419a0 + React-RuntimeCore: d39322c59bef2a4b343fda663d20649f29f57fcc React-runtimeexecutor: 876dfc1d8daa819dfd039c40f78f277c5a3e66a6 - React-RuntimeHermes: e7a051fd91cab8849df56ac917022ef6064ad621 - React-runtimescheduler: c544141f2124ee3d5f3d5bf0d69f4029a61a68b0 + React-RuntimeHermes: 44f5f2baf039f249b31ea4f3e224484fd1731e0e + React-runtimescheduler: 3b3c5b50743bb8743ca49b9e5a70c2c385f156e1 React-timing: 1ee3572c398f5579c9df5bf76aacddf5683ff74e - React-utils: 18703928768cb37e70cf2efff09def12d74a399e - ReactAppDependencyProvider: 4893bde33952f997a323eb1a1ee87a72764018ff - ReactCodegen: da30aff1cea9b5993dcbc33bf1ef47a463c55194 - ReactCommon: 865ebe76504a95e115b6229dd00a31e56d2d4bfe - RNCPicker: cfb51a08c6e10357d9a65832e791825b0747b483 - RNScreens: 790123c4a28783d80a342ce42e8c7381bed62db1 + React-utils: 0cfb7c7fb37d4e5f31cc18ffc7426be0ae6bf907 + ReactAppDependencyProvider: b48473fe434569ff8f6cb6ed4421217ebcbda878 + ReactCodegen: 653a0d8532d8c7dab50c391392044d98e20c9f79 + ReactCommon: 547db015202a80a5b3e7e041586ea54c4a087180 + RNCPicker: ffbd7b9fc7c1341929e61dbef6219f7860f57418 + RNScreens: 0f01bbed9bd8045a8d58e4b46993c28c7f498f3c SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: e14bad835e12b6c7e2260fc320bd00e0f4b45add diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 960a656be..d41df0346 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 2.30.2) - DatadogRUM (2.30.2): - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.0): + - DatadogSDKReactNative (2.13.1): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -37,7 +37,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (2.13.0): + - DatadogSDKReactNative/Tests (2.13.1): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -1855,7 +1855,7 @@ SPEC CHECKSUMS: DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 259a7851629a58cc42f3e3e7871bc041cc82209b + DatadogSDKReactNative: 9e089993dd0bd7f28fc2540f83acfaf0aafda319 DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 @@ -1866,62 +1866,62 @@ SPEC CHECKSUMS: hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11 OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 - RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17 + RCT-Folly: 7b4f73a92ad9571b9dbdb05bb30fad927fa971e1 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 RCTTypeSafety: e7678bd60850ca5a41df9b8dc7154638cb66871f React: 4641770499c39f45d4e7cde1eba30e081f9d8a3d React-callinvoker: 4bef67b5c7f3f68db5929ab6a4d44b8a002998ea - React-Core: a68cea3e762814e60ecc3fa521c7f14c36c99245 - React-CoreModules: d81b1eaf8066add66299bab9d23c9f00c9484c7c - React-cxxreact: 984f8b1feeca37181d4e95301fcd6f5f6501c6ab + React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455 + React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0 + React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 - React-defaultsnativemodule: 18a684542f82ce1897552a1c4b847be414c9566e - React-domnativemodule: 90bdd4ec3ab38c47cfc3461c1e9283a8507d613f - React-Fabric: f6dade7007533daeb785ba5925039d83f343be4b - React-FabricComponents: b0655cc3e1b5ae12a4a1119aa7d8308f0ad33520 - React-FabricImage: 9b157c4c01ac2bf433f834f0e1e5fe234113a576 + React-defaultsnativemodule: 814830ccbc3fb08d67d0190e63b179ee4098c67b + React-domnativemodule: 270acf94bd0960b026bc3bfb327e703665d27fb4 + React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b + React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb + React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c - React-featureflagsnativemodule: 742a8325b3c821d2a1ca13a6d2a0fc72d04555e0 - React-graphics: 68969e4e49d73f89da7abef4116c9b5f466aa121 - React-hermes: ac0bcba26a5d288ebc99b500e1097da2d0297ddf - React-idlecallbacksnativemodule: d61d9c9816131bf70d3d80cd04889fc625ee523f - React-ImageManager: e906eec93a9eb6102a06576b89d48d80a4683020 - React-jserrorhandler: ac5dde01104ff444e043cad8f574ca02756e20d6 - React-jsi: 496fa2b9d63b726aeb07d0ac800064617d71211d - React-jsiexecutor: dd22ab48371b80f37a0a30d0e8915b6d0f43a893 - React-jsinspector: 4629ac376f5765e684d19064f2093e55c97fd086 - React-jsitracing: 7a1c9cd484248870cf660733cd3b8114d54c035f - React-logger: c4052eb941cca9a097ef01b59543a656dc088559 - React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de - React-microtasksnativemodule: d80ff86c8902872d397d9622f1a97aadcc12cead + React-featureflagsnativemodule: 0d7091ae344d6160c0557048e127897654a5c00f + React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386 + React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3 + React-idlecallbacksnativemodule: 6b84add48971da9c40403bd1860d4896462590f2 + React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2 + React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64 + React-jsi: 95f7676103137861b79b0f319467627bcfa629ee + React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932 + React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2 + React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b + React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20 + React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc + React-microtasksnativemodule: a645237a841d733861c70b69908ab4a1707b52ad React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 - React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e - React-perflogger: 72e653eb3aba9122f9e57cf012d22d2486f33358 - React-performancetimeline: cd6a9374a72001165995d2ab632f672df04076dc + React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22 + React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d + React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9 React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 - React-RCTAnimation: 395ab53fd064dff81507c15efb781c8684d9a585 - React-RCTAppDelegate: 345a6f1b82abc578437df0ce7e9c48740eca827c - React-RCTBlob: 13311e554c1a367de063c10ee7c5e6573b2dd1d6 - React-RCTFabric: 007b1a98201cc49b5bc6e1417d7fe3f6fc6e2b78 - React-RCTImage: 1b1f914bcc12187c49ba5d949dac38c2eb9f5cc8 - React-RCTLinking: 4ac7c42beb65e36fba0376f3498f3cd8dd0be7fa - React-RCTNetwork: 938902773add4381e84426a7aa17a2414f5f94f7 - React-RCTSettings: e848f1ba17a7a18479cf5a31d28145f567da8223 - React-RCTText: 7e98fafdde7d29e888b80f0b35544e0cb07913cf - React-RCTVibration: cd7d80affd97dc7afa62f9acd491419558b64b78 + React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4 + React-RCTAppDelegate: 1774aa421a29a41a704ecaf789811ef73c4634b6 + React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8 + React-RCTFabric: 731cda82aed592aacce2d32ead69d78cde5d9274 + React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0 + React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a + React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3 + React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40 + React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2 + React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 - React-rendererdebug: aa181c36dd6cf5b35511d1ed875d6638fd38f0ec + React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5 React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 - React-RuntimeApple: d033becbbd1eba6f9f6e3af6f1893030ce203edd - React-RuntimeCore: 38af280bb678e66ba000a3c3d42920b2a138eebb + React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655 + React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157 React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: 37aad735ff21ca6de2d8450a96de1afe9f86c385 - React-runtimescheduler: 8ec34cc885281a34696ea16c4fd86892d631f38d + React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549 + React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 - React-utils: ed818f19ab445000d6b5c4efa9d462449326cc9f - ReactCodegen: f853a20cc9125c5521c8766b4b49375fec20648b - ReactCommon: 300d8d9c5cb1a6cd79a67cf5d8f91e4d477195f9 + React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e + ReactCodegen: 21a52ccddc6479448fc91903a437dd23ddc7366c + ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 691bbdb62..95b23b301 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 2.30.2) - DatadogRUM (2.30.2): - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.0): + - DatadogSDKReactNative (2.13.1): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -18,7 +18,7 @@ PODS: - DatadogTrace (= 2.30.2) - DatadogWebViewTracking (= 2.30.2) - React-Core - - DatadogSDKReactNative/Tests (2.13.0): + - DatadogSDKReactNative/Tests (2.13.1): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -26,7 +26,7 @@ PODS: - DatadogTrace (= 2.30.2) - DatadogWebViewTracking (= 2.30.2) - React-Core - - DatadogSDKReactNativeSessionReplay (2.13.0): + - DatadogSDKReactNativeSessionReplay (2.13.1): - DatadogSDKReactNative - DatadogSessionReplay (= 2.30.2) - DoubleConversion @@ -49,7 +49,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeSessionReplay/Tests (2.13.0): + - DatadogSDKReactNativeSessionReplay/Tests (2.13.1): - DatadogSDKReactNative - DatadogSessionReplay (= 2.30.2) - DoubleConversion @@ -73,12 +73,12 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.0): + - DatadogSDKReactNativeWebView (2.13.1): - DatadogInternal (= 2.30.2) - DatadogSDKReactNative - DatadogWebViewTracking (= 2.30.2) - React-Core - - DatadogSDKReactNativeWebView/Tests (2.13.0): + - DatadogSDKReactNativeWebView/Tests (2.13.1): - DatadogInternal (= 2.30.2) - DatadogSDKReactNative - DatadogWebViewTracking (= 2.30.2) @@ -1993,9 +1993,9 @@ SPEC CHECKSUMS: DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 881e179daeb0af9b43a53c5a56a9a5084bdf4566 - DatadogSDKReactNativeSessionReplay: 9e75e392ebd1adc6bfc131def6fe82f098afd32b - DatadogSDKReactNativeWebView: 082e0b8a07d7eea11ce014b9f04410053ea3e179 + DatadogSDKReactNative: cdc2dfc45180e2ff58fe73cc49559554699f0b3c + DatadogSDKReactNativeSessionReplay: cdfe6590f22deeeb38538396a07ef3577a5383de + DatadogSDKReactNativeWebView: e71edd71ca7305c69278981fd0d758893072d0f3 DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be @@ -2008,69 +2008,69 @@ SPEC CHECKSUMS: HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352 OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 - RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17 + RCT-Folly: 7b4f73a92ad9571b9dbdb05bb30fad927fa971e1 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 RCTTypeSafety: e7678bd60850ca5a41df9b8dc7154638cb66871f React: 4641770499c39f45d4e7cde1eba30e081f9d8a3d React-callinvoker: 4bef67b5c7f3f68db5929ab6a4d44b8a002998ea - React-Core: a68cea3e762814e60ecc3fa521c7f14c36c99245 - React-CoreModules: d81b1eaf8066add66299bab9d23c9f00c9484c7c - React-cxxreact: 984f8b1feeca37181d4e95301fcd6f5f6501c6ab + React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455 + React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0 + React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 - React-defaultsnativemodule: 21f216e8db975897eb32b5f13247f5bbfaa97f41 - React-domnativemodule: 19270ad4b8d33312838d257f24731a0026809d49 - React-Fabric: f6dade7007533daeb785ba5925039d83f343be4b - React-FabricComponents: b0655cc3e1b5ae12a4a1119aa7d8308f0ad33520 - React-FabricImage: 9b157c4c01ac2bf433f834f0e1e5fe234113a576 + React-defaultsnativemodule: a965cb39fb0a79276ab611793d39f52e59a9a851 + React-domnativemodule: d647f94e503c62c44f54291334b1aa22a30fa08b + React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b + React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb + React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c - React-featureflagsnativemodule: 3a8731d8fd9f755be57e00d9fa8a7f92aa77e87d - React-graphics: 68969e4e49d73f89da7abef4116c9b5f466aa121 - React-hermes: ac0bcba26a5d288ebc99b500e1097da2d0297ddf - React-idlecallbacksnativemodule: 9a2c5b5c174c0c476f039bedc1b9497a8272133e - React-ImageManager: e906eec93a9eb6102a06576b89d48d80a4683020 - React-jserrorhandler: ac5dde01104ff444e043cad8f574ca02756e20d6 - React-jsi: 496fa2b9d63b726aeb07d0ac800064617d71211d - React-jsiexecutor: dd22ab48371b80f37a0a30d0e8915b6d0f43a893 - React-jsinspector: 4629ac376f5765e684d19064f2093e55c97fd086 - React-jsitracing: 7a1c9cd484248870cf660733cd3b8114d54c035f - React-logger: c4052eb941cca9a097ef01b59543a656dc088559 - React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de - React-microtasksnativemodule: 5c3d795318c22ab8df55100e50b151384a4a60b3 - react-native-crash-tester: 48bde9d6f5256c61ef2e0c52dfc74256b26e55eb - react-native-safe-area-context: e134b241010ebe2aacdcea013565963d13826faa - react-native-webview: 2ea635bc43fd8a4b89de61133e8cc0607084e9f8 + React-featureflagsnativemodule: 95a02d895475de8ace78fedd76143866838bb720 + React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386 + React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3 + React-idlecallbacksnativemodule: 0c1ae840cc5587197cd926a3cb76828ad059d116 + React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2 + React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64 + React-jsi: 95f7676103137861b79b0f319467627bcfa629ee + React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932 + React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2 + React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b + React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20 + React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc + React-microtasksnativemodule: 8732b71aa66045da4bb341ddee1bb539f71e5f38 + react-native-crash-tester: 3ffaa64141427ca362079cb53559fe9a532487ae + react-native-safe-area-context: 04803a01f39f31cc6605a5531280b477b48f8a88 + react-native-webview: 1e12de2fad74c17b4f8b1b53ebd1e3baa0148d71 React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 - React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e - React-perflogger: 72e653eb3aba9122f9e57cf012d22d2486f33358 - React-performancetimeline: cd6a9374a72001165995d2ab632f672df04076dc + React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22 + React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d + React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9 React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 - React-RCTAnimation: 395ab53fd064dff81507c15efb781c8684d9a585 - React-RCTAppDelegate: 1e5b43833e3e36e9fa34eec20be98174bc0e14a2 - React-RCTBlob: 13311e554c1a367de063c10ee7c5e6573b2dd1d6 - React-RCTFabric: bd906861a4e971e21d8df496c2d8f3ca6956f840 - React-RCTImage: 1b1f914bcc12187c49ba5d949dac38c2eb9f5cc8 - React-RCTLinking: 4ac7c42beb65e36fba0376f3498f3cd8dd0be7fa - React-RCTNetwork: 938902773add4381e84426a7aa17a2414f5f94f7 - React-RCTSettings: e848f1ba17a7a18479cf5a31d28145f567da8223 - React-RCTText: 7e98fafdde7d29e888b80f0b35544e0cb07913cf - React-RCTVibration: cd7d80affd97dc7afa62f9acd491419558b64b78 + React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4 + React-RCTAppDelegate: 6c0377d9c4058773ea7073bb34bb9ebd6ddf5a84 + React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8 + React-RCTFabric: 7eb6dd2c8fda98cb860a572e3f4e4eb60d62c89e + React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0 + React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a + React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3 + React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40 + React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2 + React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 - React-rendererdebug: aa181c36dd6cf5b35511d1ed875d6638fd38f0ec + React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5 React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 - React-RuntimeApple: d033becbbd1eba6f9f6e3af6f1893030ce203edd - React-RuntimeCore: 38af280bb678e66ba000a3c3d42920b2a138eebb + React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655 + React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157 React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: 37aad735ff21ca6de2d8450a96de1afe9f86c385 - React-runtimescheduler: 8ec34cc885281a34696ea16c4fd86892d631f38d + React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549 + React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 - React-utils: ed818f19ab445000d6b5c4efa9d462449326cc9f - ReactCodegen: f853a20cc9125c5521c8766b4b49375fec20648b - ReactCommon: 300d8d9c5cb1a6cd79a67cf5d8f91e4d477195f9 - ReactNativeNavigation: 445f86273eb245d15b14023ee4ef9d6e4f891ad6 - RNCAsyncStorage: b44e8a4e798c3e1f56bffccd0f591f674fb9198f - RNGestureHandler: cb711d56ee3b03a5adea1d38324d4459ab55653f - RNScreens: f75b26fd4777848c216e27b0a09e1bf9c9f4760a + React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e + ReactCodegen: 21a52ccddc6479448fc91903a437dd23ddc7366c + ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd + ReactNativeNavigation: 50c1eef68b821e7265eff3a391d27ed18fdce459 + RNCAsyncStorage: 23e56519cc41d3bade3c8d4479f7760cb1c11996 + RNGestureHandler: 950dfa674dbf481460ca389c65b9036ac4ab8ada + RNScreens: 606ab1cf68162f7ba0d049a31f2a84089a6fffb4 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a diff --git a/lerna.json b/lerna.json index 78860fa18..b202692de 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "npmClient": "yarn", - "version": "2.13.0", + "version": "2.13.1", "packages": [ "packages/*" ], diff --git a/packages/codepush/package.json b/packages/codepush/package.json index 68127da64..d4fdcde0f 100644 --- a/packages/codepush/package.json +++ b/packages/codepush/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-code-push", - "version": "2.13.0", + "version": "2.13.1", "description": "A client-side React Native module to interact with Appcenter Codepush and Datadog", "keywords": [ "datadog", diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt index 68398ae72..ca49985a9 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt @@ -7,4 +7,4 @@ package com.datadog.reactnative // This is automatically updated by the update-version.sh script -internal const val SDK_VERSION = "2.13.0" +internal const val SDK_VERSION = "2.13.1" diff --git a/packages/core/ios/Sources/SdkVersion.swift b/packages/core/ios/Sources/SdkVersion.swift index 1e660e421..616f0be9b 100644 --- a/packages/core/ios/Sources/SdkVersion.swift +++ b/packages/core/ios/Sources/SdkVersion.swift @@ -7,4 +7,4 @@ import Foundation // This is automatically updated by the update-version.sh script -let SdkVersion = "2.13.0" +let SdkVersion = "2.13.1" diff --git a/packages/core/package.json b/packages/core/package.json index f6c55c590..545026a26 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native", - "version": "2.13.0", + "version": "2.13.1", "description": "A client-side React Native module to interact with Datadog", "keywords": [ "datadog", diff --git a/packages/core/release-content.txt b/packages/core/release-content.txt index 858124da6..57bb2aede 100644 --- a/packages/core/release-content.txt +++ b/packages/core/release-content.txt @@ -174,10 +174,14 @@ package/lib/commonjs/rum/instrumentation/resourceTracking/distributedTracing/Tra package/lib/commonjs/rum/instrumentation/resourceTracking/distributedTracing/TracingIdentifier.js.map package/lib/commonjs/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.js package/lib/commonjs/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.js.map +package/lib/commonjs/rum/instrumentation/resourceTracking/headers.js +package/lib/commonjs/rum/instrumentation/resourceTracking/headers.js.map package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.js package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.js.map package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.js package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.js.map +package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.js +package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.js.map package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.js package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.js.map package/lib/commonjs/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/ResourceReporter.js @@ -350,10 +354,14 @@ package/lib/module/rum/instrumentation/resourceTracking/distributedTracing/Traci package/lib/module/rum/instrumentation/resourceTracking/distributedTracing/TracingIdentifier.js.map package/lib/module/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.js package/lib/module/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.js.map +package/lib/module/rum/instrumentation/resourceTracking/headers.js +package/lib/module/rum/instrumentation/resourceTracking/headers.js.map package/lib/module/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.js package/lib/module/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.js.map package/lib/module/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.js package/lib/module/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.js.map +package/lib/module/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.js +package/lib/module/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.js.map package/lib/module/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.js package/lib/module/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.js.map package/lib/module/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/ResourceReporter.js @@ -524,10 +532,14 @@ package/lib/typescript/rum/instrumentation/resourceTracking/distributedTracing/T package/lib/typescript/rum/instrumentation/resourceTracking/distributedTracing/TracingIdentifier.d.ts.map package/lib/typescript/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts package/lib/typescript/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts.map +package/lib/typescript/rum/instrumentation/resourceTracking/headers.d.ts +package/lib/typescript/rum/instrumentation/resourceTracking/headers.d.ts.map package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts.map package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts.map +package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts +package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts.map package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts.map package/lib/typescript/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/ResourceReporter.d.ts @@ -675,6 +687,7 @@ package/src/rum/instrumentation/interactionTracking/NoOpEventsInterceptor.tsx package/src/rum/instrumentation/interactionTracking/ShallowObjectEqualityChecker.ts package/src/rum/instrumentation/resourceTracking/__tests__/__utils__/XMLHttpRequestMock.ts package/src/rum/instrumentation/resourceTracking/__tests__/DdRumResourceTracking.test.ts +package/src/rum/instrumentation/resourceTracking/__tests__/headers.test.ts package/src/rum/instrumentation/resourceTracking/DdRumResourceTracking.tsx package/src/rum/instrumentation/resourceTracking/distributedTracing/__tests__/__utils__/TracingIdentifierUtils.ts package/src/rum/instrumentation/resourceTracking/distributedTracing/__tests__/distributedTracing.test.ts @@ -687,10 +700,13 @@ package/src/rum/instrumentation/resourceTracking/distributedTracing/firstPartyHo package/src/rum/instrumentation/resourceTracking/distributedTracing/TracingIdentifier.tsx package/src/rum/instrumentation/resourceTracking/graphql/__tests__/graphqlHeaders.test.ts package/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.ts +package/src/rum/instrumentation/resourceTracking/headers.ts package/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.ts package/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.ts +package/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/baggageHeaderUtils.test.ts package/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/URLHostParser.test.ts package/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts +package/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts package/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/__tests__/__utils__/ResourceMockFactory.ts package/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/__tests__/internalDevResourceBlocklist.test.ts package/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/__tests__/ResourceReporter.test.ts diff --git a/packages/core/src/version.ts b/packages/core/src/version.ts index b5d8dcc54..fd89e50b4 100644 --- a/packages/core/src/version.ts +++ b/packages/core/src/version.ts @@ -1,2 +1,2 @@ // generated by genversion -export const version = '2.13.0'; +export const version = '2.13.1'; diff --git a/packages/internal-testing-tools/package.json b/packages/internal-testing-tools/package.json index 490c73460..5844bbce4 100644 --- a/packages/internal-testing-tools/package.json +++ b/packages/internal-testing-tools/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/react-native-internal-testing-tools", - "version": "2.13.0", + "version": "2.13.1", "description": "Internal tools for testing the Datadog React Native SDK.", "keywords": [ "datadog", diff --git a/packages/react-native-apollo-client/package.json b/packages/react-native-apollo-client/package.json index 2cb10d1e6..f69a6919b 100644 --- a/packages/react-native-apollo-client/package.json +++ b/packages/react-native-apollo-client/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-apollo-client", - "version": "2.13.0", + "version": "2.13.1", "description": "A client-side React Native module to interact with Apollo Client and Datadog", "keywords": [ "datadog", diff --git a/packages/react-native-apollo-client/release-content.txt b/packages/react-native-apollo-client/release-content.txt index 9db57c882..d2695809d 100644 --- a/packages/react-native-apollo-client/release-content.txt +++ b/packages/react-native-apollo-client/release-content.txt @@ -80,10 +80,14 @@ package/lib/typescript/core/src/rum/instrumentation/resourceTracking/distributed package/lib/typescript/core/src/rum/instrumentation/resourceTracking/distributedTracing/TracingIdentifier.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts.map +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/headers.d.ts +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/headers.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts.map +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/ResourceReporter.d.ts diff --git a/packages/react-native-babel-plugin/package.json b/packages/react-native-babel-plugin/package.json index 13292fef8..7a6152238 100644 --- a/packages/react-native-babel-plugin/package.json +++ b/packages/react-native-babel-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-babel-plugin", - "version": "2.13.0", + "version": "2.13.1", "description": "A Babel plugin that enhances Datadog's React Native SDK by automatically enriching React components with contextual metadata.", "keywords": [ "babel", diff --git a/packages/react-native-navigation/package.json b/packages/react-native-navigation/package.json index c3c4b3ab5..8fd6f2e2e 100644 --- a/packages/react-native-navigation/package.json +++ b/packages/react-native-navigation/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-navigation", - "version": "2.13.0", + "version": "2.13.1", "description": "A client-side React Native module to interact with Datadog", "keywords": [ "datadog", @@ -36,7 +36,7 @@ "prepare": "rm -rf lib && yarn bob build" }, "devDependencies": { - "@datadog/mobile-react-native": "^2.13.0", + "@datadog/mobile-react-native": "^2.13.1", "@testing-library/react-native": "7.0.2", "react-native-builder-bob": "0.26.0", "react-native-gesture-handler": "1.10.3", diff --git a/packages/react-native-navigation/release-content.txt b/packages/react-native-navigation/release-content.txt index 632da48d9..ad491fc7b 100644 --- a/packages/react-native-navigation/release-content.txt +++ b/packages/react-native-navigation/release-content.txt @@ -72,10 +72,14 @@ package/lib/typescript/core/src/rum/instrumentation/resourceTracking/distributed package/lib/typescript/core/src/rum/instrumentation/resourceTracking/distributedTracing/TracingIdentifier.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts.map +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/headers.d.ts +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/headers.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts.map +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/ResourceReporter.d.ts diff --git a/packages/react-native-session-replay/package.json b/packages/react-native-session-replay/package.json index 2bb4bfcd5..e35be543a 100644 --- a/packages/react-native-session-replay/package.json +++ b/packages/react-native-session-replay/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-session-replay", - "version": "2.13.0", + "version": "2.13.1", "description": "A client-side React Native module to enable session replay with Datadog", "keywords": [ "datadog", diff --git a/packages/react-native-webview/package.json b/packages/react-native-webview/package.json index b0b3d3dea..d0593e44f 100644 --- a/packages/react-native-webview/package.json +++ b/packages/react-native-webview/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-webview", - "version": "2.13.0", + "version": "2.13.1", "description": "A client-side React Native module to interact with react-native-webview and Datadog", "keywords": [ "datadog", diff --git a/packages/react-navigation/package.json b/packages/react-navigation/package.json index d5177ac7d..9e219e042 100644 --- a/packages/react-navigation/package.json +++ b/packages/react-navigation/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-navigation", - "version": "2.13.0", + "version": "2.13.1", "description": "A client-side React Native module to interact with Datadog", "keywords": [ "datadog", @@ -36,7 +36,7 @@ "prepare": "rm -rf lib && yarn bob build" }, "devDependencies": { - "@datadog/mobile-react-native": "^2.13.0", + "@datadog/mobile-react-native": "^2.13.1", "@react-navigation/native-v5": "npm:@react-navigation/native@5.9.8", "@react-navigation/native-v6": "npm:@react-navigation/native@6.1.2", "@react-navigation/stack-v5": "npm:@react-navigation/stack@5.14.2", diff --git a/packages/react-navigation/release-content.txt b/packages/react-navigation/release-content.txt index 5562ee82d..2fe584893 100644 --- a/packages/react-navigation/release-content.txt +++ b/packages/react-navigation/release-content.txt @@ -80,10 +80,14 @@ package/lib/typescript/core/src/rum/instrumentation/resourceTracking/distributed package/lib/typescript/core/src/rum/instrumentation/resourceTracking/distributedTracing/TracingIdentifier.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/graphql/graphqlHeaders.d.ts.map +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/headers.d.ts +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/headers.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RumResource.d.ts.map +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts +package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.d.ts.map package/lib/typescript/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/ResourceReporter.d.ts diff --git a/yarn.lock b/yarn.lock index 7d6dd13f7..a75685585 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3820,7 +3820,7 @@ __metadata: version: 0.0.0-use.local resolution: "@datadog/mobile-react-native-navigation@workspace:packages/react-native-navigation" dependencies: - "@datadog/mobile-react-native": ^2.13.0 + "@datadog/mobile-react-native": ^2.13.1 "@testing-library/react-native": 7.0.2 react-native-builder-bob: 0.26.0 react-native-gesture-handler: 1.10.3 @@ -3862,7 +3862,7 @@ __metadata: languageName: unknown linkType: soft -"@datadog/mobile-react-native@^2.13.0, @datadog/mobile-react-native@workspace:packages/core": +"@datadog/mobile-react-native@^2.13.1, @datadog/mobile-react-native@workspace:packages/core": version: 0.0.0-use.local resolution: "@datadog/mobile-react-native@workspace:packages/core" dependencies: @@ -3879,7 +3879,7 @@ __metadata: version: 0.0.0-use.local resolution: "@datadog/mobile-react-navigation@workspace:packages/react-navigation" dependencies: - "@datadog/mobile-react-native": ^2.13.0 + "@datadog/mobile-react-native": ^2.13.1 "@react-navigation/native-v5": "npm:@react-navigation/native@5.9.8" "@react-navigation/native-v6": "npm:@react-navigation/native@6.1.2" "@react-navigation/stack-v5": "npm:@react-navigation/stack@5.14.2" From 55345083a5689514066b2ac255ce4bb7e4761867 Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Thu, 6 Nov 2025 09:35:52 +0000 Subject: [PATCH 13/62] Check if view attributes property exists before accessing it to avoid silent crash --- .../ios/Sources/SvgViewRecorder.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift b/packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift index 4a19de2ad..fd3c74a69 100644 --- a/packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift +++ b/packages/react-native-session-replay/ios/Sources/SvgViewRecorder.swift @@ -71,6 +71,9 @@ internal class SvgViewRecorder: SessionReplayNodeRecorder { } } + let sel = NSSelectorFromString(SVGConstants.attributes) + guard view.responds(to: sel) else { return nil } + guard let attrs = view.value(forKey: SVGConstants.attributes) as? [String: String] else { return nil } From 1d25819a19814fb6808562d88be6f70d9d369879 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Thu, 6 Nov 2025 17:23:38 +0100 Subject: [PATCH 14/62] Bump lerna to 9.0.0 --- package.json | 2 +- yarn.lock | 2202 +++++++++++++++++++++++++++++++------------------- 2 files changed, 1382 insertions(+), 822 deletions(-) diff --git a/package.json b/package.json index 886d6c539..be39fd23e 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "eslint-plugin-react-native": "3.10.0", "genversion": "3.0.2", "jest": "^29.7.0", - "lerna": "8.1.6", + "lerna": "9.0.0", "metro": "^0.83.1", "pod-install": "0.1.14", "prettier": "2.2.0", diff --git a/yarn.lock b/yarn.lock index a75685585..335b47458 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4252,6 +4252,269 @@ __metadata: languageName: node linkType: hard +"@inquirer/ansi@npm:^1.0.0, @inquirer/ansi@npm:^1.0.1": + version: 1.0.1 + resolution: "@inquirer/ansi@npm:1.0.1" + checksum: 0dda65720736f3e730715f3778e0e90f039ebd1382c277495a4d1cdbd2b2863095aa7291cd8ea7d3c0618bdee04a375db6e10a7bae5fb904df0b632a1c7774f9 + languageName: node + linkType: hard + +"@inquirer/checkbox@npm:^4.3.0": + version: 4.3.0 + resolution: "@inquirer/checkbox@npm:4.3.0" + dependencies: + "@inquirer/ansi": ^1.0.1 + "@inquirer/core": ^10.3.0 + "@inquirer/figures": ^1.0.14 + "@inquirer/type": ^3.0.9 + yoctocolors-cjs: ^2.1.2 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: d4957d0ce205c5c0bc70eb9491ca4ebe983cce0abaf552cc8ad521179db94841fb25603121d0af1b31757bb8381377a410c21cde2a48754af18f694b31477c14 + languageName: node + linkType: hard + +"@inquirer/confirm@npm:^5.1.19": + version: 5.1.19 + resolution: "@inquirer/confirm@npm:5.1.19" + dependencies: + "@inquirer/core": ^10.3.0 + "@inquirer/type": ^3.0.9 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: d65e0addf80c146d71a74057d77048bd78a4a80d74a9e0d774b759ff1adf38a33cde6c06a6d6ef802bb61ef9158770315dec3931f89b3624c0e63c595c0473c1 + languageName: node + linkType: hard + +"@inquirer/core@npm:^10.2.2, @inquirer/core@npm:^10.3.0": + version: 10.3.0 + resolution: "@inquirer/core@npm:10.3.0" + dependencies: + "@inquirer/ansi": ^1.0.1 + "@inquirer/figures": ^1.0.14 + "@inquirer/type": ^3.0.9 + cli-width: ^4.1.0 + mute-stream: ^2.0.0 + signal-exit: ^4.1.0 + wrap-ansi: ^6.2.0 + yoctocolors-cjs: ^2.1.2 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 42607c2e8388bf6505f5ce1716d47750f9386085f3080733b7f27bfe59d576d480ec622d7468fcf1bd9b854ff117311421d9eae0c083873c67324023635e103a + languageName: node + linkType: hard + +"@inquirer/editor@npm:^4.2.21": + version: 4.2.21 + resolution: "@inquirer/editor@npm:4.2.21" + dependencies: + "@inquirer/core": ^10.3.0 + "@inquirer/external-editor": ^1.0.2 + "@inquirer/type": ^3.0.9 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 8467c192f9c1573853718c15c020146268cf4b076d99a14e014a61d124c46157c57780d770caeeba94f309259504f3602248591842d11b9465ad12fd82185276 + languageName: node + linkType: hard + +"@inquirer/expand@npm:^4.0.21": + version: 4.0.21 + resolution: "@inquirer/expand@npm:4.0.21" + dependencies: + "@inquirer/core": ^10.3.0 + "@inquirer/type": ^3.0.9 + yoctocolors-cjs: ^2.1.2 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: eb1900c443895377c03652c3e2b6ca29c572fe6ee2682e264572957b9b4a596d3d55c9ea271934846fb05d5cc5195cca0dffde1386e41358ac5c308698320e93 + languageName: node + linkType: hard + +"@inquirer/external-editor@npm:^1.0.2": + version: 1.0.2 + resolution: "@inquirer/external-editor@npm:1.0.2" + dependencies: + chardet: ^2.1.0 + iconv-lite: ^0.7.0 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 57f32889969e0128561beb2b1225f0320a55fe90356dcf679804b3405534b0f909024e446d61b812d91b85d3e85ac6f762f29d34243d022fd68eecfd85483c1a + languageName: node + linkType: hard + +"@inquirer/figures@npm:^1.0.14": + version: 1.0.14 + resolution: "@inquirer/figures@npm:1.0.14" + checksum: 37eec986f119eabb6c231c8c1481c6a48ab2347e9f57b2d6442161f7b83936678221fccb7ead60582026c2ae20d457467d0727c485ff53aee2cf965077b0f51b + languageName: node + linkType: hard + +"@inquirer/input@npm:^4.2.5": + version: 4.2.5 + resolution: "@inquirer/input@npm:4.2.5" + dependencies: + "@inquirer/core": ^10.3.0 + "@inquirer/type": ^3.0.9 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 9d192556aefc8f8fbc70626f9a90cd2806032ec9e7d323b46afff0a0813f5c0f766ff9a5d2f8bdc39863688f8fdd081ce23b782c19aebf61ff8692c9135528b6 + languageName: node + linkType: hard + +"@inquirer/number@npm:^3.0.21": + version: 3.0.21 + resolution: "@inquirer/number@npm:3.0.21" + dependencies: + "@inquirer/core": ^10.3.0 + "@inquirer/type": ^3.0.9 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 445ba93639ecfc3755efa7ee9cf7cf972919abc1cd022ada27e7d73b93e01680ffcf56a8ca6fe090775358c8d2aec259890aa33b6c0e1c3aeba7306f25ba633a + languageName: node + linkType: hard + +"@inquirer/password@npm:^4.0.21": + version: 4.0.21 + resolution: "@inquirer/password@npm:4.0.21" + dependencies: + "@inquirer/ansi": ^1.0.1 + "@inquirer/core": ^10.3.0 + "@inquirer/type": ^3.0.9 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 07fb1527ea2d44a81b79d9263f59713e66977e21fbf44efedb6bf08d27d617900ef481c49c91b0a749caf1d282f2b5e19fe6b7474acc98db3edd174eb5d45416 + languageName: node + linkType: hard + +"@inquirer/prompts@npm:^7.8.6": + version: 7.9.0 + resolution: "@inquirer/prompts@npm:7.9.0" + dependencies: + "@inquirer/checkbox": ^4.3.0 + "@inquirer/confirm": ^5.1.19 + "@inquirer/editor": ^4.2.21 + "@inquirer/expand": ^4.0.21 + "@inquirer/input": ^4.2.5 + "@inquirer/number": ^3.0.21 + "@inquirer/password": ^4.0.21 + "@inquirer/rawlist": ^4.1.9 + "@inquirer/search": ^3.2.0 + "@inquirer/select": ^4.4.0 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 1dd6a87bcf77d1a8b728c781a7d34c0dd4028d7ec96e4e41e173a260d3ef9a76cba5eb8715d8674d75b18681d3f7eac9bd9f3ff1d82d8e786fb5222893498ea3 + languageName: node + linkType: hard + +"@inquirer/rawlist@npm:^4.1.9": + version: 4.1.9 + resolution: "@inquirer/rawlist@npm:4.1.9" + dependencies: + "@inquirer/core": ^10.3.0 + "@inquirer/type": ^3.0.9 + yoctocolors-cjs: ^2.1.2 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: ec23e087bfa9497b36d51b53e8da18c837e4a0c5c091bce7d1a6b52d9664035d7e22c3753993dd3c7c9ebfd5e9b71f1738873f2c25422668733ddb28d74bf26b + languageName: node + linkType: hard + +"@inquirer/search@npm:^3.2.0": + version: 3.2.0 + resolution: "@inquirer/search@npm:3.2.0" + dependencies: + "@inquirer/core": ^10.3.0 + "@inquirer/figures": ^1.0.14 + "@inquirer/type": ^3.0.9 + yoctocolors-cjs: ^2.1.2 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 5f8f86368513d29d9119a04cc65bbe075d0d93ec55af27a555f02bf740c7a65497e36df80da722cbee020ab348c9038856f0e070e9a22615ff9d5c3155c3296a + languageName: node + linkType: hard + +"@inquirer/select@npm:^4.4.0": + version: 4.4.0 + resolution: "@inquirer/select@npm:4.4.0" + dependencies: + "@inquirer/ansi": ^1.0.1 + "@inquirer/core": ^10.3.0 + "@inquirer/figures": ^1.0.14 + "@inquirer/type": ^3.0.9 + yoctocolors-cjs: ^2.1.2 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: cb0441f5ec981011f3e451fa062897e8991ca3b0cadca99432d2556a1f90e9c0251b277233056db63b717b5f77caaf32b2c5db7a1881fcc78d5c357d1e912616 + languageName: node + linkType: hard + +"@inquirer/type@npm:^3.0.8, @inquirer/type@npm:^3.0.9": + version: 3.0.9 + resolution: "@inquirer/type@npm:3.0.9" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 960ba4737405f70bac17e7cdc4696c60064b06c8dd13a4b3d0783763ba1714bdadbd598b88d537ab9415b7d5d61e011ac042cfbd1438b2a35298e2868724b853 + languageName: node + linkType: hard + +"@isaacs/balanced-match@npm:^4.0.1": + version: 4.0.1 + resolution: "@isaacs/balanced-match@npm:4.0.1" + checksum: 102fbc6d2c0d5edf8f6dbf2b3feb21695a21bc850f11bc47c4f06aa83bd8884fde3fe9d6d797d619901d96865fdcb4569ac2a54c937992c48885c5e3d9967fe8 + languageName: node + linkType: hard + +"@isaacs/brace-expansion@npm:^5.0.0": + version: 5.0.0 + resolution: "@isaacs/brace-expansion@npm:5.0.0" + dependencies: + "@isaacs/balanced-match": ^4.0.1 + checksum: d7a3b8b0ddbf0ccd8eeb1300e29dd0a0c02147e823d8138f248375a365682360620895c66d113e05ee02389318c654379b0e538b996345b83c914941786705b1 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -4382,6 +4645,13 @@ __metadata: languageName: node linkType: hard +"@jest/diff-sequences@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/diff-sequences@npm:30.0.1" + checksum: e5f931ca69c15a9b3a9b23b723f51ffc97f031b2f3ca37f901333dab99bd4dfa1ad4192a5cd893cd1272f7602eb09b9cfb5fc6bb62a0232c96fb8b5e96094970 + languageName: node + linkType: hard + "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -4427,6 +4697,13 @@ __metadata: languageName: node linkType: hard +"@jest/get-type@npm:30.1.0": + version: 30.1.0 + resolution: "@jest/get-type@npm:30.1.0" + checksum: e2a95fbb49ce2d15547db8af5602626caf9b05f62a5e583b4a2de9bd93a2bfe7175f9bbb2b8a5c3909ce261d467b6991d7265bb1d547cb60e7e97f571f361a70 + languageName: node + linkType: hard + "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -4706,81 +4983,78 @@ __metadata: languageName: node linkType: hard -"@lerna/create@npm:8.1.6": - version: 8.1.6 - resolution: "@lerna/create@npm:8.1.6" +"@lerna/create@npm:9.0.0": + version: 9.0.0 + resolution: "@lerna/create@npm:9.0.0" dependencies: - "@npmcli/arborist": 7.5.3 - "@npmcli/package-json": 5.2.0 - "@npmcli/run-script": 8.1.0 - "@nx/devkit": ">=17.1.2 < 20" + "@npmcli/arborist": 9.1.4 + "@npmcli/package-json": 7.0.0 + "@npmcli/run-script": 10.0.0 + "@nx/devkit": ">=21.5.2 < 22.0.0" "@octokit/plugin-enterprise-rest": 6.0.1 - "@octokit/rest": 19.0.11 + "@octokit/rest": 20.1.2 aproba: 2.0.0 byte-size: 8.1.1 chalk: 4.1.0 - clone-deep: 4.0.1 cmd-shim: 6.0.3 color-support: 1.1.3 columnify: 1.6.0 console-control-strings: ^1.1.0 conventional-changelog-core: 5.0.1 conventional-recommended-bump: 7.0.1 - cosmiconfig: ^8.2.0 + cosmiconfig: 9.0.0 dedent: 1.5.3 execa: 5.0.0 fs-extra: ^11.2.0 get-stream: 6.0.0 git-url-parse: 14.0.0 glob-parent: 6.0.2 - globby: 11.1.0 - graceful-fs: 4.2.11 has-unicode: 2.0.1 ini: ^1.3.8 - init-package-json: 6.0.3 - inquirer: ^8.2.4 + init-package-json: 8.2.2 + inquirer: 12.9.6 is-ci: 3.0.1 is-stream: 2.0.0 js-yaml: 4.1.0 - libnpmpublish: 9.0.9 + libnpmpublish: 11.1.0 load-json-file: 6.2.0 - lodash: ^4.17.21 make-dir: 4.0.0 + make-fetch-happen: 15.0.2 minimatch: 3.0.5 multimatch: 5.0.0 - node-fetch: 2.6.7 - npm-package-arg: 11.0.2 - npm-packlist: 8.0.2 - npm-registry-fetch: ^17.1.0 - nx: ">=17.1.2 < 20" + npm-package-arg: 13.0.0 + npm-packlist: 10.0.1 + npm-registry-fetch: 19.0.0 + nx: ">=21.5.3 < 22.0.0" p-map: 4.0.0 p-map-series: 2.1.0 p-queue: 6.6.2 p-reduce: ^2.1.0 - pacote: ^18.0.6 + pacote: 21.0.1 pify: 5.0.0 read-cmd-shim: 4.0.0 resolve-from: 5.0.0 rimraf: ^4.4.1 - semver: ^7.3.4 + semver: 7.7.2 set-blocking: ^2.0.0 signal-exit: 3.0.7 slash: ^3.0.0 - ssri: ^10.0.6 + ssri: 12.0.0 string-width: ^4.2.3 - strong-log-transformer: 2.1.0 tar: 6.2.1 temp-dir: 1.0.0 + through: 2.3.8 + tinyglobby: 0.2.12 upath: 2.0.1 - uuid: ^10.0.0 - validate-npm-package-license: ^3.0.4 - validate-npm-package-name: 5.0.1 + uuid: ^11.1.0 + validate-npm-package-license: 3.0.4 + validate-npm-package-name: 6.0.2 wide-align: 1.1.5 write-file-atomic: 5.0.1 write-pkg: 4.0.0 yargs: 17.7.2 yargs-parser: 21.1.1 - checksum: 13ed415ebe75ba570665074a53ff2496c44c126ca06b0a18db6bb11b525b19957ecabdf11dc059798a5d46848522b85709f2d15ee987240f1360042af0537b4c + checksum: 6b0df6039a449dfde2619e8f0163e9ccf7d80b99f88560e5cfbb82b61e4764cdf5784d32470242ed94d227488816e45932bb2705dfa0f1a371769af01c9cc298 languageName: node linkType: hard @@ -4845,83 +5119,73 @@ __metadata: languageName: node linkType: hard -"@npmcli/agent@npm:^2.0.0": - version: 2.2.2 - resolution: "@npmcli/agent@npm:2.2.2" +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" dependencies: agent-base: ^7.1.0 http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.1 lru-cache: ^10.0.1 socks-proxy-agent: ^8.0.3 - checksum: 67de7b88cc627a79743c88bab35e023e23daf13831a8aa4e15f998b92f5507b644d8ffc3788afc8e64423c612e0785a6a92b74782ce368f49a6746084b50d874 + checksum: e8fc25d536250ed3e669813b36e8c6d805628b472353c57afd8c4fde0fcfcf3dda4ffe22f7af8c9070812ec2e7a03fb41d7151547cef3508efe661a5a3add20f languageName: node linkType: hard -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" +"@npmcli/agent@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/agent@npm:4.0.0" dependencies: agent-base: ^7.1.0 http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.1 - lru-cache: ^10.0.1 + lru-cache: ^11.2.1 socks-proxy-agent: ^8.0.3 - checksum: e8fc25d536250ed3e669813b36e8c6d805628b472353c57afd8c4fde0fcfcf3dda4ffe22f7af8c9070812ec2e7a03fb41d7151547cef3508efe661a5a3add20f + checksum: 89ae20b44859ff8d4de56ade319d8ceaa267a0742d6f7345fe98aa5cd8614ced7db85ea4dc5bfbd6614dbb200a10b134e087143582534c939e8a02219e8665c8 languageName: node linkType: hard -"@npmcli/arborist@npm:7.5.3": - version: 7.5.3 - resolution: "@npmcli/arborist@npm:7.5.3" +"@npmcli/arborist@npm:9.1.4": + version: 9.1.4 + resolution: "@npmcli/arborist@npm:9.1.4" dependencies: "@isaacs/string-locale-compare": ^1.1.0 - "@npmcli/fs": ^3.1.1 - "@npmcli/installed-package-contents": ^2.1.0 - "@npmcli/map-workspaces": ^3.0.2 - "@npmcli/metavuln-calculator": ^7.1.1 - "@npmcli/name-from-folder": ^2.0.0 - "@npmcli/node-gyp": ^3.0.0 - "@npmcli/package-json": ^5.1.0 - "@npmcli/query": ^3.1.0 - "@npmcli/redact": ^2.0.0 - "@npmcli/run-script": ^8.1.0 - bin-links: ^4.0.4 - cacache: ^18.0.3 + "@npmcli/fs": ^4.0.0 + "@npmcli/installed-package-contents": ^3.0.0 + "@npmcli/map-workspaces": ^4.0.1 + "@npmcli/metavuln-calculator": ^9.0.0 + "@npmcli/name-from-folder": ^3.0.0 + "@npmcli/node-gyp": ^4.0.0 + "@npmcli/package-json": ^6.0.1 + "@npmcli/query": ^4.0.0 + "@npmcli/redact": ^3.0.0 + "@npmcli/run-script": ^9.0.1 + bin-links: ^5.0.0 + cacache: ^19.0.1 common-ancestor-path: ^1.0.1 - hosted-git-info: ^7.0.2 - json-parse-even-better-errors: ^3.0.2 + hosted-git-info: ^8.0.0 json-stringify-nice: ^1.1.4 lru-cache: ^10.2.2 minimatch: ^9.0.4 - nopt: ^7.2.1 - npm-install-checks: ^6.2.0 - npm-package-arg: ^11.0.2 - npm-pick-manifest: ^9.0.1 - npm-registry-fetch: ^17.0.1 - pacote: ^18.0.6 - parse-conflict-json: ^3.0.0 - proc-log: ^4.2.0 - proggy: ^2.0.0 + nopt: ^8.0.0 + npm-install-checks: ^7.1.0 + npm-package-arg: ^12.0.0 + npm-pick-manifest: ^10.0.0 + npm-registry-fetch: ^18.0.1 + pacote: ^21.0.0 + parse-conflict-json: ^4.0.0 + proc-log: ^5.0.0 + proggy: ^3.0.0 promise-all-reject-late: ^1.0.0 promise-call-limit: ^3.0.1 - read-package-json-fast: ^3.0.2 + read-package-json-fast: ^4.0.0 semver: ^7.3.7 - ssri: ^10.0.6 + ssri: ^12.0.0 treeverse: ^3.0.0 - walk-up-path: ^3.0.1 + walk-up-path: ^4.0.0 bin: arborist: bin/index.js - checksum: 5fa70eb628427e52f6f074ee4e9ccd5794eeac0b416076d101b299250faf38aabac2b6230e214fe5a6b9f119b8e15312f62e001c15ba2cca3c72c50fe0f03c80 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^3.1.0, @npmcli/fs@npm:^3.1.1": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" - dependencies: - semver: ^7.3.5 - checksum: d960cab4b93adcb31ce223bfb75c5714edbd55747342efb67dcc2f25e023d930a7af6ece3e75f2f459b6f38fc14d031c766f116cd124fdc937fd33112579e820 + checksum: 987468d3e4219501e747168dea0824668351f9c070d3737be6c6df6de9544864ad3eefb838e8784060d5a69068d3300dea32d8ca3934ddec1607a920c779a2b8 languageName: node linkType: hard @@ -4934,301 +5198,351 @@ __metadata: languageName: node linkType: hard -"@npmcli/git@npm:^5.0.0": - version: 5.0.8 - resolution: "@npmcli/git@npm:5.0.8" +"@npmcli/git@npm:^6.0.0": + version: 6.0.3 + resolution: "@npmcli/git@npm:6.0.3" dependencies: - "@npmcli/promise-spawn": ^7.0.0 - ini: ^4.1.3 + "@npmcli/promise-spawn": ^8.0.0 + ini: ^5.0.0 lru-cache: ^10.0.1 - npm-pick-manifest: ^9.0.0 - proc-log: ^4.0.0 - promise-inflight: ^1.0.1 + npm-pick-manifest: ^10.0.0 + proc-log: ^5.0.0 promise-retry: ^2.0.1 semver: ^7.3.5 - which: ^4.0.0 - checksum: 8c1733b591e428719c60fceaca74b3355967f6ddbce851c0d163a3c2e8123aaa717361b8226f8f8e606685f14721ea97d8f99c4b5831bc9251007bb1a20663cd + which: ^5.0.0 + checksum: 7710c2fe837eb6a7dcf17408896275e85cc45b51180d2c9fb50a0b2addbc3602f8b8c4cb99be00e7e84f2d5bdae9cf6dd479c94ed904922ce8d8fb1c507d9e4a languageName: node linkType: hard -"@npmcli/installed-package-contents@npm:^2.0.1, @npmcli/installed-package-contents@npm:^2.1.0": - version: 2.1.0 - resolution: "@npmcli/installed-package-contents@npm:2.1.0" +"@npmcli/git@npm:^7.0.0": + version: 7.0.0 + resolution: "@npmcli/git@npm:7.0.0" + dependencies: + "@npmcli/promise-spawn": ^8.0.0 + ini: ^5.0.0 + lru-cache: ^11.2.1 + npm-pick-manifest: ^11.0.1 + proc-log: ^5.0.0 + promise-retry: ^2.0.1 + semver: ^7.3.5 + which: ^5.0.0 + checksum: 9ff9d79a8d719755b0f713ec619720c1f29d7a0737a9b871103dd608055d297ade46bb8a100428a81ccb8c4f1ca6964eb9450a6389e175849e922297afeb58ed + languageName: node + linkType: hard + +"@npmcli/installed-package-contents@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/installed-package-contents@npm:3.0.0" dependencies: - npm-bundled: ^3.0.0 - npm-normalize-package-bin: ^3.0.0 + npm-bundled: ^4.0.0 + npm-normalize-package-bin: ^4.0.0 bin: installed-package-contents: bin/index.js - checksum: d0f307e0c971a4ffaea44d4f38d53b57e19222413f338bab26d4321c4a7b9098318d74719dd1f8747a6de0575ac0ba29aeb388edf6599ac8299506947f53ffb6 + checksum: b259157c682512b1eb8a3df58d0cdb73189befda1e5eca8a2c8e4128698a098aa93038931d45f819463fa0f9a5873f782936cf5ab0941f1d125387144361f577 languageName: node linkType: hard -"@npmcli/map-workspaces@npm:^3.0.2": - version: 3.0.6 - resolution: "@npmcli/map-workspaces@npm:3.0.6" +"@npmcli/map-workspaces@npm:^4.0.1": + version: 4.0.2 + resolution: "@npmcli/map-workspaces@npm:4.0.2" dependencies: - "@npmcli/name-from-folder": ^2.0.0 + "@npmcli/name-from-folder": ^3.0.0 + "@npmcli/package-json": ^6.0.0 glob: ^10.2.2 minimatch: ^9.0.0 - read-package-json-fast: ^3.0.0 - checksum: bdb09ee1d044bb9b2857d9e2d7ca82f40783a8549b5a7e150e25f874ee354cdbc8109ad7c3df42ec412f7057d95baa05920c4d361c868a93a42146b8e4390d3d + checksum: 1dba46e94b1e53b59e9b735f89b93ba39c5925120d3f27acb122033833c0e36e5017ab5bdbb0b5dc190300a4359eb4ef9c3539e36e7e2484875b9ac0c75fcfd6 languageName: node linkType: hard -"@npmcli/metavuln-calculator@npm:^7.1.1": - version: 7.1.1 - resolution: "@npmcli/metavuln-calculator@npm:7.1.1" +"@npmcli/metavuln-calculator@npm:^9.0.0": + version: 9.0.3 + resolution: "@npmcli/metavuln-calculator@npm:9.0.3" dependencies: - cacache: ^18.0.0 - json-parse-even-better-errors: ^3.0.0 - pacote: ^18.0.0 - proc-log: ^4.1.0 + cacache: ^20.0.0 + json-parse-even-better-errors: ^5.0.0 + pacote: ^21.0.0 + proc-log: ^6.0.0 semver: ^7.3.5 - checksum: c6297e40f914100c4effb574c55ef95cbf15d0c28e73e39f29de317b12a3d3d82571f8aca3f7635cc4c8e97bff35942c71c59a79e1a8abc93475744e61abc399 + checksum: 4d938758dec806e62b3a8a33f2b65dd3a38da1ab10744df72c1919e4b93b7ebaf0bc6618908d9de27c5fa70a500de423e1979ae74dcc43f40a3e69c96fd28d5e languageName: node linkType: hard -"@npmcli/name-from-folder@npm:^2.0.0": - version: 2.0.0 - resolution: "@npmcli/name-from-folder@npm:2.0.0" - checksum: fb3ef891aa57315fb6171866847f298577c8bda98a028e93e458048477133e142b4eb45ce9f3b80454f7c257612cb01754ee782d608507698dd712164436f5bd +"@npmcli/name-from-folder@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/name-from-folder@npm:3.0.0" + checksum: 1b56429f56c8228bf0eaea8298627b36e383930800a49c9445ae4500b905c98eae1d5f506042a36f49d863d5b79f2aadd154a03d9862dc381ce3fabadcb46e70 languageName: node linkType: hard -"@npmcli/node-gyp@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/node-gyp@npm:3.0.0" - checksum: fe3802b813eecb4ade7ad77c9396cb56721664275faab027e3bd8a5e15adfbbe39e2ecc19f7885feb3cfa009b96632741cc81caf7850ba74440c6a2eee7b4ffc +"@npmcli/node-gyp@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/node-gyp@npm:4.0.0" + checksum: ea4ac6aa273d762a540841315c59c61f3e4ef182c29b1295c30f287cd9d0e33650cd60d626cdce38caf5cff43a5848ea6c213bad5f884110fc90beb167ccbc46 languageName: node linkType: hard -"@npmcli/package-json@npm:5.2.0": - version: 5.2.0 - resolution: "@npmcli/package-json@npm:5.2.0" +"@npmcli/node-gyp@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/node-gyp@npm:5.0.0" + checksum: 6b257d2b220c58ed655c9e267b07daca854a4a0d041f542b6ce16e8bee3bdb5d912beb23b1f8a80f47d68d43f0c0bac214a1f7d48e3d60b8da0ec806d872c48a + languageName: node + linkType: hard + +"@npmcli/package-json@npm:7.0.0": + version: 7.0.0 + resolution: "@npmcli/package-json@npm:7.0.0" dependencies: - "@npmcli/git": ^5.0.0 - glob: ^10.2.2 - hosted-git-info: ^7.0.0 - json-parse-even-better-errors: ^3.0.0 - normalize-package-data: ^6.0.0 - proc-log: ^4.0.0 + "@npmcli/git": ^6.0.0 + glob: ^11.0.3 + hosted-git-info: ^9.0.0 + json-parse-even-better-errors: ^4.0.0 + proc-log: ^5.0.0 semver: ^7.5.3 - checksum: 8df289c45b52cca88826cc737195cabf21757008e11d90b1f62d5400ff65834c0e9bcb552f235ba560c3af436a1ca3fc553b23b5cb5da8330ae56929065a6988 + validate-npm-package-license: ^3.0.4 + checksum: 8ca952021a8d418e25ac32177b1c35e42fb2af3f5039432a6f7dc6811ab1c1dbe11d0f97a3c876dce08aaea33267193da344a979071f194f915a2a374de37f14 languageName: node linkType: hard -"@npmcli/package-json@npm:^5.0.0, @npmcli/package-json@npm:^5.1.0": - version: 5.2.1 - resolution: "@npmcli/package-json@npm:5.2.1" +"@npmcli/package-json@npm:^6.0.0, @npmcli/package-json@npm:^6.0.1, @npmcli/package-json@npm:^6.2.0": + version: 6.2.0 + resolution: "@npmcli/package-json@npm:6.2.0" dependencies: - "@npmcli/git": ^5.0.0 + "@npmcli/git": ^6.0.0 glob: ^10.2.2 - hosted-git-info: ^7.0.0 - json-parse-even-better-errors: ^3.0.0 - normalize-package-data: ^6.0.0 - proc-log: ^4.0.0 + hosted-git-info: ^8.0.0 + json-parse-even-better-errors: ^4.0.0 + proc-log: ^5.0.0 semver: ^7.5.3 - checksum: f9f76428fb3b3350fe840f1fa49854d18ff1ecb82b426c9cf53a62a37389c357a89d64a07497f50b7fbf1c742f5a0cd349d8efdddef0bb6982497f8356c1f98a + validate-npm-package-license: ^3.0.4 + checksum: 4aee5d2c27c9704c313ff207947fd43d28c76cc3bed9d8004046d4b0989b7a67718173259f45ba1647cf439b3675b50a052e67d5a68f0c34899db8d131c45113 languageName: node linkType: hard -"@npmcli/promise-spawn@npm:^7.0.0": +"@npmcli/package-json@npm:^7.0.0": version: 7.0.2 - resolution: "@npmcli/promise-spawn@npm:7.0.2" + resolution: "@npmcli/package-json@npm:7.0.2" dependencies: - which: ^4.0.0 - checksum: 728256506ecbafb53064036e28c2815b9a9e9190ba7a48eec77b011a9f8a899515a6d96760dbde960bc1d3e5b828fd0b0b7fe3b512efaf049d299bacbd732fda + "@npmcli/git": ^7.0.0 + glob: ^11.0.3 + hosted-git-info: ^9.0.0 + json-parse-even-better-errors: ^5.0.0 + proc-log: ^6.0.0 + semver: ^7.5.3 + validate-npm-package-license: ^3.0.4 + checksum: cb237240c0f844f8e4b0fb13fb425c1abbfdc510e894412cdf88071c3bfb1bd864867797bd13d214a396ae51cc4f6d68a31eb23f9682f6898a7eb09d6e5be58b languageName: node linkType: hard -"@npmcli/query@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/query@npm:3.1.0" +"@npmcli/promise-spawn@npm:^8.0.0": + version: 8.0.3 + resolution: "@npmcli/promise-spawn@npm:8.0.3" dependencies: - postcss-selector-parser: ^6.0.10 - checksum: 33c018bfcc6d64593e7969847d0442beab4e8a42b6c9f932237c9fd135c95ab55de5c4b5d5d66302dd9fc3c748bc4ead780d3595e5d586fedf9859ed6b5f2744 + which: ^5.0.0 + checksum: 155d6577a976a2b6cff1e4954f08b8a94b9b28fa03f8b5f8e3daf9e575b649669127a63b8ae4e86e218c55e413277458c383df33d654e8f538cffcafcbfe1b63 languageName: node linkType: hard -"@npmcli/redact@npm:^2.0.0": - version: 2.0.1 - resolution: "@npmcli/redact@npm:2.0.1" - checksum: 78b0a71f0f578191dd2e19044894ded0328359138deb167f4ca75ec63a81ae59bae5289287793fdc36c125608be7631c5b3b32eaa083f62a551430c68b64d295 +"@npmcli/promise-spawn@npm:^9.0.0": + version: 9.0.0 + resolution: "@npmcli/promise-spawn@npm:9.0.0" + dependencies: + which: ^5.0.0 + checksum: 79e9838abf57391e0345253cf0b3d2b1f22ac48bb86a8b542486f41c5b52e2d6f48dd5944775542c90f9da33f0b06868023c1b37ca9f9336a265858a546757c9 languageName: node linkType: hard -"@npmcli/run-script@npm:8.1.0, @npmcli/run-script@npm:^8.0.0, @npmcli/run-script@npm:^8.1.0": - version: 8.1.0 - resolution: "@npmcli/run-script@npm:8.1.0" +"@npmcli/query@npm:^4.0.0": + version: 4.0.1 + resolution: "@npmcli/query@npm:4.0.1" dependencies: - "@npmcli/node-gyp": ^3.0.0 - "@npmcli/package-json": ^5.0.0 - "@npmcli/promise-spawn": ^7.0.0 - node-gyp: ^10.0.0 - proc-log: ^4.0.0 - which: ^4.0.0 - checksum: 21adfb308b9064041d6d2f7f0d53924be0e1466d558de1c9802fab9eb84850bd8e04fdd5695924f331e1a36565461500d912e187909f91c03188cc763a106986 + postcss-selector-parser: ^7.0.0 + checksum: d648db388b94fe177b6b05a6602f917ed30a8ead9c85b96f2e2585d5b90d62de316f3a294e5301dcb7eb4c947a77119e28ba8d42b2bc48dad8a785e2271a6ea8 languageName: node linkType: hard -"@nrwl/devkit@npm:19.8.14": - version: 19.8.14 - resolution: "@nrwl/devkit@npm:19.8.14" +"@npmcli/redact@npm:^3.0.0": + version: 3.2.2 + resolution: "@npmcli/redact@npm:3.2.2" + checksum: f1b9132771255e7c6e9335312809cff7769fc8d0f26cf4696e6f5966279530e32138fb433f0f49758cb65ea68a9404cbdcd9d7ad92e2df6e539b7df28a1079a9 + languageName: node + linkType: hard + +"@npmcli/run-script@npm:10.0.0": + version: 10.0.0 + resolution: "@npmcli/run-script@npm:10.0.0" dependencies: - "@nx/devkit": 19.8.14 - checksum: 847c5a1b2d4dbeec9f477f14037d42f5308aa444e48faf5a10454b8d4322653f00b3c58d5cd996e062bf32de09b5a18a0e6dda539b9c6966ab5edf2f41050573 + "@npmcli/node-gyp": ^4.0.0 + "@npmcli/package-json": ^7.0.0 + "@npmcli/promise-spawn": ^8.0.0 + node-gyp: ^11.0.0 + proc-log: ^5.0.0 + which: ^5.0.0 + checksum: cad0d870d4d6f5fad0d0eb188a7030ccbfdec410dd69b762a28ea3747665878c3ac9c4528c9099c7dc13c351bfb051d2afec158c79ba6379399e73dc74202327 languageName: node linkType: hard -"@nrwl/tao@npm:19.8.14": - version: 19.8.14 - resolution: "@nrwl/tao@npm:19.8.14" +"@npmcli/run-script@npm:^10.0.0": + version: 10.0.2 + resolution: "@npmcli/run-script@npm:10.0.2" dependencies: - nx: 19.8.14 - tslib: ^2.3.0 - bin: - tao: index.js - checksum: f9e10d1edb2089c091a1e234d206b5f37e4a62666788cf00c4b9767885df7d3c2dd1d36f9de7b932de72a699e02e3013fbf41e3243a35ce197b3fb5ca5f165af + "@npmcli/node-gyp": ^5.0.0 + "@npmcli/package-json": ^7.0.0 + "@npmcli/promise-spawn": ^9.0.0 + node-gyp: ^11.0.0 + proc-log: ^6.0.0 + which: ^5.0.0 + checksum: 4f5aacc872974422be5d79f68f298d97c52a985b9e200c7b8df05da072080bcf3c1519e92321e88e21131175c13404f6acc5d4e8c42510a1041da61be56bb17d + languageName: node + linkType: hard + +"@npmcli/run-script@npm:^9.0.1": + version: 9.1.0 + resolution: "@npmcli/run-script@npm:9.1.0" + dependencies: + "@npmcli/node-gyp": ^4.0.0 + "@npmcli/package-json": ^6.0.0 + "@npmcli/promise-spawn": ^8.0.0 + node-gyp: ^11.0.0 + proc-log: ^5.0.0 + which: ^5.0.0 + checksum: b9965b3d9212459a97e820dbe28b7e46312c2ecddb72b85383e3f72b73453416a1ddfb4b5bac92b9a8508e9817621141caf8e60967de3e158c758cd280494c79 languageName: node linkType: hard -"@nx/devkit@npm:19.8.14, @nx/devkit@npm:>=17.1.2 < 20": - version: 19.8.14 - resolution: "@nx/devkit@npm:19.8.14" +"@nx/devkit@npm:>=21.5.2 < 22.0.0": + version: 21.6.8 + resolution: "@nx/devkit@npm:21.6.8" dependencies: - "@nrwl/devkit": 19.8.14 ejs: ^3.1.7 enquirer: ~2.3.6 ignore: ^5.0.4 minimatch: 9.0.3 semver: ^7.5.3 - tmp: ~0.2.1 tslib: ^2.3.0 yargs-parser: 21.1.1 peerDependencies: - nx: ">= 19 <= 21" - checksum: ee462aeb35a78d305f3f193e0be45b5afa8afd7eda7e8e2d5d82c066769ea0d04f1375638e8421081d72b76dee8040c84d5edb61e351572ff00ad2e837c6f9d3 + nx: ">= 20 <= 22" + checksum: e484cea83bcad4162c80218e7b9a958d0f116ef9d0c2816ca795c534394ac2fdcc245fa3f421cfc4f98521ebbd8e916b6e65628c110b5bc67d80eddcaeb05f13 languageName: node linkType: hard -"@nx/nx-darwin-arm64@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-darwin-arm64@npm:19.8.14" +"@nx/nx-darwin-arm64@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-darwin-arm64@npm:21.6.8" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@nx/nx-darwin-x64@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-darwin-x64@npm:19.8.14" +"@nx/nx-darwin-x64@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-darwin-x64@npm:21.6.8" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@nx/nx-freebsd-x64@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-freebsd-x64@npm:19.8.14" +"@nx/nx-freebsd-x64@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-freebsd-x64@npm:21.6.8" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@nx/nx-linux-arm-gnueabihf@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-linux-arm-gnueabihf@npm:19.8.14" +"@nx/nx-linux-arm-gnueabihf@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-linux-arm-gnueabihf@npm:21.6.8" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@nx/nx-linux-arm64-gnu@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-linux-arm64-gnu@npm:19.8.14" +"@nx/nx-linux-arm64-gnu@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-linux-arm64-gnu@npm:21.6.8" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@nx/nx-linux-arm64-musl@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-linux-arm64-musl@npm:19.8.14" +"@nx/nx-linux-arm64-musl@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-linux-arm64-musl@npm:21.6.8" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@nx/nx-linux-x64-gnu@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-linux-x64-gnu@npm:19.8.14" +"@nx/nx-linux-x64-gnu@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-linux-x64-gnu@npm:21.6.8" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@nx/nx-linux-x64-musl@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-linux-x64-musl@npm:19.8.14" +"@nx/nx-linux-x64-musl@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-linux-x64-musl@npm:21.6.8" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@nx/nx-win32-arm64-msvc@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-win32-arm64-msvc@npm:19.8.14" +"@nx/nx-win32-arm64-msvc@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-win32-arm64-msvc@npm:21.6.8" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@nx/nx-win32-x64-msvc@npm:19.8.14": - version: 19.8.14 - resolution: "@nx/nx-win32-x64-msvc@npm:19.8.14" +"@nx/nx-win32-x64-msvc@npm:21.6.8": + version: 21.6.8 + resolution: "@nx/nx-win32-x64-msvc@npm:21.6.8" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@octokit/auth-token@npm:^3.0.0": - version: 3.0.4 - resolution: "@octokit/auth-token@npm:3.0.4" - checksum: 42f533a873d4192e6df406b3176141c1f95287423ebdc4cf23a38bb77ee00ccbc0e60e3fbd5874234fc2ed2e67bbc6035e3b0561dacc1d078adb5c4ced3579e3 +"@octokit/auth-token@npm:^4.0.0": + version: 4.0.0 + resolution: "@octokit/auth-token@npm:4.0.0" + checksum: d78f4dc48b214d374aeb39caec4fdbf5c1e4fd8b9fcb18f630b1fe2cbd5a880fca05445f32b4561f41262cb551746aeb0b49e89c95c6dd99299706684d0cae2f languageName: node linkType: hard -"@octokit/core@npm:^4.2.1": - version: 4.2.4 - resolution: "@octokit/core@npm:4.2.4" +"@octokit/core@npm:^5.0.2": + version: 5.2.2 + resolution: "@octokit/core@npm:5.2.2" dependencies: - "@octokit/auth-token": ^3.0.0 - "@octokit/graphql": ^5.0.0 - "@octokit/request": ^6.0.0 - "@octokit/request-error": ^3.0.0 - "@octokit/types": ^9.0.0 + "@octokit/auth-token": ^4.0.0 + "@octokit/graphql": ^7.1.0 + "@octokit/request": ^8.4.1 + "@octokit/request-error": ^5.1.1 + "@octokit/types": ^13.0.0 before-after-hook: ^2.2.0 universal-user-agent: ^6.0.0 - checksum: ac8ab47440a31b0228a034aacac6994b64d6b073ad5b688b4c5157fc5ee0d1af1c926e6087bf17fd7244ee9c5998839da89065a90819bde4a97cb77d4edf58a6 + checksum: d4303d808c6b8eca32ce03381db5f6230440c1c6cfd9d73376ed583973094abd8ca56d9a64d490e6b0045f827a8f913b619bd90eae99c2cba682487720dc8002 languageName: node linkType: hard -"@octokit/endpoint@npm:^7.0.0": - version: 7.0.6 - resolution: "@octokit/endpoint@npm:7.0.6" +"@octokit/endpoint@npm:^9.0.6": + version: 9.0.6 + resolution: "@octokit/endpoint@npm:9.0.6" dependencies: - "@octokit/types": ^9.0.0 - is-plain-object: ^5.0.0 + "@octokit/types": ^13.1.0 universal-user-agent: ^6.0.0 - checksum: 7caebf30ceec50eb7f253341ed419df355232f03d4638a95c178ee96620400db7e4a5e15d89773fe14db19b8653d4ab4cc81b2e93ca0c760b4e0f7eb7ad80301 + checksum: f853c08f0777a8cc7c3d2509835d478e11a76d722f807d4f2ad7c0e64bf4dd159536409f466b367a907886aa3b78574d3d09ed95ac462c769e4fccaaad81e72a languageName: node linkType: hard -"@octokit/graphql@npm:^5.0.0": - version: 5.0.6 - resolution: "@octokit/graphql@npm:5.0.6" +"@octokit/graphql@npm:^7.1.0": + version: 7.1.1 + resolution: "@octokit/graphql@npm:7.1.1" dependencies: - "@octokit/request": ^6.0.0 - "@octokit/types": ^9.0.0 + "@octokit/request": ^8.4.1 + "@octokit/types": ^13.0.0 universal-user-agent: ^6.0.0 - checksum: 7be545d348ef31dcab0a2478dd64d5746419a2f82f61459c774602bcf8a9b577989c18001f50b03f5f61a3d9e34203bdc021a4e4d75ff2d981e8c9c09cf8a65c + checksum: afb60d5dda6d365334480540610d67b0c5f8e3977dd895fe504ce988f8b7183f29f3b16b88d895a701a739cf29d157d49f8f9fbc71b6c57eb4fc9bd97e099f55 languageName: node linkType: hard -"@octokit/openapi-types@npm:^18.0.0": - version: 18.1.1 - resolution: "@octokit/openapi-types@npm:18.1.1" - checksum: 94f42977fd2fcb9983c781fd199bc11218885a1226d492680bfb1268524a1b2af48a768eef90c63b80a2874437de641d59b3b7f640a5afa93e7c21fe1a79069a +"@octokit/openapi-types@npm:^24.2.0": + version: 24.2.0 + resolution: "@octokit/openapi-types@npm:24.2.0" + checksum: 3c2d2f4cafd21c8a1e6a6fe6b56df6a3c09bc52ab6f829c151f9397694d028aa183ae856f08e006ee7ecaa7bd7eb413a903fbc0ffa6403e7b284ddcda20b1294 languageName: node linkType: hard @@ -5239,97 +5553,78 @@ __metadata: languageName: node linkType: hard -"@octokit/plugin-paginate-rest@npm:^6.1.2": - version: 6.1.2 - resolution: "@octokit/plugin-paginate-rest@npm:6.1.2" +"@octokit/plugin-paginate-rest@npm:11.4.4-cjs.2": + version: 11.4.4-cjs.2 + resolution: "@octokit/plugin-paginate-rest@npm:11.4.4-cjs.2" dependencies: - "@octokit/tsconfig": ^1.0.2 - "@octokit/types": ^9.2.3 + "@octokit/types": ^13.7.0 peerDependencies: - "@octokit/core": ">=4" - checksum: a7b3e686c7cbd27ec07871cde6e0b1dc96337afbcef426bbe3067152a17b535abd480db1861ca28c88d93db5f7bfdbcadd0919ead19818c28a69d0e194038065 + "@octokit/core": 5 + checksum: e6d1f4da255d08c24188b5df1436f22680e7fe2608d3af5d2f08a98f40d565bd3df0c58d306f05caae923247fffe861ec12d5f1273a882333fcdb34255e6c8b0 languageName: node linkType: hard -"@octokit/plugin-request-log@npm:^1.0.4": - version: 1.0.4 - resolution: "@octokit/plugin-request-log@npm:1.0.4" +"@octokit/plugin-request-log@npm:^4.0.0": + version: 4.0.1 + resolution: "@octokit/plugin-request-log@npm:4.0.1" peerDependencies: - "@octokit/core": ">=3" - checksum: 2086db00056aee0f8ebd79797b5b57149ae1014e757ea08985b71eec8c3d85dbb54533f4fd34b6b9ecaa760904ae6a7536be27d71e50a3782ab47809094bfc0c + "@octokit/core": 5 + checksum: fd8c0a201490cba00084689a0d1d54fc7b5ab5b6bdb7e447056b947b1754f78526e9685400eab10d3522bfa7b5bc49c555f41ec412c788610b96500b168f3789 languageName: node linkType: hard -"@octokit/plugin-rest-endpoint-methods@npm:^7.1.2": - version: 7.2.3 - resolution: "@octokit/plugin-rest-endpoint-methods@npm:7.2.3" +"@octokit/plugin-rest-endpoint-methods@npm:13.3.2-cjs.1": + version: 13.3.2-cjs.1 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:13.3.2-cjs.1" dependencies: - "@octokit/types": ^10.0.0 + "@octokit/types": ^13.8.0 peerDependencies: - "@octokit/core": ">=3" - checksum: 21dfb98514dbe900c29cddb13b335bbce43d613800c6b17eba3c1fd31d17e69c1960f3067f7bf864bb38fdd5043391f4a23edee42729d8c7fbabd00569a80336 + "@octokit/core": ^5 + checksum: de38a7fe33aa41ecfa62dd8546d9b603cf43b1a6cf3a31e8c1950684e1cf0f9dc7ccbcff8ef570e825729f3800f42e6ae33447c836dfa12259391ced421df64f languageName: node linkType: hard -"@octokit/request-error@npm:^3.0.0": - version: 3.0.3 - resolution: "@octokit/request-error@npm:3.0.3" +"@octokit/request-error@npm:^5.1.1": + version: 5.1.1 + resolution: "@octokit/request-error@npm:5.1.1" dependencies: - "@octokit/types": ^9.0.0 + "@octokit/types": ^13.1.0 deprecation: ^2.0.0 once: ^1.4.0 - checksum: 5db0b514732686b627e6ed9ef1ccdbc10501f1b271a9b31f784783f01beee70083d7edcfeb35fbd7e569fa31fdd6762b1ff6b46101700d2d97e7e48e749520d0 + checksum: 17d0b3f59c2a8a285715bfe6a85168d9c417aa7a0ff553b9be4198a3bc8bb00384a3530221a448eb19f8f07ea9fc48d264869624f5f84fa63a948a7af8cddc8c languageName: node linkType: hard -"@octokit/request@npm:^6.0.0": - version: 6.2.8 - resolution: "@octokit/request@npm:6.2.8" +"@octokit/request@npm:^8.4.1": + version: 8.4.1 + resolution: "@octokit/request@npm:8.4.1" dependencies: - "@octokit/endpoint": ^7.0.0 - "@octokit/request-error": ^3.0.0 - "@octokit/types": ^9.0.0 - is-plain-object: ^5.0.0 - node-fetch: ^2.6.7 + "@octokit/endpoint": ^9.0.6 + "@octokit/request-error": ^5.1.1 + "@octokit/types": ^13.1.0 universal-user-agent: ^6.0.0 - checksum: 3747106f50d7c462131ff995b13defdd78024b7becc40283f4ac9ea0af2391ff33a0bb476a05aa710346fe766d20254979079a1d6f626112015ba271fe38f3e2 + checksum: 0ba76728583543baeef9fda98690bc86c57e0a3ccac8c189d2b7d144d248c89167eb37a071ed8fead8f4da0a1c55c4dd98a8fc598769c263b95179fb200959de languageName: node linkType: hard -"@octokit/rest@npm:19.0.11": - version: 19.0.11 - resolution: "@octokit/rest@npm:19.0.11" +"@octokit/rest@npm:20.1.2": + version: 20.1.2 + resolution: "@octokit/rest@npm:20.1.2" dependencies: - "@octokit/core": ^4.2.1 - "@octokit/plugin-paginate-rest": ^6.1.2 - "@octokit/plugin-request-log": ^1.0.4 - "@octokit/plugin-rest-endpoint-methods": ^7.1.2 - checksum: 147518ad51d214ead88adc717b5fdc4f33317949d58c124f4069bdf07d2e6b49fa66861036b9e233aed71fcb88ff367a6da0357653484e466175ab4fb7183b3b + "@octokit/core": ^5.0.2 + "@octokit/plugin-paginate-rest": 11.4.4-cjs.2 + "@octokit/plugin-request-log": ^4.0.0 + "@octokit/plugin-rest-endpoint-methods": 13.3.2-cjs.1 + checksum: 72309dd393f3424f0c4213d045332c1c1a00893bea4db9b54d6add7316d9a9b461932de3afe3c866bff52cc084c79e98f644dabd386cda95068690cc9ae97456 languageName: node linkType: hard -"@octokit/tsconfig@npm:^1.0.2": - version: 1.0.2 - resolution: "@octokit/tsconfig@npm:1.0.2" - checksum: 74d56f3e9f326a8dd63700e9a51a7c75487180629c7a68bbafee97c612fbf57af8347369bfa6610b9268a3e8b833c19c1e4beb03f26db9a9dce31f6f7a19b5b1 - languageName: node - linkType: hard - -"@octokit/types@npm:^10.0.0": - version: 10.0.0 - resolution: "@octokit/types@npm:10.0.0" - dependencies: - "@octokit/openapi-types": ^18.0.0 - checksum: 8aafba2ff0cd2435fb70c291bf75ed071c0fa8a865cf6169648732068a35dec7b85a345851f18920ec5f3e94ee0e954988485caac0da09ec3f6781cc44fe153a - languageName: node - linkType: hard - -"@octokit/types@npm:^9.0.0, @octokit/types@npm:^9.2.3": - version: 9.3.2 - resolution: "@octokit/types@npm:9.3.2" +"@octokit/types@npm:^13.0.0, @octokit/types@npm:^13.1.0, @octokit/types@npm:^13.7.0, @octokit/types@npm:^13.8.0": + version: 13.10.0 + resolution: "@octokit/types@npm:13.10.0" dependencies: - "@octokit/openapi-types": ^18.0.0 - checksum: f55d096aaed3e04b8308d4422104fb888f355988056ba7b7ef0a4c397b8a3e54290d7827b06774dbe0c9ce55280b00db486286954f9c265aa6b03091026d9da8 + "@octokit/openapi-types": ^24.2.0 + checksum: fca3764548d5872535b9025c3b5fe6373fe588b287cb5b5259364796c1931bbe5e9ab8a86a5274ce43bb2b3e43b730067c3b86b6b1ade12a98cd59b2e8b3610d languageName: node linkType: hard @@ -6531,61 +6826,119 @@ __metadata: languageName: node linkType: hard -"@sigstore/bundle@npm:^2.3.2": - version: 2.3.2 - resolution: "@sigstore/bundle@npm:2.3.2" +"@sigstore/bundle@npm:^3.1.0": + version: 3.1.0 + resolution: "@sigstore/bundle@npm:3.1.0" dependencies: - "@sigstore/protobuf-specs": ^0.3.2 - checksum: 851095ef71473b187df4d8b3374821d53c152646e591557973bd9648a9f08e3e8f686c7523194f513ded9534b4d057aa18697ee11f784ec4e36161907ce6d8ee + "@sigstore/protobuf-specs": ^0.4.0 + checksum: 8f560c77eb1cc45785afb1bcb6adfb2af499523038941a92c65fd80924b055bacc0266fa973407c275dbdcf48a976f215f627fea5c9d8f68bd618cfe247393aa languageName: node linkType: hard -"@sigstore/core@npm:^1.0.0, @sigstore/core@npm:^1.1.0": - version: 1.1.0 - resolution: "@sigstore/core@npm:1.1.0" - checksum: bb870cf11cfb260d9e83f40cc29e6bbaf6ef5211d42eacbb48517ff87b1f647ff687eff557b0b30f9880fac2517d14704ec6036ae4a0d99ef3265b3d40cef29c +"@sigstore/bundle@npm:^4.0.0": + version: 4.0.0 + resolution: "@sigstore/bundle@npm:4.0.0" + dependencies: + "@sigstore/protobuf-specs": ^0.5.0 + checksum: 1a7ca1722c31ba42af0d33a14114224a90e61061eab4248f2ba8241430dc6dfca3b59e1878c7ad3693d6938c87aeedb2dff4819a2261b3d00b751240e2044eb9 languageName: node linkType: hard -"@sigstore/protobuf-specs@npm:^0.3.2": - version: 0.3.3 - resolution: "@sigstore/protobuf-specs@npm:0.3.3" - checksum: 5457c64efd564ef1a7fcf06fe48fc2c96f2e5865b9a4cde818ebbee6e592492b3834bd8f1c1202e5790f21278ad45f2dc771c1f7328175c099147ce3a680614a +"@sigstore/core@npm:^2.0.0": + version: 2.0.0 + resolution: "@sigstore/core@npm:2.0.0" + checksum: fd21df6ce574ef8fed855955ce864523368bdca8202ed9d90f2b4822f4889315a23f52eef72cbf09534af669329c8affdd36a3615c9598eb9311a4cc22f3f21a languageName: node linkType: hard -"@sigstore/sign@npm:^2.3.2": - version: 2.3.2 - resolution: "@sigstore/sign@npm:2.3.2" +"@sigstore/core@npm:^3.0.0": + version: 3.0.0 + resolution: "@sigstore/core@npm:3.0.0" + checksum: d3650b6089b0d1411677fc8ddb32c2e494a288968efd99c9c6b18d4447df1265f6c3b6585e1c88997f863015b03bc83b92e63d83d7625280b0f64e18ad74c20c + languageName: node + linkType: hard + +"@sigstore/protobuf-specs@npm:^0.4.0, @sigstore/protobuf-specs@npm:^0.4.1": + version: 0.4.3 + resolution: "@sigstore/protobuf-specs@npm:0.4.3" + checksum: a1254864fd3b8795436a3720c61efafd8ca093d79d7bdb1de56a94ef7f7862cc07f2a5e11a926cad8fc58429bbcbba70c561581b0a52dbbef2d1248b8bf5748b + languageName: node + linkType: hard + +"@sigstore/protobuf-specs@npm:^0.5.0": + version: 0.5.0 + resolution: "@sigstore/protobuf-specs@npm:0.5.0" + checksum: bfb34ce233f893635d6a757c11bde23cabfa173b5f7c8bc28e02181ca23c4eeb9272b507bdf5543a8254697acc65b9781d714397edeb09c6f3fa781857e9b9d5 + languageName: node + linkType: hard + +"@sigstore/sign@npm:^3.1.0": + version: 3.1.0 + resolution: "@sigstore/sign@npm:3.1.0" dependencies: - "@sigstore/bundle": ^2.3.2 - "@sigstore/core": ^1.0.0 - "@sigstore/protobuf-specs": ^0.3.2 - make-fetch-happen: ^13.0.1 - proc-log: ^4.2.0 + "@sigstore/bundle": ^3.1.0 + "@sigstore/core": ^2.0.0 + "@sigstore/protobuf-specs": ^0.4.0 + make-fetch-happen: ^14.0.2 + proc-log: ^5.0.0 promise-retry: ^2.0.1 - checksum: b8bfc38716956df0aadbba8a78ed4b3a758747e31e1ed775deab0632243ff94aee51f6c17cf344834cf6e5174449358988ce35e3437e80e49867a7821ad5aa45 + checksum: 0518aaa542ad7684d86d7c3d6829119cf35fc4084b61329a376e298acda4ffbc8fa53afaf0b6a8dfba41d5e5943034d2cb5bf8034c07dbd0aa86dd32fb01c3d3 languageName: node linkType: hard -"@sigstore/tuf@npm:^2.3.4": - version: 2.3.4 - resolution: "@sigstore/tuf@npm:2.3.4" +"@sigstore/sign@npm:^4.0.0": + version: 4.0.1 + resolution: "@sigstore/sign@npm:4.0.1" dependencies: - "@sigstore/protobuf-specs": ^0.3.2 - tuf-js: ^2.2.1 - checksum: 62f0b17e116d42d224c7d9f40a4037c7c20f456e026059ce6ebfc155e6d6445396549acd01a6f799943857e900f1bb2b0523d00a9353b8f3f99862f1eba59f6d + "@sigstore/bundle": ^4.0.0 + "@sigstore/core": ^3.0.0 + "@sigstore/protobuf-specs": ^0.5.0 + make-fetch-happen: ^15.0.2 + proc-log: ^5.0.0 + promise-retry: ^2.0.1 + checksum: 40c7183b779ac27f3c7a032ae648e29a067826f19129719b817c3d3ebf08090bef6562278a46db2ac9701f94bfe24ea088868372cb23875b8a2e96fcabefd27b languageName: node linkType: hard -"@sigstore/verify@npm:^1.2.1": - version: 1.2.1 - resolution: "@sigstore/verify@npm:1.2.1" +"@sigstore/tuf@npm:^3.1.0": + version: 3.1.1 + resolution: "@sigstore/tuf@npm:3.1.1" dependencies: - "@sigstore/bundle": ^2.3.2 - "@sigstore/core": ^1.1.0 - "@sigstore/protobuf-specs": ^0.3.2 - checksum: bcd08c152d6166e9c6a019c8cb50afe1b284c01753e219e126665d21b5923cbdba3700daa3cee5197a07af551ecca8b209a6c557fbc0e5f6a4ee6f9c531047fe + "@sigstore/protobuf-specs": ^0.4.1 + tuf-js: ^3.0.1 + checksum: 876a1f749458e280b77ec4084ee1e7594b42bfd4391ed22c41bc2984d6dfa46cb52a28756adb58f6c1cc8b018481a220f9fcef1dbd890ae457253ae7225fd7eb + languageName: node + linkType: hard + +"@sigstore/tuf@npm:^4.0.0": + version: 4.0.0 + resolution: "@sigstore/tuf@npm:4.0.0" + dependencies: + "@sigstore/protobuf-specs": ^0.5.0 + tuf-js: ^4.0.0 + checksum: e5766239120c16cab983354d147bdea52ee9eefc5f7cddbf9b30bf56fb9f101e20b2c0fd223a1a669f2c1ef51ad8d9bad8c686f7be89abc6cfbdc9d8a11d730a + languageName: node + linkType: hard + +"@sigstore/verify@npm:^2.1.0": + version: 2.1.1 + resolution: "@sigstore/verify@npm:2.1.1" + dependencies: + "@sigstore/bundle": ^3.1.0 + "@sigstore/core": ^2.0.0 + "@sigstore/protobuf-specs": ^0.4.1 + checksum: 378316e2b5462ef400f9ad764b037a046a9835ac11b341137d6b16120d9fbfcf261a87ee8f918ba3cf67846e0ae639caae01b830697c0f10316685afdd319ec8 + languageName: node + linkType: hard + +"@sigstore/verify@npm:^3.0.0": + version: 3.0.0 + resolution: "@sigstore/verify@npm:3.0.0" + dependencies: + "@sigstore/bundle": ^4.0.0 + "@sigstore/core": ^3.0.0 + "@sigstore/protobuf-specs": ^0.5.0 + checksum: 336d8af044691e7d342fedfd7748c9815974bfac72924bdc541889d6b5a3e844c568f8c8c7c3e3d0594e7e405610d33a11199d6dbbe9370005bd83f7a0df3500 languageName: node linkType: hard @@ -7549,13 +7902,23 @@ __metadata: languageName: node linkType: hard -"@tufjs/models@npm:2.0.1": - version: 2.0.1 - resolution: "@tufjs/models@npm:2.0.1" +"@tufjs/models@npm:3.0.1": + version: 3.0.1 + resolution: "@tufjs/models@npm:3.0.1" dependencies: "@tufjs/canonical-json": 2.0.0 - minimatch: ^9.0.4 - checksum: 7a7370ac8dc3c18b66dddca3269d9b9282d891f1c289beb2060649fd50ef74eaa6494bd6d6b3edfe11f0f1efa14ec19c5ec819c7cf1871476c9e002115ffb9a7 + minimatch: ^9.0.5 + checksum: 95b179bc09e5a0b6dfc9e7001e15882e863e034bf41e0502e89f2fa82cb3f6d5bd9edaefd2baf2a7f515abdb521127adf771e8bbe66f3e7f212e3b777ae993f5 + languageName: node + linkType: hard + +"@tufjs/models@npm:4.0.0": + version: 4.0.0 + resolution: "@tufjs/models@npm:4.0.0" + dependencies: + "@tufjs/canonical-json": 2.0.0 + minimatch: ^9.0.5 + checksum: 46327be1524628b7b6bc2756a8153c04c9de996335d9babf3706a22f743db3584e26887d76a6ccd68d098b5ec79cf2c4a6615deb19318b5cc20f5804aa13afa9 languageName: node linkType: hard @@ -8257,13 +8620,13 @@ __metadata: languageName: node linkType: hard -"@yarnpkg/parsers@npm:3.0.0-rc.46": - version: 3.0.0-rc.46 - resolution: "@yarnpkg/parsers@npm:3.0.0-rc.46" +"@yarnpkg/parsers@npm:3.0.2": + version: 3.0.2 + resolution: "@yarnpkg/parsers@npm:3.0.2" dependencies: js-yaml: ^3.10.0 tslib: ^2.4.0 - checksum: 35dfd1b1ac7ed9babf231721eb90b58156e840e575f6792a8e5ab559beaed6e2d60833b857310e67d6282c9406357648df2f510e670ec37ef4bd41657f329a51 + checksum: fb40a87ae7c9f3fc0b2a6b7d84375d1c69ae8304daf598c089b52966bfb4ac94fbd2dcd87ed041970416e03d34359cb5ff16be5f5601f48d1f936213a8edaf4d languageName: node linkType: hard @@ -8318,13 +8681,6 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 - languageName: node - linkType: hard - "abbrev@npm:^3.0.0": version: 3.0.1 resolution: "abbrev@npm:3.0.1" @@ -8522,7 +8878,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 @@ -9154,15 +9510,16 @@ __metadata: languageName: node linkType: hard -"bin-links@npm:^4.0.4": - version: 4.0.4 - resolution: "bin-links@npm:4.0.4" +"bin-links@npm:^5.0.0": + version: 5.0.0 + resolution: "bin-links@npm:5.0.0" dependencies: - cmd-shim: ^6.0.0 - npm-normalize-package-bin: ^3.0.0 - read-cmd-shim: ^4.0.0 - write-file-atomic: ^5.0.0 - checksum: 9fca1fddaa3c1c9f7efd6fd7a6d991e3d8f6aaa9de5d0b9355469c2c594d8d06c9b2e0519bb0304202c14ddbe832d27b6d419d55cea4340e2c26116f9190e5c9 + cmd-shim: ^7.0.0 + npm-normalize-package-bin: ^4.0.0 + proc-log: ^5.0.0 + read-cmd-shim: ^5.0.0 + write-file-atomic: ^6.0.0 + checksum: b3793e0e5af4b42ac911c4a2abf78c460f0a787c038d4b401ee1017e64823679d8aef25ada5f9c39f53889c62329a23547f724b7a784aab128fb6defd9515485 languageName: node linkType: hard @@ -9349,11 +9706,11 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^18.0.0, cacache@npm:^18.0.3": - version: 18.0.4 - resolution: "cacache@npm:18.0.4" +"cacache@npm:^19.0.1": + version: 19.0.1 + resolution: "cacache@npm:19.0.1" dependencies: - "@npmcli/fs": ^3.1.0 + "@npmcli/fs": ^4.0.0 fs-minipass: ^3.0.0 glob: ^10.2.2 lru-cache: ^10.0.1 @@ -9361,31 +9718,30 @@ __metadata: minipass-collect: ^2.0.1 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 - p-map: ^4.0.0 - ssri: ^10.0.0 - tar: ^6.1.11 - unique-filename: ^3.0.0 - checksum: b7422c113b4ec750f33beeca0f426a0024c28e3172f332218f48f963e5b970647fa1ac05679fe5bb448832c51efea9fda4456b9a95c3a1af1105fe6c1833cde2 + p-map: ^7.0.2 + ssri: ^12.0.0 + tar: ^7.4.3 + unique-filename: ^4.0.0 + checksum: e95684717de6881b4cdaa949fa7574e3171946421cd8291769dd3d2417dbf7abf4aa557d1f968cca83dcbc95bed2a281072b09abfc977c942413146ef7ed4525 languageName: node linkType: hard -"cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" +"cacache@npm:^20.0.0, cacache@npm:^20.0.1": + version: 20.0.1 + resolution: "cacache@npm:20.0.1" dependencies: "@npmcli/fs": ^4.0.0 fs-minipass: ^3.0.0 - glob: ^10.2.2 - lru-cache: ^10.0.1 + glob: ^11.0.3 + lru-cache: ^11.1.0 minipass: ^7.0.3 minipass-collect: ^2.0.1 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 p-map: ^7.0.2 ssri: ^12.0.0 - tar: ^7.4.3 unique-filename: ^4.0.0 - checksum: e95684717de6881b4cdaa949fa7574e3171946421cd8291769dd3d2417dbf7abf4aa557d1f968cca83dcbc95bed2a281072b09abfc977c942413146ef7ed4525 + checksum: 33d1514f5c05ba761601fe6e5a49eb396e91bdb439a2ceabdb5a3490552393a5c01d97b14eb2eb12849f7062e5704a3ec3de48f22fa7196e0cbc4b2623406527 languageName: node linkType: hard @@ -9536,6 +9892,13 @@ __metadata: languageName: node linkType: hard +"chardet@npm:^2.1.0": + version: 2.1.1 + resolution: "chardet@npm:2.1.1" + checksum: 4e3dba2699018b79bb90a9562b5e5be27fcaab55250c12fa72f026b859fb24846396c346968546c14efc69b9f23aca3ef2b9816775012d08a4686ce3c362415c + languageName: node + linkType: hard + "chokidar@npm:^3.5.3, chokidar@npm:^3.6.0": version: 3.6.0 resolution: "chokidar@npm:3.6.0" @@ -9671,6 +10034,13 @@ __metadata: languageName: node linkType: hard +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 0a79cff2dbf89ef530bcd54c713703ba94461457b11e5634bd024c78796ed21401e32349c004995954e06f442d82609287e7aabf6a5f02c919a1cf3b9b6854ff + languageName: node + linkType: hard + "clipanion@npm:^3.2.1": version: 3.2.1 resolution: "clipanion@npm:3.2.1" @@ -9715,7 +10085,7 @@ __metadata: languageName: node linkType: hard -"clone-deep@npm:4.0.1, clone-deep@npm:^4.0.1": +"clone-deep@npm:^4.0.1": version: 4.0.1 resolution: "clone-deep@npm:4.0.1" dependencies: @@ -9733,13 +10103,20 @@ __metadata: languageName: node linkType: hard -"cmd-shim@npm:6.0.3, cmd-shim@npm:^6.0.0": +"cmd-shim@npm:6.0.3": version: 6.0.3 resolution: "cmd-shim@npm:6.0.3" checksum: bd79ac1505fea77cba0caf271c16210ebfbe50f348a1907f4700740876ab2157e00882b9baa685a9fcf9bc92e08a87e21bd757f45a6938f00290422f80f7d27a languageName: node linkType: hard +"cmd-shim@npm:^7.0.0": + version: 7.0.0 + resolution: "cmd-shim@npm:7.0.0" + checksum: 4cf622d175b505aff1f8a9ad26164022cfb5599c88a7d0f4b443b78a45945b0950ff6898a854bdefdf5c3155f84e862e2502756a1a83115b0d1d40825be30e96 + languageName: node + linkType: hard + "co@npm:^4.6.0": version: 4.6.0 resolution: "co@npm:4.6.0" @@ -10139,36 +10516,7 @@ __metadata: languageName: node linkType: hard -"cosmiconfig@npm:^5.0.5": - version: 5.2.1 - resolution: "cosmiconfig@npm:5.2.1" - dependencies: - import-fresh: ^2.0.0 - is-directory: ^0.3.1 - js-yaml: ^3.13.1 - parse-json: ^4.0.0 - checksum: 8b6f1d3c8a5ffdf663a952f17af0761adf210b7a5933d0fe8988f3ca3a1f0e1e5cbbb74d5b419c15933dd2fdcaec31dbc5cc85cb8259a822342b93b529eff89c - languageName: node - linkType: hard - -"cosmiconfig@npm:^8.2.0": - version: 8.3.6 - resolution: "cosmiconfig@npm:8.3.6" - dependencies: - import-fresh: ^3.3.0 - js-yaml: ^4.1.0 - parse-json: ^5.2.0 - path-type: ^4.0.0 - peerDependencies: - typescript: ">=4.9.5" - peerDependenciesMeta: - typescript: - optional: true - checksum: dc339ebea427898c9e03bf01b56ba7afbac07fc7d2a2d5a15d6e9c14de98275a9565da949375aee1809591c152c0a3877bb86dbeaf74d5bd5aaa79955ad9e7a0 - languageName: node - linkType: hard - -"cosmiconfig@npm:^9.0.0": +"cosmiconfig@npm:9.0.0, cosmiconfig@npm:^9.0.0": version: 9.0.0 resolution: "cosmiconfig@npm:9.0.0" dependencies: @@ -10185,6 +10533,18 @@ __metadata: languageName: node linkType: hard +"cosmiconfig@npm:^5.0.5": + version: 5.2.1 + resolution: "cosmiconfig@npm:5.2.1" + dependencies: + import-fresh: ^2.0.0 + is-directory: ^0.3.1 + js-yaml: ^3.13.1 + parse-json: ^4.0.0 + checksum: 8b6f1d3c8a5ffdf663a952f17af0761adf210b7a5933d0fe8988f3ca3a1f0e1e5cbbb74d5b419c15933dd2fdcaec31dbc5cc85cb8259a822342b93b529eff89c + languageName: node + linkType: hard + "cpu-features@npm:~0.0.10": version: 0.0.10 resolution: "cpu-features@npm:0.0.10" @@ -10472,7 +10832,7 @@ __metadata: eslint-plugin-react-native: 3.10.0 genversion: 3.0.2 jest: ^29.7.0 - lerna: 8.1.6 + lerna: 9.0.0 metro: ^0.83.1 pod-install: 0.1.14 prettier: 2.2.0 @@ -10953,13 +11313,6 @@ __metadata: languageName: node linkType: hard -"duplexer@npm:^0.1.1": - version: 0.1.2 - resolution: "duplexer@npm:0.1.2" - checksum: 62ba61a830c56801db28ff6305c7d289b6dc9f859054e8c982abd8ee0b0a14d2e9a8e7d086ffee12e868d43e2bbe8a964be55ddbd8c8957714c87373c7a4f9b0 - languageName: node - linkType: hard - "duplexify@npm:^4.0.0, duplexify@npm:^4.1.1, duplexify@npm:^4.1.3": version: 4.1.3 resolution: "duplexify@npm:4.1.3" @@ -12052,6 +12405,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.4.3": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: bd537daa9d3cd53887eed35efa0eab2dbb1ca408790e10e024120e7a36c6e9ae2b33710cb8381e35def01bc9c1d7eaba746f886338413e68ff6ebaee07b9a6e8 + languageName: node + linkType: hard + "fdir@npm:^6.4.4": version: 6.4.6 resolution: "fdir@npm:6.4.6" @@ -12276,7 +12641,7 @@ __metadata: languageName: node linkType: hard -"foreground-child@npm:^3.1.0": +"foreground-child@npm:^3.1.0, foreground-child@npm:^3.3.1": version: 3.3.1 resolution: "foreground-child@npm:3.3.1" dependencies: @@ -12766,7 +13131,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.4.5": +"glob@npm:^10.2.2, glob@npm:^10.4.5": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -12782,6 +13147,22 @@ __metadata: languageName: node linkType: hard +"glob@npm:^11.0.3": + version: 11.0.3 + resolution: "glob@npm:11.0.3" + dependencies: + foreground-child: ^3.3.1 + jackspeak: ^4.1.1 + minimatch: ^10.0.3 + minipass: ^7.1.2 + package-json-from-dist: ^1.0.0 + path-scurry: ^2.0.0 + bin: + glob: dist/esm/bin.mjs + checksum: 65ddc1e3c969e87999880580048763cc8b5bdd375930dd43b8100a5ba481d2e2563e4553de42875790800c602522a98aa8d3ed1c5bd4d27621609e6471eb371d + languageName: node + linkType: hard + "glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -12861,7 +13242,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:11.1.0, globby@npm:^11.0.1, globby@npm:^11.0.4, globby@npm:^11.1.0": +"globby@npm:^11.0.1, globby@npm:^11.0.4, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -12964,7 +13345,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:4.2.11, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -13192,12 +13573,21 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^7.0.0, hosted-git-info@npm:^7.0.2": - version: 7.0.2 - resolution: "hosted-git-info@npm:7.0.2" +"hosted-git-info@npm:^8.0.0": + version: 8.1.0 + resolution: "hosted-git-info@npm:8.1.0" dependencies: lru-cache: ^10.0.1 - checksum: 467cf908a56556417b18e86ae3b8dee03c2360ef1d51e61c4028fe87f6f309b6ff038589c94b5666af207da9d972d5107698906aabeb78aca134641962a5c6f8 + checksum: 964f6a293a008978b540a08cf22356a141b78207086824e4133fb4a384d081142d3da75f253530c098e3370f0c8f7a2e3b68bf49140c59e6673fc49c638faa31 + languageName: node + linkType: hard + +"hosted-git-info@npm:^9.0.0": + version: 9.0.2 + resolution: "hosted-git-info@npm:9.0.2" + dependencies: + lru-cache: ^11.1.0 + checksum: 01687a41925189ab10dfd6c5b295d9186366faf22f74face5f83c6ac8e9927f25d5d91fad3352ee6833a3130e35d5fd71c9037a2d684e307cfd321724a90a689 languageName: node linkType: hard @@ -13308,6 +13698,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:^0.7.0": + version: 0.7.0 + resolution: "iconv-lite@npm:0.7.0" + dependencies: + safer-buffer: ">= 2.1.2 < 3.0.0" + checksum: f362a8befb95e37f29be1d1290c17e0c9d0d4ad4fa62fcfd813cc9c937ab89401abed9a011f83e10651a267abb2aa231ec7da91d843570bec873bd98489b5bf8 + languageName: node + linkType: hard + "ieee754@npm:^1.1.13": version: 1.2.1 resolution: "ieee754@npm:1.2.1" @@ -13315,12 +13714,12 @@ __metadata: languageName: node linkType: hard -"ignore-walk@npm:^6.0.4": - version: 6.0.5 - resolution: "ignore-walk@npm:6.0.5" +"ignore-walk@npm:^8.0.0": + version: 8.0.0 + resolution: "ignore-walk@npm:8.0.0" dependencies: - minimatch: ^9.0.0 - checksum: 06f88a53c412385ca7333276149a7e9461b7fad977c44272d854522b0d456c2aa75d832bd3980a530e2c3881126aa9cc4782b3551ca270fffc0ce7c2b4a2e199 + minimatch: ^10.0.3 + checksum: 4146c18cd441b538bd68b62cfb95f71fed0a7ff54ba50cd22ae3c05abc538ea3a8272c96bd7a5d38feb0ea79c3f4ffc2ac0092f18bf906c6c1ef151b76c21b30 languageName: node linkType: hard @@ -13443,25 +13842,25 @@ __metadata: languageName: node linkType: hard -"ini@npm:^4.1.3": - version: 4.1.3 - resolution: "ini@npm:4.1.3" - checksum: 004b2be42388877c58add606149f1a0c7985c90a0ba5dbf45a4738fdc70b0798d922caecaa54617029626505898ac451ff0537a08b949836b49d3267f66542c9 +"ini@npm:^5.0.0": + version: 5.0.0 + resolution: "ini@npm:5.0.0" + checksum: a1cd2a06bf4d995b072ebe97132d8d50a6630798cc3a1c56d325d7b3aaf1f236b3301816f0079e4d47a9887f08e60a6fb95673f19bcafe4f0f9c4a5b5e30aff4 languageName: node linkType: hard -"init-package-json@npm:6.0.3": - version: 6.0.3 - resolution: "init-package-json@npm:6.0.3" +"init-package-json@npm:8.2.2": + version: 8.2.2 + resolution: "init-package-json@npm:8.2.2" dependencies: - "@npmcli/package-json": ^5.0.0 - npm-package-arg: ^11.0.0 - promzard: ^1.0.0 - read: ^3.0.1 - semver: ^7.3.5 + "@npmcli/package-json": ^7.0.0 + npm-package-arg: ^13.0.0 + promzard: ^2.0.0 + read: ^4.0.0 + semver: ^7.7.2 validate-npm-package-license: ^3.0.4 - validate-npm-package-name: ^5.0.0 - checksum: 332de50c7433551b9fcd192e337ec9a345ad2e5ac21fc190a676f56a2e88221c8149994fc370cf5cdad6c41d3ed420b354fe4914643d0d63cfb46c87d319e795 + validate-npm-package-name: ^6.0.2 + checksum: 02f58ce7f517ff3b3331c28aae49e1b4ed702ea4920f2f1fc155cc845bce43a173641a91a2aacb8a9c424010fcbebb6ac92ea2dddcb8a8408a1a8dad564a133f languageName: node linkType: hard @@ -13480,7 +13879,27 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:^8.1.5, inquirer@npm:^8.2.4, inquirer@npm:^8.2.5": +"inquirer@npm:12.9.6": + version: 12.9.6 + resolution: "inquirer@npm:12.9.6" + dependencies: + "@inquirer/ansi": ^1.0.0 + "@inquirer/core": ^10.2.2 + "@inquirer/prompts": ^7.8.6 + "@inquirer/type": ^3.0.8 + mute-stream: ^2.0.0 + run-async: ^4.0.5 + rxjs: ^7.8.2 + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 5fae189bcc5a71cef91839b396249bbda42579a39c0b1b468b1f79015e9b831703c1ccbdd5e6b3f5f73407c6f9c4917c6728fc8c240f14a8aa97a3de81e95511 + languageName: node + linkType: hard + +"inquirer@npm:^8.1.5, inquirer@npm:^8.2.5": version: 8.2.6 resolution: "inquirer@npm:8.2.6" dependencies: @@ -13778,13 +14197,6 @@ __metadata: languageName: node linkType: hard -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 - languageName: node - linkType: hard - "is-map@npm:^2.0.3": version: 2.0.3 resolution: "is-map@npm:2.0.3" @@ -13860,13 +14272,6 @@ __metadata: languageName: node linkType: hard -"is-plain-object@npm:^5.0.0": - version: 5.0.0 - resolution: "is-plain-object@npm:5.0.0" - checksum: e32d27061eef62c0847d303125440a38660517e586f2f3db7c9d179ae5b6674ab0f469d519b2e25c147a1a3bc87156d0d5f4d8821e0ce4a9ee7fe1fcf11ce45c - languageName: node - linkType: hard - "is-primitive@npm:^3.0.1": version: 3.0.1 resolution: "is-primitive@npm:3.0.1" @@ -14174,6 +14579,15 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^4.1.1": + version: 4.1.1 + resolution: "jackspeak@npm:4.1.1" + dependencies: + "@isaacs/cliui": ^8.0.2 + checksum: daca714c5adebfb80932c0b0334025307b68602765098d73d52ec546bc4defdb083292893384261c052742255d0a77d8fcf96f4c669bcb4a99b498b94a74955e + languageName: node + linkType: hard + "jake@npm:^10.8.5": version: 10.9.2 resolution: "jake@npm:10.9.2" @@ -14291,7 +14705,19 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:>=29.4.3 < 30, jest-diff@npm:^29.4.1, jest-diff@npm:^29.7.0": +"jest-diff@npm:>=30.0.0 < 31, jest-diff@npm:^30.0.2": + version: 30.2.0 + resolution: "jest-diff@npm:30.2.0" + dependencies: + "@jest/diff-sequences": 30.0.1 + "@jest/get-type": 30.1.0 + chalk: ^4.1.2 + pretty-format: 30.2.0 + checksum: 62fd17d3174316bf0140c2d342ac5ad84574763fa78fc4dd4e5ee605f121699033c9bfb7507ba8f1c5cc7fa95539a19abab13d3909a5aec1b447ab14d03c5386 + languageName: node + linkType: hard + +"jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" dependencies: @@ -14848,10 +15274,17 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^3.0.0, json-parse-even-better-errors@npm:^3.0.2": - version: 3.0.2 - resolution: "json-parse-even-better-errors@npm:3.0.2" - checksum: 6f04ea6c9ccb783630a59297959247e921cc90b917b8351197ca7fd058fccc7079268fd9362be21ba876fc26aa5039369dd0a2280aae49aae425784794a94927 +"json-parse-even-better-errors@npm:^4.0.0": + version: 4.0.0 + resolution: "json-parse-even-better-errors@npm:4.0.0" + checksum: da1ae7ef0cc9db02972a06a71322f26bdcda5d7f648c23b28ce7f158ba35707461bcbd91945d8aace10d8d79c383b896725c65ffa410242352692328aa9b5edf + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^5.0.0": + version: 5.0.0 + resolution: "json-parse-even-better-errors@npm:5.0.0" + checksum: b5aeaa65e072bc3bda2cb1da50bf1822814b4aa7c568e7c2bed25af89d730f113dcb74393da574c0a32e889eeba4a826db600b8a6ecef917c59c8c6b38f2efaa languageName: node linkType: hard @@ -15120,21 +15553,20 @@ __metadata: languageName: node linkType: hard -"lerna@npm:8.1.6": - version: 8.1.6 - resolution: "lerna@npm:8.1.6" +"lerna@npm:9.0.0": + version: 9.0.0 + resolution: "lerna@npm:9.0.0" dependencies: - "@lerna/create": 8.1.6 - "@npmcli/arborist": 7.5.3 - "@npmcli/package-json": 5.2.0 - "@npmcli/run-script": 8.1.0 - "@nx/devkit": ">=17.1.2 < 20" + "@lerna/create": 9.0.0 + "@npmcli/arborist": 9.1.4 + "@npmcli/package-json": 7.0.0 + "@npmcli/run-script": 10.0.0 + "@nx/devkit": ">=21.5.2 < 22.0.0" "@octokit/plugin-enterprise-rest": 6.0.1 - "@octokit/rest": 19.0.11 + "@octokit/rest": 20.1.2 aproba: 2.0.0 byte-size: 8.1.1 chalk: 4.1.0 - clone-deep: 4.0.1 cmd-shim: 6.0.3 color-support: 1.1.3 columnify: 1.6.0 @@ -15142,7 +15574,7 @@ __metadata: conventional-changelog-angular: 7.0.0 conventional-changelog-core: 5.0.1 conventional-recommended-bump: 7.0.1 - cosmiconfig: ^8.2.0 + cosmiconfig: 9.0.0 dedent: 1.5.3 envinfo: 7.13.0 execa: 5.0.0 @@ -15151,54 +15583,52 @@ __metadata: get-stream: 6.0.0 git-url-parse: 14.0.0 glob-parent: 6.0.2 - globby: 11.1.0 - graceful-fs: 4.2.11 has-unicode: 2.0.1 import-local: 3.1.0 ini: ^1.3.8 - init-package-json: 6.0.3 - inquirer: ^8.2.4 + init-package-json: 8.2.2 + inquirer: 12.9.6 is-ci: 3.0.1 is-stream: 2.0.0 - jest-diff: ">=29.4.3 < 30" + jest-diff: ">=30.0.0 < 31" js-yaml: 4.1.0 - libnpmaccess: 8.0.6 - libnpmpublish: 9.0.9 + libnpmaccess: 10.0.1 + libnpmpublish: 11.1.0 load-json-file: 6.2.0 - lodash: ^4.17.21 make-dir: 4.0.0 + make-fetch-happen: 15.0.2 minimatch: 3.0.5 multimatch: 5.0.0 - node-fetch: 2.6.7 - npm-package-arg: 11.0.2 - npm-packlist: 8.0.2 - npm-registry-fetch: ^17.1.0 - nx: ">=17.1.2 < 20" + npm-package-arg: 13.0.0 + npm-packlist: 10.0.1 + npm-registry-fetch: 19.0.0 + nx: ">=21.5.3 < 22.0.0" p-map: 4.0.0 p-map-series: 2.1.0 p-pipe: 3.1.0 p-queue: 6.6.2 p-reduce: 2.1.0 p-waterfall: 2.1.1 - pacote: ^18.0.6 + pacote: 21.0.1 pify: 5.0.0 read-cmd-shim: 4.0.0 resolve-from: 5.0.0 rimraf: ^4.4.1 - semver: ^7.3.8 + semver: 7.7.2 set-blocking: ^2.0.0 signal-exit: 3.0.7 slash: 3.0.0 - ssri: ^10.0.6 + ssri: 12.0.0 string-width: ^4.2.3 - strong-log-transformer: 2.1.0 tar: 6.2.1 temp-dir: 1.0.0 + through: 2.3.8 + tinyglobby: 0.2.12 typescript: ">=3 < 6" upath: 2.0.1 - uuid: ^10.0.0 + uuid: ^11.1.0 validate-npm-package-license: 3.0.4 - validate-npm-package-name: 5.0.1 + validate-npm-package-name: 6.0.2 wide-align: 1.1.5 write-file-atomic: 5.0.1 write-pkg: 4.0.0 @@ -15206,7 +15636,7 @@ __metadata: yargs-parser: 21.1.1 bin: lerna: dist/cli.js - checksum: d8edfd458d8529662fbfae2515fcdddc431d4379da99c69bf8448e343e2dd9a30a37c0fc3ab7628b40239f1f51d4bb037bce6d249f29fa9b871e2849130508db + checksum: 4c788ccb909a80cfb69d194aea02789fcb3865b7cedf9d5c8f77c5bbc4dceeaf4eb01c822c529f23dc892af228b5420231c1af7c6ccd51d09224fd0db0d8f6aa languageName: node linkType: hard @@ -15227,29 +15657,29 @@ __metadata: languageName: node linkType: hard -"libnpmaccess@npm:8.0.6": - version: 8.0.6 - resolution: "libnpmaccess@npm:8.0.6" +"libnpmaccess@npm:10.0.1": + version: 10.0.1 + resolution: "libnpmaccess@npm:10.0.1" dependencies: - npm-package-arg: ^11.0.2 - npm-registry-fetch: ^17.0.1 - checksum: 62fa6a476321268ebd379f35782d9ead8993964bd9dfc8afbd201921d9037b7bc9d956f8b2717f1247e44ab33cb7de45b556ded66144f4b3038a828299cb260d + npm-package-arg: ^12.0.0 + npm-registry-fetch: ^18.0.1 + checksum: c8f7e30f7a6d33a63c4989087c2fb2d135b271c293f6e0963cd92dc45cc5b8a1ca488c1d8828b8d1d66ea25c20ebd1b56d1b92e69eacb00845960b9acbf1b134 languageName: node linkType: hard -"libnpmpublish@npm:9.0.9": - version: 9.0.9 - resolution: "libnpmpublish@npm:9.0.9" +"libnpmpublish@npm:11.1.0": + version: 11.1.0 + resolution: "libnpmpublish@npm:11.1.0" dependencies: + "@npmcli/package-json": ^6.2.0 ci-info: ^4.0.0 - normalize-package-data: ^6.0.1 - npm-package-arg: ^11.0.2 - npm-registry-fetch: ^17.0.1 - proc-log: ^4.2.0 + npm-package-arg: ^12.0.0 + npm-registry-fetch: ^18.0.1 + proc-log: ^5.0.0 semver: ^7.3.7 - sigstore: ^2.2.0 - ssri: ^10.0.6 - checksum: bce18edcc02df5e08981f64093ed1772953b8efb27ed98018522f8c11cb91c882d420d790d3e3091dccd4f83a229f87b98562cbbed7ac4dc28af7eec9e5da9c1 + sigstore: ^3.0.0 + ssri: ^12.0.0 + checksum: b33bd488f6ae04bb6bfbf747f77e3c30341565714104b706246757ce3703771e507516e6212559642442ee372a91bcbf627136f7b7d9cab0823aee2889dfcf3b languageName: node linkType: hard @@ -15540,6 +15970,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": + version: 11.2.2 + resolution: "lru-cache@npm:11.2.2" + checksum: 052b3d0b81a02dd017e8b6d82422bed273732c89c9c63762f538e0a75b7018247896b365c19d9392cc7de9c6a304cde3ac11eb7376f96a4885d0ab32b5c46d5b + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -15584,27 +16021,26 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^13.0.0, make-fetch-happen@npm:^13.0.1": - version: 13.0.1 - resolution: "make-fetch-happen@npm:13.0.1" +"make-fetch-happen@npm:15.0.2, make-fetch-happen@npm:^15.0.0, make-fetch-happen@npm:^15.0.2": + version: 15.0.2 + resolution: "make-fetch-happen@npm:15.0.2" dependencies: - "@npmcli/agent": ^2.0.0 - cacache: ^18.0.0 + "@npmcli/agent": ^4.0.0 + cacache: ^20.0.1 http-cache-semantics: ^4.1.1 - is-lambda: ^1.0.1 minipass: ^7.0.2 - minipass-fetch: ^3.0.0 + minipass-fetch: ^4.0.0 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 - negotiator: ^0.6.3 - proc-log: ^4.2.0 + negotiator: ^1.0.0 + proc-log: ^5.0.0 promise-retry: ^2.0.1 - ssri: ^10.0.0 - checksum: 5c9fad695579b79488fa100da05777213dd9365222f85e4757630f8dd2a21a79ddd3206c78cfd6f9b37346819681782b67900ac847a57cf04190f52dda5343fd + ssri: ^12.0.0 + checksum: 27413f3d69e4cc9277417d279941476ef099c86a551256500918c3adfcfc32fc8a940766991143675ddf7754c9a9ac3753b445da7d675eb46b9880e7253feb55 languageName: node linkType: hard -"make-fetch-happen@npm:^14.0.3": +"make-fetch-happen@npm:^14.0.0, make-fetch-happen@npm:^14.0.2, make-fetch-happen@npm:^14.0.3": version: 14.0.3 resolution: "make-fetch-happen@npm:14.0.3" dependencies: @@ -16271,6 +16707,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^10.0.3": + version: 10.1.1 + resolution: "minimatch@npm:10.1.1" + dependencies: + "@isaacs/brace-expansion": ^5.0.0 + checksum: 8820c0be92994f57281f0a7a2cc4268dcc4b610f9a1ab666685716b4efe4b5898b43c835a8f22298875b31c7a278a5e3b7e253eee7c886546bb0b61fb94bca6b + languageName: node + linkType: hard + "minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -16298,7 +16743,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.0, minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -16334,21 +16779,6 @@ __metadata: languageName: node linkType: hard -"minipass-fetch@npm:^3.0.0": - version: 3.0.5 - resolution: "minipass-fetch@npm:3.0.5" - dependencies: - encoding: ^0.1.13 - minipass: ^7.0.3 - minipass-sized: ^1.0.3 - minizlib: ^2.1.2 - dependenciesMeta: - encoding: - optional: true - checksum: 8047d273236157aab27ab7cd8eab7ea79e6ecd63e8f80c3366ec076cb9a0fed550a6935bab51764369027c414647fd8256c2a20c5445fb250c483de43350de83 - languageName: node - linkType: hard - "minipass-fetch@npm:^4.0.0": version: 4.0.1 resolution: "minipass-fetch@npm:4.0.1" @@ -16421,7 +16851,7 @@ __metadata: languageName: node linkType: hard -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": +"minizlib@npm:^2.1.1": version: 2.1.2 resolution: "minizlib@npm:2.1.2" dependencies: @@ -16537,10 +16967,10 @@ __metadata: languageName: node linkType: hard -"mute-stream@npm:^1.0.0": - version: 1.0.0 - resolution: "mute-stream@npm:1.0.0" - checksum: 36fc968b0e9c9c63029d4f9dc63911950a3bdf55c9a87f58d3a266289b67180201cade911e7699f8b2fa596b34c9db43dad37649e3f7fdd13c3bb9edb0017ee7 +"mute-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "mute-stream@npm:2.0.0" + checksum: d2e4fd2f5aa342b89b98134a8d899d8ef9b0a6d69274c4af9df46faa2d97aeb1f2ce83d867880d6de63643c52386579b99139801e24e7526c3b9b0a6d1e18d6c languageName: node linkType: hard @@ -16591,18 +17021,11 @@ __metadata: checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d languageName: node linkType: hard - -"negotiator@npm:0.6.3": - version: 0.6.3 - resolution: "negotiator@npm:0.6.3" - checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 - languageName: node - linkType: hard - -"negotiator@npm:^0.6.3, negotiator@npm:~0.6.4": - version: 0.6.4 - resolution: "negotiator@npm:0.6.4" - checksum: 7ded10aa02a0707d1d12a9973fdb5954f98547ca7beb60e31cb3a403cc6e8f11138db7a3b0128425cf836fc85d145ec4ce983b2bdf83dca436af879c2d683510 + +"negotiator@npm:0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 languageName: node linkType: hard @@ -16613,6 +17036,13 @@ __metadata: languageName: node linkType: hard +"negotiator@npm:~0.6.4": + version: 0.6.4 + resolution: "negotiator@npm:0.6.4" + checksum: 7ded10aa02a0707d1d12a9973fdb5954f98547ca7beb60e31cb3a403cc6e8f11138db7a3b0128425cf836fc85d145ec4ce983b2bdf83dca436af879c2d683510 + languageName: node + linkType: hard + "neo-async@npm:^2.5.0, neo-async@npm:^2.6.2": version: 2.6.2 resolution: "neo-async@npm:2.6.2" @@ -16659,21 +17089,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.6.7": - version: 2.6.7 - resolution: "node-fetch@npm:2.6.7" - dependencies: - whatwg-url: ^5.0.0 - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 8d816ffd1ee22cab8301c7756ef04f3437f18dace86a1dae22cf81db8ef29c0bf6655f3215cb0cdb22b420b6fe141e64b26905e7f33f9377a7fa59135ea3e10b - languageName: node - linkType: hard - -"node-fetch@npm:^2.2.0, node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9, node-fetch@npm:^2.7.0": +"node-fetch@npm:^2.2.0, node-fetch@npm:^2.6.9, node-fetch@npm:^2.7.0": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -16727,23 +17143,23 @@ __metadata: languageName: node linkType: hard -"node-gyp@npm:^10.0.0": - version: 10.3.1 - resolution: "node-gyp@npm:10.3.1" +"node-gyp@npm:^11.0.0": + version: 11.5.0 + resolution: "node-gyp@npm:11.5.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 - glob: ^10.3.10 graceful-fs: ^4.2.6 - make-fetch-happen: ^13.0.0 - nopt: ^7.0.0 - proc-log: ^4.1.0 + make-fetch-happen: ^14.0.3 + nopt: ^8.0.0 + proc-log: ^5.0.0 semver: ^7.3.5 - tar: ^6.2.1 - which: ^4.0.0 + tar: ^7.4.3 + tinyglobby: ^0.2.12 + which: ^5.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 91b0690ab504fe051ad66863226dc5ecac72b8471f85e8428e4d5ca3217d3a2adfffae48cd555e8d009a4164689fff558b88d2bc9bfd246452a3336ab308cf99 + checksum: 6cc29b9d454d9a684c8fe299668db618875bb4282e37717ca5b79689cc5ce99cd553c70944bb367979f2eba40ad6a50afaf7b12a6b214172edc7377384efa051 languageName: node linkType: hard @@ -16795,17 +17211,6 @@ __metadata: languageName: node linkType: hard -"nopt@npm:^7.0.0, nopt@npm:^7.2.1": - version: 7.2.1 - resolution: "nopt@npm:7.2.1" - dependencies: - abbrev: ^2.0.0 - bin: - nopt: bin/nopt.js - checksum: 6fa729cc77ce4162cfad8abbc9ba31d4a0ff6850c3af61d59b505653bef4781ec059f8890ecfe93ee8aa0c511093369cca88bfc998101616a2904e715bbbb7c9 - languageName: node - linkType: hard - "nopt@npm:^8.0.0": version: 8.1.0 resolution: "nopt@npm:8.1.0" @@ -16841,17 +17246,6 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^6.0.0, normalize-package-data@npm:^6.0.1": - version: 6.0.2 - resolution: "normalize-package-data@npm:6.0.2" - dependencies: - hosted-git-info: ^7.0.0 - semver: ^7.3.5 - validate-npm-package-license: ^3.0.4 - checksum: ea35f8de68e03fc845f545c8197857c0cd256207fdb809ca63c2b39fe76ae77765ee939eb21811fb6c3b533296abf49ebe3cd617064f98a775adaccb24ff2e03 - languageName: node - linkType: hard - "normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" @@ -16859,89 +17253,171 @@ __metadata: languageName: node linkType: hard -"npm-bundled@npm:^3.0.0": - version: 3.0.1 - resolution: "npm-bundled@npm:3.0.1" +"npm-bundled@npm:^4.0.0": + version: 4.0.0 + resolution: "npm-bundled@npm:4.0.0" dependencies: - npm-normalize-package-bin: ^3.0.0 - checksum: 1f4f7307d0ff2fbd31638689490f1fd673a4540cd1d027c7c5d15e484c71d63c4b27979944b6f8738035260cf5a5477ebaae75b08818420508e7cf317d71416e + npm-normalize-package-bin: ^4.0.0 + checksum: 028711cda73d162c01abc39ee2caddacf80c3bfc258092b4112250515f084888780aee6fdfed0dc727be3b4f5d56b8736367485aca19a641255868200860459f languageName: node linkType: hard -"npm-install-checks@npm:^6.0.0, npm-install-checks@npm:^6.2.0": - version: 6.3.0 - resolution: "npm-install-checks@npm:6.3.0" +"npm-install-checks@npm:^7.1.0": + version: 7.1.2 + resolution: "npm-install-checks@npm:7.1.2" dependencies: semver: ^7.1.1 - checksum: 6c20dadb878a0d2f1f777405217b6b63af1299d0b43e556af9363ee6eefaa98a17dfb7b612a473a473e96faf7e789c58b221e0d8ffdc1d34903c4f71618df3b4 + checksum: 8adca5a3067aa9eb9c074bb2c2ba23d2f191702d917197224d59ccf736471ca5b32c75528b4546f870e152c660c189550ff15d7448a2c8f897a221850d3bc0a8 languageName: node linkType: hard -"npm-normalize-package-bin@npm:^3.0.0": - version: 3.0.1 - resolution: "npm-normalize-package-bin@npm:3.0.1" - checksum: de416d720ab22137a36292ff8a333af499ea0933ef2320a8c6f56a73b0f0448227fec4db5c890d702e26d21d04f271415eab6580b5546456861cc0c19498a4bf +"npm-install-checks@npm:^8.0.0": + version: 8.0.0 + resolution: "npm-install-checks@npm:8.0.0" + dependencies: + semver: ^7.1.1 + checksum: 7a58a84b676ea7fa8b40dca71c93161f77d9c60f1ac2786c7c502009674ee64058f0c628f8fbbb0bbb247bf4924b535549bdb8956e20c2e5337dee04184b2d4c languageName: node linkType: hard -"npm-package-arg@npm:11.0.2": - version: 11.0.2 - resolution: "npm-package-arg@npm:11.0.2" +"npm-normalize-package-bin@npm:^4.0.0": + version: 4.0.0 + resolution: "npm-normalize-package-bin@npm:4.0.0" + checksum: e1a0971e5640bc116c5197f9707d86dc404b6d8e13da2c7ea82baa5583b8da279a3c8607234aa1d733c2baac3b3eba87b156f021f20ae183dc4806530e61675d + languageName: node + linkType: hard + +"npm-normalize-package-bin@npm:^5.0.0": + version: 5.0.0 + resolution: "npm-normalize-package-bin@npm:5.0.0" + checksum: 969bc042d7bb029b5da7eb733e7642b238e3cb071ad57b56a3f128069bc1a3cbc2a4f4af30ee75b11660c368d60b89811ecd1430cf2ea1a7ff36f30052a4aeda + languageName: node + linkType: hard + +"npm-package-arg@npm:13.0.0": + version: 13.0.0 + resolution: "npm-package-arg@npm:13.0.0" dependencies: - hosted-git-info: ^7.0.0 - proc-log: ^4.0.0 + hosted-git-info: ^9.0.0 + proc-log: ^5.0.0 semver: ^7.3.5 - validate-npm-package-name: ^5.0.0 - checksum: cb78da54d42373fc87fcecfc68e74b10be02fea940becddf9fdcc8941334a5d57b5e867da2647e8b74880e1dc2b212d0fcc963fafd41cbccca8da3a1afef5b12 + validate-npm-package-name: ^6.0.0 + checksum: 6c2dc4029f6633300dfcc7223dcdcee713014e3702daee76410dfe48e8e93d4db35703721569fcec3fdeb03fefa398eb38b799d6e9af46b92cc8162827eb9fa7 languageName: node linkType: hard -"npm-package-arg@npm:^11.0.0, npm-package-arg@npm:^11.0.2": - version: 11.0.3 - resolution: "npm-package-arg@npm:11.0.3" +"npm-package-arg@npm:^12.0.0": + version: 12.0.2 + resolution: "npm-package-arg@npm:12.0.2" dependencies: - hosted-git-info: ^7.0.0 - proc-log: ^4.0.0 + hosted-git-info: ^8.0.0 + proc-log: ^5.0.0 semver: ^7.3.5 - validate-npm-package-name: ^5.0.0 - checksum: cc6f22c39201aa14dcceeddb81bfbf7fa0484f94bcd2b3ad038e18afec5167c843cdde90c897f6034dc368faa0100c1eeee6e3f436a89e0af32ba932af4a8c28 + validate-npm-package-name: ^6.0.0 + checksum: fcf4b7315a6b04035001dfde535ed4613bdcfcd06b30be54fc853bba8218e57933d5448102931da6ccfdf774b9222258dc8ab0d42a1633b3944dddab1916bef0 languageName: node linkType: hard -"npm-packlist@npm:8.0.2, npm-packlist@npm:^8.0.0": - version: 8.0.2 - resolution: "npm-packlist@npm:8.0.2" +"npm-package-arg@npm:^13.0.0": + version: 13.0.1 + resolution: "npm-package-arg@npm:13.0.1" dependencies: - ignore-walk: ^6.0.4 - checksum: c75ae66b285503409e07878274d0580c1915e8db3a52539e7588a00d8c7c27b5c3c8459906d26142ffd772f0e8f291e9aa4ea076bb44a4ab0ba7e0f25b46423b + hosted-git-info: ^9.0.0 + proc-log: ^5.0.0 + semver: ^7.3.5 + validate-npm-package-name: ^6.0.0 + checksum: aba57acfaa0f18c42e3fe432cafd5e316b4dffa8c2c3ddaa36c2af3186968eb9cd89fcd5dfb18410fbbcb4ffc3b2b0cf02b2c0630d5642b33ab2f3fb500aa2b5 languageName: node linkType: hard -"npm-pick-manifest@npm:^9.0.0, npm-pick-manifest@npm:^9.0.1": - version: 9.1.0 - resolution: "npm-pick-manifest@npm:9.1.0" +"npm-packlist@npm:10.0.1": + version: 10.0.1 + resolution: "npm-packlist@npm:10.0.1" dependencies: - npm-install-checks: ^6.0.0 - npm-normalize-package-bin: ^3.0.0 - npm-package-arg: ^11.0.0 + ignore-walk: ^8.0.0 + checksum: 051630a785fe91023ba28b2787c7e8c81d82008bba4eeaf183fdf0318961b24f5143247eb765f9a8a769de04f378dff842c9e3fdf5b61eccd9433c1229a9a523 + languageName: node + linkType: hard + +"npm-packlist@npm:^10.0.1": + version: 10.0.3 + resolution: "npm-packlist@npm:10.0.3" + dependencies: + ignore-walk: ^8.0.0 + proc-log: ^6.0.0 + checksum: f61e3aec179d82332b22e577d0a48bc3fc67012321db80f06a9b71dc58e2876ac18bb3b837e3635967b2641f4374a5b81794e25e35771b6a1fd9c65543e6e235 + languageName: node + linkType: hard + +"npm-pick-manifest@npm:^10.0.0": + version: 10.0.0 + resolution: "npm-pick-manifest@npm:10.0.0" + dependencies: + npm-install-checks: ^7.1.0 + npm-normalize-package-bin: ^4.0.0 + npm-package-arg: ^12.0.0 + semver: ^7.3.5 + checksum: 2139bd612ee853d86b6420a223dd19dd562cfc7c875ae27895a2d18a9b980e48fe9e895acf69224010b20d01d00150d8da35569d87f09047cc938927ffa2c282 + languageName: node + linkType: hard + +"npm-pick-manifest@npm:^11.0.1": + version: 11.0.3 + resolution: "npm-pick-manifest@npm:11.0.3" + dependencies: + npm-install-checks: ^8.0.0 + npm-normalize-package-bin: ^5.0.0 + npm-package-arg: ^13.0.0 semver: ^7.3.5 - checksum: cbaad1e1420869efa851e8ba5d725263f679779e15bfca3713ec3ee1e897efab254e75c5445f442ffc96453cdfb15d362d25b0c0fcb03b156fe1653f9220cc40 + checksum: e3247d06d6866f9903ab4dfd92a2dc823ef418fd447fe88d099ec880ffa7ed15837b56f1c77841fb851440a520aa5a1bc810b5309715d49c5d234be35f33c6b4 + languageName: node + linkType: hard + +"npm-registry-fetch@npm:19.0.0": + version: 19.0.0 + resolution: "npm-registry-fetch@npm:19.0.0" + dependencies: + "@npmcli/redact": ^3.0.0 + jsonparse: ^1.3.1 + make-fetch-happen: ^15.0.0 + minipass: ^7.0.2 + minipass-fetch: ^4.0.0 + minizlib: ^3.0.1 + npm-package-arg: ^13.0.0 + proc-log: ^5.0.0 + checksum: 3f8698ed049fc574d5036772cdf53a3de398550b8102253a76f565346ad792090a4261aa821dfe9246bff085d04ebc7de61ed843e3a1673f1198835dff654059 + languageName: node + linkType: hard + +"npm-registry-fetch@npm:^18.0.1": + version: 18.0.2 + resolution: "npm-registry-fetch@npm:18.0.2" + dependencies: + "@npmcli/redact": ^3.0.0 + jsonparse: ^1.3.1 + make-fetch-happen: ^14.0.0 + minipass: ^7.0.2 + minipass-fetch: ^4.0.0 + minizlib: ^3.0.1 + npm-package-arg: ^12.0.0 + proc-log: ^5.0.0 + checksum: 99d11962674f56ebf2e3a4623e486ec45db6cbc2bc3e1678afb3fbe0fe827ab668aeb04ee3e5aea0534e293a6ac98d01fd5a15dab8a3647e36c9c34342ff5211 languageName: node linkType: hard -"npm-registry-fetch@npm:^17.0.0, npm-registry-fetch@npm:^17.0.1, npm-registry-fetch@npm:^17.1.0": - version: 17.1.0 - resolution: "npm-registry-fetch@npm:17.1.0" +"npm-registry-fetch@npm:^19.0.0": + version: 19.1.0 + resolution: "npm-registry-fetch@npm:19.1.0" dependencies: - "@npmcli/redact": ^2.0.0 + "@npmcli/redact": ^3.0.0 jsonparse: ^1.3.1 - make-fetch-happen: ^13.0.0 + make-fetch-happen: ^15.0.0 minipass: ^7.0.2 - minipass-fetch: ^3.0.0 - minizlib: ^2.1.2 - npm-package-arg: ^11.0.0 - proc-log: ^4.0.0 - checksum: 12452e690aa98a4504fe70a40e97877656799a66d31b8e6d5786b85d1d27aee168162cd5d78acc05a7eac5fa56f2b5ba0bdf80e83daaf5ef67e66c3d8c979c39 + minipass-fetch: ^4.0.0 + minizlib: ^3.0.1 + npm-package-arg: ^13.0.0 + proc-log: ^5.0.0 + checksum: f3fe6ad73fee41feaca8c03ca9ef6cfc1c46e3471dd2914f3a914ecbbd2fdb59eee0afc81f16cb3e870343e2c12324e50bd574d8d75296461a12e3f8e7d7b09c languageName: node linkType: hard @@ -16970,26 +17446,25 @@ __metadata: languageName: node linkType: hard -"nx@npm:19.8.14, nx@npm:>=17.1.2 < 20": - version: 19.8.14 - resolution: "nx@npm:19.8.14" +"nx@npm:>=21.5.3 < 22.0.0": + version: 21.6.8 + resolution: "nx@npm:21.6.8" dependencies: "@napi-rs/wasm-runtime": 0.2.4 - "@nrwl/tao": 19.8.14 - "@nx/nx-darwin-arm64": 19.8.14 - "@nx/nx-darwin-x64": 19.8.14 - "@nx/nx-freebsd-x64": 19.8.14 - "@nx/nx-linux-arm-gnueabihf": 19.8.14 - "@nx/nx-linux-arm64-gnu": 19.8.14 - "@nx/nx-linux-arm64-musl": 19.8.14 - "@nx/nx-linux-x64-gnu": 19.8.14 - "@nx/nx-linux-x64-musl": 19.8.14 - "@nx/nx-win32-arm64-msvc": 19.8.14 - "@nx/nx-win32-x64-msvc": 19.8.14 + "@nx/nx-darwin-arm64": 21.6.8 + "@nx/nx-darwin-x64": 21.6.8 + "@nx/nx-freebsd-x64": 21.6.8 + "@nx/nx-linux-arm-gnueabihf": 21.6.8 + "@nx/nx-linux-arm64-gnu": 21.6.8 + "@nx/nx-linux-arm64-musl": 21.6.8 + "@nx/nx-linux-x64-gnu": 21.6.8 + "@nx/nx-linux-x64-musl": 21.6.8 + "@nx/nx-win32-arm64-msvc": 21.6.8 + "@nx/nx-win32-x64-msvc": 21.6.8 "@yarnpkg/lockfile": ^1.1.0 - "@yarnpkg/parsers": 3.0.0-rc.46 + "@yarnpkg/parsers": 3.0.2 "@zkochan/js-yaml": 0.0.7 - axios: ^1.7.4 + axios: ^1.12.0 chalk: ^4.1.0 cli-cursor: 3.1.0 cli-spinners: 2.6.1 @@ -17001,7 +17476,7 @@ __metadata: flat: ^5.0.2 front-matter: ^4.0.2 ignore: ^5.0.4 - jest-diff: ^29.4.1 + jest-diff: ^30.0.2 jsonc-parser: 3.2.0 lines-and-columns: 2.0.3 minimatch: 9.0.3 @@ -17009,13 +17484,15 @@ __metadata: npm-run-path: ^4.0.1 open: ^8.4.0 ora: 5.3.0 + resolve.exports: 2.0.3 semver: ^7.5.3 string-width: ^4.2.3 - strong-log-transformer: ^2.1.0 tar-stream: ~2.2.0 tmp: ~0.2.1 + tree-kill: ^1.2.2 tsconfig-paths: ^4.1.2 tslib: ^2.3.0 + yaml: ^2.6.0 yargs: ^17.6.2 yargs-parser: 21.1.1 peerDependencies: @@ -17050,7 +17527,7 @@ __metadata: bin: nx: bin/nx.js nx-cloud: bin/nx-cloud.js - checksum: fc735eae2ab9e43986fc19649a20238ce4dc121074231e666515145ca4fa64fa093a7b2196e6a3899032d7445a0396edab22db9344e84f4f5c10bef3177e5cc0 + checksum: 4b07f3c6b55f2c4bb25ad1baa2190570f41ca78a0c99045d68203d7372c69bc82344257bdb0e001dd4a8b426832a3d527884e665cd84d81449db21118fad8956 languageName: node linkType: hard @@ -17512,30 +17989,57 @@ __metadata: languageName: node linkType: hard -"pacote@npm:^18.0.0, pacote@npm:^18.0.6": - version: 18.0.6 - resolution: "pacote@npm:18.0.6" +"pacote@npm:21.0.1": + version: 21.0.1 + resolution: "pacote@npm:21.0.1" dependencies: - "@npmcli/git": ^5.0.0 - "@npmcli/installed-package-contents": ^2.0.1 - "@npmcli/package-json": ^5.1.0 - "@npmcli/promise-spawn": ^7.0.0 - "@npmcli/run-script": ^8.0.0 - cacache: ^18.0.0 + "@npmcli/git": ^6.0.0 + "@npmcli/installed-package-contents": ^3.0.0 + "@npmcli/package-json": ^7.0.0 + "@npmcli/promise-spawn": ^8.0.0 + "@npmcli/run-script": ^10.0.0 + cacache: ^20.0.0 + fs-minipass: ^3.0.0 + minipass: ^7.0.2 + npm-package-arg: ^13.0.0 + npm-packlist: ^10.0.1 + npm-pick-manifest: ^10.0.0 + npm-registry-fetch: ^19.0.0 + proc-log: ^5.0.0 + promise-retry: ^2.0.1 + sigstore: ^4.0.0 + ssri: ^12.0.0 + tar: ^7.4.3 + bin: + pacote: bin/index.js + checksum: fc153c75a9b737d2f314e4735748f3b160050aa7e11b398965a73d03f5785901abccedc83fa41463193dfadc06ec400ae5b2696afcb96b5ac9056b03ad52420c + languageName: node + linkType: hard + +"pacote@npm:^21.0.0": + version: 21.0.3 + resolution: "pacote@npm:21.0.3" + dependencies: + "@npmcli/git": ^7.0.0 + "@npmcli/installed-package-contents": ^3.0.0 + "@npmcli/package-json": ^7.0.0 + "@npmcli/promise-spawn": ^8.0.0 + "@npmcli/run-script": ^10.0.0 + cacache: ^20.0.0 fs-minipass: ^3.0.0 minipass: ^7.0.2 - npm-package-arg: ^11.0.0 - npm-packlist: ^8.0.0 - npm-pick-manifest: ^9.0.0 - npm-registry-fetch: ^17.0.0 - proc-log: ^4.0.0 + npm-package-arg: ^13.0.0 + npm-packlist: ^10.0.1 + npm-pick-manifest: ^11.0.1 + npm-registry-fetch: ^19.0.0 + proc-log: ^5.0.0 promise-retry: ^2.0.1 - sigstore: ^2.2.0 - ssri: ^10.0.0 - tar: ^6.1.11 + sigstore: ^4.0.0 + ssri: ^12.0.0 + tar: ^7.4.3 bin: pacote: bin/index.js - checksum: a28a7aa0f4e1375d3f11917e5982e576611aa9057999e7b3a7fd18706e43d6ae4ab34b1002dc0a9821df95c3136dec6d2b6b72cfc7b02afcc1273cec006dea39 + checksum: 44a82906e480ee5b6e69c4d9c6bbdc0b6bc025f3c6f44f6aece06140d8aae073a601de3ea9eba50b1ac31d9793f78598e1972dc23fff03c9dbc99adfc26cc6dc languageName: node linkType: hard @@ -17564,14 +18068,14 @@ __metadata: languageName: node linkType: hard -"parse-conflict-json@npm:^3.0.0": - version: 3.0.1 - resolution: "parse-conflict-json@npm:3.0.1" +"parse-conflict-json@npm:^4.0.0": + version: 4.0.0 + resolution: "parse-conflict-json@npm:4.0.0" dependencies: - json-parse-even-better-errors: ^3.0.0 + json-parse-even-better-errors: ^4.0.0 just-diff: ^6.0.0 just-diff-apply: ^5.2.0 - checksum: d8d2656bc02d4df36846366baec36b419da2fe944e31298719a4d28d28f772aa7cad2a69d01f6f329918e7c298ac481d1e6a9138d62d5662d5620a74f794af8f + checksum: ee4e1da52a54a127460713c82a12fffc1071dd2945350ebd9e203337b944901d086d515f7b15f42c6c5d9cf031de76eae0ebf5338fe8339d5695a7882d0aeba9 languageName: node linkType: hard @@ -17699,6 +18203,16 @@ __metadata: languageName: node linkType: hard +"path-scurry@npm:^2.0.0": + version: 2.0.0 + resolution: "path-scurry@npm:2.0.0" + dependencies: + lru-cache: ^11.0.0 + minipass: ^7.1.2 + checksum: 9953ce3857f7e0796b187a7066eede63864b7e1dfc14bf0484249801a5ab9afb90d9a58fc533ebb1b552d23767df8aa6a2c6c62caf3f8a65f6ce336a97bbb484 + languageName: node + linkType: hard + "path-to-regexp@npm:^0.1.12": version: 0.1.12 resolution: "path-to-regexp@npm:0.1.12" @@ -17841,13 +18355,13 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.10": - version: 6.1.2 - resolution: "postcss-selector-parser@npm:6.1.2" +"postcss-selector-parser@npm:^7.0.0": + version: 7.1.0 + resolution: "postcss-selector-parser@npm:7.1.0" dependencies: cssesc: ^3.0.0 util-deprecate: ^1.0.2 - checksum: ce9440fc42a5419d103f4c7c1847cb75488f3ac9cbe81093b408ee9701193a509f664b4d10a2b4d82c694ee7495e022f8f482d254f92b7ffd9ed9dea696c6f84 + checksum: 1300e7871dd60a5132ee5462cc6e94edd4f3df28462b2495ca9ff025bd83768a908e892a18fde62cae63ff63524641baa6d58c64120f04fe6884b916663ce737 languageName: node linkType: hard @@ -17899,6 +18413,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:30.2.0": + version: 30.2.0 + resolution: "pretty-format@npm:30.2.0" + dependencies: + "@jest/schemas": 30.0.5 + ansi-styles: ^5.2.0 + react-is: ^18.3.1 + checksum: 4c54f5ed8bcf450df9d5d70726c3373f26896845a9704f5a4a835913dacea794fabb5de4ab19fabb0d867de496f9fc8bf854ccdb661c45af334026308557d622 + languageName: node + linkType: hard + "pretty-format@npm:^26.0.1, pretty-format@npm:^26.6.2": version: 26.6.2 resolution: "pretty-format@npm:26.6.2" @@ -17922,13 +18447,6 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^4.0.0, proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 98f6cd012d54b5334144c5255ecb941ee171744f45fca8b43b58ae5a0c1af07352475f481cadd9848e7f0250376ee584f6aa0951a856ff8f021bdfbff4eb33fc - languageName: node - linkType: hard - "proc-log@npm:^5.0.0": version: 5.0.0 resolution: "proc-log@npm:5.0.0" @@ -17936,6 +18454,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^6.0.0": + version: 6.0.0 + resolution: "proc-log@npm:6.0.0" + checksum: 005a2aa24b8cbc98ca24fc49ccbdbbefb1f7932fcc96664e1008c59459ea66e8cc8bd463716d6c67e39327d45e8e080eb73bf32be70461425593b0f0d6acb91f + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -17943,10 +18468,10 @@ __metadata: languageName: node linkType: hard -"proggy@npm:^2.0.0": - version: 2.0.0 - resolution: "proggy@npm:2.0.0" - checksum: 398f38c5e53d8f3dd8e1f67140dd1044dfde0a8e43edb2df55f7f38b958912841c78a970e61f2ee7222be4f3f1ee0da134e21d0eb537805cb1b10516555c7ac1 +"proggy@npm:^3.0.0": + version: 3.0.0 + resolution: "proggy@npm:3.0.0" + checksum: 8c274b56e8eaaa1f59ea938df3c501d80d24fbfd3dffd1de42a66e2657d131f5e0b7165127457a3a7b38e1dcc71a81060a685c6840001136ecad36cec900bfc8 languageName: node linkType: hard @@ -17964,13 +18489,6 @@ __metadata: languageName: node linkType: hard -"promise-inflight@npm:^1.0.1": - version: 1.0.1 - resolution: "promise-inflight@npm:1.0.1" - checksum: 22749483091d2c594261517f4f80e05226d4d5ecc1fc917e1886929da56e22b5718b7f2a75f3807e7a7d471bc3be2907fe92e6e8f373ddf5c64bae35b5af3981 - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -18009,12 +18527,12 @@ __metadata: languageName: node linkType: hard -"promzard@npm:^1.0.0": - version: 1.0.2 - resolution: "promzard@npm:1.0.2" +"promzard@npm:^2.0.0": + version: 2.0.0 + resolution: "promzard@npm:2.0.0" dependencies: - read: ^3.0.1 - checksum: 08dee9179e79d4a6446f707cce46fb3e8e8d93ec8b8d722ddc1ec4043c4c07e2e88dc90c64326a58f83d1a7e2b0d6b3bdf11b8b2687b9c74bfb410bafe630ad8 + read: ^4.0.0 + checksum: 599ccf47b82df7b01dbef0fe833350436a9762c92237a684525733918179e7ae36151218d6a51d36f9cfffb83966d553cf1308de443836cf97d8be13fda1f57e languageName: node linkType: hard @@ -18726,20 +19244,27 @@ __metadata: languageName: node linkType: hard -"read-cmd-shim@npm:4.0.0, read-cmd-shim@npm:^4.0.0": +"read-cmd-shim@npm:4.0.0": version: 4.0.0 resolution: "read-cmd-shim@npm:4.0.0" checksum: 2fb5a8a38984088476f559b17c6a73324a5db4e77e210ae0aab6270480fd85c355fc990d1c79102e25e555a8201606ed12844d6e3cd9f35d6a1518791184e05b languageName: node linkType: hard -"read-package-json-fast@npm:^3.0.0, read-package-json-fast@npm:^3.0.2": - version: 3.0.2 - resolution: "read-package-json-fast@npm:3.0.2" +"read-cmd-shim@npm:^5.0.0": + version: 5.0.0 + resolution: "read-cmd-shim@npm:5.0.0" + checksum: 7b403e009373d0e441c4ed3364f791680c6846fb6d7c4041e5af2f4da45b07a0325c43c60b3066e16e567d2c3a37f1b6096ed0e93a7b5e575806df0b860ff308 + languageName: node + linkType: hard + +"read-package-json-fast@npm:^4.0.0": + version: 4.0.0 + resolution: "read-package-json-fast@npm:4.0.0" dependencies: - json-parse-even-better-errors: ^3.0.0 - npm-normalize-package-bin: ^3.0.0 - checksum: 8d406869f045f1d76e2a99865a8fd1c1af9c1dc06200b94d2b07eef87ed734b22703a8d72e1cd36ea36cc48e22020bdd187f88243c7dd0563f72114d38c17072 + json-parse-even-better-errors: ^4.0.0 + npm-normalize-package-bin: ^4.0.0 + checksum: bf0becd7d0b652dcc5874b466d1dbd98313180e89505c072f35ff48a1ad6bdaf2427143301e1924d64e4af5064cda8be5df16f14de882f03130e29051bbaab87 languageName: node linkType: hard @@ -18787,12 +19312,12 @@ __metadata: languageName: node linkType: hard -"read@npm:^3.0.1": - version: 3.0.1 - resolution: "read@npm:3.0.1" +"read@npm:^4.0.0": + version: 4.1.0 + resolution: "read@npm:4.1.0" dependencies: - mute-stream: ^1.0.0 - checksum: 65fdc31c18f457b08a4f6eea3624cbbe82f82d5f297f256062278627ed897381d1637dd494ba7419dd3c5ed73fb21a4cef1342748c6e108b0f8fc7f627a0b281 + mute-stream: ^2.0.0 + checksum: 72226d6b2a8fb44e2fb4ad135779c2721932e7f21b6ef7a1e4af5bcc9d66660769c85423daeb0cac130c9db6cfdaa47960077320f936a4d1543bd96ac5d2aea9 languageName: node linkType: hard @@ -19085,7 +19610,7 @@ __metadata: languageName: node linkType: hard -"resolve.exports@npm:^2.0.0": +"resolve.exports@npm:2.0.3, resolve.exports@npm:^2.0.0": version: 2.0.3 resolution: "resolve.exports@npm:2.0.3" checksum: abfb9f98278dcd0c19b8a49bb486abfafa23df4636d49128ea270dc982053c3ef230a530aecda1fae1322873fdfa6c97674fc539651ddfdb375ac58e0b8ef6df @@ -19283,6 +19808,13 @@ __metadata: languageName: node linkType: hard +"run-async@npm:^4.0.5": + version: 4.0.6 + resolution: "run-async@npm:4.0.6" + checksum: 1338a046d4f4ea03a62dfcb426d44af8c9991221ec74983e52845cbb7ee0c685dc0e9e07cbb6958ee6a1103b7a66c0204b86e110e37909965a92e6fbb7b3b837 + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -19301,7 +19833,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.5.5": +"rxjs@npm:^7.5.5, rxjs@npm:^7.8.2": version: 7.8.2 resolution: "rxjs@npm:7.8.2" dependencies: @@ -19430,6 +19962,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:7.7.2, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: dd94ba8f1cbc903d8eeb4dd8bf19f46b3deb14262b6717d0de3c804b594058ae785ef2e4b46c5c3b58733c99c83339068203002f9e37cfe44f7e2cc5e3d2f621 + languageName: node + linkType: hard + "semver@npm:^6.1.1, semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -19439,12 +19980,12 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": - version: 7.7.2 - resolution: "semver@npm:7.7.2" +"semver@npm:^7.7.2": + version: 7.7.3 + resolution: "semver@npm:7.7.3" bin: semver: bin/semver.js - checksum: dd94ba8f1cbc903d8eeb4dd8bf19f46b3deb14262b6717d0de3c804b594058ae785ef2e4b46c5c3b58733c99c83339068203002f9e37cfe44f7e2cc5e3d2f621 + checksum: f013a3ee4607857bcd3503b6ac1d80165f7f8ea94f5d55e2d3e33df82fce487aa3313b987abf9b39e0793c83c9fc67b76c36c067625141a9f6f704ae0ea18db2 languageName: node linkType: hard @@ -19652,24 +20193,38 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.0.1": +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 languageName: node linkType: hard -"sigstore@npm:^2.2.0": - version: 2.3.1 - resolution: "sigstore@npm:2.3.1" +"sigstore@npm:^3.0.0": + version: 3.1.0 + resolution: "sigstore@npm:3.1.0" + dependencies: + "@sigstore/bundle": ^3.1.0 + "@sigstore/core": ^2.0.0 + "@sigstore/protobuf-specs": ^0.4.0 + "@sigstore/sign": ^3.1.0 + "@sigstore/tuf": ^3.1.0 + "@sigstore/verify": ^2.1.0 + checksum: 52a1d88b0e48f4008ef8c7135cd9a6edbca3c0fcda0234a73a304eeff57ad6e37ff605cc0a21ad2cffd8bdb510742e556ba3ef04a60bd968f9821ec3ace00f93 + languageName: node + linkType: hard + +"sigstore@npm:^4.0.0": + version: 4.0.0 + resolution: "sigstore@npm:4.0.0" dependencies: - "@sigstore/bundle": ^2.3.2 - "@sigstore/core": ^1.0.0 - "@sigstore/protobuf-specs": ^0.3.2 - "@sigstore/sign": ^2.3.2 - "@sigstore/tuf": ^2.3.4 - "@sigstore/verify": ^1.2.1 - checksum: 9e8c5e60dbe56591770fb26a0d0e987f1859d47d519532578540380d6464499bcd1f1765291d6a360d3ffe9aba171fc8b0c3e559931b0ea262140aff7e892296 + "@sigstore/bundle": ^4.0.0 + "@sigstore/core": ^3.0.0 + "@sigstore/protobuf-specs": ^0.5.0 + "@sigstore/sign": ^4.0.0 + "@sigstore/tuf": ^4.0.0 + "@sigstore/verify": ^3.0.0 + checksum: a8179dade1e86aee2a235b47813063c063d5356df8fc95cd3731774a8a3f12e9321c48a1dedd8ff67c0ca6c3db365b5cd1f26607b847a4382c9bffd745230c2b languageName: node linkType: hard @@ -19962,16 +20517,7 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^10.0.0, ssri@npm:^10.0.6": - version: 10.0.6 - resolution: "ssri@npm:10.0.6" - dependencies: - minipass: ^7.0.3 - checksum: 4603d53a05bcd44188747d38f1cc43833b9951b5a1ee43ba50535bdfc5fe4a0897472dbe69837570a5417c3c073377ef4f8c1a272683b401857f72738ee57299 - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": +"ssri@npm:12.0.0, ssri@npm:^12.0.0": version: 12.0.0 resolution: "ssri@npm:12.0.0" dependencies: @@ -20270,19 +20816,6 @@ __metadata: languageName: node linkType: hard -"strong-log-transformer@npm:2.1.0, strong-log-transformer@npm:^2.1.0": - version: 2.1.0 - resolution: "strong-log-transformer@npm:2.1.0" - dependencies: - duplexer: ^0.1.1 - minimist: ^1.2.0 - through: ^2.3.4 - bin: - sl-log-transformer: bin/sl-log-transformer.js - checksum: abf9a4ac143118f26c3a0771b204b02f5cf4fa80384ae158f25e02bfbff761038accc44a7f65869ccd5a5995a7f2c16b1466b83149644ba6cecd3072a8927297 - languageName: node - linkType: hard - "stubs@npm:^3.0.0": version: 3.0.0 resolution: "stubs@npm:3.0.0" @@ -20413,7 +20946,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:6.2.1, tar@npm:^6.1.11, tar@npm:^6.2.1": +"tar@npm:6.2.1": version: 6.2.1 resolution: "tar@npm:6.2.1" dependencies: @@ -20548,7 +21081,7 @@ __metadata: languageName: node linkType: hard -"through@npm:2, through@npm:>=2.2.7 <3, through@npm:^2.3.4, through@npm:^2.3.6": +"through@npm:2, through@npm:2.3.8, through@npm:>=2.2.7 <3, through@npm:^2.3.6": version: 2.3.8 resolution: "through@npm:2.3.8" checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd @@ -20569,6 +21102,16 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:0.2.12": + version: 0.2.12 + resolution: "tinyglobby@npm:0.2.12" + dependencies: + fdir: ^6.4.3 + picomatch: ^4.0.2 + checksum: ef9357fa1b2b661afdccd315cb4995f5f36bce948faaace68aae85fe57bdd8f837883045c88efc50d3186bac6586e4ae2f31026b9a3aac061b884217e6092e23 + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.12": version: 0.2.14 resolution: "tinyglobby@npm:0.2.14" @@ -20623,6 +21166,15 @@ __metadata: languageName: node linkType: hard +"tree-kill@npm:^1.2.2": + version: 1.2.2 + resolution: "tree-kill@npm:1.2.2" + bin: + tree-kill: cli.js + checksum: 49117f5f410d19c84b0464d29afb9642c863bc5ba40fcb9a245d474c6d5cc64d1b177a6e6713129eb346b40aebb9d4631d967517f9fbe8251c35b21b13cd96c7 + languageName: node + linkType: hard + "treeverse@npm:^3.0.0": version: 3.0.0 resolution: "treeverse@npm:3.0.0" @@ -20736,14 +21288,25 @@ __metadata: languageName: node linkType: hard -"tuf-js@npm:^2.2.1": - version: 2.2.1 - resolution: "tuf-js@npm:2.2.1" +"tuf-js@npm:^3.0.1": + version: 3.1.0 + resolution: "tuf-js@npm:3.1.0" dependencies: - "@tufjs/models": 2.0.1 - debug: ^4.3.4 - make-fetch-happen: ^13.0.1 - checksum: 23a8f84a33f4569296c7d1d6919ea87273923a3d0c6cc837a84fb200041a54bb1b50623f79cc77307325d945dfe10e372ac1cad105956e34d3df2d4984027bd8 + "@tufjs/models": 3.0.1 + debug: ^4.4.1 + make-fetch-happen: ^14.0.3 + checksum: 1a45a055e97041459aacca576e439baf0517d88db3eb600479b57fb60c2403dc193048135f1a2612378dc0b00c8437ec990b132d404b0a5e7471bf2e2824d2aa + languageName: node + linkType: hard + +"tuf-js@npm:^4.0.0": + version: 4.0.0 + resolution: "tuf-js@npm:4.0.0" + dependencies: + "@tufjs/models": 4.0.0 + debug: ^4.4.1 + make-fetch-happen: ^15.0.0 + checksum: c4a92ec90f5efa74111fef7d6511e5f42c00a1e8b425d7bf4620aa7b318b46d3eabbcc1f73f434d4c5a7e0b021b848595cd0f43f66285d1a3d024fbd10bfcb22 languageName: node linkType: hard @@ -21008,15 +21571,6 @@ __metadata: languageName: node linkType: hard -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" - dependencies: - unique-slug: ^4.0.0 - checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df - languageName: node - linkType: hard - "unique-filename@npm:^4.0.0": version: 4.0.0 resolution: "unique-filename@npm:4.0.0" @@ -21026,15 +21580,6 @@ __metadata: languageName: node linkType: hard -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" - dependencies: - imurmurhash: ^0.1.4 - checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 - languageName: node - linkType: hard - "unique-slug@npm:^5.0.0": version: 5.0.0 resolution: "unique-slug@npm:5.0.0" @@ -21144,12 +21689,12 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^10.0.0": - version: 10.0.0 - resolution: "uuid@npm:10.0.0" +"uuid@npm:^11.1.0": + version: 11.1.0 + resolution: "uuid@npm:11.1.0" bin: - uuid: dist/bin/uuid - checksum: 4b81611ade2885d2313ddd8dc865d93d8dccc13ddf901745edca8f86d99bc46d7a330d678e7532e7ebf93ce616679fb19b2e3568873ac0c14c999032acb25869 + uuid: dist/esm/bin/uuid + checksum: 840f19758543c4631e58a29439e51b5b669d5f34b4dd2700b6a1d15c5708c7a6e0c3e2c8c4a2eae761a3a7caa7e9884d00c86c02622ba91137bd3deade6b4b4a languageName: node linkType: hard @@ -21208,10 +21753,10 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-name@npm:5.0.1, validate-npm-package-name@npm:^5.0.0": - version: 5.0.1 - resolution: "validate-npm-package-name@npm:5.0.1" - checksum: 0d583a1af23aeffea7748742cf22b6802458736fb8b60323ba5949763824d46f796474b0e1b9206beb716f9d75269e19dbd7795d6b038b29d561be95dd827381 +"validate-npm-package-name@npm:6.0.2, validate-npm-package-name@npm:^6.0.0, validate-npm-package-name@npm:^6.0.2": + version: 6.0.2 + resolution: "validate-npm-package-name@npm:6.0.2" + checksum: f0e022b0a7f11345a92b64121b059b720204cd64406a0d65d81526181dcb70aef551c7c6bf9ca37b91607a7c6ff4d62e1f63a86c8d9b7346d722a641a4bd8789 languageName: node linkType: hard @@ -21229,10 +21774,10 @@ __metadata: languageName: node linkType: hard -"walk-up-path@npm:^3.0.1": - version: 3.0.1 - resolution: "walk-up-path@npm:3.0.1" - checksum: 9ffca02fe30fb65f6db531260582988c5e766f4c739cf86a6109380a7f791236b5d0b92b1dce37a6f73e22dca6bc9d93bf3700413e16251b2bd6bbd1ca2be316 +"walk-up-path@npm:^4.0.0": + version: 4.0.0 + resolution: "walk-up-path@npm:4.0.0" + checksum: 6a230b20e5de296895116dc12b09dafaec1f72b8060c089533d296e241aff059dfaebe0d015c77467f857e4b40c78e08f7481add76f340233a1f34fa8af9ed63 languageName: node linkType: hard @@ -21371,17 +21916,6 @@ __metadata: languageName: node linkType: hard -"which@npm:^4.0.0": - version: 4.0.0 - resolution: "which@npm:4.0.0" - dependencies: - isexe: ^3.1.1 - bin: - node-which: bin/which.js - checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 - languageName: node - linkType: hard - "which@npm:^5.0.0": version: 5.0.0 resolution: "which@npm:5.0.0" @@ -21456,7 +21990,7 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:5.0.1, write-file-atomic@npm:^5.0.0, write-file-atomic@npm:^5.0.1": +"write-file-atomic@npm:5.0.1, write-file-atomic@npm:^5.0.1": version: 5.0.1 resolution: "write-file-atomic@npm:5.0.1" dependencies: @@ -21487,6 +22021,16 @@ __metadata: languageName: node linkType: hard +"write-file-atomic@npm:^6.0.0": + version: 6.0.0 + resolution: "write-file-atomic@npm:6.0.0" + dependencies: + imurmurhash: ^0.1.4 + signal-exit: ^4.0.1 + checksum: 35f1303b0229c89c36d0817de9912b43a242f775cb0f386fecf97bac735013e1fde5f464c2ce9f63288d2c91b1ec5bc18d55347b0e37c0e4dbc64b60dc220629 + languageName: node + linkType: hard + "write-json-file@npm:^3.2.0": version: 3.2.0 resolution: "write-json-file@npm:3.2.0" @@ -21621,6 +22165,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.6.0": + version: 2.8.1 + resolution: "yaml@npm:2.8.1" + bin: + yaml: bin.mjs + checksum: 35b46150d48bc1da2fd5b1521a48a4fa36d68deaabe496f3c3fa9646d5796b6b974f3930a02c4b5aee6c85c860d7d7f79009416724465e835f40b87898c36de4 + languageName: node + linkType: hard + "yamux-js@npm:0.1.2": version: 0.1.2 resolution: "yamux-js@npm:0.1.2" @@ -21717,6 +22270,13 @@ __metadata: languageName: node linkType: hard +"yoctocolors-cjs@npm:^2.1.2": + version: 2.1.3 + resolution: "yoctocolors-cjs@npm:2.1.3" + checksum: 207df586996c3b604fa85903f81cc54676f1f372613a0c7247f0d24b1ca781905685075d06955211c4d5d4f629d7d5628464f8af0a42d286b7a8ff88e9dadcb8 + languageName: node + linkType: hard + "zen-observable-ts@npm:^1.2.5": version: 1.2.5 resolution: "zen-observable-ts@npm:1.2.5" From 7e6d4539ffae8fff0fab9808b29b91a33b1bc5e0 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Fri, 7 Nov 2025 10:22:03 +0100 Subject: [PATCH 15/62] Replaced 'Buffer' with custom function to get UTF8 str byte length --- .../XHRProxy/baggageHeaderUtils.ts | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts index 7094ec4e8..dccae9ddf 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts @@ -110,7 +110,7 @@ export function formatBaggageHeader(entries: Set): string | null { } const headerValue = formattedParts.join(','); - const byteLength = Buffer.byteLength(headerValue, 'utf8'); + const byteLength = utf8ByteLength(headerValue); if (byteLength > MAX_BYTES) { InternalLog.log( @@ -122,6 +122,40 @@ export function formatBaggageHeader(entries: Set): string | null { return headerValue; } +/** + * Returns the number of bytes needed to encode a string in UTF-8. + * + * Useful as a lightweight alternative to Node.js `Buffer.byteLength()` + * for older environments that do not support it. + * + * @param text - The input string. + * @returns The UTF-8 byte length of the string. + */ +function utf8ByteLength(text: string): number { + let byteLength = text.length; + for (let i = text.length - 1; i >= 0; i--) { + const code = text.charCodeAt(i); + + // 2-byte characters (U+0080 to U+07FF) + if (code > 0x7f && code <= 0x7ff) { + byteLength++; + } + // 3-byte characters (U+0800 to U+FFFF) + else if (code > 0x7ff && code <= 0xffff) { + byteLength += 2; + } + + // Handle surrogate pairs (4-byte characters, e.g. emoji) + // These characters already count as 2 in the initial length + // Encountering the low surrogate already accounts for the full 4 bytes + // (2 from the initial length + 2 for the 3-byte characters logic above) + if (code >= 0xdc00 && code <= 0xdfff) { + i--; // prevents double counting the same character by skipping high surrogate + } + } + return byteLength; +} + /** * Returns a set of valid baggage header characters. */ From 6654254507619232bbe3bf8fc26a606de1f9a831 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Mon, 10 Nov 2025 13:01:45 +0100 Subject: [PATCH 16/62] Bump @react-native-community/cli to 17.0.1 --- benchmarks/package.json | 6 +- example-new-architecture/package.json | 6 +- example/package.json | 6 +- package.json | 6 +- yarn.lock | 283 ++++++++++++++++---------- 5 files changed, 191 insertions(+), 116 deletions(-) diff --git a/benchmarks/package.json b/benchmarks/package.json index 03c86ac9e..db3e42677 100644 --- a/benchmarks/package.json +++ b/benchmarks/package.json @@ -41,9 +41,9 @@ "@babel/preset-env": "7.25.3", "@babel/runtime": "^7.26.10", "@datadog/datadog-ci": "3.12.0", - "@react-native-community/cli": "15.0.1", - "@react-native-community/cli-platform-android": "15.0.1", - "@react-native-community/cli-platform-ios": "15.0.1", + "@react-native-community/cli": "17.0.1", + "@react-native-community/cli-platform-android": "17.0.1", + "@react-native-community/cli-platform-ios": "17.0.1", "@react-native/babel-preset": "0.78.2", "@react-native/eslint-config": "0.78.2", "@react-native/metro-config": "0.78.2", diff --git a/example-new-architecture/package.json b/example-new-architecture/package.json index b72ce69e4..49671a341 100644 --- a/example-new-architecture/package.json +++ b/example-new-architecture/package.json @@ -16,9 +16,9 @@ "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.26.10", - "@react-native-community/cli": "15.0.1", - "@react-native-community/cli-platform-android": "15.0.1", - "@react-native-community/cli-platform-ios": "15.0.1", + "@react-native-community/cli": "17.0.1", + "@react-native-community/cli-platform-android": "17.0.1", + "@react-native-community/cli-platform-ios": "17.0.1", "@react-native/babel-preset": "0.76.9", "@react-native/eslint-config": "0.76.9", "@react-native/metro-config": "0.76.9", diff --git a/example/package.json b/example/package.json index d114dc49a..75f13aaa8 100644 --- a/example/package.json +++ b/example/package.json @@ -16,9 +16,9 @@ "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview", "@datadog/mobile-react-navigation": "workspace:packages/react-navigation", "@react-native-async-storage/async-storage": "^2.1.2", - "@react-native-community/cli": "15.0.1", - "@react-native-community/cli-platform-android": "15.0.1", - "@react-native-community/cli-platform-ios": "15.0.1", + "@react-native-community/cli": "17.0.1", + "@react-native-community/cli-platform-android": "17.0.1", + "@react-native-community/cli-platform-ios": "17.0.1", "@react-navigation/bottom-tabs": "^6.3.1", "@react-navigation/native": "^6.1.18", "@react-navigation/stack": "^6.2.1", diff --git a/package.json b/package.json index be39fd23e..29dfdee81 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,9 @@ "@babel/plugin-transform-runtime": "^7.25.0", "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.26.10", - "@react-native-community/cli": "15.0.1", - "@react-native-community/cli-platform-android": "15.0.1", - "@react-native-community/cli-platform-ios": "15.0.1", + "@react-native-community/cli": "17.0.1", + "@react-native-community/cli-platform-android": "17.0.1", + "@react-native-community/cli-platform-ios": "17.0.1", "@react-native/babel-preset": "0.76.9", "@react-native/eslint-config": "0.76.9", "@react-native/metro-config": "0.76.9", diff --git a/yarn.lock b/yarn.lock index 335b47458..55b867247 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5760,62 +5760,65 @@ __metadata: languageName: node linkType: hard -"@react-native-community/cli-clean@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-clean@npm:15.0.1" +"@react-native-community/cli-clean@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-clean@npm:17.0.1" dependencies: - "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-tools": 17.0.1 chalk: ^4.1.2 execa: ^5.0.0 fast-glob: ^3.3.2 - checksum: ea6c663ec56cfe3a2c4fac7d3f0fec2ac8de9c34458f241b2afdf7f45dfb00d1de9e367fec732f8fef6e2b17046f4ed03c3be2ea4d2075633197dc23c516f986 + checksum: 4f39568399cc0198ec85a3d721151be3c0507e95d2de72319f3380ed44c303b9a60e452330e3d099b4f4c65b8339bdb7b60f5f980b2e7fd65854afc22730998f languageName: node linkType: hard -"@react-native-community/cli-config-apple@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-config-apple@npm:15.0.1" +"@react-native-community/cli-config-android@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-config-android@npm:17.0.1" dependencies: - "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-tools": 17.0.1 chalk: ^4.1.2 - execa: ^5.0.0 fast-glob: ^3.3.2 - checksum: 67b9be8b6cce14f764a5734b9599eb7d1095c7fb5c06b0b6cd3518cf3a00c90026018c1eb8d497338da092a3cdcaa9b33fec34c5b766a4517c70293e5f1df58d + fast-xml-parser: ^4.4.1 + checksum: b6c57a4d23a08a837648cc02cca3c1d6665bb56d7bba10794feb0946767092f7a7a6b975b143946baf3de8e23c612e2ab9e9b4d0e00d7bad02d1d3cdd1ce853c languageName: node linkType: hard -"@react-native-community/cli-config@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-config@npm:15.0.1" +"@react-native-community/cli-config-apple@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-config-apple@npm:17.0.1" dependencies: - "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-tools": 17.0.1 chalk: ^4.1.2 - cosmiconfig: ^9.0.0 - deepmerge: ^4.3.0 + execa: ^5.0.0 fast-glob: ^3.3.2 - joi: ^17.2.1 - checksum: 23314bcdf465974ee71a01792f0a1149ea51eea1dc66416e53aa2bc3a123dba6a8e0654d68211d2b20570bc875145b2e5d4abf923190c685c0021bb280230c3f + checksum: 860e7545ea102d0076a33484165d29e743e4ef376f7a917cd63f8bb4b10e473db7c46fbc61993cdab751416dc16ab81f626a6dd63e59495f293849e5f0f9e6de languageName: node linkType: hard -"@react-native-community/cli-debugger-ui@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-debugger-ui@npm:15.0.1" +"@react-native-community/cli-config@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-config@npm:17.0.1" dependencies: - serve-static: ^1.13.1 - checksum: a97bb195f3722b91e0acf4c63f4e6956d572f5a275a13be01513b6797bd81ad0b838aa4fc8440131e64c39547c8e83feebb6435a34773269355a497122ed2209 + "@react-native-community/cli-tools": 17.0.1 + chalk: ^4.1.2 + cosmiconfig: ^9.0.0 + deepmerge: ^4.3.0 + fast-glob: ^3.3.2 + joi: ^17.2.1 + checksum: 0ecd79f9a8b82155eb50733f65045895417c61ff92a7b3a0ed26e86872c46e8513b1c5c666e25f64bfb71078af1b005909fadd3ba176a83807b56a82dd5b9e1d languageName: node linkType: hard -"@react-native-community/cli-doctor@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-doctor@npm:15.0.1" +"@react-native-community/cli-doctor@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-doctor@npm:17.0.1" dependencies: - "@react-native-community/cli-config": 15.0.1 - "@react-native-community/cli-platform-android": 15.0.1 - "@react-native-community/cli-platform-apple": 15.0.1 - "@react-native-community/cli-platform-ios": 15.0.1 - "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-config": 17.0.1 + "@react-native-community/cli-platform-android": 17.0.1 + "@react-native-community/cli-platform-apple": 17.0.1 + "@react-native-community/cli-platform-ios": 17.0.1 + "@react-native-community/cli-tools": 17.0.1 chalk: ^4.1.2 command-exists: ^1.2.8 deepmerge: ^4.3.0 @@ -5824,105 +5827,102 @@ __metadata: node-stream-zip: ^1.9.1 ora: ^5.4.1 semver: ^7.5.2 - strip-ansi: ^5.2.0 wcwidth: ^1.0.1 yaml: ^2.2.1 - checksum: 6df1825df9f563096e48528f16d0bc521aceb2933e864921c8092eeeeeade0893963964897a6145b26a3d4de72ce05259f2d06f873eae64796d8c3815f22f1a5 + checksum: fef3af3aede375eced42cfdedc8cd3267fc1f2916ea6a7d7502346bda2ab9153360815d12ac269d040de7d38b26b1470fc86d00be566611633f06f87d58e761b languageName: node linkType: hard -"@react-native-community/cli-platform-android@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-platform-android@npm:15.0.1" +"@react-native-community/cli-platform-android@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-platform-android@npm:17.0.1" dependencies: - "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-config-android": 17.0.1 + "@react-native-community/cli-tools": 17.0.1 chalk: ^4.1.2 execa: ^5.0.0 - fast-glob: ^3.3.2 - fast-xml-parser: ^4.4.1 logkitty: ^0.7.1 - checksum: 6c5e5912b7c81a6cb9076ae08897470090e1ff20fdaa502d500b4700235f2411942c6e38e3373111efa025dee9a1d3cc71dea6a4c42a89272f0d56b1eeb7b38a + checksum: 4848d5f4fd88b9bdd90f2775c8b97772d8edbb144000282ba56360b567584f7fcf619b81bc33c839fe6c7ae1c6949611a3cda3d3008a94c152f0709ced421499 languageName: node linkType: hard -"@react-native-community/cli-platform-apple@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-platform-apple@npm:15.0.1" +"@react-native-community/cli-platform-apple@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-platform-apple@npm:17.0.1" dependencies: - "@react-native-community/cli-config-apple": 15.0.1 - "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-config-apple": 17.0.1 + "@react-native-community/cli-tools": 17.0.1 chalk: ^4.1.2 execa: ^5.0.0 fast-xml-parser: ^4.4.1 - checksum: 27278ff8790fddc220cba9daa4b05cb027403b7c3b81cd3f025b09f52ceccd41f68e86b71d493794eadc2d54fa4a5f6a1032608c4ec7ce928cc1985dce7b9bd2 + checksum: 123fb119aac57e642ccaa123bae60058420680e8fbeb7a3d5cd20069ea624cb17dbc4d6486588fd8612e8cad93330c6bdfde147770999edc4d1fce07a71493d7 languageName: node linkType: hard -"@react-native-community/cli-platform-ios@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-platform-ios@npm:15.0.1" +"@react-native-community/cli-platform-ios@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-platform-ios@npm:17.0.1" dependencies: - "@react-native-community/cli-platform-apple": 15.0.1 - checksum: 27b4775af43ce06e9315fda54f299e96405975c44d20a495443074d2818fc085dcb85cf2d2e6581990b71ab2e9ffc7d88666337bec8eb9412e80abf8dd793851 + "@react-native-community/cli-platform-apple": 17.0.1 + checksum: 8d9d945f3416953010c65b13bfc0b37c2c30815b2ebd40e1cb8d687ef35712e3c45889a5d72b1f6d02c5a38298afc51299af0398648d19e76dd273966f538715 languageName: node linkType: hard -"@react-native-community/cli-server-api@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-server-api@npm:15.0.1" +"@react-native-community/cli-server-api@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-server-api@npm:17.0.1" dependencies: - "@react-native-community/cli-debugger-ui": 15.0.1 - "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-tools": 17.0.1 + body-parser: ^1.20.3 compression: ^1.7.1 connect: ^3.6.5 errorhandler: ^1.5.1 nocache: ^3.0.1 + open: ^6.2.0 pretty-format: ^26.6.2 serve-static: ^1.13.1 ws: ^6.2.3 - checksum: 354eba589433251a56db7edf005886aa3c4886ff70f52b999db7c3718435f01a3f1081bc56cc681a1b7de2fa50ea4891c4ea673fe0a02eb855ecbc001bd86654 + checksum: e8ae175fb5a6d1826a1006aef63848780947b8eb7b8518cf64c01eaa8c37ba773da4a3b6332e3c19f48e9f418dc4f815c8c4b10c880c34cb98d4b503ea7986c4 languageName: node linkType: hard -"@react-native-community/cli-tools@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-tools@npm:15.0.1" +"@react-native-community/cli-tools@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-tools@npm:17.0.1" dependencies: + "@vscode/sudo-prompt": ^9.0.0 appdirsjs: ^1.2.4 chalk: ^4.1.2 execa: ^5.0.0 find-up: ^5.0.0 + launch-editor: ^2.9.1 mime: ^2.4.1 - open: ^6.2.0 ora: ^5.4.1 prompts: ^2.4.2 semver: ^7.5.2 - shell-quote: ^1.7.3 - sudo-prompt: ^9.0.0 - checksum: 0c40d5aa2306a2bfc1ee15362d045b0eff3cb162dd1b070f504508b2bbdd00c791151cf9f8679d248b4480b75b758e60b8d0cf3c19a19a02b4b4ece9928a119c + checksum: a8bda556775d9a7de71e02c0d603c556af6525a7a6d082a3fa6fb0e354ea1eba82d295f2a6258ac44a737875e1c1854aa72646afe04f85a49815a811e9a96373 languageName: node linkType: hard -"@react-native-community/cli-types@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli-types@npm:15.0.1" +"@react-native-community/cli-types@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli-types@npm:17.0.1" dependencies: joi: ^17.2.1 - checksum: 77452486158afcf1f03a3596135b6dba16dba5dd10209dacd5a6a4b176df36d37b8e49af61590d5a64df4907cf0575b6f37e0a3893335f961a9380edaee32152 + checksum: 8a609ec363b18cc2098499d4519ad592a463da7d32f5bc8d581daeac5dbb507a75f70e7ec93a64ddc38510e96f9a4a650f9a010b2e1e0f104cc59e5995f1bfce languageName: node linkType: hard -"@react-native-community/cli@npm:15.0.1": - version: 15.0.1 - resolution: "@react-native-community/cli@npm:15.0.1" +"@react-native-community/cli@npm:17.0.1": + version: 17.0.1 + resolution: "@react-native-community/cli@npm:17.0.1" dependencies: - "@react-native-community/cli-clean": 15.0.1 - "@react-native-community/cli-config": 15.0.1 - "@react-native-community/cli-debugger-ui": 15.0.1 - "@react-native-community/cli-doctor": 15.0.1 - "@react-native-community/cli-server-api": 15.0.1 - "@react-native-community/cli-tools": 15.0.1 - "@react-native-community/cli-types": 15.0.1 + "@react-native-community/cli-clean": 17.0.1 + "@react-native-community/cli-config": 17.0.1 + "@react-native-community/cli-doctor": 17.0.1 + "@react-native-community/cli-server-api": 17.0.1 + "@react-native-community/cli-tools": 17.0.1 + "@react-native-community/cli-types": 17.0.1 chalk: ^4.1.2 commander: ^9.4.1 deepmerge: ^4.3.0 @@ -5934,7 +5934,7 @@ __metadata: semver: ^7.5.2 bin: rnc-cli: build/bin.js - checksum: 26c98ef67b4b89d3af13f2a3b19e51c7b2de5d320ca908cb628ca22b32bff5a17b8a1cc7f4b0ece303c4e53dc10e8ac0e88df9b376e63ebc97acb8d358f78c2e + checksum: 5b9ed387637daf6a65d9086f0832f3016a257e95ef63cb2f3ecd343f7eb4c34b4882bcd8e6b1ba897ef177040c9955a10e4f4359913286e69972d95fed123263 languageName: node linkType: hard @@ -8570,6 +8570,13 @@ __metadata: languageName: node linkType: hard +"@vscode/sudo-prompt@npm:^9.0.0": + version: 9.3.1 + resolution: "@vscode/sudo-prompt@npm:9.3.1" + checksum: 07a6ce9ef2e4e2b369288b78344f7ef3db977d5f1576b944075c22aacb9cf830acfd5f773d1b0497610bec4f811d44793142234114e57763abc78ea2cef8940a + languageName: node + linkType: hard + "@wry/caches@npm:^1.0.0": version: 1.0.1 resolution: "@wry/caches@npm:1.0.1" @@ -8649,9 +8656,9 @@ __metadata: "@babel/preset-env": ^7.25.3 "@babel/runtime": ^7.26.10 "@datadog/mobile-react-native": "workspace:packages/core" - "@react-native-community/cli": 15.0.1 - "@react-native-community/cli-platform-android": 15.0.1 - "@react-native-community/cli-platform-ios": 15.0.1 + "@react-native-community/cli": 17.0.1 + "@react-native-community/cli-platform-android": 17.0.1 + "@react-native-community/cli-platform-ios": 17.0.1 "@react-native/babel-preset": 0.76.9 "@react-native/eslint-config": 0.76.9 "@react-native/metro-config": 0.76.9 @@ -9467,9 +9474,9 @@ __metadata: "@datadog/mobile-react-native-session-replay": "workspace:packages/react-native-session-replay" "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview" "@datadog/mobile-react-navigation": "workspace:packages/react-navigation" - "@react-native-community/cli": 15.0.1 - "@react-native-community/cli-platform-android": 15.0.1 - "@react-native-community/cli-platform-ios": 15.0.1 + "@react-native-community/cli": 17.0.1 + "@react-native-community/cli-platform-android": 17.0.1 + "@react-native-community/cli-platform-ios": 17.0.1 "@react-native-community/slider": 4.5.7 "@react-native-picker/picker": 2.11.0 "@react-native/babel-preset": 0.78.2 @@ -9541,6 +9548,26 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:^1.20.3": + version: 1.20.3 + resolution: "body-parser@npm:1.20.3" + dependencies: + bytes: 3.1.2 + content-type: ~1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: ~1.6.18 + unpipe: 1.0.0 + checksum: 1a35c59a6be8d852b00946330141c4f142c6af0f970faa87f10ad74f1ee7118078056706a05ae3093c54dabca9cd3770fa62a170a85801da1a4324f04381167d + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -10384,6 +10411,13 @@ __metadata: languageName: node linkType: hard +"content-type@npm:~1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 + languageName: node + linkType: hard + "conventional-changelog-angular@npm:7.0.0": version: 7.0.0 resolution: "conventional-changelog-angular@npm:7.0.0" @@ -10773,9 +10807,9 @@ __metadata: "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview" "@datadog/mobile-react-navigation": "workspace:packages/react-navigation" "@react-native-async-storage/async-storage": ^2.1.2 - "@react-native-community/cli": 15.0.1 - "@react-native-community/cli-platform-android": 15.0.1 - "@react-native-community/cli-platform-ios": 15.0.1 + "@react-native-community/cli": 17.0.1 + "@react-native-community/cli-platform-android": 17.0.1 + "@react-native-community/cli-platform-ios": 17.0.1 "@react-native/babel-preset": 0.76.9 "@react-native/eslint-config": 0.76.9 "@react-native/metro-config": 0.76.9 @@ -10807,9 +10841,9 @@ __metadata: "@babel/plugin-transform-runtime": ^7.25.0 "@babel/preset-env": ^7.25.3 "@babel/runtime": ^7.26.10 - "@react-native-community/cli": 15.0.1 - "@react-native-community/cli-platform-android": 15.0.1 - "@react-native-community/cli-platform-ios": 15.0.1 + "@react-native-community/cli": 17.0.1 + "@react-native-community/cli-platform-android": 17.0.1 + "@react-native-community/cli-platform-ios": 17.0.1 "@react-native/babel-preset": 0.76.9 "@react-native/eslint-config": 0.76.9 "@react-native/metro-config": 0.76.9 @@ -13680,7 +13714,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.4.24": +"iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" dependencies: @@ -15553,6 +15587,16 @@ __metadata: languageName: node linkType: hard +"launch-editor@npm:^2.9.1": + version: 2.12.0 + resolution: "launch-editor@npm:2.12.0" + dependencies: + picocolors: ^1.1.1 + shell-quote: ^1.8.3 + checksum: b1aa1b92ef4e720d1edd7f80affb90b2fa1cc2c41641cf80158940698c18a4b6a67e2a7cb060547712e858f0ec1a7c8c39f605e0eb299f516a6184f4e680ffc8 + languageName: node + linkType: hard + "lerna@npm:9.0.0": version: 9.0.0 resolution: "lerna@npm:9.0.0" @@ -16119,6 +16163,13 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 + languageName: node + linkType: hard + "memoize-one@npm:^5.0.0": version: 5.2.1 resolution: "memoize-one@npm:5.2.1" @@ -16648,7 +16699,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -18650,6 +18701,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:6.13.0": + version: 6.13.0 + resolution: "qs@npm:6.13.0" + dependencies: + side-channel: ^1.0.6 + checksum: e9404dc0fc2849245107108ce9ec2766cde3be1b271de0bf1021d049dc5b98d1a2901e67b431ac5509f865420a7ed80b7acb3980099fe1c118a1c5d2e1432ad8 + languageName: node + linkType: hard + "qs@npm:^6.11.0, qs@npm:^6.7.0": version: 6.14.0 resolution: "qs@npm:6.14.0" @@ -18745,6 +18805,18 @@ __metadata: languageName: node linkType: hard +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 + languageName: node + linkType: hard + "rc@npm:^1.2.8": version: 1.2.8 resolution: "rc@npm:1.2.8" @@ -20173,7 +20245,7 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.1.0": +"side-channel@npm:^1.0.6, side-channel@npm:^1.1.0": version: 1.1.0 resolution: "side-channel@npm:1.1.0" dependencies: @@ -20747,7 +20819,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^5.0.0, strip-ansi@npm:^5.2.0": +"strip-ansi@npm:^5.0.0": version: 5.2.0 resolution: "strip-ansi@npm:5.2.0" dependencies: @@ -20823,13 +20895,6 @@ __metadata: languageName: node linkType: hard -"sudo-prompt@npm:^9.0.0": - version: 9.2.1 - resolution: "sudo-prompt@npm:9.2.1" - checksum: 50a29eec2f264f2b78d891452a64112d839a30bffbff4ec065dba4af691a35b23cdb8f9107d413e25c1a9f1925644a19994c00602495cab033d53f585fdfd665 - languageName: node - linkType: hard - "superagent@npm:5.1.0": version: 5.1.0 resolution: "superagent@npm:5.1.0" @@ -21396,6 +21461,16 @@ __metadata: languageName: node linkType: hard +"type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: 0.3.0 + mime-types: ~2.1.24 + checksum: 2c8e47675d55f8b4e404bcf529abdf5036c537a04c2b20177bcf78c9e3c1da69da3942b1346e6edb09e823228c0ee656ef0e033765ec39a70d496ef601a0c657 + languageName: node + linkType: hard + "typed-array-buffer@npm:^1.0.3": version: 1.0.3 resolution: "typed-array-buffer@npm:1.0.3" @@ -21610,7 +21685,7 @@ __metadata: languageName: node linkType: hard -"unpipe@npm:~1.0.0": +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 From 06ad239e7231088f31e9c8c5e9a6d4ee7984411d Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Mon, 10 Nov 2025 16:15:13 +0100 Subject: [PATCH 17/62] Bump to version 2.13.2 --- NATIVE_SDK_VERSIONS.md | 1 + benchmarks/ios/Podfile.lock | 12 ++++++------ example-new-architecture/ios/Podfile.lock | 6 +++--- example/ios/Podfile.lock | 18 +++++++++--------- lerna.json | 2 +- packages/codepush/package.json | 4 ++-- .../com/datadog/reactnative/SdkVersion.kt | 2 +- packages/core/ios/Sources/SdkVersion.swift | 2 +- packages/core/package.json | 2 +- packages/core/src/version.ts | 2 +- packages/internal-testing-tools/package.json | 2 +- .../react-native-apollo-client/package.json | 2 +- .../react-native-babel-plugin/package.json | 2 +- packages/react-native-navigation/package.json | 4 ++-- .../react-native-session-replay/package.json | 2 +- packages/react-native-webview/package.json | 2 +- packages/react-navigation/package.json | 4 ++-- yarn.lock | 8 ++++---- 18 files changed, 39 insertions(+), 38 deletions(-) diff --git a/NATIVE_SDK_VERSIONS.md b/NATIVE_SDK_VERSIONS.md index 0c19e3c82..678affc0e 100644 --- a/NATIVE_SDK_VERSIONS.md +++ b/NATIVE_SDK_VERSIONS.md @@ -1,5 +1,6 @@ | React Native | iOS Bridge / iOS SDK | Android Bridge / Android SDK | |-------------|---------------------|-----------------------------| +| 2.13.2 | 2.30.2 | 2.26.2 | | 2.13.1 | 2.30.2 | 2.26.2 | | 2.13.0 | 2.30.2 | 2.26.2 | | 2.12.4 | 2.30.0 | 2.25.0 | diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 3b1d0b0cc..f42e0cd31 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 2.30.2) - DatadogRUM (2.30.2): - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.1): + - DatadogSDKReactNative (2.13.2): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -37,7 +37,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeSessionReplay (2.13.1): + - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - DatadogSessionReplay (= 2.30.2) - DoubleConversion @@ -60,7 +60,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.1): + - DatadogSDKReactNativeWebView (2.13.2): - DatadogInternal (= 2.30.2) - DatadogSDKReactNative - DatadogWebViewTracking (= 2.30.2) @@ -2075,9 +2075,9 @@ SPEC CHECKSUMS: DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 40ac2d99dc3110c21fc2a670a8c6cd915ddc0d2c - DatadogSDKReactNativeSessionReplay: 679968d631841592a930122220c906eca487fd7e - DatadogSDKReactNativeWebView: 78d1a2ddc52c528d78b7559ce04973193c90f1dc + DatadogSDKReactNative: 4138a93c3168b4378de498052d0e00ea9560339d + DatadogSDKReactNativeSessionReplay: baa4de76d97d5f03303dde0e0db922a2fd812019 + DatadogSDKReactNativeWebView: 399e43d18902e3012c968fb9b7fd634b3936a882 DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index d41df0346..84b5f1d8c 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 2.30.2) - DatadogRUM (2.30.2): - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.1): + - DatadogSDKReactNative (2.13.2): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -37,7 +37,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (2.13.1): + - DatadogSDKReactNative/Tests (2.13.2): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -1855,7 +1855,7 @@ SPEC CHECKSUMS: DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 9e089993dd0bd7f28fc2540f83acfaf0aafda319 + DatadogSDKReactNative: afd267f110a3de4e179acc0bea6a492b0b8b00cf DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 95b23b301..45a7a2dea 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 2.30.2) - DatadogRUM (2.30.2): - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.1): + - DatadogSDKReactNative (2.13.2): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -18,7 +18,7 @@ PODS: - DatadogTrace (= 2.30.2) - DatadogWebViewTracking (= 2.30.2) - React-Core - - DatadogSDKReactNative/Tests (2.13.1): + - DatadogSDKReactNative/Tests (2.13.2): - DatadogCore (= 2.30.2) - DatadogCrashReporting (= 2.30.2) - DatadogLogs (= 2.30.2) @@ -26,7 +26,7 @@ PODS: - DatadogTrace (= 2.30.2) - DatadogWebViewTracking (= 2.30.2) - React-Core - - DatadogSDKReactNativeSessionReplay (2.13.1): + - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - DatadogSessionReplay (= 2.30.2) - DoubleConversion @@ -49,7 +49,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeSessionReplay/Tests (2.13.1): + - DatadogSDKReactNativeSessionReplay/Tests (2.13.2): - DatadogSDKReactNative - DatadogSessionReplay (= 2.30.2) - DoubleConversion @@ -73,12 +73,12 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.1): + - DatadogSDKReactNativeWebView (2.13.2): - DatadogInternal (= 2.30.2) - DatadogSDKReactNative - DatadogWebViewTracking (= 2.30.2) - React-Core - - DatadogSDKReactNativeWebView/Tests (2.13.1): + - DatadogSDKReactNativeWebView/Tests (2.13.2): - DatadogInternal (= 2.30.2) - DatadogSDKReactNative - DatadogWebViewTracking (= 2.30.2) @@ -1993,9 +1993,9 @@ SPEC CHECKSUMS: DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: cdc2dfc45180e2ff58fe73cc49559554699f0b3c - DatadogSDKReactNativeSessionReplay: cdfe6590f22deeeb38538396a07ef3577a5383de - DatadogSDKReactNativeWebView: e71edd71ca7305c69278981fd0d758893072d0f3 + DatadogSDKReactNative: b04b5f9fd71aaa8a26affc43b1b0a2a43674a072 + DatadogSDKReactNativeSessionReplay: 102b0ecb56fb2baf3e8183e7c54631c5e31bf24a + DatadogSDKReactNativeWebView: 4343376f9a6be5e2af685444173f4b54e8b15d83 DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be diff --git a/lerna.json b/lerna.json index b202692de..25572f225 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "npmClient": "yarn", - "version": "2.13.1", + "version": "2.13.2", "packages": [ "packages/*" ], diff --git a/packages/codepush/package.json b/packages/codepush/package.json index d4fdcde0f..b52a8f017 100644 --- a/packages/codepush/package.json +++ b/packages/codepush/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-code-push", - "version": "2.13.1", + "version": "2.13.2", "description": "A client-side React Native module to interact with Appcenter Codepush and Datadog", "keywords": [ "datadog", @@ -38,7 +38,7 @@ "prepare": "rm -rf lib && yarn bob build" }, "devDependencies": { - "@datadog/mobile-react-native": "workspace:packages/core", + "@datadog/mobile-react-native": "workspace:2.13.2", "@testing-library/react-native": "7.0.2", "react-native-builder-bob": "0.26.0", "react-native-code-push": "7.1.0" diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt index ca49985a9..f1f47e06c 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/SdkVersion.kt @@ -7,4 +7,4 @@ package com.datadog.reactnative // This is automatically updated by the update-version.sh script -internal const val SDK_VERSION = "2.13.1" +internal const val SDK_VERSION = "2.13.2" diff --git a/packages/core/ios/Sources/SdkVersion.swift b/packages/core/ios/Sources/SdkVersion.swift index 616f0be9b..0d6ed2d5b 100644 --- a/packages/core/ios/Sources/SdkVersion.swift +++ b/packages/core/ios/Sources/SdkVersion.swift @@ -7,4 +7,4 @@ import Foundation // This is automatically updated by the update-version.sh script -let SdkVersion = "2.13.1" +let SdkVersion = "2.13.2" diff --git a/packages/core/package.json b/packages/core/package.json index 545026a26..56818b180 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native", - "version": "2.13.1", + "version": "2.13.2", "description": "A client-side React Native module to interact with Datadog", "keywords": [ "datadog", diff --git a/packages/core/src/version.ts b/packages/core/src/version.ts index fd89e50b4..00d00d874 100644 --- a/packages/core/src/version.ts +++ b/packages/core/src/version.ts @@ -1,2 +1,2 @@ // generated by genversion -export const version = '2.13.1'; +export const version = '2.13.2'; diff --git a/packages/internal-testing-tools/package.json b/packages/internal-testing-tools/package.json index 5844bbce4..7d647fa0a 100644 --- a/packages/internal-testing-tools/package.json +++ b/packages/internal-testing-tools/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/react-native-internal-testing-tools", - "version": "2.13.1", + "version": "2.13.2", "description": "Internal tools for testing the Datadog React Native SDK.", "keywords": [ "datadog", diff --git a/packages/react-native-apollo-client/package.json b/packages/react-native-apollo-client/package.json index f69a6919b..f7dfa6095 100644 --- a/packages/react-native-apollo-client/package.json +++ b/packages/react-native-apollo-client/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-apollo-client", - "version": "2.13.1", + "version": "2.13.2", "description": "A client-side React Native module to interact with Apollo Client and Datadog", "keywords": [ "datadog", diff --git a/packages/react-native-babel-plugin/package.json b/packages/react-native-babel-plugin/package.json index 7a6152238..17507d192 100644 --- a/packages/react-native-babel-plugin/package.json +++ b/packages/react-native-babel-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-babel-plugin", - "version": "2.13.1", + "version": "2.13.2", "description": "A Babel plugin that enhances Datadog's React Native SDK by automatically enriching React components with contextual metadata.", "keywords": [ "babel", diff --git a/packages/react-native-navigation/package.json b/packages/react-native-navigation/package.json index 8fd6f2e2e..715145949 100644 --- a/packages/react-native-navigation/package.json +++ b/packages/react-native-navigation/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-navigation", - "version": "2.13.1", + "version": "2.13.2", "description": "A client-side React Native module to interact with Datadog", "keywords": [ "datadog", @@ -36,7 +36,7 @@ "prepare": "rm -rf lib && yarn bob build" }, "devDependencies": { - "@datadog/mobile-react-native": "^2.13.1", + "@datadog/mobile-react-native": "^2.13.2", "@testing-library/react-native": "7.0.2", "react-native-builder-bob": "0.26.0", "react-native-gesture-handler": "1.10.3", diff --git a/packages/react-native-session-replay/package.json b/packages/react-native-session-replay/package.json index e35be543a..afec1307f 100644 --- a/packages/react-native-session-replay/package.json +++ b/packages/react-native-session-replay/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-session-replay", - "version": "2.13.1", + "version": "2.13.2", "description": "A client-side React Native module to enable session replay with Datadog", "keywords": [ "datadog", diff --git a/packages/react-native-webview/package.json b/packages/react-native-webview/package.json index d0593e44f..e0fb2182b 100644 --- a/packages/react-native-webview/package.json +++ b/packages/react-native-webview/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-native-webview", - "version": "2.13.1", + "version": "2.13.2", "description": "A client-side React Native module to interact with react-native-webview and Datadog", "keywords": [ "datadog", diff --git a/packages/react-navigation/package.json b/packages/react-navigation/package.json index 9e219e042..b2f15d9dc 100644 --- a/packages/react-navigation/package.json +++ b/packages/react-navigation/package.json @@ -1,6 +1,6 @@ { "name": "@datadog/mobile-react-navigation", - "version": "2.13.1", + "version": "2.13.2", "description": "A client-side React Native module to interact with Datadog", "keywords": [ "datadog", @@ -36,7 +36,7 @@ "prepare": "rm -rf lib && yarn bob build" }, "devDependencies": { - "@datadog/mobile-react-native": "^2.13.1", + "@datadog/mobile-react-native": "^2.13.2", "@react-navigation/native-v5": "npm:@react-navigation/native@5.9.8", "@react-navigation/native-v6": "npm:@react-navigation/native@6.1.2", "@react-navigation/stack-v5": "npm:@react-navigation/stack@5.14.2", diff --git a/yarn.lock b/yarn.lock index 335b47458..0b1d90cd9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3804,7 +3804,7 @@ __metadata: version: 0.0.0-use.local resolution: "@datadog/mobile-react-native-code-push@workspace:packages/codepush" dependencies: - "@datadog/mobile-react-native": "workspace:packages/core" + "@datadog/mobile-react-native": "workspace:2.13.2" "@testing-library/react-native": 7.0.2 react-native-builder-bob: 0.26.0 react-native-code-push: 7.1.0 @@ -3820,7 +3820,7 @@ __metadata: version: 0.0.0-use.local resolution: "@datadog/mobile-react-native-navigation@workspace:packages/react-native-navigation" dependencies: - "@datadog/mobile-react-native": ^2.13.1 + "@datadog/mobile-react-native": ^2.13.2 "@testing-library/react-native": 7.0.2 react-native-builder-bob: 0.26.0 react-native-gesture-handler: 1.10.3 @@ -3862,7 +3862,7 @@ __metadata: languageName: unknown linkType: soft -"@datadog/mobile-react-native@^2.13.1, @datadog/mobile-react-native@workspace:packages/core": +"@datadog/mobile-react-native@^2.13.2, @datadog/mobile-react-native@workspace:2.13.2, @datadog/mobile-react-native@workspace:packages/core": version: 0.0.0-use.local resolution: "@datadog/mobile-react-native@workspace:packages/core" dependencies: @@ -3879,7 +3879,7 @@ __metadata: version: 0.0.0-use.local resolution: "@datadog/mobile-react-navigation@workspace:packages/react-navigation" dependencies: - "@datadog/mobile-react-native": ^2.13.1 + "@datadog/mobile-react-native": ^2.13.2 "@react-navigation/native-v5": "npm:@react-navigation/native@5.9.8" "@react-navigation/native-v6": "npm:@react-navigation/native@6.1.2" "@react-navigation/stack-v5": "npm:@react-navigation/stack@5.14.2" From 06177262653027c5f87dd3a515bd3a932546f24a Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Tue, 18 Nov 2025 10:17:25 +0000 Subject: [PATCH 18/62] Revert update to `react-native-community/cli` in example apps and remove it from main package --- benchmarks/package.json | 6 +- .../project.pbxproj | 64 ++-- example-new-architecture/package.json | 6 +- .../project.pbxproj | 64 ++-- example/package.json | 6 +- package.json | 3 - yarn.lock | 280 +++++++----------- 7 files changed, 174 insertions(+), 255 deletions(-) diff --git a/benchmarks/package.json b/benchmarks/package.json index db3e42677..03c86ac9e 100644 --- a/benchmarks/package.json +++ b/benchmarks/package.json @@ -41,9 +41,9 @@ "@babel/preset-env": "7.25.3", "@babel/runtime": "^7.26.10", "@datadog/datadog-ci": "3.12.0", - "@react-native-community/cli": "17.0.1", - "@react-native-community/cli-platform-android": "17.0.1", - "@react-native-community/cli-platform-ios": "17.0.1", + "@react-native-community/cli": "15.0.1", + "@react-native-community/cli-platform-android": "15.0.1", + "@react-native-community/cli-platform-ios": "15.0.1", "@react-native/babel-preset": "0.78.2", "@react-native/eslint-config": "0.78.2", "@react-native/metro-config": "0.78.2", diff --git a/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj b/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj index ed252adbc..88c5aff8b 100644 --- a/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj +++ b/example-new-architecture/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj @@ -10,9 +10,9 @@ 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 6E6EEF96505B7B7C13273254 /* libPods-DdSdkReactNativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5F70B3586D3871B1E4AEC6 /* libPods-DdSdkReactNativeExample.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; E05973ABEC106467505BAF84 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 91A6167299744A7A5E90FD00 /* PrivacyInfo.xcprivacy */; }; - F59778933728396AC9586AC3 /* libPods-DdSdkReactNativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F15FCB308661F5FE9CD1E2F0 /* libPods-DdSdkReactNativeExample.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -24,12 +24,12 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = DdSdkReactNativeExample/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = DdSdkReactNativeExample/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = DdSdkReactNativeExample/main.m; sourceTree = ""; }; - 4A4B8157669F7C844ABF982B /* Pods-DdSdkReactNativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DdSdkReactNativeExample.release.xcconfig"; path = "Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample.release.xcconfig"; sourceTree = ""; }; + 7F2E43785E4C9F07671D568A /* Pods-DdSdkReactNativeExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DdSdkReactNativeExample.debug.xcconfig"; path = "Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample.debug.xcconfig"; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = DdSdkReactNativeExample/LaunchScreen.storyboard; sourceTree = ""; }; + 8D5F70B3586D3871B1E4AEC6 /* libPods-DdSdkReactNativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-DdSdkReactNativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 91A6167299744A7A5E90FD00 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = DdSdkReactNativeExample/PrivacyInfo.xcprivacy; sourceTree = ""; }; - 943593C03DDD65A0F77DAD08 /* Pods-DdSdkReactNativeExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DdSdkReactNativeExample.debug.xcconfig"; path = "Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample.debug.xcconfig"; sourceTree = ""; }; + DA0CFD2F6619BC6603A45329 /* Pods-DdSdkReactNativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DdSdkReactNativeExample.release.xcconfig"; path = "Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; - F15FCB308661F5FE9CD1E2F0 /* libPods-DdSdkReactNativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-DdSdkReactNativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -37,7 +37,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - F59778933728396AC9586AC3 /* libPods-DdSdkReactNativeExample.a in Frameworks */, + 6E6EEF96505B7B7C13273254 /* libPods-DdSdkReactNativeExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -79,7 +79,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - F15FCB308661F5FE9CD1E2F0 /* libPods-DdSdkReactNativeExample.a */, + 8D5F70B3586D3871B1E4AEC6 /* libPods-DdSdkReactNativeExample.a */, ); name = Frameworks; sourceTree = ""; @@ -117,8 +117,8 @@ BBD78D7AC51CEA395F1C20DB /* Pods */ = { isa = PBXGroup; children = ( - 943593C03DDD65A0F77DAD08 /* Pods-DdSdkReactNativeExample.debug.xcconfig */, - 4A4B8157669F7C844ABF982B /* Pods-DdSdkReactNativeExample.release.xcconfig */, + 7F2E43785E4C9F07671D568A /* Pods-DdSdkReactNativeExample.debug.xcconfig */, + DA0CFD2F6619BC6603A45329 /* Pods-DdSdkReactNativeExample.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -130,14 +130,14 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "DdSdkReactNativeExample" */; buildPhases = ( - 6D376D298F855F5CC23E9ED5 /* [CP] Check Pods Manifest.lock */, + 5291E89473F9073072159A48 /* [CP] Check Pods Manifest.lock */, FD10A7F022414F080027D42C /* Start Packager */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 07743436841738907FE3FD72 /* [CP] Embed Pods Frameworks */, - 961EBCFFF8E0F6A3F5781446 /* [CP] Copy Pods Resources */, + DA35A58E9060D5B33AC9F19B /* [CP] Embed Pods Frameworks */, + A63B10F8607064B7862D32CF /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -209,24 +209,7 @@ shellPath = /bin/sh; shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; }; - 07743436841738907FE3FD72 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 6D376D298F855F5CC23E9ED5 /* [CP] Check Pods Manifest.lock */ = { + 5291E89473F9073072159A48 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -248,7 +231,7 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 961EBCFFF8E0F6A3F5781446 /* [CP] Copy Pods Resources */ = { + A63B10F8607064B7862D32CF /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -265,6 +248,23 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample-resources.sh\"\n"; showEnvVarsInLog = 0; }; + DA35A58E9060D5B33AC9F19B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-DdSdkReactNativeExample/Pods-DdSdkReactNativeExample-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; FD10A7F022414F080027D42C /* Start Packager */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -301,7 +301,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 943593C03DDD65A0F77DAD08 /* Pods-DdSdkReactNativeExample.debug.xcconfig */; + baseConfigurationReference = 7F2E43785E4C9F07671D568A /* Pods-DdSdkReactNativeExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -328,7 +328,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4A4B8157669F7C844ABF982B /* Pods-DdSdkReactNativeExample.release.xcconfig */; + baseConfigurationReference = DA0CFD2F6619BC6603A45329 /* Pods-DdSdkReactNativeExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; diff --git a/example-new-architecture/package.json b/example-new-architecture/package.json index 49671a341..b72ce69e4 100644 --- a/example-new-architecture/package.json +++ b/example-new-architecture/package.json @@ -16,9 +16,9 @@ "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.26.10", - "@react-native-community/cli": "17.0.1", - "@react-native-community/cli-platform-android": "17.0.1", - "@react-native-community/cli-platform-ios": "17.0.1", + "@react-native-community/cli": "15.0.1", + "@react-native-community/cli-platform-android": "15.0.1", + "@react-native-community/cli-platform-ios": "15.0.1", "@react-native/babel-preset": "0.76.9", "@react-native/eslint-config": "0.76.9", "@react-native/metro-config": "0.76.9", diff --git a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj index 89e853c02..f64fe027d 100644 --- a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj @@ -10,7 +10,7 @@ 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 3C22D5364B1021ACC55154F6 /* libPods-ddSdkReactnativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CB817BBBBA03E56F5DA20EF /* libPods-ddSdkReactnativeExample.a */; }; + 4EA9AF1CEFE311BB68B9F0D5 /* libPods-ddSdkReactnativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F2F7BC23E08401E57C9E1BD4 /* libPods-ddSdkReactnativeExample.a */; }; 7115D38EB0DCB0BDB39D62A2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A54EC6889135AAF4EFAD7EF0 /* PrivacyInfo.xcprivacy */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ @@ -22,12 +22,12 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ddSdkReactnativeExample/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ddSdkReactnativeExample/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ddSdkReactnativeExample/main.m; sourceTree = ""; }; - 4DB4C3F3292F6360F4956606 /* Pods-ddSdkReactnativeExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ddSdkReactnativeExample.debug.xcconfig"; path = "Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample.debug.xcconfig"; sourceTree = ""; }; - 5CB817BBBBA03E56F5DA20EF /* libPods-ddSdkReactnativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ddSdkReactnativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 738D7986F1BA482EC04EE24F /* Pods-ddSdkReactnativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ddSdkReactnativeExample.release.xcconfig"; path = "Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample.release.xcconfig"; sourceTree = ""; }; + 721D7A3AE3FE57C57E466CBF /* Pods-ddSdkReactnativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ddSdkReactnativeExample.release.xcconfig"; path = "Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample.release.xcconfig"; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ddSdkReactnativeExample/LaunchScreen.storyboard; sourceTree = ""; }; A54EC6889135AAF4EFAD7EF0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = ddSdkReactnativeExample/PrivacyInfo.xcprivacy; sourceTree = ""; }; + B59EAF8B2F29BE577AE7F797 /* Pods-ddSdkReactnativeExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ddSdkReactnativeExample.debug.xcconfig"; path = "Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample.debug.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + F2F7BC23E08401E57C9E1BD4 /* libPods-ddSdkReactnativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ddSdkReactnativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -35,7 +35,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3C22D5364B1021ACC55154F6 /* libPods-ddSdkReactnativeExample.a in Frameworks */, + 4EA9AF1CEFE311BB68B9F0D5 /* libPods-ddSdkReactnativeExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -60,7 +60,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 5CB817BBBBA03E56F5DA20EF /* libPods-ddSdkReactnativeExample.a */, + F2F7BC23E08401E57C9E1BD4 /* libPods-ddSdkReactnativeExample.a */, ); name = Frameworks; sourceTree = ""; @@ -97,8 +97,8 @@ BBD78D7AC51CEA395F1C20DB /* Pods */ = { isa = PBXGroup; children = ( - 4DB4C3F3292F6360F4956606 /* Pods-ddSdkReactnativeExample.debug.xcconfig */, - 738D7986F1BA482EC04EE24F /* Pods-ddSdkReactnativeExample.release.xcconfig */, + B59EAF8B2F29BE577AE7F797 /* Pods-ddSdkReactnativeExample.debug.xcconfig */, + 721D7A3AE3FE57C57E466CBF /* Pods-ddSdkReactnativeExample.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -110,14 +110,14 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ddSdkReactnativeExample" */; buildPhases = ( - AD46715DA8F0A559F0C2DD56 /* [CP] Check Pods Manifest.lock */, + C84F58B12D35F481E83A840A /* [CP] Check Pods Manifest.lock */, FD10A7F022414F080027D42C /* Start Packager */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 9FCE5EA816AC9B0965148B3A /* [CP] Embed Pods Frameworks */, - 315CB1439E0032A0595DF991 /* [CP] Copy Pods Resources */, + 21A29D19EE0D8BA789DB48E2 /* [CP] Embed Pods Frameworks */, + CFB529A04D071A5133DC7E2B /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -189,24 +189,7 @@ shellPath = /bin/sh; shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; }; - 315CB1439E0032A0595DF991 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 9FCE5EA816AC9B0965148B3A /* [CP] Embed Pods Frameworks */ = { + 21A29D19EE0D8BA789DB48E2 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -223,7 +206,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - AD46715DA8F0A559F0C2DD56 /* [CP] Check Pods Manifest.lock */ = { + C84F58B12D35F481E83A840A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -245,6 +228,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + CFB529A04D071A5133DC7E2B /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ddSdkReactnativeExample/Pods-ddSdkReactnativeExample-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; FD10A7F022414F080027D42C /* Start Packager */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -281,7 +281,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4DB4C3F3292F6360F4956606 /* Pods-ddSdkReactnativeExample.debug.xcconfig */; + baseConfigurationReference = B59EAF8B2F29BE577AE7F797 /* Pods-ddSdkReactnativeExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -308,7 +308,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 738D7986F1BA482EC04EE24F /* Pods-ddSdkReactnativeExample.release.xcconfig */; + baseConfigurationReference = 721D7A3AE3FE57C57E466CBF /* Pods-ddSdkReactnativeExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; diff --git a/example/package.json b/example/package.json index 75f13aaa8..d114dc49a 100644 --- a/example/package.json +++ b/example/package.json @@ -16,9 +16,9 @@ "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview", "@datadog/mobile-react-navigation": "workspace:packages/react-navigation", "@react-native-async-storage/async-storage": "^2.1.2", - "@react-native-community/cli": "17.0.1", - "@react-native-community/cli-platform-android": "17.0.1", - "@react-native-community/cli-platform-ios": "17.0.1", + "@react-native-community/cli": "15.0.1", + "@react-native-community/cli-platform-android": "15.0.1", + "@react-native-community/cli-platform-ios": "15.0.1", "@react-navigation/bottom-tabs": "^6.3.1", "@react-navigation/native": "^6.1.18", "@react-navigation/stack": "^6.2.1", diff --git a/package.json b/package.json index 29dfdee81..4d77a4ac4 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,6 @@ "@babel/plugin-transform-runtime": "^7.25.0", "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.26.10", - "@react-native-community/cli": "17.0.1", - "@react-native-community/cli-platform-android": "17.0.1", - "@react-native-community/cli-platform-ios": "17.0.1", "@react-native/babel-preset": "0.76.9", "@react-native/eslint-config": "0.76.9", "@react-native/metro-config": "0.76.9", diff --git a/yarn.lock b/yarn.lock index d73aaddc6..dfcec9595 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5760,65 +5760,62 @@ __metadata: languageName: node linkType: hard -"@react-native-community/cli-clean@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-clean@npm:17.0.1" +"@react-native-community/cli-clean@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-clean@npm:15.0.1" dependencies: - "@react-native-community/cli-tools": 17.0.1 + "@react-native-community/cli-tools": 15.0.1 chalk: ^4.1.2 execa: ^5.0.0 fast-glob: ^3.3.2 - checksum: 4f39568399cc0198ec85a3d721151be3c0507e95d2de72319f3380ed44c303b9a60e452330e3d099b4f4c65b8339bdb7b60f5f980b2e7fd65854afc22730998f + checksum: ea6c663ec56cfe3a2c4fac7d3f0fec2ac8de9c34458f241b2afdf7f45dfb00d1de9e367fec732f8fef6e2b17046f4ed03c3be2ea4d2075633197dc23c516f986 languageName: node linkType: hard -"@react-native-community/cli-config-android@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-config-android@npm:17.0.1" +"@react-native-community/cli-config-apple@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-config-apple@npm:15.0.1" dependencies: - "@react-native-community/cli-tools": 17.0.1 - chalk: ^4.1.2 - fast-glob: ^3.3.2 - fast-xml-parser: ^4.4.1 - checksum: b6c57a4d23a08a837648cc02cca3c1d6665bb56d7bba10794feb0946767092f7a7a6b975b143946baf3de8e23c612e2ab9e9b4d0e00d7bad02d1d3cdd1ce853c - languageName: node - linkType: hard - -"@react-native-community/cli-config-apple@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-config-apple@npm:17.0.1" - dependencies: - "@react-native-community/cli-tools": 17.0.1 + "@react-native-community/cli-tools": 15.0.1 chalk: ^4.1.2 execa: ^5.0.0 fast-glob: ^3.3.2 - checksum: 860e7545ea102d0076a33484165d29e743e4ef376f7a917cd63f8bb4b10e473db7c46fbc61993cdab751416dc16ab81f626a6dd63e59495f293849e5f0f9e6de + checksum: 67b9be8b6cce14f764a5734b9599eb7d1095c7fb5c06b0b6cd3518cf3a00c90026018c1eb8d497338da092a3cdcaa9b33fec34c5b766a4517c70293e5f1df58d languageName: node linkType: hard -"@react-native-community/cli-config@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-config@npm:17.0.1" +"@react-native-community/cli-config@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-config@npm:15.0.1" dependencies: - "@react-native-community/cli-tools": 17.0.1 + "@react-native-community/cli-tools": 15.0.1 chalk: ^4.1.2 cosmiconfig: ^9.0.0 deepmerge: ^4.3.0 fast-glob: ^3.3.2 joi: ^17.2.1 - checksum: 0ecd79f9a8b82155eb50733f65045895417c61ff92a7b3a0ed26e86872c46e8513b1c5c666e25f64bfb71078af1b005909fadd3ba176a83807b56a82dd5b9e1d + checksum: 23314bcdf465974ee71a01792f0a1149ea51eea1dc66416e53aa2bc3a123dba6a8e0654d68211d2b20570bc875145b2e5d4abf923190c685c0021bb280230c3f languageName: node linkType: hard -"@react-native-community/cli-doctor@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-doctor@npm:17.0.1" +"@react-native-community/cli-debugger-ui@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-debugger-ui@npm:15.0.1" dependencies: - "@react-native-community/cli-config": 17.0.1 - "@react-native-community/cli-platform-android": 17.0.1 - "@react-native-community/cli-platform-apple": 17.0.1 - "@react-native-community/cli-platform-ios": 17.0.1 - "@react-native-community/cli-tools": 17.0.1 + serve-static: ^1.13.1 + checksum: a97bb195f3722b91e0acf4c63f4e6956d572f5a275a13be01513b6797bd81ad0b838aa4fc8440131e64c39547c8e83feebb6435a34773269355a497122ed2209 + languageName: node + linkType: hard + +"@react-native-community/cli-doctor@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-doctor@npm:15.0.1" + dependencies: + "@react-native-community/cli-config": 15.0.1 + "@react-native-community/cli-platform-android": 15.0.1 + "@react-native-community/cli-platform-apple": 15.0.1 + "@react-native-community/cli-platform-ios": 15.0.1 + "@react-native-community/cli-tools": 15.0.1 chalk: ^4.1.2 command-exists: ^1.2.8 deepmerge: ^4.3.0 @@ -5827,102 +5824,105 @@ __metadata: node-stream-zip: ^1.9.1 ora: ^5.4.1 semver: ^7.5.2 + strip-ansi: ^5.2.0 wcwidth: ^1.0.1 yaml: ^2.2.1 - checksum: fef3af3aede375eced42cfdedc8cd3267fc1f2916ea6a7d7502346bda2ab9153360815d12ac269d040de7d38b26b1470fc86d00be566611633f06f87d58e761b + checksum: 6df1825df9f563096e48528f16d0bc521aceb2933e864921c8092eeeeeade0893963964897a6145b26a3d4de72ce05259f2d06f873eae64796d8c3815f22f1a5 languageName: node linkType: hard -"@react-native-community/cli-platform-android@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-platform-android@npm:17.0.1" +"@react-native-community/cli-platform-android@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-platform-android@npm:15.0.1" dependencies: - "@react-native-community/cli-config-android": 17.0.1 - "@react-native-community/cli-tools": 17.0.1 + "@react-native-community/cli-tools": 15.0.1 chalk: ^4.1.2 execa: ^5.0.0 + fast-glob: ^3.3.2 + fast-xml-parser: ^4.4.1 logkitty: ^0.7.1 - checksum: 4848d5f4fd88b9bdd90f2775c8b97772d8edbb144000282ba56360b567584f7fcf619b81bc33c839fe6c7ae1c6949611a3cda3d3008a94c152f0709ced421499 + checksum: 6c5e5912b7c81a6cb9076ae08897470090e1ff20fdaa502d500b4700235f2411942c6e38e3373111efa025dee9a1d3cc71dea6a4c42a89272f0d56b1eeb7b38a languageName: node linkType: hard -"@react-native-community/cli-platform-apple@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-platform-apple@npm:17.0.1" +"@react-native-community/cli-platform-apple@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-platform-apple@npm:15.0.1" dependencies: - "@react-native-community/cli-config-apple": 17.0.1 - "@react-native-community/cli-tools": 17.0.1 + "@react-native-community/cli-config-apple": 15.0.1 + "@react-native-community/cli-tools": 15.0.1 chalk: ^4.1.2 execa: ^5.0.0 fast-xml-parser: ^4.4.1 - checksum: 123fb119aac57e642ccaa123bae60058420680e8fbeb7a3d5cd20069ea624cb17dbc4d6486588fd8612e8cad93330c6bdfde147770999edc4d1fce07a71493d7 + checksum: 27278ff8790fddc220cba9daa4b05cb027403b7c3b81cd3f025b09f52ceccd41f68e86b71d493794eadc2d54fa4a5f6a1032608c4ec7ce928cc1985dce7b9bd2 languageName: node linkType: hard -"@react-native-community/cli-platform-ios@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-platform-ios@npm:17.0.1" +"@react-native-community/cli-platform-ios@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-platform-ios@npm:15.0.1" dependencies: - "@react-native-community/cli-platform-apple": 17.0.1 - checksum: 8d9d945f3416953010c65b13bfc0b37c2c30815b2ebd40e1cb8d687ef35712e3c45889a5d72b1f6d02c5a38298afc51299af0398648d19e76dd273966f538715 + "@react-native-community/cli-platform-apple": 15.0.1 + checksum: 27b4775af43ce06e9315fda54f299e96405975c44d20a495443074d2818fc085dcb85cf2d2e6581990b71ab2e9ffc7d88666337bec8eb9412e80abf8dd793851 languageName: node linkType: hard -"@react-native-community/cli-server-api@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-server-api@npm:17.0.1" +"@react-native-community/cli-server-api@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-server-api@npm:15.0.1" dependencies: - "@react-native-community/cli-tools": 17.0.1 - body-parser: ^1.20.3 + "@react-native-community/cli-debugger-ui": 15.0.1 + "@react-native-community/cli-tools": 15.0.1 compression: ^1.7.1 connect: ^3.6.5 errorhandler: ^1.5.1 nocache: ^3.0.1 - open: ^6.2.0 pretty-format: ^26.6.2 serve-static: ^1.13.1 ws: ^6.2.3 - checksum: e8ae175fb5a6d1826a1006aef63848780947b8eb7b8518cf64c01eaa8c37ba773da4a3b6332e3c19f48e9f418dc4f815c8c4b10c880c34cb98d4b503ea7986c4 + checksum: 354eba589433251a56db7edf005886aa3c4886ff70f52b999db7c3718435f01a3f1081bc56cc681a1b7de2fa50ea4891c4ea673fe0a02eb855ecbc001bd86654 languageName: node linkType: hard -"@react-native-community/cli-tools@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-tools@npm:17.0.1" +"@react-native-community/cli-tools@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-tools@npm:15.0.1" dependencies: - "@vscode/sudo-prompt": ^9.0.0 appdirsjs: ^1.2.4 chalk: ^4.1.2 execa: ^5.0.0 find-up: ^5.0.0 - launch-editor: ^2.9.1 mime: ^2.4.1 + open: ^6.2.0 ora: ^5.4.1 prompts: ^2.4.2 semver: ^7.5.2 - checksum: a8bda556775d9a7de71e02c0d603c556af6525a7a6d082a3fa6fb0e354ea1eba82d295f2a6258ac44a737875e1c1854aa72646afe04f85a49815a811e9a96373 + shell-quote: ^1.7.3 + sudo-prompt: ^9.0.0 + checksum: 0c40d5aa2306a2bfc1ee15362d045b0eff3cb162dd1b070f504508b2bbdd00c791151cf9f8679d248b4480b75b758e60b8d0cf3c19a19a02b4b4ece9928a119c languageName: node linkType: hard -"@react-native-community/cli-types@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli-types@npm:17.0.1" +"@react-native-community/cli-types@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-types@npm:15.0.1" dependencies: joi: ^17.2.1 - checksum: 8a609ec363b18cc2098499d4519ad592a463da7d32f5bc8d581daeac5dbb507a75f70e7ec93a64ddc38510e96f9a4a650f9a010b2e1e0f104cc59e5995f1bfce + checksum: 77452486158afcf1f03a3596135b6dba16dba5dd10209dacd5a6a4b176df36d37b8e49af61590d5a64df4907cf0575b6f37e0a3893335f961a9380edaee32152 languageName: node linkType: hard -"@react-native-community/cli@npm:17.0.1": - version: 17.0.1 - resolution: "@react-native-community/cli@npm:17.0.1" +"@react-native-community/cli@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli@npm:15.0.1" dependencies: - "@react-native-community/cli-clean": 17.0.1 - "@react-native-community/cli-config": 17.0.1 - "@react-native-community/cli-doctor": 17.0.1 - "@react-native-community/cli-server-api": 17.0.1 - "@react-native-community/cli-tools": 17.0.1 - "@react-native-community/cli-types": 17.0.1 + "@react-native-community/cli-clean": 15.0.1 + "@react-native-community/cli-config": 15.0.1 + "@react-native-community/cli-debugger-ui": 15.0.1 + "@react-native-community/cli-doctor": 15.0.1 + "@react-native-community/cli-server-api": 15.0.1 + "@react-native-community/cli-tools": 15.0.1 + "@react-native-community/cli-types": 15.0.1 chalk: ^4.1.2 commander: ^9.4.1 deepmerge: ^4.3.0 @@ -5934,7 +5934,7 @@ __metadata: semver: ^7.5.2 bin: rnc-cli: build/bin.js - checksum: 5b9ed387637daf6a65d9086f0832f3016a257e95ef63cb2f3ecd343f7eb4c34b4882bcd8e6b1ba897ef177040c9955a10e4f4359913286e69972d95fed123263 + checksum: 26c98ef67b4b89d3af13f2a3b19e51c7b2de5d320ca908cb628ca22b32bff5a17b8a1cc7f4b0ece303c4e53dc10e8ac0e88df9b376e63ebc97acb8d358f78c2e languageName: node linkType: hard @@ -8570,13 +8570,6 @@ __metadata: languageName: node linkType: hard -"@vscode/sudo-prompt@npm:^9.0.0": - version: 9.3.1 - resolution: "@vscode/sudo-prompt@npm:9.3.1" - checksum: 07a6ce9ef2e4e2b369288b78344f7ef3db977d5f1576b944075c22aacb9cf830acfd5f773d1b0497610bec4f811d44793142234114e57763abc78ea2cef8940a - languageName: node - linkType: hard - "@wry/caches@npm:^1.0.0": version: 1.0.1 resolution: "@wry/caches@npm:1.0.1" @@ -8656,9 +8649,9 @@ __metadata: "@babel/preset-env": ^7.25.3 "@babel/runtime": ^7.26.10 "@datadog/mobile-react-native": "workspace:packages/core" - "@react-native-community/cli": 17.0.1 - "@react-native-community/cli-platform-android": 17.0.1 - "@react-native-community/cli-platform-ios": 17.0.1 + "@react-native-community/cli": 15.0.1 + "@react-native-community/cli-platform-android": 15.0.1 + "@react-native-community/cli-platform-ios": 15.0.1 "@react-native/babel-preset": 0.76.9 "@react-native/eslint-config": 0.76.9 "@react-native/metro-config": 0.76.9 @@ -9474,9 +9467,9 @@ __metadata: "@datadog/mobile-react-native-session-replay": "workspace:packages/react-native-session-replay" "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview" "@datadog/mobile-react-navigation": "workspace:packages/react-navigation" - "@react-native-community/cli": 17.0.1 - "@react-native-community/cli-platform-android": 17.0.1 - "@react-native-community/cli-platform-ios": 17.0.1 + "@react-native-community/cli": 15.0.1 + "@react-native-community/cli-platform-android": 15.0.1 + "@react-native-community/cli-platform-ios": 15.0.1 "@react-native-community/slider": 4.5.7 "@react-native-picker/picker": 2.11.0 "@react-native/babel-preset": 0.78.2 @@ -9548,26 +9541,6 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:^1.20.3": - version: 1.20.3 - resolution: "body-parser@npm:1.20.3" - dependencies: - bytes: 3.1.2 - content-type: ~1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.13.0 - raw-body: 2.5.2 - type-is: ~1.6.18 - unpipe: 1.0.0 - checksum: 1a35c59a6be8d852b00946330141c4f142c6af0f970faa87f10ad74f1ee7118078056706a05ae3093c54dabca9cd3770fa62a170a85801da1a4324f04381167d - languageName: node - linkType: hard - "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -10411,13 +10384,6 @@ __metadata: languageName: node linkType: hard -"content-type@npm:~1.0.5": - version: 1.0.5 - resolution: "content-type@npm:1.0.5" - checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 - languageName: node - linkType: hard - "conventional-changelog-angular@npm:7.0.0": version: 7.0.0 resolution: "conventional-changelog-angular@npm:7.0.0" @@ -10807,9 +10773,9 @@ __metadata: "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview" "@datadog/mobile-react-navigation": "workspace:packages/react-navigation" "@react-native-async-storage/async-storage": ^2.1.2 - "@react-native-community/cli": 17.0.1 - "@react-native-community/cli-platform-android": 17.0.1 - "@react-native-community/cli-platform-ios": 17.0.1 + "@react-native-community/cli": 15.0.1 + "@react-native-community/cli-platform-android": 15.0.1 + "@react-native-community/cli-platform-ios": 15.0.1 "@react-native/babel-preset": 0.76.9 "@react-native/eslint-config": 0.76.9 "@react-native/metro-config": 0.76.9 @@ -10841,9 +10807,6 @@ __metadata: "@babel/plugin-transform-runtime": ^7.25.0 "@babel/preset-env": ^7.25.3 "@babel/runtime": ^7.26.10 - "@react-native-community/cli": 17.0.1 - "@react-native-community/cli-platform-android": 17.0.1 - "@react-native-community/cli-platform-ios": 17.0.1 "@react-native/babel-preset": 0.76.9 "@react-native/eslint-config": 0.76.9 "@react-native/metro-config": 0.76.9 @@ -13714,7 +13677,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": +"iconv-lite@npm:^0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" dependencies: @@ -15587,16 +15550,6 @@ __metadata: languageName: node linkType: hard -"launch-editor@npm:^2.9.1": - version: 2.12.0 - resolution: "launch-editor@npm:2.12.0" - dependencies: - picocolors: ^1.1.1 - shell-quote: ^1.8.3 - checksum: b1aa1b92ef4e720d1edd7f80affb90b2fa1cc2c41641cf80158940698c18a4b6a67e2a7cb060547712e858f0ec1a7c8c39f605e0eb299f516a6184f4e680ffc8 - languageName: node - linkType: hard - "lerna@npm:9.0.0": version: 9.0.0 resolution: "lerna@npm:9.0.0" @@ -16163,13 +16116,6 @@ __metadata: languageName: node linkType: hard -"media-typer@npm:0.3.0": - version: 0.3.0 - resolution: "media-typer@npm:0.3.0" - checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 - languageName: node - linkType: hard - "memoize-one@npm:^5.0.0": version: 5.2.1 resolution: "memoize-one@npm:5.2.1" @@ -16699,7 +16645,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -18701,15 +18647,6 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.13.0": - version: 6.13.0 - resolution: "qs@npm:6.13.0" - dependencies: - side-channel: ^1.0.6 - checksum: e9404dc0fc2849245107108ce9ec2766cde3be1b271de0bf1021d049dc5b98d1a2901e67b431ac5509f865420a7ed80b7acb3980099fe1c118a1c5d2e1432ad8 - languageName: node - linkType: hard - "qs@npm:^6.11.0, qs@npm:^6.7.0": version: 6.14.0 resolution: "qs@npm:6.14.0" @@ -18805,18 +18742,6 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.2": - version: 2.5.2 - resolution: "raw-body@npm:2.5.2" - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 - languageName: node - linkType: hard - "rc@npm:^1.2.8": version: 1.2.8 resolution: "rc@npm:1.2.8" @@ -20245,7 +20170,7 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.6, side-channel@npm:^1.1.0": +"side-channel@npm:^1.1.0": version: 1.1.0 resolution: "side-channel@npm:1.1.0" dependencies: @@ -20819,7 +20744,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^5.0.0": +"strip-ansi@npm:^5.0.0, strip-ansi@npm:^5.2.0": version: 5.2.0 resolution: "strip-ansi@npm:5.2.0" dependencies: @@ -20895,6 +20820,13 @@ __metadata: languageName: node linkType: hard +"sudo-prompt@npm:^9.0.0": + version: 9.2.1 + resolution: "sudo-prompt@npm:9.2.1" + checksum: 50a29eec2f264f2b78d891452a64112d839a30bffbff4ec065dba4af691a35b23cdb8f9107d413e25c1a9f1925644a19994c00602495cab033d53f585fdfd665 + languageName: node + linkType: hard + "superagent@npm:5.1.0": version: 5.1.0 resolution: "superagent@npm:5.1.0" @@ -21461,16 +21393,6 @@ __metadata: languageName: node linkType: hard -"type-is@npm:~1.6.18": - version: 1.6.18 - resolution: "type-is@npm:1.6.18" - dependencies: - media-typer: 0.3.0 - mime-types: ~2.1.24 - checksum: 2c8e47675d55f8b4e404bcf529abdf5036c537a04c2b20177bcf78c9e3c1da69da3942b1346e6edb09e823228c0ee656ef0e033765ec39a70d496ef601a0c657 - languageName: node - linkType: hard - "typed-array-buffer@npm:^1.0.3": version: 1.0.3 resolution: "typed-array-buffer@npm:1.0.3" @@ -21685,7 +21607,7 @@ __metadata: languageName: node linkType: hard -"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": +"unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 From cc544c64d1a317b5a1aa3f6f6793c2ebe4d2c4d8 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Wed, 19 Nov 2025 10:52:22 +0100 Subject: [PATCH 19/62] Add Session Replay support for React Native 0.83 --- .../android/build.gradle | 4 +- .../extensions/ComputedBorderRadiusExt.kt | 27 +++++ .../utils/ReactViewBackgroundDrawableUtils.kt | 103 ++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/extensions/ComputedBorderRadiusExt.kt create mode 100644 packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index afb5f5c09..5851ee598 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -137,7 +137,9 @@ android { java.srcDirs += ['src/oldarch/kotlin'] } - if (reactNativeMinorVersion >= 80) { + if (reactNativeMinorVersion >= 83) { + java.srcDirs += ['src/rn83/kotlin'] + } else if (reactNativeMinorVersion >= 80) { java.srcDirs += ['src/rn80/kotlin'] } else if (reactNativeMinorVersion >= 79) { java.srcDirs += ['src/rn79/kotlin'] diff --git a/packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/extensions/ComputedBorderRadiusExt.kt b/packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/extensions/ComputedBorderRadiusExt.kt new file mode 100644 index 000000000..e7ac00beb --- /dev/null +++ b/packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/extensions/ComputedBorderRadiusExt.kt @@ -0,0 +1,27 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ +package com.datadog.reactnative.sessionreplay.extensions + +import com.facebook.react.uimanager.style.ComputedBorderRadius +import com.facebook.react.uimanager.style.ComputedBorderRadiusProp + +internal fun ComputedBorderRadius?.getAverage(): Float { + val topRightRadius = this + ?.getAverageForProp(ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS) ?: 0f + val topLeftRadius = this + ?.getAverageForProp(ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS) ?: 0f + val bottomRightRadius = this + ?.getAverageForProp(ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS) ?: 0f + val bottomLeftRadius = this + ?.getAverageForProp(ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS) ?: 0f + return (topRightRadius + topLeftRadius + bottomRightRadius + bottomLeftRadius) / 4f +} + +internal fun ComputedBorderRadius?.getAverageForProp(prop: ComputedBorderRadiusProp): Float { + val vertical = this?.get(prop)?.vertical ?: 0f + val horizontal = this?.get(prop)?.vertical ?: 0f + return (vertical + horizontal) / 2f +} diff --git a/packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt b/packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt new file mode 100644 index 000000000..046c9002f --- /dev/null +++ b/packages/react-native-session-replay/android/src/rn83/kotlin/com/datadog/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt @@ -0,0 +1,103 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.ColorFilter +import android.graphics.PixelFormat +import android.graphics.drawable.Drawable +import android.graphics.drawable.InsetDrawable +import android.graphics.drawable.LayerDrawable +import com.datadog.android.sessionreplay.model.MobileSegment +import com.datadog.reactnative.sessionreplay.extensions.getAverage +import com.datadog.reactnative.sessionreplay.utils.DrawableUtils +import com.datadog.reactnative.sessionreplay.utils.formatAsRgba +import com.facebook.react.common.annotations.UnstableReactNativeAPI +import com.facebook.react.uimanager.Spacing +import com.facebook.react.uimanager.style.ComputedBorderRadius + +internal class ReactViewBackgroundDrawableUtils : DrawableUtils() { + /** + * Used to wrap instances of internal class: + * com.facebook.react.uimanager.drawable.BackgroundDrawable + */ + class BackgroundDrawableWrapper( + val backgroundColor: String, + val cornerRadius: Float + ) : Drawable() { + override fun draw(p0: Canvas) {} + override fun setAlpha(p0: Int) {} + override fun setColorFilter(p0: ColorFilter?) {} + @Suppress("OVERRIDE_DEPRECATION") + override fun getOpacity(): Int { return PixelFormat.OPAQUE } + } + + @OptIn(UnstableReactNativeAPI::class) + override fun resolveShapeAndBorder( + drawable: Drawable, + opacity: Float, + pixelDensity: Float + ): Pair { + if (drawable is BackgroundDrawableWrapper) { + return MobileSegment.ShapeStyle( + drawable.backgroundColor, + opacity, + drawable.cornerRadius + ) to null + } + + return null to null + } + + @OptIn(UnstableReactNativeAPI::class) + override fun getReactBackgroundFromDrawable(drawable: Drawable?): Drawable? { + return when(drawable) { + is InsetDrawable -> getReactBackgroundFromDrawable(drawable.drawable) + is LayerDrawable -> getDrawableFromLayerDrawable(drawable) + else -> null + } + } + + @OptIn(UnstableReactNativeAPI::class) + private fun getDrawableFromLayerDrawable(layerDrawable: LayerDrawable): Drawable? { + for (layerNumber in 0 until layerDrawable.numberOfLayers) { + val layer = layerDrawable.getDrawable(layerNumber) + if (layer != null) { + if (layer.javaClass.name == "com.facebook.react.uimanager.drawable.BackgroundDrawable") { + val backgroundColor = getBackgroundColor(layer) ?: Color.TRANSPARENT + val cornerRadius = getComputedBorderRadius(layer)?.getAverage() ?: 0f + return BackgroundDrawableWrapper( + backgroundColor = formatAsRgba(backgroundColor), + cornerRadius = cornerRadius, + ) + } + } + } + return null + } + + private fun getComputedBorderRadius( + drawable: Any + ): ComputedBorderRadius? { + return reflectionUtils.getDeclaredField( + drawable, + COMPUTED_BORDER_RADIUS_FIELD_NAME + ) as? ComputedBorderRadius + } + + private fun getBackgroundColor( + backgroundDrawable: Any + ): Int? { + return reflectionUtils.getDeclaredField( + backgroundDrawable, + BACKGROUND_COLOR_FIELD_NAME + ) as? Int + } + + private companion object { + private const val COMPUTED_BORDER_RADIUS_FIELD_NAME = "computedBorderRadius" + private const val BACKGROUND_COLOR_FIELD_NAME = "backgroundColor" + } +} From 0af85d385ae1213cd0d26e3dc77df2e81e488a87 Mon Sep 17 00:00:00 2001 From: "Xavier F. Gouchet" Date: Mon, 7 Apr 2025 14:55:53 +0200 Subject: [PATCH 20/62] RUM-9023 use session id to sample network traces --- .../distributedTracing/distributedTracing.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx index e529f3cd1..9c4fcbff7 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx @@ -77,7 +77,12 @@ export const generateTracingAttributesWithSampling = ( } const traceId = TracingIdentifier.createTraceId(); - const hash = Number(traceId.id.multiply(knuthFactor).remainder(twoPow64)); + // for a UUID with value aaaaaaaa-bbbb-Mccc-Nddd-1234567890ab + // we use as the input id the last part : 0x1234567890ab + const baseId = rumSessionId + ? BigInt(rumSessionId.split('-')[4], 16) + : traceId.id; + const hash = Number(baseId.multiply(knuthFactor).remainder(twoPow64)); const threshold = (tracingSamplingRate / 100) * Number(twoPow64); const isSampled = hash <= threshold; From 45cc7892dbdd421aaccf4f626cfb15115c9c0cc7 Mon Sep 17 00:00:00 2001 From: "Xavier F. Gouchet" Date: Mon, 28 Apr 2025 13:55:23 +0200 Subject: [PATCH 21/62] RUM-7747 update default tracing sampling rate --- packages/core/ios/Sources/RNDdSdkConfiguration.swift | 2 +- packages/core/src/DdSdkReactNativeConfiguration.tsx | 2 +- .../src/__tests__/DdSdkReactNativeConfiguration.test.ts | 6 +++--- .../sdk/DatadogProvider/__tests__/initialization.test.tsx | 2 +- .../__tests__/FileBasedConfiguration.test.ts | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/core/ios/Sources/RNDdSdkConfiguration.swift b/packages/core/ios/Sources/RNDdSdkConfiguration.swift index a765e9759..66437c481 100644 --- a/packages/core/ios/Sources/RNDdSdkConfiguration.swift +++ b/packages/core/ios/Sources/RNDdSdkConfiguration.swift @@ -194,7 +194,7 @@ extension NSArray { internal struct DefaultConfiguration { static let nativeCrashReportEnabled = false static let sessionSamplingRate = 100.0 - static let resourceTracingSamplingRate = 20.0 + static let resourceTracingSamplingRate = 100.0 static let longTaskThresholdMs = 0.0 static let nativeLongTaskThresholdMs = 200.0 static let nativeViewTracking = false diff --git a/packages/core/src/DdSdkReactNativeConfiguration.tsx b/packages/core/src/DdSdkReactNativeConfiguration.tsx index 158d258eb..9be08fa28 100644 --- a/packages/core/src/DdSdkReactNativeConfiguration.tsx +++ b/packages/core/src/DdSdkReactNativeConfiguration.tsx @@ -109,7 +109,7 @@ export const formatFirstPartyHosts = ( export const DEFAULTS = { nativeCrashReportEnabled: false, sessionSamplingRate: 100.0, - resourceTracingSamplingRate: 20.0, + resourceTracingSamplingRate: 100.0, site: 'US1', longTaskThresholdMs: 0, nativeLongTaskThresholdMs: 200, diff --git a/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts b/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts index 6d9d081af..b1522ef7f 100644 --- a/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts +++ b/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts @@ -51,7 +51,7 @@ describe('DdSdkReactNativeConfiguration', () => { "nativeViewTracking": false, "proxyConfig": undefined, "resourceEventMapper": null, - "resourceTracingSamplingRate": 20, + "resourceTracingSamplingRate": 100, "serviceName": undefined, "sessionSamplingRate": 100, "site": "US1", @@ -79,7 +79,7 @@ describe('DdSdkReactNativeConfiguration', () => { trackInteractions: true, trackResources: true, firstPartyHosts: ['api.com'], - resourceTracingSamplingRate: 100, + resourceTracingSamplingRate: 80, logEventMapper: event => event, errorEventMapper: event => event, resourceEventMapper: event => event, @@ -161,7 +161,7 @@ describe('DdSdkReactNativeConfiguration', () => { "type": "https", }, "resourceEventMapper": [Function], - "resourceTracingSamplingRate": 100, + "resourceTracingSamplingRate": 80, "serviceName": "com.test.app", "sessionSamplingRate": 80, "site": "EU", diff --git a/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx b/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx index 590c34b98..c654cd24b 100644 --- a/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx +++ b/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx @@ -93,7 +93,7 @@ describe('DatadogProvider', () => { "nativeLongTaskThresholdMs": 200, "nativeViewTracking": false, "proxyConfig": undefined, - "resourceTracingSamplingRate": 20, + "resourceTracingSamplingRate": 100, "sampleRate": 100, "serviceName": undefined, "site": "US1", diff --git a/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts b/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts index 523cf67cc..716243e86 100644 --- a/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts +++ b/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts @@ -134,7 +134,7 @@ describe('FileBasedConfiguration', () => { "nativeViewTracking": false, "proxyConfig": undefined, "resourceEventMapper": null, - "resourceTracingSamplingRate": 20, + "resourceTracingSamplingRate": 100, "serviceName": undefined, "sessionSamplingRate": 100, "site": "US1", From 8683f6c297a14ba82f314d9f63cdeb03bf043d50 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Tue, 2 Sep 2025 10:49:34 +0200 Subject: [PATCH 22/62] Remove fatal errors from logs --- .../DdRumErrorTracking.test.tsx | 202 +----------------- .../core/src/logs/__tests__/DdLogs.test.ts | 4 +- .../instrumentation/DdRumErrorTracking.tsx | 41 +--- 3 files changed, 14 insertions(+), 233 deletions(-) diff --git a/packages/core/src/__tests__/rum/instrumentation/DdRumErrorTracking.test.tsx b/packages/core/src/__tests__/rum/instrumentation/DdRumErrorTracking.test.tsx index 7f66bb58e..fc34de5b0 100644 --- a/packages/core/src/__tests__/rum/instrumentation/DdRumErrorTracking.test.tsx +++ b/packages/core/src/__tests__/rum/instrumentation/DdRumErrorTracking.test.tsx @@ -6,17 +6,13 @@ import { NativeModules } from 'react-native'; -import type { - DdNativeLogsType, - DdNativeRumType -} from '../../../nativeModulesTypes'; +import type { DdNativeRumType } from '../../../nativeModulesTypes'; import { DdRumErrorTracking } from '../../../rum/instrumentation/DdRumErrorTracking'; import { BufferSingleton } from '../../../sdk/DatadogProvider/Buffer/BufferSingleton'; jest.mock('../../../utils/jsUtils'); const DdRum = NativeModules.DdRum as DdNativeRumType; -const DdLogs = NativeModules.DdLogs as DdNativeLogsType; let baseErrorHandlerCalled = false; const baseErrorHandler = (error: any, isFatal?: boolean) => { @@ -77,19 +73,6 @@ it('M intercept and send a RUM event W onGlobalError() {no message}', async () = '' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - '[object Object]', - 'Error', - '[object Object]', - 'doSomething() at ./path/to/file.js:67:3', - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onGlobalError() {empty stack trace}', async () => { @@ -119,19 +102,6 @@ it('M intercept and send a RUM event W onGlobalError() {empty stack trace}', asy '' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - '', - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onGlobalError() {Error object}', async () => { @@ -162,19 +132,6 @@ it('M intercept and send a RUM event W onGlobalError() {Error object}', async () '/packages/core/src/__tests__/rum/instrumentation/DdRumErrorTracking.test.tsx' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - expect.stringContaining('Error: Something bad happened'), - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onGlobalError() {CustomError object}', async () => { @@ -209,19 +166,6 @@ it('M intercept and send a RUM event W onGlobalError() {CustomError object}', as '/packages/core/src/__tests__/rum/instrumentation/DdRumErrorTracking.test.tsx' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'CustomError', - 'Something bad happened', - expect.stringContaining('Error: Something bad happened'), - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onGlobalError() {with source file info}', async () => { @@ -254,19 +198,6 @@ it('M intercept and send a RUM event W onGlobalError() {with source file info}', '' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - 'at ./path/to/file.js:1038:57', - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onGlobalError() {with component stack}', async () => { @@ -301,19 +232,6 @@ it('M intercept and send a RUM event W onGlobalError() {with component stack}', '' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - 'doSomething() at ./path/to/file.js:67:3,nestedCall() at ./path/to/file.js:1064:9,root() at ./path/to/index.js:10:1', - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onGlobalError() {with stack}', async () => { @@ -348,19 +266,6 @@ it('M intercept and send a RUM event W onGlobalError() {with stack}', async () = '' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - 'doSomething() at ./path/to/file.js:67:3,nestedCall() at ./path/to/file.js:1064:9,root() at ./path/to/index.js:10:1', - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onGlobalError() {with stacktrace}', async () => { @@ -396,19 +301,6 @@ it('M intercept and send a RUM event W onGlobalError() {with stacktrace}', async ); expect(baseErrorHandlerCalled).toStrictEqual(true); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - 'doSomething() at ./path/to/file.js:67:3,nestedCall() at ./path/to/file.js:1064:9,root() at ./path/to/index.js:10:1', - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M not report error in console handler W onGlobalError() {with console reporting handler}', async () => { @@ -450,19 +342,6 @@ it('M not report error in console handler W onGlobalError() {with console report expect(consoleReportingErrorHandler).toBeCalledTimes(1); expect(baseConsoleErrorCalled).toStrictEqual(false); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - 'doSomething() at ./path/to/file.js:67:3,nestedCall() at ./path/to/file.js:1064:9,root() at ./path/to/index.js:10:1', - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onConsole() {Error with source file info}', async () => { @@ -493,17 +372,6 @@ it('M intercept and send a RUM event W onConsole() {Error with source file info} '' ); expect(baseConsoleErrorCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Oops I did it again! Something bad happened', - 'Error', - 'Oops I did it again! Something bad happened', - 'at ./path/to/file.js:1038:57', - { - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onConsole() {Error with component stack}', async () => { @@ -536,17 +404,6 @@ it('M intercept and send a RUM event W onConsole() {Error with component stack}' '' ); expect(baseConsoleErrorCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Oops I did it again! Something bad happened', - 'Error', - 'Oops I did it again! Something bad happened', - 'doSomething() at ./path/to/file.js:67:3,nestedCall() at ./path/to/file.js:1064:9,root() at ./path/to/index.js:10:1', - { - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onConsole() {message only}', async () => { @@ -571,17 +428,6 @@ it('M intercept and send a RUM event W onConsole() {message only}', async () => '' ); expect(baseConsoleErrorCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - '', - { - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onConsole() {Error with source file and name}', async () => { @@ -613,17 +459,6 @@ it('M intercept and send a RUM event W onConsole() {Error with source file and n '' ); expect(baseConsoleErrorCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Oops I did it again! Something bad happened', - 'CustomConsoleError', - 'Oops I did it again! Something bad happened', - 'at ./path/to/file.js:1038:57', - { - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); describe.each([ @@ -661,17 +496,6 @@ describe.each([ '' ); expect(baseConsoleErrorCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - errorMessage, - 'Error', - errorMessage, - '', - { - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); }); @@ -704,19 +528,6 @@ it('M intercept and send a RUM event W on error() {called from RNErrorHandler}', '/packages/core/src/__tests__/rum/instrumentation/DdRumErrorTracking.test.tsx' ); expect(baseErrorHandlerCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Something bad happened', - 'Error', - 'Something bad happened', - expect.stringContaining('Error: Something bad happened'), - { - '_dd.error.raw': error, - '_dd.error.is_crash': is_fatal, - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); it('M intercept and send a RUM event W onConsole() {called from RNErrorHandler}', async () => { @@ -742,17 +553,6 @@ it('M intercept and send a RUM event W onConsole() {called from RNErrorHandler}' '' ); expect(baseConsoleErrorCalled).toStrictEqual(true); - expect(DdLogs.errorWithError).toHaveBeenCalledTimes(1); - expect(DdLogs.errorWithError).toHaveBeenCalledWith( - 'Oops I did it again!', - 'Error', - 'Oops I did it again!', - '', - { - '_dd.error.source_type': 'react-native', - '_dd.error_log.is_crash': true - } - ); }); /** diff --git a/packages/core/src/logs/__tests__/DdLogs.test.ts b/packages/core/src/logs/__tests__/DdLogs.test.ts index f99280bfe..6a530ec36 100644 --- a/packages/core/src/logs/__tests__/DdLogs.test.ts +++ b/packages/core/src/logs/__tests__/DdLogs.test.ts @@ -225,7 +225,7 @@ describe('DdLogs', () => { console.error('console-error-message'); expect(NativeModules.DdLogs.error).not.toHaveBeenCalled(); expect(InternalLog.log).toHaveBeenCalledWith( - 'error log dropped by log mapper: "console-error-message"', + 'Adding RUM Error “console-error-message”', 'debug' ); @@ -278,7 +278,7 @@ describe('DdLogs', () => { console.error('console-error-message'); expect(NativeModules.DdLogs.error).not.toHaveBeenCalled(); expect(InternalLog.log).toHaveBeenCalledWith( - 'Tracking error log "console-error-message"', + 'Adding RUM Error “console-error-message”', 'debug' ); }); diff --git a/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx b/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx index 04b01290c..5a45bdc65 100644 --- a/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx +++ b/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx @@ -8,7 +8,6 @@ import type { ErrorHandlerCallback } from 'react-native'; import { InternalLog } from '../../InternalLog'; import { SdkVerbosity } from '../../SdkVerbosity'; -import { DdLogs } from '../../logs/DdLogs'; import { getErrorMessage, getErrorStackTrace, @@ -71,8 +70,7 @@ export class DdRumErrorTracking { static onGlobalError = (error: any, isFatal?: boolean): void => { const message = getErrorMessage(error); const stacktrace = getErrorStackTrace(error); - const errorName = getErrorName(error); - this.reportError(message, ErrorSource.SOURCE, stacktrace, errorName, { + this.reportError(message, ErrorSource.SOURCE, stacktrace, { '_dd.error.is_crash': isFatal, '_dd.error.raw': error }).then(async () => { @@ -131,39 +129,22 @@ export class DdRumErrorTracking { }) .join(' '); - this.reportError(message, ErrorSource.CONSOLE, stack, errorName).then( - () => { - DdRumErrorTracking.defaultConsoleError.apply(console, params); - } - ); + this.reportError(message, ErrorSource.CONSOLE, stack).then(() => { + DdRumErrorTracking.defaultConsoleError.apply(console, params); + }); }; private static reportError = ( message: string, source: ErrorSource, stacktrace: string, - errorName: string, context: object = {} - ): Promise<[void, void]> => { - return Promise.all([ - DdRum.addError( - message, - source, - stacktrace, - getErrorContext(context) - ), - DdLogs.error( - message, - errorName, - message, - stacktrace, - { - ...context, - '_dd.error_log.is_crash': true - }, - undefined, - source - ) - ]); + ): Promise => { + return DdRum.addError( + message, + source, + stacktrace, + getErrorContext(context) + ); }; } From 17bb3b8ce2441f4c8e2cc483a9101ba769797c1b Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Tue, 2 Sep 2025 17:06:28 +0200 Subject: [PATCH 23/62] Improve module wrapper singleton creation --- packages/core/src/logs/DdLogs.ts | 4 +- packages/core/src/rum/DdRum.ts | 5 +- packages/core/src/trace/DdTrace.ts | 10 ++- .../utils/__tests__/singletonUtils.test.ts | 75 +++++++++++++++++++ packages/core/src/utils/singletonUtils.ts | 12 +++ 5 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 packages/core/src/utils/__tests__/singletonUtils.test.ts create mode 100644 packages/core/src/utils/singletonUtils.ts diff --git a/packages/core/src/logs/DdLogs.ts b/packages/core/src/logs/DdLogs.ts index 9ac35fa73..e00e4fc0d 100644 --- a/packages/core/src/logs/DdLogs.ts +++ b/packages/core/src/logs/DdLogs.ts @@ -10,6 +10,7 @@ import type { DdNativeLogsType } from '../nativeModulesTypes'; import { DdAttributes } from '../rum/DdAttributes'; import type { ErrorSource } from '../rum/types'; import { validateContext } from '../utils/argsUtils'; +import { getGlobalInstance } from '../utils/singletonUtils'; import { generateEventMapper } from './eventMapper'; import type { @@ -21,6 +22,7 @@ import type { RawLogWithError } from './types'; +const LOGS_MODULE = 'com.datadog.reactnative.logs'; const SDK_NOT_INITIALIZED_MESSAGE = 'DD_INTERNAL_LOG_SENT_BEFORE_SDK_INIT'; const generateEmptyPromise = () => new Promise(resolve => resolve()); @@ -240,4 +242,4 @@ class DdLogsWrapper implements DdLogsType { } } -export const DdLogs = new DdLogsWrapper(); +export const DdLogs = getGlobalInstance(LOGS_MODULE, () => new DdLogsWrapper()); diff --git a/packages/core/src/rum/DdRum.ts b/packages/core/src/rum/DdRum.ts index cbd06f4fe..fdc7a2ec8 100644 --- a/packages/core/src/rum/DdRum.ts +++ b/packages/core/src/rum/DdRum.ts @@ -13,6 +13,7 @@ import { DdSdk } from '../sdk/DdSdk'; import { GlobalState } from '../sdk/GlobalState/GlobalState'; import { validateContext } from '../utils/argsUtils'; import { getErrorContext } from '../utils/errorUtils'; +import { getGlobalInstance } from '../utils/singletonUtils'; import { DefaultTimeProvider } from '../utils/time-provider/DefaultTimeProvider'; import type { TimeProvider } from '../utils/time-provider/TimeProvider'; @@ -44,6 +45,8 @@ import type { PropagatorType } from './types'; +const RUM_MODULE = 'com.datadog.reactnative.rum'; + const generateEmptyPromise = () => new Promise(resolve => resolve()); class DdRumWrapper implements DdRumType { @@ -503,4 +506,4 @@ const isOldStopActionAPI = ( return typeof args[0] === 'object' || typeof args[0] === 'undefined'; }; -export const DdRum = new DdRumWrapper(); +export const DdRum = getGlobalInstance(RUM_MODULE, () => new DdRumWrapper()); diff --git a/packages/core/src/trace/DdTrace.ts b/packages/core/src/trace/DdTrace.ts index b106a97d8..119716914 100644 --- a/packages/core/src/trace/DdTrace.ts +++ b/packages/core/src/trace/DdTrace.ts @@ -13,8 +13,11 @@ import { } from '../sdk/DatadogProvider/Buffer/bufferNativeCall'; import type { DdTraceType } from '../types'; import { validateContext } from '../utils/argsUtils'; +import { getGlobalInstance } from '../utils/singletonUtils'; import { DefaultTimeProvider } from '../utils/time-provider/DefaultTimeProvider'; +const TRACE_MODULE = 'com.datadog.reactnative.trace'; + const timeProvider = new DefaultTimeProvider(); class DdTraceWrapper implements DdTraceType { @@ -59,6 +62,7 @@ class DdTraceWrapper implements DdTraceType { }; } -const DdTrace: DdTraceType = new DdTraceWrapper(); - -export { DdTrace }; +export const DdTrace: DdTraceType = getGlobalInstance( + TRACE_MODULE, + () => new DdTraceWrapper() +); diff --git a/packages/core/src/utils/__tests__/singletonUtils.test.ts b/packages/core/src/utils/__tests__/singletonUtils.test.ts new file mode 100644 index 000000000..f424562c6 --- /dev/null +++ b/packages/core/src/utils/__tests__/singletonUtils.test.ts @@ -0,0 +1,75 @@ +import { getGlobalInstance } from '../singletonUtils'; + +describe('singletonUtils', () => { + const createdSymbols: symbol[] = []; + const g = (globalThis as unknown) as Record; + + afterEach(() => { + for (const symbol of createdSymbols) { + delete g[symbol]; + } + + createdSymbols.length = 0; + jest.restoreAllMocks(); + }); + + it('only creates one instance for the same key', () => { + const key = 'com.datadog.reactnative.test'; + const symbol = Symbol.for(key); + createdSymbols.push(symbol); + + const objectConstructor = jest.fn(() => ({ id: 1 })); + const a = getGlobalInstance(key, objectConstructor); + const b = getGlobalInstance(key, objectConstructor); + + expect(a).toBe(b); + expect(objectConstructor).toHaveBeenCalledTimes(1); + expect(g[symbol]).toBe(a); + }); + + it('returns a pre-existing instance without creating a new one for the same key', () => { + const key = 'com.datadog.reactnative.test'; + const symbol = Symbol.for(key); + createdSymbols.push(symbol); + + const existing = { pre: true }; + g[symbol] = existing; + + const objectConstructor = jest.fn(() => ({ created: true })); + const result = getGlobalInstance(key, objectConstructor); + + expect(result).toBe(existing); + expect(objectConstructor).not.toHaveBeenCalled(); + }); + + it('creates a new instance for a different key', () => { + const keyA = 'com.datadog.reactnative.test.a'; + const keyB = 'com.datadog.reactnative.test.b'; + const symbolA = Symbol.for(keyA); + const symbolB = Symbol.for(keyB); + createdSymbols.push(symbolA, symbolB); + + const a = getGlobalInstance(keyA, () => ({ id: 'A' })); + const b = getGlobalInstance(keyB, () => ({ id: 'B' })); + + expect(a).not.toBe(b); + expect((a as any).id).toBe('A'); + expect((b as any).id).toBe('B'); + }); + + it('does not overwrite existing instance if called with a different constructor', () => { + const key = 'com.datadog.reactnative.test'; + const symbol = Symbol.for(key); + createdSymbols.push(symbol); + + const firstObjectConstructor = jest.fn(() => ({ id: 1 })); + const first = getGlobalInstance(key, firstObjectConstructor); + + const secondObjectConstructor = jest.fn(() => ({ id: 2 })); + const second = getGlobalInstance(key, secondObjectConstructor); + + expect(first).toBe(second); + expect(firstObjectConstructor).toHaveBeenCalledTimes(1); + expect(secondObjectConstructor).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/core/src/utils/singletonUtils.ts b/packages/core/src/utils/singletonUtils.ts new file mode 100644 index 000000000..9f00c2cd0 --- /dev/null +++ b/packages/core/src/utils/singletonUtils.ts @@ -0,0 +1,12 @@ +export const getGlobalInstance = ( + key: string, + objectConstructor: () => T +): T => { + const symbol = Symbol.for(key); + const g = (globalThis as unknown) as Record; + + if (!(symbol in g)) { + g[symbol] = objectConstructor(); + } + return g[symbol] as T; +}; From a957186978690997186f8f8d02aa27d98318a1b3 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 5 Sep 2025 17:47:29 +0200 Subject: [PATCH 24/62] Use native sdk's core instance instead of the one inside RN SDK wrapper --- .../datadog/reactnative/DatadogSDKWrapper.kt | 90 +------------------ .../com/datadog/reactnative/DatadogWrapper.kt | 48 ---------- .../reactnative/DdLogsImplementation.kt | 3 +- .../reactnative/DdSdkImplementation.kt | 9 +- .../reactnative/DdSdkNativeInitialization.kt | 13 ++- .../reactnative/DdSdkReactNativePackage.kt | 3 +- .../com/datadog/reactnative/DdTelemetry.kt | 56 ++++++++++++ .../kotlin/com/datadog/reactnative/DdSdk.kt | 3 +- .../kotlin/com/datadog/reactnative/DdSdk.kt | 5 +- .../DdSdkNativeInitializationTest.kt | 4 + .../com/datadog/reactnative/DdSdkTest.kt | 6 +- .../DdInternalTestingImplementation.kt | 2 +- .../DdInternalTestingImplementationTest.kt | 74 ++++++++------- .../DdSessionReplayImplementation.kt | 8 +- 14 files changed, 140 insertions(+), 184 deletions(-) create mode 100644 packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt index c9865a5d7..da0841ac4 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt @@ -8,23 +8,14 @@ package com.datadog.reactnative import android.content.Context -import android.util.Log import com.datadog.android.Datadog -import com.datadog.android._InternalProxy import com.datadog.android.api.InternalLogger -import com.datadog.android.api.SdkCore import com.datadog.android.api.feature.FeatureSdkCore import com.datadog.android.core.InternalSdkCore import com.datadog.android.core.configuration.Configuration -import com.datadog.android.log.Logs -import com.datadog.android.log.LogsConfiguration import com.datadog.android.privacy.TrackingConsent import com.datadog.android.rum.GlobalRumMonitor -import com.datadog.android.rum.Rum -import com.datadog.android.rum.RumConfiguration import com.datadog.android.rum.RumMonitor -import com.datadog.android.trace.Trace -import com.datadog.android.trace.TraceConfiguration import com.datadog.android.webview.WebViewTracking import com.facebook.react.bridge.ReadableMap @@ -50,50 +41,18 @@ object DatadogSDKWrapperStorage { listener(ddCore) } } - - /** - * Sets instance of core SDK to be used to initialize features. - */ - fun setSdkCore(core: InternalSdkCore?) { - this.core = core - } - - /** - * Returns the core set by setSdkCore or the default core instance by default. - */ - fun getSdkCore(): SdkCore { - core?.let { - return it - } - Log.d( - DatadogSDKWrapperStorage::class.java.canonicalName, - "SdkCore was not set in DatadogSDKWrapperStorage, using default instance." - ) - return Datadog.getInstance() - } } internal class DatadogSDKWrapper : DatadogWrapper { override var bundleLogsWithRum = DefaultConfiguration.bundleLogsWithRum override var bundleLogsWithTraces = DefaultConfiguration.bundleLogsWithTraces - // We use Kotlin backing field here to initialize once the telemetry proxy - // and make sure it is only after SDK is initialized. - private var telemetryProxy: _InternalProxy._TelemetryProxy? = null - get() { - if (field == null && isInitialized()) { - field = Datadog._internalProxy()._telemetry - } - - return field - } - // We use Kotlin backing field here to initialize once the telemetry proxy // and make sure it is only after SDK is initialized. private var webViewProxy: WebViewTracking._InternalWebViewProxy? = null get() { if (field == null && isInitialized()) { - field = WebViewTracking._InternalWebViewProxy(DatadogSDKWrapperStorage.getSdkCore()) + field = WebViewTracking._InternalWebViewProxy(Datadog.getInstance()) } return field @@ -109,20 +68,7 @@ internal class DatadogSDKWrapper : DatadogWrapper { consent: TrackingConsent ) { val core = Datadog.initialize(context, configuration, consent) - DatadogSDKWrapperStorage.setSdkCore(core as InternalSdkCore) - DatadogSDKWrapperStorage.notifyOnInitializedListeners(core) - } - - override fun enableRum(configuration: RumConfiguration) { - Rum.enable(configuration, DatadogSDKWrapperStorage.getSdkCore()) - } - - override fun enableLogs(configuration: LogsConfiguration) { - Logs.enable(configuration, DatadogSDKWrapperStorage.getSdkCore()) - } - - override fun enableTrace(configuration: TraceConfiguration) { - Trace.enable(configuration, DatadogSDKWrapperStorage.getSdkCore()) + DatadogSDKWrapperStorage.notifyOnInitializedListeners(core as InternalSdkCore) } @Deprecated("Use setUserInfo instead; the user ID is now required.") @@ -161,34 +107,6 @@ internal class DatadogSDKWrapper : DatadogWrapper { Datadog.setTrackingConsent(trackingConsent) } - override fun sendTelemetryLog(message: String, attributes: ReadableMap, config: ReadableMap) { - val core = DatadogSDKWrapperStorage.getSdkCore() as FeatureSdkCore? - val logger = core?.internalLogger; - - val additionalProperties = attributes.toMap() - val telemetryConfig = config.toMap() - - logger?.log( - level = InternalLogger.Level.INFO, - target = InternalLogger.Target.TELEMETRY, - messageBuilder = { message }, - onlyOnce = (telemetryConfig["onlyOnce"] as? Boolean) ?: true, - additionalProperties = additionalProperties - ) - } - - override fun telemetryDebug(message: String) { - telemetryProxy?.debug(message) - } - - override fun telemetryError(message: String, stack: String?, kind: String?) { - telemetryProxy?.error(message, stack, kind) - } - - override fun telemetryError(message: String, throwable: Throwable?) { - telemetryProxy?.error(message, throwable) - } - override fun consumeWebviewEvent(message: String) { webViewProxy?.consumeWebviewEvent(message) } @@ -198,11 +116,11 @@ internal class DatadogSDKWrapper : DatadogWrapper { } override fun getRumMonitor(): RumMonitor { - return GlobalRumMonitor.get(DatadogSDKWrapperStorage.getSdkCore()) + return GlobalRumMonitor.get(Datadog.getInstance()) } override fun clearAllData() { - return Datadog.clearAllData(DatadogSDKWrapperStorage.getSdkCore()) + return Datadog.clearAllData(Datadog.getInstance()) } } diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt index 41e86f4d5..9ac591d80 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt @@ -64,33 +64,6 @@ interface DatadogWrapper { consent: TrackingConsent ) - /** - * Enables the RUM feature of the SDK. - * - * @param configuration the configuration for the RUM feature - */ - fun enableRum( - configuration: RumConfiguration - ) - - /** - * Enables the Logs feature of the SDK. - * - * @param configuration the configuration for the Logs feature - */ - fun enableLogs( - configuration: LogsConfiguration - ) - - /** - * Enables the Trace feature of the SDK. - * - * @param configuration the configuration for the Trace feature - */ - fun enableTrace( - configuration: TraceConfiguration - ) - /** * Sets the user information. * @@ -144,27 +117,6 @@ interface DatadogWrapper { */ fun setTrackingConsent(trackingConsent: TrackingConsent) - - /** - * Sends telemetry event with attributes. - */ - fun sendTelemetryLog(message: String, attributes: ReadableMap, config: ReadableMap) - - /** - * Sends telemetry debug event. - */ - fun telemetryDebug(message: String) - - /** - * Sends telemetry error. - */ - fun telemetryError(message: String, stack: String?, kind: String?) - - /** - * Sends telemetry error. - */ - fun telemetryError(message: String, throwable: Throwable?) - /** * Sends Webview events. */ diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdLogsImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdLogsImplementation.kt index 9a84496ec..2f9bceff2 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdLogsImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdLogsImplementation.kt @@ -7,6 +7,7 @@ package com.datadog.reactnative import android.util.Log as AndroidLog +import com.datadog.android.Datadog import com.datadog.android.log.Logger import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReadableMap @@ -22,7 +23,7 @@ class DdLogsImplementation( val bundleLogsWithRum = datadog.bundleLogsWithRum val bundleLogsWithTraces = datadog.bundleLogsWithTraces - logger ?: Logger.Builder(DatadogSDKWrapperStorage.getSdkCore()) + logger ?: Logger.Builder(Datadog.getInstance()) .setLogcatLogsEnabled(true) .setBundleWithRumEnabled(bundleLogsWithRum) .setBundleWithTraceEnabled(bundleLogsWithTraces) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index cdd6b0614..b04a2ddf3 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicBoolean class DdSdkImplementation( private val reactContext: ReactApplicationContext, private val datadog: DatadogWrapper = DatadogSDKWrapper(), + private val ddTelemetry: DdTelemetry = DdTelemetry(), private val uiThreadExecutor: UiThreadExecutor = ReactUiThreadExecutor() ) { internal val appContext: Context = reactContext.applicationContext @@ -39,7 +40,7 @@ class DdSdkImplementation( fun initialize(configuration: ReadableMap, promise: Promise) { val ddSdkConfiguration = configuration.asDdSdkConfiguration() - val nativeInitialization = DdSdkNativeInitialization(appContext, datadog) + val nativeInitialization = DdSdkNativeInitialization(appContext, datadog, ddTelemetry) nativeInitialization.initialize(ddSdkConfiguration) this.frameRateProvider = createFrameRateProvider(ddSdkConfiguration) @@ -145,7 +146,7 @@ class DdSdkImplementation( * @param config Configuration object, can take 'onlyOnce: Boolean' */ fun sendTelemetryLog(message: String, attributes: ReadableMap, config: ReadableMap, promise: Promise) { - datadog.sendTelemetryLog(message, attributes, config) + ddTelemetry.sendTelemetryLog(message, attributes, config) promise.resolve(null) } @@ -154,7 +155,7 @@ class DdSdkImplementation( * @param message Debug message. */ fun telemetryDebug(message: String, promise: Promise) { - datadog.telemetryDebug(message) + ddTelemetry.telemetryDebug(message) promise.resolve(null) } @@ -165,7 +166,7 @@ class DdSdkImplementation( * @param kind Error kind. */ fun telemetryError(message: String, stack: String, kind: String, promise: Promise) { - datadog.telemetryError(message, stack, kind) + ddTelemetry.telemetryError(message, stack, kind) promise.resolve(null) } diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt index 9c8e8370d..ee55d08fe 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt @@ -9,14 +9,17 @@ package com.datadog.reactnative import android.content.Context import android.content.pm.PackageManager import android.util.Log +import com.datadog.android.Datadog import com.datadog.android.DatadogSite import com.datadog.android.core.configuration.BatchProcessingLevel import com.datadog.android.core.configuration.BatchSize import com.datadog.android.core.configuration.Configuration import com.datadog.android.core.configuration.UploadFrequency import com.datadog.android.event.EventMapper +import com.datadog.android.log.Logs import com.datadog.android.log.LogsConfiguration import com.datadog.android.privacy.TrackingConsent +import com.datadog.android.rum.Rum import com.datadog.android.rum.RumConfiguration import com.datadog.android.rum._RumInternalProxy import com.datadog.android.rum.configuration.VitalsUpdateFrequency @@ -25,6 +28,7 @@ import com.datadog.android.rum.model.ActionEvent import com.datadog.android.rum.model.ResourceEvent import com.datadog.android.rum.tracking.ActivityViewTrackingStrategy import com.datadog.android.telemetry.model.TelemetryConfigurationEvent +import com.datadog.android.trace.Trace import com.datadog.android.trace.TraceConfiguration import com.google.gson.Gson import java.util.Locale @@ -37,6 +41,7 @@ import kotlin.time.Duration.Companion.seconds class DdSdkNativeInitialization internal constructor( private val appContext: Context, private val datadog: DatadogWrapper = DatadogSDKWrapper(), + private val ddTelemetry: DdTelemetry = DdTelemetry(), private val jsonFileReader: JSONFileReader = JSONFileReader() ) { internal fun initialize(ddSdkConfiguration: DdSdkConfiguration) { @@ -59,11 +64,11 @@ class DdSdkNativeInitialization internal constructor( datadog.initialize(appContext, sdkConfiguration, trackingConsent) - datadog.enableRum(rumConfiguration) + Rum.enable(rumConfiguration, Datadog.getInstance()) - datadog.enableTrace(traceConfiguration) + Logs.enable(logsConfiguration, Datadog.getInstance()) - datadog.enableLogs(logsConfiguration) + Trace.enable(traceConfiguration, Datadog.getInstance()) } private fun configureRumAndTracesForLogs(configuration: DdSdkConfiguration) { @@ -95,7 +100,7 @@ class DdSdkNativeInitialization internal constructor( try { appContext.packageManager.getPackageInfo(packageName, 0) } catch (e: PackageManager.NameNotFoundException) { - datadog.telemetryError(e.message ?: DdSdkImplementation.PACKAGE_INFO_NOT_FOUND_ERROR_MESSAGE, e) + ddTelemetry.telemetryError(e.message ?: DdSdkImplementation.PACKAGE_INFO_NOT_FOUND_ERROR_MESSAGE, e) return DdSdkImplementation.DEFAULT_APP_VERSION } diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkReactNativePackage.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkReactNativePackage.kt index bac9f49f5..3a5b022c1 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkReactNativePackage.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkReactNativePackage.kt @@ -18,9 +18,10 @@ import com.facebook.react.module.model.ReactModuleInfoProvider */ class DdSdkReactNativePackage : TurboReactPackage() { private val sdkWrapper = DatadogSDKWrapper() + private val ddTelemetry = DdTelemetry() override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { return when (name) { - DdSdkImplementation.NAME -> DdSdk(reactContext, sdkWrapper) + DdSdkImplementation.NAME -> DdSdk(reactContext, sdkWrapper, ddTelemetry) DdRumImplementation.NAME -> DdRum(reactContext, sdkWrapper) DdTraceImplementation.NAME -> DdTrace(reactContext) DdLogsImplementation.NAME -> DdLogs(reactContext, sdkWrapper) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt new file mode 100644 index 000000000..2d60df004 --- /dev/null +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt @@ -0,0 +1,56 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.reactnative + +import com.datadog.android.Datadog +import com.datadog.android._InternalProxy +import com.datadog.android.api.InternalLogger +import com.datadog.android.api.feature.FeatureSdkCore +import com.facebook.react.bridge.ReadableMap + +class DdTelemetry { + + // We use Kotlin backing field here to initialize once the telemetry proxy + // and make sure it is only after SDK is initialized. + private var telemetryProxy: _InternalProxy._TelemetryProxy? = null + get() { + if (field == null && Datadog.isInitialized()) { + field = Datadog._internalProxy()._telemetry + } + + return field + } + + fun sendTelemetryLog(message: String, attributes: ReadableMap, config: ReadableMap) { + val core = Datadog.getInstance() as FeatureSdkCore? + val logger = core?.internalLogger; + + val additionalProperties = attributes.toMap() + val telemetryConfig = config.toMap() + + logger?.log( + level = InternalLogger.Level.INFO, + target = InternalLogger.Target.TELEMETRY, + messageBuilder = { message }, + onlyOnce = (telemetryConfig["onlyOnce"] as? Boolean) ?: true, + additionalProperties = additionalProperties + ) + } + + fun telemetryDebug(message: String) { + telemetryProxy?.debug(message) + } + + fun telemetryError(message: String, stack: String?, kind: String?) { + telemetryProxy?.error(message, stack, kind) + } + + fun telemetryError(message: String, throwable: Throwable?) { + telemetryProxy?.error(message, throwable) + } +} + diff --git a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt index d46e53ade..5bc470947 100644 --- a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -19,9 +19,10 @@ import com.facebook.react.modules.core.DeviceEventManagerModule class DdSdk( reactContext: ReactApplicationContext, datadogWrapper: DatadogWrapper = DatadogSDKWrapper() + ddTelemetry: DdTelemetry = DdTelemetry() ) : NativeDdSdkSpec(reactContext) { - private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper) + private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper, ddTelemetry) override fun getName(): String = DdSdkImplementation.NAME diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index b41eff1db..af8f87c29 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -17,10 +17,11 @@ import com.facebook.react.bridge.ReadableMap /** The entry point to initialize Datadog's features. */ class DdSdk( reactContext: ReactApplicationContext, - datadogWrapper: DatadogWrapper = DatadogSDKWrapper() + datadogWrapper: DatadogWrapper = DatadogSDKWrapper(), + ddTelemetry: DdTelemetry = DdTelemetry() ) : ReactContextBaseJavaModule(reactContext) { - private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper) + private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper, ddTelemetry) private var lifecycleEventListener: LifecycleEventListener? = null override fun getName(): String = DdSdkImplementation.NAME diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkNativeInitializationTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkNativeInitializationTest.kt index d05d43c57..e25bfe999 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkNativeInitializationTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkNativeInitializationTest.kt @@ -48,6 +48,9 @@ internal class DdSdkNativeInitializationTest { @Mock lateinit var mockDatadog: DatadogWrapper + @Mock + lateinit var mockDdTelemetry: DdTelemetry + @Mock lateinit var mockJSONFileReader: JSONFileReader @@ -64,6 +67,7 @@ internal class DdSdkNativeInitializationTest { testedNativeInitialization = DdSdkNativeInitialization( mockContext, mockDatadog, + mockDdTelemetry, mockJSONFileReader ) } diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index 5cda53616..9e7d671fd 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -120,6 +120,9 @@ internal class DdSdkTest { @Mock lateinit var mockDatadog: DatadogWrapper + @Mock + lateinit var mockDdTelemetry: DdTelemetry + @Forgery lateinit var fakeConfiguration: DdSdkConfiguration @@ -157,9 +160,8 @@ internal class DdSdkTest { answer.getArgument(0).run() true } - testedBridgeSdk = DdSdkImplementation(mockReactContext, mockDatadog, TestUiThreadExecutor()) + testedBridgeSdk = DdSdkImplementation(mockReactContext, mockDatadog, mockDdTelemetry, TestUiThreadExecutor()) - DatadogSDKWrapperStorage.setSdkCore(null) DatadogSDKWrapperStorage.onInitializedListeners.clear() } diff --git a/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt b/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt index 197a9df75..df0030fb5 100644 --- a/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt +++ b/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt @@ -7,6 +7,7 @@ package com.datadog.reactnative.internaltesting import com.datadog.android.api.InternalLogger +import com.datadog.android.Datadog import com.datadog.android.api.context.DatadogContext import com.datadog.android.api.context.NetworkInfo import com.datadog.android.api.context.TimeInfo @@ -53,7 +54,6 @@ class DdInternalTestingImplementation { fun enable(promise: Promise) { DatadogSDKWrapperStorage.addOnInitializedListener { ddCore -> this.wrappedCore = StubSDKCore(ddCore) - DatadogSDKWrapperStorage.setSdkCore(this.wrappedCore) } promise.resolve(null) } diff --git a/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt b/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt index 6c278026a..c542ed6bc 100644 --- a/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt +++ b/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt @@ -7,6 +7,8 @@ package com.datadog.reactnative.internaltesting import android.content.Context +import com.datadog.android.Datadog +import com.datadog.android.api.SdkCore import com.datadog.android.api.context.DatadogContext import com.datadog.android.api.feature.Feature import com.datadog.android.api.feature.FeatureScope @@ -24,6 +26,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.Extensions import org.mockito.Mock +import org.mockito.Mockito import org.mockito.Mockito.mock import org.mockito.junit.jupiter.MockitoExtension import org.mockito.junit.jupiter.MockitoSettings @@ -57,37 +60,47 @@ internal class DdInternalTestingImplementationTest { @Test fun `M return captured events W enable()`() { - // Given - val mockFeature = MockFeature("mockFeature") - val mockFeatureScope = MockFeatureScope(mockFeature) - whenever(mockCore.getFeature(mockFeature.name)).doReturn( - mockFeatureScope - ) - whenever(mockCore.getDatadogContext()).doReturn( - mockContext - ) - - // When - testedInternalTesting.enable(mockPromise) - // Simulating DdSdkImplementation initialization - DatadogSDKWrapperStorage.setSdkCore(mockCore) - DatadogSDKWrapperStorage.notifyOnInitializedListeners(mockCore) - - val wrappedCore = DatadogSDKWrapperStorage.getSdkCore() as StubSDKCore - wrappedCore.registerFeature(mockFeature) - requireNotNull(wrappedCore.getFeature(mockFeature.name)) - .withWriteContext { _, eventBatchWriter -> - eventBatchWriter.write( - RawBatchEvent(data = "mock event for test".toByteArray()), - batchMetadata = null, - eventType = EventType.DEFAULT + Mockito.mockStatic(Datadog::class.java).use { datadogStatic -> + // Given + datadogStatic.`when` { + Datadog.getInstance() + }.thenReturn(mockCore) + + val mockFeature = MockFeature("mockFeature") + val mockFeatureScope = MockFeatureScope(mockFeature) + whenever(mockCore.getFeature(mockFeature.name)).doReturn( + mockFeatureScope + ) + whenever(mockCore.getDatadogContext()).doReturn( + mockContext + ) + + // When + testedInternalTesting.enable(mockPromise) + // Simulating DdSdkImplementation initialization + DatadogSDKWrapperStorage.notifyOnInitializedListeners(mockCore) + + val wrappedCore = Datadog.getInstance() as StubSDKCore + wrappedCore.registerFeature(mockFeature) + requireNotNull(wrappedCore.getFeature(mockFeature.name)) + .withWriteContext { _, eventBatchWriter -> + eventBatchWriter.write( + RawBatchEvent(data = "mock event for test".toByteArray()), + batchMetadata = null, + eventType = EventType.DEFAULT + ) + } + + // Then + assertThat( + wrappedCore.featureScopes[mockFeature.name] + ?.eventsWritten() + ?.first() + ) + .isEqualTo( + "mock event for test" ) - } - - // Then - assertThat(wrappedCore.featureScopes[mockFeature.name]?.eventsWritten()?.first()).isEqualTo( - "mock event for test" - ) + } } } @@ -96,6 +109,7 @@ internal class MockFeatureScope(private val feature: Feature) : FeatureScope { override fun sendEvent(event: Any) {} + @Suppress("UNCHECKED_CAST") override fun unwrap(): T { return feature as T } diff --git a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt index ef5467bc4..cc2fd64dc 100644 --- a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt +++ b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt @@ -7,10 +7,10 @@ package com.datadog.reactnative.sessionreplay import android.annotation.SuppressLint +import com.datadog.android.Datadog import com.datadog.android.api.feature.FeatureSdkCore import com.datadog.android.sessionreplay.SessionReplayConfiguration import com.datadog.android.sessionreplay._SessionReplayInternalProxy -import com.datadog.reactnative.DatadogSDKWrapperStorage import com.datadog.reactnative.sessionreplay.utils.text.TextViewUtils import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactContext @@ -40,7 +40,7 @@ class DdSessionReplayImplementation( startRecordingImmediately: Boolean, promise: Promise ) { - val sdkCore = DatadogSDKWrapperStorage.getSdkCore() as FeatureSdkCore + val sdkCore = Datadog.getInstance() as FeatureSdkCore val logger = sdkCore.internalLogger val textViewUtils = TextViewUtils.create(reactContext, logger) val internalCallback = ReactNativeInternalCallback(reactContext) @@ -68,7 +68,7 @@ class DdSessionReplayImplementation( */ fun startRecording(promise: Promise) { sessionReplayProvider().startRecording( - DatadogSDKWrapperStorage.getSdkCore() as FeatureSdkCore + Datadog.getInstance() as FeatureSdkCore ) promise.resolve(null) } @@ -78,7 +78,7 @@ class DdSessionReplayImplementation( */ fun stopRecording(promise: Promise) { sessionReplayProvider().stopRecording( - DatadogSDKWrapperStorage.getSdkCore() as FeatureSdkCore + Datadog.getInstance() as FeatureSdkCore ) promise.resolve(null) } From a61f2c4ec191c9aee665702c7cf229ff445caf49 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Mon, 22 Sep 2025 16:20:27 +0200 Subject: [PATCH 25/62] Fixed internal testing tools and unit tests --- .../com/datadog/reactnative/DatadogWrapper.kt | 8 +- .../reactnative/DdSdkNativeInitialization.kt | 2 - .../com/datadog/reactnative/DdTelemetry.kt | 40 + .../kotlin/com/datadog/reactnative/DdSdk.kt | 6 +- .../com/datadog/reactnative/DdSdkTest.kt | 2628 ++++++++++------- .../DdInternalTestingImplementation.kt | 6 + .../DdInternalTestingImplementationTest.kt | 4 +- 7 files changed, 1695 insertions(+), 999 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt index 9ac591d80..19b25e587 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt @@ -18,7 +18,7 @@ import com.facebook.react.bridge.ReadableMap import java.lang.IllegalArgumentException /** - * Wrapper around [Datadog]. + * Wrapper around [com.datadog.android.Datadog]. */ @Suppress("ComplexInterface", "TooManyFunctions") interface DatadogWrapper { @@ -49,10 +49,8 @@ interface DatadogWrapper { /** * Initializes the Datadog SDK. * @param context your application context - * @param credentials your organization credentials * @param configuration the configuration for the SDK library - * @param trackingConsent as the initial state of the tracking consent flag. - * @see [Credentials] + * @param consent as the initial state of the tracking consent flag. * @see [Configuration] * @see [TrackingConsent] * @throws IllegalArgumentException if the env name is using illegal characters and your @@ -99,7 +97,7 @@ interface DatadogWrapper { /** * Sets the user information. - * @param extraUserInfo: The additional information. (To set the id, name or email please user setUserInfo). + * @param extraInfo: The additional information. (To set the id, name or email please user setUserInfo). */ fun addUserExtraInfo( extraInfo: Map diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt index ee55d08fe..4388ad5f6 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt @@ -65,9 +65,7 @@ class DdSdkNativeInitialization internal constructor( datadog.initialize(appContext, sdkConfiguration, trackingConsent) Rum.enable(rumConfiguration, Datadog.getInstance()) - Logs.enable(logsConfiguration, Datadog.getInstance()) - Trace.enable(traceConfiguration, Datadog.getInstance()) } diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt index 2d60df004..24354ce78 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTelemetry.kt @@ -12,6 +12,13 @@ import com.datadog.android.api.InternalLogger import com.datadog.android.api.feature.FeatureSdkCore import com.facebook.react.bridge.ReadableMap +/** + * **[INTERNAL USAGE]** + * + * Utility class used by React Native modules to forward telemetry events to the Datadog SDK. + * + * This class is **public only for Datadog internal package visibility** and should not be used. + */ class DdTelemetry { // We use Kotlin backing field here to initialize once the telemetry proxy @@ -25,6 +32,15 @@ class DdTelemetry { return field } + /** + * **[INTERNAL USAGE]** + * + * Sends a telemetry log message with additional attributes and configuration options. + * + * @param message the message to log + * @param attributes additional key–value properties to include in the log + * @param config configuration options for the telemetry log (e.g. `onlyOnce` flag) + */ fun sendTelemetryLog(message: String, attributes: ReadableMap, config: ReadableMap) { val core = Datadog.getInstance() as FeatureSdkCore? val logger = core?.internalLogger; @@ -41,14 +57,38 @@ class DdTelemetry { ) } + /** + * **[INTERNAL USAGE]** + * + * Sends a debug-level telemetry message. + * + * @param message the debug message + */ fun telemetryDebug(message: String) { telemetryProxy?.debug(message) } + /** + * **[INTERNAL USAGE]** + * + * Sends an error-level telemetry message with optional details. + * + * @param message the error message + * @param stack an optional stack trace string + * @param kind an optional error kind or category + */ fun telemetryError(message: String, stack: String?, kind: String?) { telemetryProxy?.error(message, stack, kind) } + /** + * **[INTERNAL USAGE]** + * + * Sends an error-level telemetry message with an attached [Throwable]. + * + * @param message the error message + * @param throwable the throwable associated with the error + */ fun telemetryError(message: String, throwable: Throwable?) { telemetryProxy?.error(message, throwable) } diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index af8f87c29..17acd6d20 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -21,7 +21,11 @@ class DdSdk( ddTelemetry: DdTelemetry = DdTelemetry() ) : ReactContextBaseJavaModule(reactContext) { - private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper, ddTelemetry) + private val implementation = DdSdkImplementation( + reactContext, + datadog = datadogWrapper, + ddTelemetry + ) private var lifecycleEventListener: LifecycleEventListener? = null override fun getName(): String = DdSdkImplementation.NAME diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index 9e7d671fd..a39485dae 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -16,8 +16,10 @@ import com.datadog.android.core.configuration.BatchSize import com.datadog.android.core.configuration.Configuration import com.datadog.android.core.configuration.UploadFrequency import com.datadog.android.event.EventMapper +import com.datadog.android.log.Logs import com.datadog.android.log.LogsConfiguration import com.datadog.android.privacy.TrackingConsent +import com.datadog.android.rum.Rum import com.datadog.android.rum.RumConfiguration import com.datadog.android.rum.RumPerformanceMetric import com.datadog.android.rum._RumInternalProxy @@ -27,6 +29,7 @@ import com.datadog.android.rum.model.ActionEvent import com.datadog.android.rum.model.ResourceEvent import com.datadog.android.rum.tracking.ActivityViewTrackingStrategy import com.datadog.android.telemetry.model.TelemetryConfigurationEvent +import com.datadog.android.trace.Trace import com.datadog.android.trace.TraceConfiguration import com.datadog.android.trace.TracingHeaderType import com.datadog.tools.unit.GenericAssert.Companion.assertThat @@ -160,7 +163,12 @@ internal class DdSdkTest { answer.getArgument(0).run() true } - testedBridgeSdk = DdSdkImplementation(mockReactContext, mockDatadog, mockDdTelemetry, TestUiThreadExecutor()) + testedBridgeSdk = DdSdkImplementation( + mockReactContext, + mockDatadog, + mockDdTelemetry, + TestUiThreadExecutor() + ) DatadogSDKWrapperStorage.onInitializedListeners.clear() } @@ -181,35 +189,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo("crashReportsEnabled", true) - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo("crashReportsEnabled", true) + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -221,75 +243,104 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo("crashReportsEnabled", false) - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo("crashReportsEnabled", false) + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test fun `𝕄 initialize native SDK 𝕎 initialize() {nativeCrashReportEnabled=null}`() { // Given fakeConfiguration = fakeConfiguration.copy(nativeCrashReportEnabled = false, site = null) + val sdkConfigCaptor = argumentCaptor() val rumConfigCaptor = argumentCaptor() val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo("crashReportsEnabled", false) - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo("crashReportsEnabled", false) + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -305,37 +356,50 @@ internal class DdSdkTest { val traceConfigCaptor = argumentCaptor() val expectedRumSampleRate = fakeConfiguration.sampleRate?.toFloat() ?: 100f - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("sampleRate", expectedRumSampleRate) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("sampleRate", expectedRumSampleRate) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -351,37 +415,50 @@ internal class DdSdkTest { val traceConfigCaptor = argumentCaptor() val expectedTelemetrySampleRate = fakeConfiguration.telemetrySampleRate?.toFloat() ?: 20f - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("telemetrySampleRate", expectedTelemetrySampleRate) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("telemetrySampleRate", expectedTelemetrySampleRate) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -397,31 +474,44 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo("additionalConfig", emptyMap()) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo("additionalConfig", emptyMap()) + assertThat(rumConfigCaptor.firstValue) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -432,34 +522,47 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -477,35 +580,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.US1) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.US1) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -520,35 +637,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.US1) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.US1) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -563,35 +694,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.US3) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.US3) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -606,35 +751,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.US5) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.US5) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -649,35 +808,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.US1_FED) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.US1_FED) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -692,35 +865,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.EU1) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.EU1) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -735,35 +922,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.AP1) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.AP1) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -778,35 +979,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) - it.hasFieldEqualTo("site", DatadogSite.AP2) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) - .hasFieldEqualTo("env", fakeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo( - "additionalConfig", - fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + it.hasFieldEqualTo("site", DatadogSite.AP2) + } + .hasFieldEqualTo("clientToken", fakeConfiguration.clientToken) + .hasFieldEqualTo("env", fakeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo( + "additionalConfig", + fakeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", fakeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -822,19 +1037,33 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - eq(TrackingConsent.PENDING) - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + eq(TrackingConsent.PENDING) + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() } } @@ -850,19 +1079,33 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - eq(TrackingConsent.PENDING) - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + eq(TrackingConsent.PENDING) + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() } } @@ -878,19 +1121,33 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - eq(TrackingConsent.GRANTED) - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + eq(TrackingConsent.GRANTED) + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() } } @@ -906,19 +1163,33 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - eq(TrackingConsent.NOT_GRANTED) - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + eq(TrackingConsent.NOT_GRANTED) + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() } } @@ -937,24 +1208,38 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("viewTrackingStrategy", NoOpViewTrackingStrategy) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("viewTrackingStrategy", NoOpViewTrackingStrategy) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -970,24 +1255,38 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("viewTrackingStrategy", ActivityViewTrackingStrategy(false)) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("viewTrackingStrategy", ActivityViewTrackingStrategy(false)) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1003,24 +1302,38 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("userActionTracking", false) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("userActionTracking", false) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1036,24 +1349,38 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("trackFrustrations", true) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("trackFrustrations", true) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1064,29 +1391,44 @@ internal class DdSdkTest { val bridgeConfiguration = configuration.copy( trackFrustrations = false ) + val sdkConfigCaptor = argumentCaptor() val rumConfigCaptor = argumentCaptor() val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("trackFrustrations", false) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("trackFrustrations", false) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1102,24 +1444,39 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("userActionTracking", true) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("userActionTracking", true) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1177,35 +1534,49 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { - it.hasFieldEqualTo("needsClearTextHttp", false) - it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - .hasFieldEqualTo("clientToken", bridgeConfiguration.clientToken) - .hasFieldEqualTo("env", bridgeConfiguration.env) - .hasFieldEqualTo("variant", "") - .hasFieldEqualTo("service", serviceName) - .hasFieldEqualTo( - "additionalConfig", - bridgeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() - ) - assertThat(rumConfigCaptor.firstValue) - .hasFieldEqualTo("applicationId", bridgeConfiguration.applicationId) + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { + it.hasFieldEqualTo("needsClearTextHttp", false) + it.hasFieldEqualTo("firstPartyHostsWithHeaderTypes", emptyMap()) + } + .hasFieldEqualTo("clientToken", bridgeConfiguration.clientToken) + .hasFieldEqualTo("env", bridgeConfiguration.env) + .hasFieldEqualTo("variant", "") + .hasFieldEqualTo("service", serviceName) + .hasFieldEqualTo( + "additionalConfig", + bridgeConfiguration.additionalConfig?.filterValues { it != null }.orEmpty() + ) + assertThat(rumConfigCaptor.firstValue) + .hasFieldEqualTo("applicationId", bridgeConfiguration.applicationId) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1224,31 +1595,45 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { rumConfig -> - rumConfig.hasField("longTaskTrackingStrategy") { longTaskTrackingStrategy -> - longTaskTrackingStrategy - .isInstanceOf( - "com.datadog.android.rum.internal.instrumentation." + - "MainLooperLongTaskStrategy" - ) - .hasFieldEqualTo("thresholdMs", threshold.toLong()) - } + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { rumConfig -> + rumConfig.hasField("longTaskTrackingStrategy") { longTaskTrackingStrategy -> + longTaskTrackingStrategy + .isInstanceOf( + "com.datadog.android.rum.internal.instrumentation." + + "MainLooperLongTaskStrategy" + ) + .hasFieldEqualTo("thresholdMs", threshold.toLong()) + } + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1265,24 +1650,38 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { rumConfig -> - rumConfig.doesNotHaveField("longTaskTrackingStrategy") + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { rumConfig -> + rumConfig.doesNotHaveField("longTaskTrackingStrategy") + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1326,27 +1725,41 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { coreConfig -> - coreConfig.hasFieldEqualTo( - "firstPartyHostsWithHeaderTypes", - tracingHosts + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { coreConfig -> + coreConfig.hasFieldEqualTo( + "firstPartyHostsWithHeaderTypes", + tracingHosts + ) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1385,27 +1798,41 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { coreConfig -> - coreConfig.hasFieldEqualTo( - "firstPartyHostsWithHeaderTypes", - tracingHosts + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { coreConfig -> + coreConfig.hasFieldEqualTo( + "firstPartyHostsWithHeaderTypes", + tracingHosts + ) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1451,27 +1878,41 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { coreConfig -> - coreConfig.hasFieldEqualTo( - "firstPartyHostsWithHeaderTypes", - tracingHosts + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { coreConfig -> + coreConfig.hasFieldEqualTo( + "firstPartyHostsWithHeaderTypes", + tracingHosts + ) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @ParameterizedTest @@ -1490,27 +1931,41 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { coreConfig -> - coreConfig.hasFieldEqualTo( - "uploadFrequency", - expectedUploadFrequency + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { coreConfig -> + coreConfig.hasFieldEqualTo( + "uploadFrequency", + expectedUploadFrequency + ) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @ParameterizedTest @@ -1529,27 +1984,41 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { coreConfig -> - coreConfig.hasFieldEqualTo( - "batchSize", - expectedBatchSize + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { coreConfig -> + coreConfig.hasFieldEqualTo( + "batchSize", + expectedBatchSize + ) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @ParameterizedTest @@ -1568,27 +2037,41 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasField("coreConfig") { coreConfig -> - coreConfig.hasFieldEqualTo( - "batchProcessingLevel", - expectedBatchSize + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(sdkConfigCaptor.firstValue) + .hasField("coreConfig") { coreConfig -> + coreConfig.hasFieldEqualTo( + "batchProcessingLevel", + expectedBatchSize + ) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1606,24 +2089,38 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("backgroundEventTracking", trackBackgroundEvents ?: false) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("backgroundEventTracking", trackBackgroundEvents ?: false) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1639,28 +2136,42 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("vitalsMonitorUpdateFrequency", VitalsUpdateFrequency.RARE) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } + + // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("vitalsMonitorUpdateFrequency", VitalsUpdateFrequency.RARE) + } - argumentCaptor { - verify(mockChoreographer).postFrameCallback(capture()) - assertThat(firstValue).isInstanceOf(FpsFrameCallback::class.java) + argumentCaptor { + verify(mockChoreographer).postFrameCallback(capture()) + assertThat(firstValue).isInstanceOf(FpsFrameCallback::class.java) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() } } @@ -1679,25 +2190,37 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("vitalsMonitorUpdateFrequency", VitalsUpdateFrequency.NEVER) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - verifyNoInteractions(mockChoreographer) + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("vitalsMonitorUpdateFrequency", VitalsUpdateFrequency.NEVER) + } + verifyNoInteractions(mockChoreographer) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1719,41 +2242,56 @@ internal class DdSdkTest { val traceConfigCaptor = argumentCaptor() val frameDurationNs = threshold + frameDurationOverThreshold - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) - - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("vitalsMonitorUpdateFrequency", VitalsUpdateFrequency.AVERAGE) - } - argumentCaptor { - verify(mockChoreographer).postFrameCallback(capture()) - assertThat(firstValue).isInstanceOf(FpsFrameCallback::class.java) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // When - firstValue.doFrame(timestampNs) - firstValue.doFrame(timestampNs + frameDurationNs) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) - // then - verify(mockRumMonitor._getInternal()!!).updatePerformanceMetric( - RumPerformanceMetric.JS_FRAME_TIME, - frameDurationNs.toDouble() - ) - verify(mockRumMonitor._getInternal()!!, never()).addLongTask( - frameDurationNs, - "javascript" - ) + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } + } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo( + "vitalsMonitorUpdateFrequency", + VitalsUpdateFrequency.AVERAGE + ) + } + argumentCaptor { + verify(mockChoreographer).postFrameCallback(capture()) + assertThat(firstValue).isInstanceOf(FpsFrameCallback::class.java) + + // When + firstValue.doFrame(timestampNs) + firstValue.doFrame(timestampNs + frameDurationNs) + + // then + verify(mockRumMonitor._getInternal()!!).updatePerformanceMetric( + RumPerformanceMetric.JS_FRAME_TIME, + frameDurationNs.toDouble() + ) + verify(mockRumMonitor._getInternal()!!, never()).addLongTask( + frameDurationNs, + "javascript" + ) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() } } @@ -1846,25 +2384,37 @@ internal class DdSdkTest { val traceConfigCaptor = argumentCaptor() val defaultTimeBasedIdentifier = TimeBasedInitialResourceIdentifier(100) - // When - testedBridgeSdk.initialize(configuration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(configuration.toReadableJavaOnlyMap(), mockPromise) - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("initialResourceIdentifier", defaultTimeBasedIdentifier) + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("initialResourceIdentifier", defaultTimeBasedIdentifier) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -1884,25 +2434,37 @@ internal class DdSdkTest { thresholdInSeconds.seconds.inWholeMilliseconds ) - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("initialResourceIdentifier", timeBasedIdentifier) + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("initialResourceIdentifier", timeBasedIdentifier) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -1925,28 +2487,42 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(sdkConfigCaptor.firstValue) - .hasFieldEqualTo( - "additionalConfig", - mapOf( - DdSdkImplementation.DD_VERSION_SUFFIX to versionSuffix, - DdSdkImplementation.DD_VERSION to mockPackageInfo.versionName + versionSuffix + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() ) - ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } + } + assertThat(sdkConfigCaptor.firstValue) + .hasFieldEqualTo( + "additionalConfig", + mapOf( + DdSdkImplementation.DD_VERSION_SUFFIX to versionSuffix, + DdSdkImplementation.DD_VERSION to ( + mockPackageInfo.versionName + versionSuffix + ) + ) + ) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -1985,47 +2561,59 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - val configurationMapper = it - .getActualValue>( - "telemetryConfigurationMapper" - ) - val result = configurationMapper.map(telemetryConfigurationEvent)!! - assertThat(result.telemetry.configuration.trackNativeErrors!!).isEqualTo( - trackNativeErrors - ) - assertThat(result.telemetry.configuration.trackCrossPlatformLongTasks!!) - .isEqualTo(false) - assertThat(result.telemetry.configuration.trackLongTask!!) - .isEqualTo(false) - assertThat(result.telemetry.configuration.trackNativeLongTasks!!) - .isEqualTo(false) - - assertThat(result.telemetry.configuration.initializationType!!) - .isEqualTo(initializationType) - assertThat(result.telemetry.configuration.trackInteractions!!) - .isEqualTo(trackInteractions) - assertThat(result.telemetry.configuration.trackErrors!!).isEqualTo(trackErrors) - assertThat(result.telemetry.configuration.trackResources!!) - .isEqualTo(trackNetworkRequests) - assertThat(result.telemetry.configuration.trackNetworkRequests!!) - .isEqualTo(trackNetworkRequests) + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + val configurationMapper = it + .getActualValue>( + "telemetryConfigurationMapper" + ) + val result = configurationMapper.map(telemetryConfigurationEvent)!! + assertThat(result.telemetry.configuration.trackNativeErrors!!).isEqualTo( + trackNativeErrors + ) + assertThat(result.telemetry.configuration.trackCrossPlatformLongTasks!!) + .isEqualTo(false) + assertThat(result.telemetry.configuration.trackLongTask!!) + .isEqualTo(false) + assertThat(result.telemetry.configuration.trackNativeLongTasks!!) + .isEqualTo(false) + + assertThat(result.telemetry.configuration.initializationType!!) + .isEqualTo(initializationType) + assertThat(result.telemetry.configuration.trackInteractions!!) + .isEqualTo(trackInteractions) + assertThat(result.telemetry.configuration.trackErrors!!).isEqualTo(trackErrors) + assertThat(result.telemetry.configuration.trackResources!!) + .isEqualTo(trackNetworkRequests) + assertThat(result.telemetry.configuration.trackNetworkRequests!!) + .isEqualTo(trackNetworkRequests) + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -2042,27 +2630,39 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - val resourceMapper = it - .getActualValue>("resourceEventMapper") - val notDroppedEvent = resourceMapper.map(resourceEvent) - assertThat(notDroppedEvent).isNotNull + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + val resourceMapper = it + .getActualValue>("resourceEventMapper") + val notDroppedEvent = resourceMapper.map(resourceEvent) + assertThat(notDroppedEvent).isNotNull + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -2076,27 +2676,39 @@ internal class DdSdkTest { val traceConfigCaptor = argumentCaptor() resourceEvent.context?.additionalProperties?.put("_dd.resource.drop_resource", true) - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - val resourceMapper = it - .getActualValue>("resourceEventMapper") - val droppedEvent = resourceMapper.map(resourceEvent) - assertThat(droppedEvent).isNull() + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + val resourceMapper = it + .getActualValue>("resourceEventMapper") + val droppedEvent = resourceMapper.map(resourceEvent) + assertThat(droppedEvent).isNull() + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -2113,27 +2725,39 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - val actionMapper = it - .getActualValue>("actionEventMapper") - val notDroppedEvent = actionMapper.map(actionEvent) - assertThat(notDroppedEvent).isNotNull + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + val actionMapper = it + .getActualValue>("actionEventMapper") + val notDroppedEvent = actionMapper.map(actionEvent) + assertThat(notDroppedEvent).isNotNull + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test @@ -2147,27 +2771,39 @@ internal class DdSdkTest { val traceConfigCaptor = argumentCaptor() actionEvent.context?.additionalProperties?.put("_dd.action.drop_action", true) - // When - testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).initialize( - same(mockContext), - sdkConfigCaptor.capture(), - any() - ) - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - val actionMapper = it - .getActualValue>("actionEventMapper") - val droppedEvent = actionMapper.map(actionEvent) - assertThat(droppedEvent).isNull() + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(fakeConfiguration.toReadableJavaOnlyMap(), mockPromise) + + // Then + inOrder(mockDatadog) { + verify(mockDatadog).initialize( + same(mockContext), + sdkConfigCaptor.capture(), + any() + ) + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + val actionMapper = it + .getActualValue>("actionEventMapper") + val droppedEvent = actionMapper.map(actionEvent) + assertThat(droppedEvent).isNull() + } + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } // endregion @@ -2580,24 +3216,36 @@ internal class DdSdkTest { val logsConfigCaptor = argumentCaptor() val traceConfigCaptor = argumentCaptor() - // When - testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) + val rumMock = org.mockito.Mockito.mockStatic(Rum::class.java) + val traceMock = org.mockito.Mockito.mockStatic(Trace::class.java) + val logsMock = org.mockito.Mockito.mockStatic(Logs::class.java) - // Then - inOrder(mockDatadog) { - verify(mockDatadog).enableRum(rumConfigCaptor.capture()) - verify(mockDatadog).enableTrace(traceConfigCaptor.capture()) - verify(mockDatadog).enableLogs(logsConfigCaptor.capture()) - } + try { + rumMock.`when` { Rum.enable(any(), any()) }.then { } + logsMock.`when` { Logs.enable(any(), any()) }.then { } + traceMock.`when` { Trace.enable(any(), any()) }.then { } // When + testedBridgeSdk.initialize(bridgeConfiguration.toReadableJavaOnlyMap(), mockPromise) - assertThat(rumConfigCaptor.firstValue) - .hasField("featureConfiguration") { - it.hasFieldEqualTo("customEndpointUrl", customRumEndpoint) + // Then + inOrder(mockDatadog) { + rumMock.verify { Rum.enable(rumConfigCaptor.capture(), any()) } + traceMock.verify { Trace.enable(traceConfigCaptor.capture(), any()) } + logsMock.verify { Logs.enable(logsConfigCaptor.capture(), any()) } } - assertThat(logsConfigCaptor.firstValue) - .hasFieldEqualTo("customEndpointUrl", customLogsEndpoint) - assertThat(traceConfigCaptor.firstValue) - .hasFieldEqualTo("customEndpointUrl", customTraceEndpoint) + + assertThat(rumConfigCaptor.firstValue) + .hasField("featureConfiguration") { + it.hasFieldEqualTo("customEndpointUrl", customRumEndpoint) + } + assertThat(logsConfigCaptor.firstValue) + .hasFieldEqualTo("customEndpointUrl", customLogsEndpoint) + assertThat(traceConfigCaptor.firstValue) + .hasFieldEqualTo("customEndpointUrl", customTraceEndpoint) + } finally { + rumMock.close() + logsMock.close() + traceMock.close() + } } @Test diff --git a/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt b/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt index df0030fb5..b33bef6de 100644 --- a/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt +++ b/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt @@ -58,6 +58,12 @@ class DdInternalTestingImplementation { promise.resolve(null) } + /** + * Get wrapped core instance. + */ + internal fun getWrappedCore(): StubSDKCore? { + return wrappedCore + } internal companion object { internal const val NAME = "DdInternalTesting" diff --git a/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt b/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt index c542ed6bc..4a6938f9b 100644 --- a/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt +++ b/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt @@ -80,7 +80,9 @@ internal class DdInternalTestingImplementationTest { // Simulating DdSdkImplementation initialization DatadogSDKWrapperStorage.notifyOnInitializedListeners(mockCore) - val wrappedCore = Datadog.getInstance() as StubSDKCore + val wrappedCore = testedInternalTesting.getWrappedCore() + requireNotNull(wrappedCore) + wrappedCore.registerFeature(mockFeature) requireNotNull(wrappedCore.getFeature(mockFeature.name)) .withWriteContext { _, eventBatchWriter -> From 5183c0a8b69ef9570f6dfb80edfa406e9c3b9814 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 5 Sep 2025 15:29:37 +0200 Subject: [PATCH 26/62] Remove type interdependencies between modules --- packages/core/src/{rum => }/DdAttributes.ts | 0 .../src/DdSdkReactNativeConfiguration.tsx | 2 +- .../src/__tests__/DdSdkReactNative.test.tsx | 3 +- packages/core/src/index.tsx | 3 +- packages/core/src/logs/DdLogs.ts | 5 +- .../core/src/logs/__tests__/DdLogs.test.ts | 4 +- .../src/logs/__tests__/eventMapper.test.ts | 2 +- packages/core/src/logs/eventMapper.ts | 3 +- packages/core/src/logs/types.ts | 21 +------- packages/core/src/rum/DdRum.ts | 4 +- packages/core/src/rum/__tests__/DdRum.test.ts | 3 +- .../src/rum/eventMappers/errorEventMapper.ts | 2 +- .../instrumentation/DdRumErrorTracking.tsx | 2 +- packages/core/src/rum/types.ts | 10 +--- packages/core/src/types.tsx | 49 ++++++++++++++++--- 15 files changed, 62 insertions(+), 51 deletions(-) rename packages/core/src/{rum => }/DdAttributes.ts (100%) diff --git a/packages/core/src/rum/DdAttributes.ts b/packages/core/src/DdAttributes.ts similarity index 100% rename from packages/core/src/rum/DdAttributes.ts rename to packages/core/src/DdAttributes.ts diff --git a/packages/core/src/DdSdkReactNativeConfiguration.tsx b/packages/core/src/DdSdkReactNativeConfiguration.tsx index 9be08fa28..44debb2d2 100644 --- a/packages/core/src/DdSdkReactNativeConfiguration.tsx +++ b/packages/core/src/DdSdkReactNativeConfiguration.tsx @@ -7,12 +7,12 @@ import type { ProxyConfiguration } from './ProxyConfiguration'; import type { SdkVerbosity } from './SdkVerbosity'; import { TrackingConsent } from './TrackingConsent'; -import type { LogEventMapper } from './logs/types'; import type { ActionEventMapper } from './rum/eventMappers/actionEventMapper'; import type { ErrorEventMapper } from './rum/eventMappers/errorEventMapper'; import type { ResourceEventMapper } from './rum/eventMappers/resourceEventMapper'; import type { FirstPartyHost } from './rum/types'; import { PropagatorType } from './rum/types'; +import type { LogEventMapper } from './types'; export enum VitalsUpdateFrequency { FREQUENT = 'FREQUENT', diff --git a/packages/core/src/__tests__/DdSdkReactNative.test.tsx b/packages/core/src/__tests__/DdSdkReactNative.test.tsx index 49c0bd1f2..18bf060ce 100644 --- a/packages/core/src/__tests__/DdSdkReactNative.test.tsx +++ b/packages/core/src/__tests__/DdSdkReactNative.test.tsx @@ -17,11 +17,12 @@ import { DdRum } from '../rum/DdRum'; import { DdRumErrorTracking } from '../rum/instrumentation/DdRumErrorTracking'; import { DdRumUserInteractionTracking } from '../rum/instrumentation/interactionTracking/DdRumUserInteractionTracking'; import { DdRumResourceTracking } from '../rum/instrumentation/resourceTracking/DdRumResourceTracking'; -import { ErrorSource, PropagatorType, RumActionType } from '../rum/types'; +import { PropagatorType, RumActionType } from '../rum/types'; import { AttributesSingleton } from '../sdk/AttributesSingleton/AttributesSingleton'; import { DdSdk } from '../sdk/DdSdk'; import { GlobalState } from '../sdk/GlobalState/GlobalState'; import { UserInfoSingleton } from '../sdk/UserInfoSingleton/UserInfoSingleton'; +import { ErrorSource } from '../types'; import type { DdSdkConfiguration } from '../types'; import { version as sdkVersion } from '../version'; diff --git a/packages/core/src/index.tsx b/packages/core/src/index.tsx index 9332354dc..062fecc90 100644 --- a/packages/core/src/index.tsx +++ b/packages/core/src/index.tsx @@ -37,11 +37,12 @@ import { DATADOG_GRAPH_QL_VARIABLES_HEADER } from './rum/instrumentation/resourceTracking/graphql/graphqlHeaders'; import type { FirstPartyHost } from './rum/types'; -import { ErrorSource, PropagatorType, RumActionType } from './rum/types'; +import { PropagatorType, RumActionType } from './rum/types'; import { DatadogProvider } from './sdk/DatadogProvider/DatadogProvider'; import { DdSdk } from './sdk/DdSdk'; import { FileBasedConfiguration } from './sdk/FileBasedConfiguration/FileBasedConfiguration'; import { DdTrace } from './trace/DdTrace'; +import { ErrorSource } from './types'; import { DefaultTimeProvider } from './utils/time-provider/DefaultTimeProvider'; import type { Timestamp } from './utils/time-provider/TimeProvider'; import { TimeProvider } from './utils/time-provider/TimeProvider'; diff --git a/packages/core/src/logs/DdLogs.ts b/packages/core/src/logs/DdLogs.ts index e00e4fc0d..e1936d211 100644 --- a/packages/core/src/logs/DdLogs.ts +++ b/packages/core/src/logs/DdLogs.ts @@ -4,11 +4,11 @@ * Copyright 2016-Present Datadog, Inc. */ +import { DdAttributes } from '../DdAttributes'; import { DATADOG_MESSAGE_PREFIX, InternalLog } from '../InternalLog'; import { SdkVerbosity } from '../SdkVerbosity'; import type { DdNativeLogsType } from '../nativeModulesTypes'; -import { DdAttributes } from '../rum/DdAttributes'; -import type { ErrorSource } from '../rum/types'; +import type { ErrorSource, LogEventMapper } from '../types'; import { validateContext } from '../utils/argsUtils'; import { getGlobalInstance } from '../utils/singletonUtils'; @@ -16,7 +16,6 @@ import { generateEventMapper } from './eventMapper'; import type { DdLogsType, LogArguments, - LogEventMapper, LogWithErrorArguments, NativeLogWithError, RawLogWithError diff --git a/packages/core/src/logs/__tests__/DdLogs.test.ts b/packages/core/src/logs/__tests__/DdLogs.test.ts index 6a530ec36..f7e848a0b 100644 --- a/packages/core/src/logs/__tests__/DdLogs.test.ts +++ b/packages/core/src/logs/__tests__/DdLogs.test.ts @@ -11,9 +11,9 @@ import { DdSdkReactNative } from '../../DdSdkReactNative'; import { InternalLog } from '../../InternalLog'; import { SdkVerbosity } from '../../SdkVerbosity'; import type { DdNativeLogsType } from '../../nativeModulesTypes'; -import { ErrorSource } from '../../rum/types'; +import { ErrorSource } from '../../types'; +import type { LogEventMapper } from '../../types'; import { DdLogs } from '../DdLogs'; -import type { LogEventMapper } from '../types'; jest.mock('../../InternalLog', () => { return { diff --git a/packages/core/src/logs/__tests__/eventMapper.test.ts b/packages/core/src/logs/__tests__/eventMapper.test.ts index 0999a6058..cd505f811 100644 --- a/packages/core/src/logs/__tests__/eventMapper.test.ts +++ b/packages/core/src/logs/__tests__/eventMapper.test.ts @@ -5,7 +5,7 @@ */ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import { ErrorSource } from '../../rum/types'; +import { ErrorSource } from '../../types'; import { formatRawLogToLogEvent } from '../eventMapper'; describe('formatRawLogToLogEvent', () => { diff --git a/packages/core/src/logs/eventMapper.ts b/packages/core/src/logs/eventMapper.ts index 2bbd398cb..eb7b5f22c 100644 --- a/packages/core/src/logs/eventMapper.ts +++ b/packages/core/src/logs/eventMapper.ts @@ -7,10 +7,9 @@ import type { Attributes } from '../sdk/AttributesSingleton/types'; import { EventMapper } from '../sdk/EventMappers/EventMapper'; import type { UserInfo } from '../sdk/UserInfoSingleton/types'; +import type { LogEvent, LogEventMapper } from '../types'; import type { - LogEvent, - LogEventMapper, NativeLog, NativeLogWithError, RawLog, diff --git a/packages/core/src/logs/types.ts b/packages/core/src/logs/types.ts index 9c1b3cb09..18cdbc533 100644 --- a/packages/core/src/logs/types.ts +++ b/packages/core/src/logs/types.ts @@ -4,8 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -import type { ErrorSource } from '../rum/types'; -import type { UserInfo } from '../sdk/UserInfoSingleton/types'; +import type { LogStatus, ErrorSource } from '../types'; /** * The entry point to use Datadog's Logs feature. @@ -75,24 +74,6 @@ export type NativeLogWithError = { fingerprint?: string; }; -export type LogStatus = 'debug' | 'info' | 'warn' | 'error'; - -export type LogEvent = { - message: string; - context: object; - errorKind?: string; - errorMessage?: string; - stacktrace?: string; - fingerprint?: string; - readonly source?: ErrorSource; - // readonly date: number; // TODO: RUMM-2446 & RUMM-2447 - readonly status: LogStatus; - readonly userInfo: UserInfo; - readonly attributes?: object; -}; - -export type LogEventMapper = (logEvent: LogEvent) => LogEvent | null; - export type LogArguments = [message: string, context?: object]; export type LogWithErrorArguments = [ diff --git a/packages/core/src/rum/DdRum.ts b/packages/core/src/rum/DdRum.ts index fdc7a2ec8..b32ab410b 100644 --- a/packages/core/src/rum/DdRum.ts +++ b/packages/core/src/rum/DdRum.ts @@ -5,19 +5,20 @@ */ import type { GestureResponderEvent } from 'react-native'; +import { DdAttributes } from '../DdAttributes'; import { InternalLog } from '../InternalLog'; import { SdkVerbosity } from '../SdkVerbosity'; import type { DdNativeRumType } from '../nativeModulesTypes'; import { bufferVoidNativeCall } from '../sdk/DatadogProvider/Buffer/bufferNativeCall'; import { DdSdk } from '../sdk/DdSdk'; import { GlobalState } from '../sdk/GlobalState/GlobalState'; +import type { ErrorSource } from '../types'; import { validateContext } from '../utils/argsUtils'; import { getErrorContext } from '../utils/errorUtils'; import { getGlobalInstance } from '../utils/singletonUtils'; import { DefaultTimeProvider } from '../utils/time-provider/DefaultTimeProvider'; import type { TimeProvider } from '../utils/time-provider/TimeProvider'; -import { DdAttributes } from './DdAttributes'; import { generateActionEventMapper } from './eventMappers/actionEventMapper'; import type { ActionEventMapper } from './eventMappers/actionEventMapper'; import { generateErrorEventMapper } from './eventMappers/errorEventMapper'; @@ -37,7 +38,6 @@ import { setCachedSessionId } from './sessionId/sessionIdHelper'; import type { - ErrorSource, DdRumType, RumActionType, ResourceKind, diff --git a/packages/core/src/rum/__tests__/DdRum.test.ts b/packages/core/src/rum/__tests__/DdRum.test.ts index 527492891..7e5fc24de 100644 --- a/packages/core/src/rum/__tests__/DdRum.test.ts +++ b/packages/core/src/rum/__tests__/DdRum.test.ts @@ -12,6 +12,7 @@ import { SdkVerbosity } from '../../SdkVerbosity'; import { BufferSingleton } from '../../sdk/DatadogProvider/Buffer/BufferSingleton'; import { DdSdk } from '../../sdk/DdSdk'; import { GlobalState } from '../../sdk/GlobalState/GlobalState'; +import { ErrorSource } from '../../types'; import { DdRum } from '../DdRum'; import type { ActionEventMapper } from '../eventMappers/actionEventMapper'; import type { ErrorEventMapper } from '../eventMappers/errorEventMapper'; @@ -22,7 +23,7 @@ import { TracingIdFormat } from '../instrumentation/resourceTracking/distributed import { TracingIdentifierUtils } from '../instrumentation/resourceTracking/distributedTracing/__tests__/__utils__/TracingIdentifierUtils'; import { setCachedSessionId } from '../sessionId/sessionIdHelper'; import type { FirstPartyHost } from '../types'; -import { ErrorSource, PropagatorType, RumActionType } from '../types'; +import { PropagatorType, RumActionType } from '../types'; import * as TracingContextUtils from './__utils__/TracingHeadersUtils'; diff --git a/packages/core/src/rum/eventMappers/errorEventMapper.ts b/packages/core/src/rum/eventMappers/errorEventMapper.ts index 462754d2c..6630d59a4 100644 --- a/packages/core/src/rum/eventMappers/errorEventMapper.ts +++ b/packages/core/src/rum/eventMappers/errorEventMapper.ts @@ -6,7 +6,7 @@ import type { AdditionalEventDataForMapper } from '../../sdk/EventMappers/EventMapper'; import { EventMapper } from '../../sdk/EventMappers/EventMapper'; -import type { ErrorSource } from '../types'; +import type { ErrorSource } from '../../types'; type RawError = { message: string; diff --git a/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx b/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx index 5a45bdc65..3c3ec9f65 100644 --- a/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx +++ b/packages/core/src/rum/instrumentation/DdRumErrorTracking.tsx @@ -8,6 +8,7 @@ import type { ErrorHandlerCallback } from 'react-native'; import { InternalLog } from '../../InternalLog'; import { SdkVerbosity } from '../../SdkVerbosity'; +import { ErrorSource } from '../../types'; import { getErrorMessage, getErrorStackTrace, @@ -18,7 +19,6 @@ import { } from '../../utils/errorUtils'; import { executeWithDelay } from '../../utils/jsUtils'; import { DdRum } from '../DdRum'; -import { ErrorSource } from '../types'; /** * Provides RUM auto-instrumentation feature to track errors as RUM events. diff --git a/packages/core/src/rum/types.ts b/packages/core/src/rum/types.ts index 5834123a6..fc8d07c02 100644 --- a/packages/core/src/rum/types.ts +++ b/packages/core/src/rum/types.ts @@ -4,6 +4,8 @@ * Copyright 2016-Present Datadog, Inc. */ +import type { ErrorSource } from '../types'; + import type { DatadogTracingContext } from './instrumentation/resourceTracking/distributedTracing/DatadogTracingContext'; import type { DatadogTracingIdentifier } from './instrumentation/resourceTracking/distributedTracing/DatadogTracingIdentifier'; @@ -233,14 +235,6 @@ export type ResourceKind = | 'other' | 'native'; -export enum ErrorSource { - NETWORK = 'NETWORK', - SOURCE = 'SOURCE', - CONSOLE = 'CONSOLE', - WEBVIEW = 'WEBVIEW', - CUSTOM = 'CUSTOM' -} - /** * Type of instrumentation on the host. * - DATADOG: Datadog’s propagator (`x-datadog-*`) diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index 4db877469..e1c5096fb 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -5,6 +5,7 @@ */ import type { BatchProcessingLevel } from './DdSdkReactNativeConfiguration'; +import type { UserInfo as UserInfoSingleton } from './sdk/UserInfoSingleton/types'; declare global { // eslint-disable-next-line no-var, vars-on-top @@ -118,13 +119,6 @@ export type DdSdkType = { setTrackingConsent(trackingConsent: string): Promise; }; -export type UserInfo = { - id: string; - name?: string; - email?: string; - extraInfo?: object; -}; - /** * The entry point to use Datadog's Trace feature. */ @@ -153,3 +147,44 @@ export type DdTraceType = { timestampMs?: number ): Promise; }; + +// Shared types across modules + +// Core + +export type UserInfo = { + id: string; + name?: string; + email?: string; + extraInfo?: object; +}; + +// DdLogs + +export type LogStatus = 'debug' | 'info' | 'warn' | 'error'; + +export type LogEvent = { + message: string; + context: object; + errorKind?: string; + errorMessage?: string; + stacktrace?: string; + fingerprint?: string; + readonly source?: ErrorSource; + // readonly date: number; // TODO: RUMM-2446 & RUMM-2447 + readonly status: LogStatus; + readonly userInfo: UserInfoSingleton; + readonly attributes?: object; +}; + +export type LogEventMapper = (logEvent: LogEvent) => LogEvent | null; + +// DdRum + +export enum ErrorSource { + NETWORK = 'NETWORK', + SOURCE = 'SOURCE', + CONSOLE = 'CONSOLE', + WEBVIEW = 'WEBVIEW', + CUSTOM = 'CUSTOM' +} From 2fbba1431d66327f5a3d4335f2cda66aa6be5f51 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Tue, 9 Sep 2025 12:08:35 +0200 Subject: [PATCH 27/62] iOS: Always use SDK default core instance --- .../core/ios/Sources/DatadogSDKWrapper.swift | 44 ++++++-------- .../ios/Sources/DdLogsImplementation.swift | 7 ++- .../ios/Sources/DdSdkImplementation.swift | 17 ++++-- .../Sources/DdSdkNativeInitialization.swift | 22 ++++--- packages/core/ios/Sources/DdTelemetry.swift | 49 ++++++++++++++++ .../ios/Tests/DatadogSdkWrapperTests.swift | 17 +++--- packages/core/ios/Tests/DdSdkTests.swift | 58 ++++++++----------- .../DdSessionReplayImplementation.swift | 28 ++------- .../ios/Tests/DdSessionReplayTests.swift | 6 +- .../Sources/RCTDatadogWebViewTracking.swift | 18 +++--- .../DatadogSDKReactNativeWebViewTests.swift | 14 +++-- 11 files changed, 158 insertions(+), 122 deletions(-) create mode 100644 packages/core/ios/Sources/DdTelemetry.swift diff --git a/packages/core/ios/Sources/DatadogSDKWrapper.swift b/packages/core/ios/Sources/DatadogSDKWrapper.swift index 9cbac3bd8..3c56688b0 100644 --- a/packages/core/ios/Sources/DatadogSDKWrapper.swift +++ b/packages/core/ios/Sources/DatadogSDKWrapper.swift @@ -13,11 +13,15 @@ import DatadogCrashReporting import DatadogInternal import Foundation +<<<<<<< HEAD #if os(iOS) import DatadogWebViewTracking #endif public typealias OnCoreInitializedListener = (DatadogCoreProtocol) -> Void +======= +public typealias OnSdkInitializedListener = () -> Void +>>>>>>> 0443e0ff (iOS: Always use SDK default core instance) /// Wrapper around the Datadog SDK. Use DatadogSDKWrapper.shared to access the instance. public class DatadogSDKWrapper { @@ -25,25 +29,14 @@ public class DatadogSDKWrapper { public static var shared = DatadogSDKWrapper() // Initialization callbacks - internal var onCoreInitializedListeners: [OnCoreInitializedListener] = [] - internal var loggerConfiguration = DatadogLogs.Logger.Configuration() - // Core instance - private var coreInstance: DatadogCoreProtocol? = nil + internal var onSdkInitializedListeners: [OnSdkInitializedListener] = [] - private init() { } - - public func addOnCoreInitializedListener(listener:@escaping OnCoreInitializedListener) { - onCoreInitializedListeners.append(listener) - } + internal private(set) var loggerConfiguration = DatadogLogs.Logger.Configuration() - /// This is intended for internal testing only. - public func setCoreInstance(core: DatadogCoreProtocol?) { - self.coreInstance = core - } + private init() { } - /// This is not supposed to be used in the SDK itself, rather by other SDKs like Session Replay. - public func getCoreInstance() -> DatadogCoreProtocol? { - return coreInstance + public func addOnSdkInitializedListener(listener:@escaping OnSdkInitializedListener) { + onSdkInitializedListeners.append(listener) } // SDK Wrapper @@ -52,15 +45,16 @@ public class DatadogSDKWrapper { loggerConfiguration: DatadogLogs.Logger.Configuration, trackingConsent: TrackingConsent ) -> Void { - let core = Datadog.initialize(with: coreConfiguration, trackingConsent: trackingConsent) - setCoreInstance(core: core) - for listener in onCoreInitializedListeners { - listener(core) + Datadog.initialize(with: coreConfiguration, trackingConsent: trackingConsent) + + for listener in onSdkInitializedListeners { + listener() } self.loggerConfiguration = loggerConfiguration } +<<<<<<< HEAD internal func isInitialized() -> Bool { return Datadog.isInitialized() } @@ -161,17 +155,15 @@ public class DatadogSDKWrapper { #if os(iOS) +======= +>>>>>>> 0443e0ff (iOS: Always use SDK default core instance) // Webview private var webviewMessageEmitter: InternalExtension.AbstractMessageEmitter? internal func enableWebviewTracking() { - if let core = coreInstance { - webviewMessageEmitter = WebViewTracking._internal.messageEmitter(in: core) - } else { - consolePrint("Core instance was not found when initializing Webview tracking.", .critical) - } + webviewMessageEmitter = WebViewTracking._internal.messageEmitter(in: CoreRegistry.default) } - + internal func sendWebviewMessage(body: NSString) throws { try self.webviewMessageEmitter?.send(body: body) } diff --git a/packages/core/ios/Sources/DdLogsImplementation.swift b/packages/core/ios/Sources/DdLogsImplementation.swift index 264a3d0b3..fe3fde092 100644 --- a/packages/core/ios/Sources/DdLogsImplementation.swift +++ b/packages/core/ios/Sources/DdLogsImplementation.swift @@ -5,7 +5,9 @@ */ import Foundation +import DatadogInternal import DatadogLogs +import DatadogCore @objc public class DdLogsImplementation: NSObject { @@ -20,7 +22,10 @@ public class DdLogsImplementation: NSObject { @objc public override convenience init() { - self.init({ DatadogSDKWrapper.shared.createLogger() }, { DatadogSDKWrapper.shared.isInitialized() }) + self.init( + { DatadogLogs.Logger.create(with: DatadogSDKWrapper.shared.loggerConfiguration) }, + { Datadog.isInitialized() } + ) } @objc diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index b4ddc59fd..973b8db9f 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -139,42 +139,47 @@ public class DdSdkImplementation: NSObject { public func sendTelemetryLog(message: NSString, attributes: NSDictionary, config: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { let castedAttributes = castAttributesToSwift(attributes) let castedConfig = castAttributesToSwift(config) - DatadogSDKWrapper.shared.sendTelemetryLog(message: message as String, attributes: castedAttributes, config: castedConfig) + DdTelemetry.sendTelemetryLog(message: message as String, attributes: castedAttributes, config: castedConfig) resolve(nil) } @objc public func telemetryDebug(message: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { - DatadogSDKWrapper.shared.telemetryDebug(id: "datadog_react_native:\(message)", message: message as String) + DdTelemetry.telemetryDebug(id: "datadog_react_native:\(message)", message: message as String) resolve(nil) } @objc public func telemetryError(message: NSString, stack: NSString, kind: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { - DatadogSDKWrapper.shared.telemetryError(id: "datadog_react_native:\(String(describing: kind)):\(message)", message: message as String, kind: kind as String, stack: stack as String) + DdTelemetry.telemetryError(id: "datadog_react_native:\(String(describing: kind)):\(message)", message: message as String, kind: kind as String, stack: stack as String) resolve(nil) } +<<<<<<< HEAD #if os(iOS) +======= + +>>>>>>> 0443e0ff (iOS: Always use SDK default core instance) @objc public func consumeWebviewEvent(message: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { do{ try DatadogSDKWrapper.shared.sendWebviewMessage(body: message) } catch { - DatadogSDKWrapper.shared.telemetryError(id: "datadog_react_native:\(error.localizedDescription)", message: "The message being sent was:\(message)" as String, kind: "WebViewEventBridgeError" as String, stack: String(describing: error) as String) + DdTelemetry.telemetryError(id: "datadog_react_native:\(error.localizedDescription)", message: "The message being sent was:\(message)" as String, kind: "WebViewEventBridgeError" as String, stack: String(describing: error) as String) } + resolve(nil) } #endif @objc public func clearAllData(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { - DatadogSDKWrapper.shared.clearAllData() + Datadog.clearAllData() resolve(nil) } func overrideReactNativeTelemetry(rnConfiguration: DdSdkConfiguration) -> Void { - DatadogSDKWrapper.shared.overrideTelemetryConfiguration( + DdTelemetry.overrideTelemetryConfiguration( initializationType: rnConfiguration.configurationForTelemetry?.initializationType as? String, reactNativeVersion: rnConfiguration.configurationForTelemetry?.reactNativeVersion as? String, reactVersion: rnConfiguration.configurationForTelemetry?.reactVersion as? String, diff --git a/packages/core/ios/Sources/DdSdkNativeInitialization.swift b/packages/core/ios/Sources/DdSdkNativeInitialization.swift index dec3cbcb2..4ea229871 100644 --- a/packages/core/ios/Sources/DdSdkNativeInitialization.swift +++ b/packages/core/ios/Sources/DdSdkNativeInitialization.swift @@ -33,12 +33,13 @@ public class DdSdkNativeInitialization: NSObject { } internal func initialize(sdkConfiguration: DdSdkConfiguration) { - // TODO: see if this `if` is still needed - if DatadogSDKWrapper.shared.isInitialized() { - // Initializing the SDK twice results in Global.rum and - // Global.sharedTracer to be set to no-op instances + if Datadog.isInitialized(instanceName: CoreRegistry.defaultInstanceName) { + // Initializing the SDK twice results in Global.rum and Global.sharedTracer to be set to no-op instances consolePrint("Datadog SDK is already initialized, skipping initialization.", .debug) - DatadogSDKWrapper.shared.telemetryDebug(id: "datadog_react_native: RN SDK was already initialized in native", message: "RN SDK was already initialized in native") + DdTelemetry.telemetryDebug( + id: "datadog_react_native: RN SDK was already initialized in native", + message: "RN SDK was already initialized in native" + ) RUMMonitor.shared().currentSessionID { sessionId in guard let id = sessionId else { return } @@ -81,21 +82,24 @@ public class DdSdkNativeInitialization: NSObject { func enableFeatures(sdkConfiguration: DdSdkConfiguration) { let rumConfig = buildRUMConfiguration(configuration: sdkConfiguration) - DatadogSDKWrapper.shared.enableRUM(with: rumConfig) + RUM.enable(with: rumConfig) let logsConfig = buildLogsConfiguration(configuration: sdkConfiguration) - DatadogSDKWrapper.shared.enableLogs(with: logsConfig) + Logs.enable(with: logsConfig) let traceConfig = buildTraceConfiguration(configuration: sdkConfiguration) - DatadogSDKWrapper.shared.enableTrace(with: traceConfig) + Trace.enable(with: traceConfig) if sdkConfiguration.nativeCrashReportEnabled ?? false { - DatadogSDKWrapper.shared.enableCrashReporting() + CrashReporting.enable() } +<<<<<<< HEAD #if os(iOS) DatadogSDKWrapper.shared.enableWebviewTracking() #endif +======= +>>>>>>> 0443e0ff (iOS: Always use SDK default core instance) } func buildSDKConfiguration(configuration: DdSdkConfiguration, defaultAppVersion: String = getDefaultAppVersion()) -> Datadog.Configuration { diff --git a/packages/core/ios/Sources/DdTelemetry.swift b/packages/core/ios/Sources/DdTelemetry.swift new file mode 100644 index 000000000..cb1896db8 --- /dev/null +++ b/packages/core/ios/Sources/DdTelemetry.swift @@ -0,0 +1,49 @@ + +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-2025 Datadog, Inc. + */ +import DatadogCore +import DatadogInternal + +public class DdTelemetry { + public static func sendTelemetryLog(message: String, attributes: [String: any Encodable], config: [String: any Encodable]) { + let id = (config["onlyOnce"] as? Bool) == true ? message : UUID().uuidString + CoreRegistry.default.telemetry.debug(id: id, message: message, attributes: attributes) + } + + public static func telemetryDebug(id: String, message: String) { + return Datadog._internal.telemetry.debug(id: id, message: message) + } + + public static func telemetryError(id: String, message: String, kind: String?, stack: String?) { + return Datadog._internal.telemetry.error(id: id, message: message, kind: kind, stack: stack) + } + + public static func overrideTelemetryConfiguration( + initializationType: String? = nil, + reactNativeVersion: String? = nil, + reactVersion: String? = nil, + trackCrossPlatformLongTasks: Bool? = nil, + trackErrors: Bool? = nil, + trackInteractions: Bool? = nil, + trackLongTask: Bool? = nil, + trackNativeErrors: Bool? = nil, + trackNativeLongTasks: Bool? = nil, + trackNetworkRequests: Bool? = nil + ) { + CoreRegistry.default.telemetry.configuration( + initializationType: initializationType, + reactNativeVersion: reactNativeVersion, + reactVersion: reactVersion, + trackCrossPlatformLongTasks: trackCrossPlatformLongTasks, + trackErrors: trackErrors, + trackLongTask: trackLongTask, + trackNativeErrors: trackNativeErrors, + trackNativeLongTasks: trackNativeLongTasks, + trackNetworkRequests: trackNetworkRequests, + trackUserInteractions: trackInteractions + ) + } +} diff --git a/packages/core/ios/Tests/DatadogSdkWrapperTests.swift b/packages/core/ios/Tests/DatadogSdkWrapperTests.swift index 4811b4c1d..a445b2bbe 100644 --- a/packages/core/ios/Tests/DatadogSdkWrapperTests.swift +++ b/packages/core/ios/Tests/DatadogSdkWrapperTests.swift @@ -8,22 +8,23 @@ import XCTest @testable import DatadogSDKReactNative import DatadogTrace import DatadogInternal - +import DatadogRUM +import DatadogLogs internal class DatadogSdkWrapperTests: XCTestCase { override func setUp() { super.setUp() - DatadogSDKWrapper.shared.setCoreInstance(core: nil) - DatadogSDKWrapper.shared.onCoreInitializedListeners = [] + DatadogSDKWrapper.shared.onSdkInitializedListeners = [] } - func testItSetsCoreUsedForFeatures() { + func testOverrideCoreRegistryDefault() { let coreMock = MockDatadogCore() - DatadogSDKWrapper.shared.setCoreInstance(core: coreMock) + CoreRegistry.register(default: coreMock) + defer { CoreRegistry.unregisterDefault() } - DatadogSDKWrapper.shared.enableTrace(with: .init()) - DatadogSDKWrapper.shared.enableRUM(with: .init(applicationID: "app-id")) - DatadogSDKWrapper.shared.enableLogs(with: .init()) + Trace.enable(with: .init()) + RUM.enable(with: .init(applicationID: "app-id")) + Logs.enable(with: .init()) XCTAssertNotNil(coreMock.features["tracing"]) XCTAssertNotNil(coreMock.features["rum"]) diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index edbbba4dd..bcc3252a8 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -34,8 +34,7 @@ class DdSdkTests: XCTestCase { private func mockReject(args _: String?, arg _: String?, err _: Error?) {} override func tearDown() { - DatadogSDKWrapper.shared.setCoreInstance(core: nil) - DatadogSDKWrapper.shared.onCoreInitializedListeners = [] + DatadogSDKWrapper.shared.onSdkInitializedListeners = [] Datadog.internalFlushAndDeinitialize() } @@ -84,11 +83,10 @@ class DdSdkTests: XCTestCase { let bridge = DispatchQueueMock() let mockJSRefreshRateMonitor = MockJSRefreshRateMonitor() let mockListener = MockOnCoreInitializedListener() - DatadogSDKWrapper.shared.addOnCoreInitializedListener(listener: mockListener.listener) + DatadogSDKWrapper.shared.addOnSdkInitializedListener(listener: mockListener.listener) - let expectation = self.expectation(description: "Core is set when promise resolves") + let expectation = self.expectation(description: "Listener is called when promise resolves") func mockPromiseResolve(_: Any?) { - XCTAssertNotNil(mockListener.core) expectation.fulfill() } @@ -276,9 +274,9 @@ class DdSdkTests: XCTestCase { } func testSDKInitializationWithOnInitializedCallback() { - var coreFromCallback: DatadogCoreProtocol? = nil - DatadogSDKWrapper.shared.addOnCoreInitializedListener(listener: { core in - coreFromCallback = core + var isInitialized = false + DatadogSDKWrapper.shared.addOnSdkInitializedListener(listener: { + isInitialized = Datadog.isInitialized() }) DdSdkImplementation( @@ -293,14 +291,16 @@ class DdSdkTests: XCTestCase { reject: mockReject ) - XCTAssertNotNil(coreFromCallback) + XCTAssertTrue(isInitialized) } func testEnableAllFeatures() { let core = MockDatadogCore() + CoreRegistry.register(default: core) + defer { CoreRegistry.unregisterDefault() } + let configuration: DdSdkConfiguration = .mockAny() - DatadogSDKWrapper.shared.setCoreInstance(core: core) DdSdkNativeInitialization().enableFeatures( sdkConfiguration: configuration ) @@ -479,9 +479,11 @@ class DdSdkTests: XCTestCase { func testBuildConfigurationWithCrashReport() { let core = MockDatadogCore() + CoreRegistry.register(default: core) + defer { CoreRegistry.unregisterDefault() } + let configuration: DdSdkConfiguration = .mockAny(nativeCrashReportEnabled: true) - DatadogSDKWrapper.shared.setCoreInstance(core: core) DdSdkNativeInitialization().enableFeatures( sdkConfiguration: configuration ) @@ -1233,6 +1235,9 @@ class DdSdkTests: XCTestCase { func testConfigurationTelemetryOverride() throws { let core = MockDatadogCore() + CoreRegistry.register(default: core) + defer { CoreRegistry.unregisterDefault() } + let configuration: DdSdkConfiguration = .mockAny( nativeCrashReportEnabled: false, nativeLongTaskThresholdMs: 0.0, @@ -1244,7 +1249,6 @@ class DdSdkTests: XCTestCase { ] ) - DatadogSDKWrapper.shared.setCoreInstance(core: core) DdSdkImplementation().overrideReactNativeTelemetry(rnConfiguration: configuration) XCTAssertEqual(core.configuration?.initializationType, "LEGACY") @@ -1313,11 +1317,12 @@ class DdSdkTests: XCTestCase { XCTAssertTrue(bridge.isSameQueue(queue: mockJSRefreshRateMonitor.jsQueue!)) } - func testCallsOnCoreInitializedListeners() throws { + func testCallsOnSdkInitializedListeners() throws { let bridge = DispatchQueueMock() let mockJSRefreshRateMonitor = MockJSRefreshRateMonitor() let mockListener = MockOnCoreInitializedListener() - DatadogSDKWrapper.shared.addOnCoreInitializedListener(listener: mockListener.listener) + + DatadogSDKWrapper.shared.addOnSdkInitializedListener(listener: mockListener.listener) DdSdkImplementation( mainDispatchQueue: DispatchQueueMock(), @@ -1331,23 +1336,7 @@ class DdSdkTests: XCTestCase { reject: mockReject ) - XCTAssertNotNil(mockListener.core) - } - - func testConsumeWebviewEvent() throws { - let configuration: DdSdkConfiguration = .mockAny() - let core = MockDatadogCore() - - DatadogSDKWrapper.shared.setCoreInstance(core: core) - DdSdkNativeInitialization().enableFeatures( - sdkConfiguration: configuration - ) - - DdSdkImplementation().consumeWebviewEvent( - message: "{\"eventType\":\"rum\",\"event\":{\"blabla\":\"custom message\"}}", - resolve: mockResolve, reject: mockReject) - - XCTAssertNotNil(core.baggages["browser-rum-event"]) + XCTAssertTrue(mockListener.called) } func testInitialResourceThreshold() { @@ -1601,9 +1590,8 @@ extension DdSdkImplementation { } class MockOnCoreInitializedListener { - var core: DatadogCoreProtocol? - - func listener(core: DatadogCoreProtocol) { - self.core = core + var called = false + func listener() { + self.called = true } } diff --git a/packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift b/packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift index 45cfc2582..0fc9c6637 100644 --- a/packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift +++ b/packages/react-native-session-replay/ios/Sources/DdSessionReplayImplementation.swift @@ -6,6 +6,7 @@ import Foundation @_spi(Internal) import DatadogSessionReplay +import DatadogCore import DatadogInternal import DatadogSDKReactNative import React @@ -66,8 +67,6 @@ public class DdSessionReplayImplementation: NSObject { customEndpoint: customEndpointURL ) -// let bundle = Bundle(for: DdSessionReplayImplementation.self) - var svgMap: [String: SVGData] = [:] if let bundle = Bundle.ddSessionReplayResources, @@ -92,38 +91,21 @@ public class DdSessionReplayImplementation: NSObject { fabricWrapper: fabricWrapper ) ]) - - if let core = DatadogSDKWrapper.shared.getCoreInstance() { - sessionReplay.enable( - with: sessionReplayConfiguration, - in: core - ) - } else { - consolePrint("Core instance was not found when initializing Session Replay.", .critical) - } + + sessionReplay.enable(with: sessionReplayConfiguration, in: CoreRegistry.default) resolve(nil) } @objc public func startRecording(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void { - if let core = DatadogSDKWrapper.shared.getCoreInstance() { - sessionReplay.startRecording(in: core) - } else { - consolePrint("Core instance was not found when calling startRecording in Session Replay.", .critical) - } - + sessionReplay.startRecording(in: CoreRegistry.default) resolve(nil) } @objc public func stopRecording(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void { - if let core = DatadogSDKWrapper.shared.getCoreInstance() { - sessionReplay.stopRecording(in: core) - } else { - consolePrint("Core instance was not found when calling stopRecording in Session Replay.", .critical) - } - + sessionReplay.stopRecording(in: CoreRegistry.default) resolve(nil) } diff --git a/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift b/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift index aa9102850..067a11df0 100644 --- a/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift +++ b/packages/react-native-session-replay/ios/Tests/DdSessionReplayTests.swift @@ -35,7 +35,11 @@ internal class DdSessionReplayTests: XCTestCase { override func setUp() { super.setUp() let mockDatadogCore = MockDatadogCore() - DatadogSDKWrapper.shared.setCoreInstance(core: mockDatadogCore) + CoreRegistry.register(default: mockDatadogCore) + } + + override func tearDown() { + CoreRegistry.unregisterDefault() } func testEnablesSessionReplayWithZeroReplaySampleRate() { diff --git a/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift b/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift index 97fd835b5..45f11e452 100644 --- a/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift +++ b/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift @@ -8,26 +8,27 @@ import WebKit import DatadogWebViewTracking import DatadogSDKReactNative import DatadogCore +import DatadogInternal @objc public class RCTDatadogWebViewTracking: NSObject { var webView: RCTDatadogWebView? = nil var allowedHosts: Set = Set() - var coreListener: OnCoreInitializedListener? + var onSdkInitializedListener: OnSdkInitializedListener? public override init() { super.init() - self.coreListener = { [weak self] (core: DatadogCoreProtocol) in + self.onSdkInitializedListener = { [weak self] in guard let strongSelf = self, let webView = strongSelf.webView else { return } strongSelf.enableWebViewTracking( webView: webView, allowedHosts: strongSelf.allowedHosts, - core: core + core: CoreRegistry.default ) } } - + /** Enables tracking on the given WebView. @@ -42,15 +43,16 @@ import DatadogCore guard !webView.isTrackingEnabled else { return } - if let core = DatadogSDKWrapper.shared.getCoreInstance() { - enableWebViewTracking(webView: webView, allowedHosts: allowedHosts, core: core) - } else if let coreListener = self.coreListener { - DatadogSDKWrapper.shared.addOnCoreInitializedListener(listener: coreListener) + if CoreRegistry.isRegistered(instanceName: CoreRegistry.defaultInstanceName) { + enableWebViewTracking(webView: webView, allowedHosts: allowedHosts, core: CoreRegistry.default) + } else if let onSdkInitializedListener = self.onSdkInitializedListener { + DatadogSDKWrapper.shared.addOnSdkInitializedListener(listener: onSdkInitializedListener) } else { // TODO: Report initialization problem } } + private func enableWebViewTracking( webView: RCTDatadogWebView, allowedHosts: Set, diff --git a/packages/react-native-webview/ios/Tests/DatadogSDKReactNativeWebViewTests.swift b/packages/react-native-webview/ios/Tests/DatadogSDKReactNativeWebViewTests.swift index 7ea36bda8..20f1b84fa 100644 --- a/packages/react-native-webview/ios/Tests/DatadogSDKReactNativeWebViewTests.swift +++ b/packages/react-native-webview/ios/Tests/DatadogSDKReactNativeWebViewTests.swift @@ -17,7 +17,11 @@ internal class DatadogSDKReactNativeWebViewTests: XCTestCase { override func setUp() { super.setUp() let mockDatadogCore = MockDatadogCore() - DatadogSDKWrapper.shared.setCoreInstance(core: mockDatadogCore) + CoreRegistry.register(default: mockDatadogCore) + } + + override func tearDown() { + CoreRegistry.unregisterDefault() } func testDatadogWebViewManagerReturnsDatadogWebView() { @@ -41,9 +45,10 @@ internal class DatadogSDKReactNativeWebViewTests: XCTestCase { XCTAssertFalse(view.isTrackingEnabled) } - func testDatadogWebViewTrackingIsDisabledIfCoreIsNotReady() { + func testDatadogWebViewTrackingIsDisabledIfSdkIsNotInitialized() { // Given - DatadogSDKWrapper.shared.setCoreInstance(core: nil) + CoreRegistry.unregisterDefault() + let viewManager = RCTDatadogWebViewManager() let allowedHosts = NSArray(objects: "example1.com", "example2.com") @@ -82,7 +87,7 @@ internal class DatadogSDKReactNativeWebViewTests: XCTestCase { view.addSubview(WKWebView()) - DatadogSDKWrapper.shared.setCoreInstance(core: nil) + CoreRegistry.unregisterDefault() // Given let selector = NSSelectorFromString("setupDatadogWebView:view:") @@ -92,7 +97,6 @@ internal class DatadogSDKReactNativeWebViewTests: XCTestCase { XCTAssertFalse(view.isTrackingEnabled) // When - DatadogSDKWrapper.shared.setCoreInstance(core: MockDatadogCore()) DatadogSDKWrapper.shared.callInitialize() let expectation = self.expectation(description: "WebView tracking is enabled through the listener.") From 51280318da38839cce13f33f4f8d033680412c5d Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Mon, 8 Sep 2025 15:27:17 +0200 Subject: [PATCH 28/62] Bump native SDK dependencies to 3.0.0 --- benchmarks/android/app/build.gradle | 2 +- benchmarks/ios/Podfile.lock | 74 +++++++------- bump-native-dd-sdk.sh | 2 +- example-new-architecture/ios/Podfile.lock | 70 +++++++------- example/ios/Podfile.lock | 96 +++++++++---------- packages/core/DatadogSDKReactNative.podspec | 12 +-- packages/core/android/build.gradle | 10 +- ...DatadogSDKReactNativeSessionReplay.podspec | 2 +- .../android/build.gradle | 4 +- .../DatadogSDKReactNativeWebView.podspec | 4 +- .../react-native-webview/android/build.gradle | 2 +- 11 files changed, 139 insertions(+), 139 deletions(-) diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle index 86d26791f..7dc4b3707 100644 --- a/benchmarks/android/app/build.gradle +++ b/benchmarks/android/app/build.gradle @@ -129,5 +129,5 @@ dependencies { // Benchmark tools from dd-sdk-android are used for vitals recording // Remember to bump thid alongside the main dd-sdk-android dependencies - implementation("com.datadoghq:dd-sdk-android-benchmark-internal:2.25.0") + implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.0.0") } diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index f42e0cd31..90043a48d 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogCrashReporting (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogCore (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogCrashReporting (3.0.0): + - DatadogInternal (= 3.0.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (2.30.2) - - DatadogLogs (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogRUM (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.2): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogInternal (3.0.0) + - DatadogLogs (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogRUM (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogSDKReactNative (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -39,7 +39,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 2.30.2) + - DatadogSessionReplay (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -60,10 +60,10 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.2): - - DatadogInternal (= 2.30.2) + - DatadogSDKReactNativeWebView (2.12.1): + - DatadogInternal (= 3.0.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 2.30.2) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -84,13 +84,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSessionReplay (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogTrace (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogSessionReplay (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogTrace (3.0.0): + - DatadogInternal (= 3.0.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogWebViewTracking (3.0.0): + - DatadogInternal (= 3.0.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.78.2) @@ -2070,17 +2070,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogCore: 8e50ad6cb68343f701707f7eeca16e0acb52ed8c - DatadogCrashReporting: 34763d4276d4fce286c7e8729cfcd2ac04dca43b - DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 - DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 - DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 4138a93c3168b4378de498052d0e00ea9560339d - DatadogSDKReactNativeSessionReplay: baa4de76d97d5f03303dde0e0db922a2fd812019 - DatadogSDKReactNativeWebView: 399e43d18902e3012c968fb9b7fd634b3936a882 - DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 - DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 - DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be + DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 + DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e + DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 + DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd + DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f + DatadogSDKReactNative: 241bf982c16ceff03d94a58e6d005e55c47b99c6 + DatadogSDKReactNativeSessionReplay: bba36092686e3183e97c1a0c7f4ca8142582ae28 + DatadogSDKReactNativeWebView: 6da060df20e235abac533e582d9fc2b3a5070840 + DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 + DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 + DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c diff --git a/bump-native-dd-sdk.sh b/bump-native-dd-sdk.sh index 8545802db..67d99a0e7 100755 --- a/bump-native-dd-sdk.sh +++ b/bump-native-dd-sdk.sh @@ -23,7 +23,7 @@ podspec_files=( "packages/react-native-webview/DatadogSDKReactNativeWebView.podspec" ) -ios_pattern="('Datadog[^']+', '~> )[0-9.]+'" +ios_pattern="('Datadog[^']+', ')[0-9.]+'" android_pattern='(com\.datadoghq:dd-sdk-android-[^:"]+):[0-9.]+' if [[ "$sdk" == "ios" ]]; then diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 84b5f1d8c..cc9913ce3 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogCrashReporting (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogCore (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogCrashReporting (3.0.0): + - DatadogInternal (= 3.0.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (2.30.2) - - DatadogLogs (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogRUM (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.2): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogInternal (3.0.0) + - DatadogLogs (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogRUM (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogSDKReactNative (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -37,13 +37,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (2.13.2): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogSDKReactNative/Tests (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -64,11 +64,11 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogTrace (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogTrace (3.0.0): + - DatadogInternal (= 3.0.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogWebViewTracking (3.0.0): + - DatadogInternal (= 3.0.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1850,14 +1850,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 8e50ad6cb68343f701707f7eeca16e0acb52ed8c - DatadogCrashReporting: 34763d4276d4fce286c7e8729cfcd2ac04dca43b - DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 - DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 - DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: afd267f110a3de4e179acc0bea6a492b0b8b00cf - DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 - DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be + DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 + DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e + DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 + DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd + DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f + DatadogSDKReactNative: 0a80aa75958d595a99be54d2838db53eda7a08af + DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 + DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 45a7a2dea..f93f0ee07 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,34 +1,34 @@ PODS: - boost (1.84.0) - - DatadogCore (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogCrashReporting (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogCore (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogCrashReporting (3.0.0): + - DatadogInternal (= 3.0.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (2.30.2) - - DatadogLogs (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogRUM (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogSDKReactNative (2.13.2): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogInternal (3.0.0) + - DatadogLogs (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogRUM (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogSDKReactNative (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - React-Core - - DatadogSDKReactNative/Tests (2.13.2): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogSDKReactNative/Tests (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - React-Core - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 2.30.2) + - DatadogSessionReplay (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -51,7 +51,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay/Tests (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 2.30.2) + - DatadogSessionReplay (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -73,25 +73,25 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.2): - - DatadogInternal (= 2.30.2) + - DatadogSDKReactNativeWebView (2.12.1): + - DatadogInternal (= 3.0.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 2.30.2) + - DatadogWebViewTracking (= 3.0.0) - React-Core - - DatadogSDKReactNativeWebView/Tests (2.13.2): - - DatadogInternal (= 2.30.2) + - DatadogSDKReactNativeWebView/Tests (2.12.1): + - DatadogInternal (= 3.0.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 2.30.2) + - DatadogWebViewTracking (= 3.0.0) - React-Core - react-native-webview - React-RCTText - - DatadogSessionReplay (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogTrace (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogSessionReplay (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogTrace (3.0.0): + - DatadogInternal (= 3.0.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogWebViewTracking (3.0.0): + - DatadogInternal (= 3.0.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1988,17 +1988,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 8e50ad6cb68343f701707f7eeca16e0acb52ed8c - DatadogCrashReporting: 34763d4276d4fce286c7e8729cfcd2ac04dca43b - DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 - DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 - DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: b04b5f9fd71aaa8a26affc43b1b0a2a43674a072 - DatadogSDKReactNativeSessionReplay: 102b0ecb56fb2baf3e8183e7c54631c5e31bf24a - DatadogSDKReactNativeWebView: 4343376f9a6be5e2af685444173f4b54e8b15d83 - DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 - DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 - DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be + DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 + DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e + DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 + DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd + DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f + DatadogSDKReactNative: e430b3f4d7adb0fac07b61e2fb65ceacdaf82b3e + DatadogSDKReactNativeSessionReplay: 4b2a3d166a79581f18522795b40141c34cf3685d + DatadogSDKReactNativeWebView: 35dc2b9736e1aaa82b366bf6b8a8a959a9b088c5 + DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 + DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 + DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index ff3b91232..a2f41ddd1 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -19,14 +19,14 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the versions in sync with DatadogSDKReactNativeSessionReplay.podspec - s.dependency 'DatadogCore', '2.30.2' - s.dependency 'DatadogLogs', '2.30.2' - s.dependency 'DatadogTrace', '2.30.2' - s.dependency 'DatadogRUM', '2.30.2' - s.dependency 'DatadogCrashReporting', '2.30.2' + s.dependency 'DatadogCore', '3.0.0' + s.dependency 'DatadogLogs', '3.0.0' + s.dependency 'DatadogTrace', '3.0.0' + s.dependency 'DatadogRUM', '3.0.0' + s.dependency 'DatadogCrashReporting', '3.0.0' # DatadogWebViewTracking is not available for tvOS - s.ios.dependency 'DatadogWebViewTracking', '2.30.2' + s.ios.dependency 'DatadogWebViewTracking', '3.0.0' s.test_spec 'Tests' do |test_spec| test_spec.source_files = 'ios/Tests/**/*.{swift,json}' diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index 0396ae323..a8d09d4d1 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -201,16 +201,16 @@ dependencies { // This breaks builds if the React Native target is below 0.76.0. as it relies on Gradle 8.5.0. // To avoid this, we enforce 1.0.0-beta01 on RN < 0.76.0 if (reactNativeMinorVersion < 76) { - implementation("com.datadoghq:dd-sdk-android-rum:2.26.2") { + implementation("com.datadoghq:dd-sdk-android-rum:3.0.0") { exclude group: "androidx.metrics", module: "metrics-performance" } implementation "androidx.metrics:metrics-performance:1.0.0-beta01" } else { - implementation "com.datadoghq:dd-sdk-android-rum:2.26.2" + implementation "com.datadoghq:dd-sdk-android-rum:3.0.0" } - implementation "com.datadoghq:dd-sdk-android-logs:2.26.2" - implementation "com.datadoghq:dd-sdk-android-trace:2.26.2" - implementation "com.datadoghq:dd-sdk-android-webview:2.26.2" + implementation "com.datadoghq:dd-sdk-android-logs:3.0.0" + implementation "com.datadoghq:dd-sdk-android-trace:3.0.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" implementation "com.google.code.gson:gson:2.10.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 915fc4129..3a2d5ff48 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogSessionReplay', '2.30.2' + s.dependency 'DatadogSessionReplay', '3.0.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index 5851ee598..6d6fe20b1 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -216,8 +216,8 @@ dependencies { api "com.facebook.react:react-android:$reactNativeVersion" } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.datadoghq:dd-sdk-android-session-replay:2.26.2" - implementation "com.datadoghq:dd-sdk-android-internal:2.26.2" + implementation "com.datadoghq:dd-sdk-android-session-replay:3.0.0" + implementation "com.datadoghq:dd-sdk-android-internal:3.0.0" implementation project(path: ':datadog_mobile-react-native') testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 3d4668bb0..26e160bbc 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -23,8 +23,8 @@ Pod::Spec.new do |s| end # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogWebViewTracking', '2.30.2' - s.dependency 'DatadogInternal', '2.30.2' + s.dependency 'DatadogWebViewTracking', '3.0.0' + s.dependency 'DatadogInternal', '3.0.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-webview/android/build.gradle b/packages/react-native-webview/android/build.gradle index 973b3ec5f..098eae019 100644 --- a/packages/react-native-webview/android/build.gradle +++ b/packages/react-native-webview/android/build.gradle @@ -190,7 +190,7 @@ dependencies { implementation "com.facebook.react:react-android:$reactNativeVersion" } - implementation "com.datadoghq:dd-sdk-android-webview:2.26.2" + implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation project(path: ':datadog_mobile-react-native') From 6b871c0ca3fac354554aab75682e28d6a416413b Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 12 Sep 2025 14:43:25 +0200 Subject: [PATCH 29/62] Remove setUser --- packages/codepush/__mocks__/react-native.ts | 3 - packages/core/__mocks__/react-native.ts | 3 - .../datadog/reactnative/DatadogSDKWrapper.kt | 10 -- .../com/datadog/reactnative/DatadogWrapper.kt | 17 -- .../reactnative/DdSdkImplementation.kt | 17 +- .../kotlin/com/datadog/reactnative/DdSdk.kt | 14 +- .../kotlin/com/datadog/reactnative/DdSdk.kt | 11 -- .../com/datadog/reactnative/DdSdkTest.kt | 158 ------------------ packages/core/ios/Sources/DdSdk.mm | 11 -- .../ios/Sources/DdSdkImplementation.swift | 15 +- packages/core/ios/Tests/DdSdkTests.swift | 132 --------------- packages/core/ios/Tests/MockRUMMonitor.swift | 16 ++ packages/core/jest/mock.js | 3 - packages/core/src/DdSdkReactNative.tsx | 25 +-- .../src/__tests__/DdSdkReactNative.test.tsx | 16 -- packages/core/src/logs/eventMapper.ts | 6 +- .../core/src/sdk/EventMappers/EventMapper.ts | 2 +- .../UserInfoSingleton/UserInfoSingleton.ts | 4 +- .../__tests__/UserInfoSingleton.test.ts | 6 +- .../core/src/sdk/UserInfoSingleton/types.ts | 5 +- packages/core/src/specs/NativeDdSdk.ts | 7 - packages/core/src/types.tsx | 10 +- .../__mocks__/react-native.ts | 3 - 23 files changed, 42 insertions(+), 452 deletions(-) diff --git a/packages/codepush/__mocks__/react-native.ts b/packages/codepush/__mocks__/react-native.ts index b35df4e31..046ced2f6 100644 --- a/packages/codepush/__mocks__/react-native.ts +++ b/packages/codepush/__mocks__/react-native.ts @@ -18,9 +18,6 @@ actualRN.NativeModules.DdSdk = { initialize: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, - setUser: jest.fn().mockImplementation( - () => new Promise(resolve => resolve()) - ) as jest.MockedFunction, setAttributes: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, diff --git a/packages/core/__mocks__/react-native.ts b/packages/core/__mocks__/react-native.ts index 9507ec33f..260fe68a7 100644 --- a/packages/core/__mocks__/react-native.ts +++ b/packages/core/__mocks__/react-native.ts @@ -18,9 +18,6 @@ actualRN.NativeModules.DdSdk = { initialize: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, - setUser: jest.fn().mockImplementation( - () => new Promise(resolve => resolve()) - ) as jest.MockedFunction, setUserInfo: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt index da0841ac4..198061d14 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt @@ -71,16 +71,6 @@ internal class DatadogSDKWrapper : DatadogWrapper { DatadogSDKWrapperStorage.notifyOnInitializedListeners(core as InternalSdkCore) } - @Deprecated("Use setUserInfo instead; the user ID is now required.") - override fun setUser( - id: String?, - name: String?, - email: String?, - extraInfo: Map - ) { - Datadog.setUserInfo(id, name, email, extraInfo) - } - override fun setUserInfo( id: String, name: String?, diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt index 19b25e587..3ae3e6266 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt @@ -62,23 +62,6 @@ interface DatadogWrapper { consent: TrackingConsent ) - /** - * Sets the user information. - * - * @param id (nullable) a unique user identifier (relevant to your business domain) - * @param name (nullable) the user name or alias - * @param email (nullable) the user email - * @param extraInfo additional information. An extra information can be - * nested up to 8 levels deep. Keys using more than 8 levels will be sanitized by SDK. - */ - @Deprecated("Use setUserInfo instead; the user ID is now required.") - fun setUser( - id: String?, - name: String?, - email: String?, - extraInfo: Map - ) - /** * Sets the user information. * diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index b04a2ddf3..7a5c6848c 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -78,21 +78,6 @@ class DdSdkImplementation( promise.resolve(null) } - /** - * Set the user information. - * @param user The user object (use builtin attributes: 'id', 'email', 'name', and/or any custom - * attribute). - */ - @Deprecated("Use setUserInfo instead; the user ID is now required.") - fun setUser(user: ReadableMap, promise: Promise) { - val extraInfo = user.toHashMap().toMutableMap() - val id = extraInfo.remove("id")?.toString() - val name = extraInfo.remove("name")?.toString() - val email = extraInfo.remove("email")?.toString() - datadog.setUser(id, name, email, extraInfo) - promise.resolve(null) - } - /** * Set the user information. * @param userInfo The user object (use builtin attributes: 'id', 'email', 'name', and any custom @@ -110,7 +95,7 @@ class DdSdkImplementation( if (id != null) { datadog.setUserInfo(id, name, email, extraInfo) } else { - datadog.setUser(null, name, email, extraInfo) + // TO DO - Log warning? } promise.resolve(null) diff --git a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt index 5bc470947..cfafffffe 100644 --- a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -51,19 +51,7 @@ class DdSdk( /** * Set the user information. - * @param user The user object (use builtin attributes: 'id', 'email', 'name', and/or any custom - * attribute). - */ - @Deprecated("Use setUserInfo instead; the user ID is now required.") - @ReactMethod - override fun setUser(user: ReadableMap, promise: Promise) { - implementation.setUser(user, promise) - } - - /** - * Set the user information. - * @param user The user object (use builtin attributes: 'id', 'email', 'name', and any custom - * attribute inside 'extraInfo'). + * @param user The user object (use builtin attributes: 'id', 'email', 'name', and any custom * attribute inside 'extraInfo'). */ @ReactMethod override fun setUserInfo(user: ReadableMap, promise: Promise) { diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index 17acd6d20..97acb2ebf 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -75,17 +75,6 @@ class DdSdk( implementation.setAttributes(attributes, promise) } - /** - * Set the user information. - * @param user The user object (use builtin attributes: 'id', 'email', 'name', and/or any custom - * attribute). - */ - @Deprecated("Use setUserInfo instead; the user ID is now required.") - @ReactMethod - fun setUser(user: ReadableMap, promise: Promise) { - implementation.setUser(user, promise) - } - /** * Set the user information. * @param user The user object (use builtin attributes: 'id', 'email', 'name', and any custom * attribute inside 'extraInfo'). diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index a39485dae..8797bcc64 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -2810,164 +2810,6 @@ internal class DdSdkTest { // region misc - @Test - fun `𝕄 set native user info 𝕎 setUser()`( - @MapForgery( - key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), - value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) - ) extraInfo: Map - ) { - // When - testedBridgeSdk.setUser(extraInfo.toReadableMap(), mockPromise) - - // Then - argumentCaptor> { - verify(mockDatadog) - .setUser( - isNull(), - isNull(), - isNull(), - capture() - ) - - assertThat(firstValue) - .containsAllEntriesOf(extraInfo) - .hasSize(extraInfo.size) - } - } - - @Test - fun `𝕄 set native user info 𝕎 setUser() {with id}`( - @StringForgery id: String, - @MapForgery( - key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), - value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) - ) extraInfo: Map - ) { - // Given - val user = extraInfo.toMutableMap().also { - it.put("id", id) - } - - // When - testedBridgeSdk.setUser(user.toReadableMap(), mockPromise) - - // Then - argumentCaptor> { - verify(mockDatadog) - .setUser( - eq(id), - isNull(), - isNull(), - capture() - ) - - assertThat(firstValue) - .containsAllEntriesOf(extraInfo) - .hasSize(extraInfo.size) - } - } - - @Test - fun `𝕄 set native user info 𝕎 setUser() {with name}`( - @StringForgery name: String, - @MapForgery( - key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), - value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) - ) extraInfo: Map - ) { - // Given - val user = extraInfo.toMutableMap().also { - it.put("name", name) - } - - // When - testedBridgeSdk.setUser(user.toReadableMap(), mockPromise) - - // Then - argumentCaptor> { - verify(mockDatadog) - .setUser( - isNull(), - eq(name), - isNull(), - capture() - ) - - assertThat(firstValue) - .containsAllEntriesOf(extraInfo) - .hasSize(extraInfo.size) - } - } - - @Test - fun `𝕄 set native user info 𝕎 setUser() {with email}`( - @StringForgery(regex = "\\w+@\\w+\\.[a-z]{3}") email: String, - @MapForgery( - key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), - value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) - ) extraInfo: Map - ) { - // Given - val user = extraInfo.toMutableMap().also { - it.put("email", email) - } - - // When - testedBridgeSdk.setUser(user.toReadableMap(), mockPromise) - - // Then - argumentCaptor> { - verify(mockDatadog) - .setUser( - isNull(), - isNull(), - eq(email), - capture() - ) - - assertThat(firstValue) - .containsAllEntriesOf(extraInfo) - .hasSize(extraInfo.size) - } - } - - @Test - fun `𝕄 set native user info 𝕎 setUser() {with id, name and email}`( - @StringForgery id: String, - @StringForgery name: String, - @StringForgery(regex = "\\w+@\\w+\\.[a-z]{3}") email: String, - @MapForgery( - key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), - value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) - ) extraInfo: Map - ) { - // Given - val user = extraInfo.toMutableMap().also { - it.put("id", id) - it.put("name", name) - it.put("email", email) - } - - // When - testedBridgeSdk.setUser(user.toReadableMap(), mockPromise) - - // Then - argumentCaptor> { - verify(mockDatadog) - .setUser( - eq(id), - eq(name), - eq(email), - capture() - ) - - assertThat(firstValue) - .containsAllEntriesOf(extraInfo) - .hasSize(extraInfo.size) - } - } - @Test fun `𝕄 set native user info 𝕎 setUserInfo() {with id}`( @StringForgery id: String diff --git a/packages/core/ios/Sources/DdSdk.mm b/packages/core/ios/Sources/DdSdk.mm index 590452c86..918a8db03 100644 --- a/packages/core/ios/Sources/DdSdk.mm +++ b/packages/core/ios/Sources/DdSdk.mm @@ -37,13 +37,6 @@ + (void)initFromNative { [self setAttributes:attributes resolve:resolve reject:reject]; } -RCT_REMAP_METHOD(setUser, withUser:(NSDictionary*)user - withResolver:(RCTPromiseResolveBlock)resolve - withRejecter:(RCTPromiseRejectBlock)reject) -{ - [self setUser:user resolve:resolve reject:reject]; -} - RCT_REMAP_METHOD(setUserInfo, withUserInfo:(NSDictionary*)userInfo withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) @@ -146,10 +139,6 @@ - (void)setTrackingConsent:(NSString *)trackingConsent resolve:(RCTPromiseResolv [self.ddSdkImplementation setTrackingConsentWithTrackingConsent:trackingConsent resolve:resolve reject:reject]; } -- (void)setUser:(NSDictionary *)user resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - [self.ddSdkImplementation setUserWithUser:user resolve:resolve reject:reject]; -} - - (void)setUserInfo:(NSDictionary *)userInfo resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { [self.ddSdkImplementation setUserInfoWithUserInfo:userInfo resolve:resolve reject:reject]; } diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 973b8db9f..b2e610635 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -87,18 +87,6 @@ public class DdSdkImplementation: NSObject { resolve(nil) } - @objc - public func setUser(user: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { - var castedUser = castAttributesToSwift(user) - let id = castedUser.removeValue(forKey: "id") as? String - let name = castedUser.removeValue(forKey: "name") as? String - let email = castedUser.removeValue(forKey: "email") as? String - let extraInfo: [String: Encodable] = castedUser // everything what's left is an `extraInfo` - - Datadog.setUserInfo(id: id, name: name, email: email, extraInfo: extraInfo) - resolve(nil) - } - @objc public func setUserInfo(userInfo: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { let castedUserInfo = castAttributesToSwift(userInfo) @@ -115,8 +103,9 @@ public class DdSdkImplementation: NSObject { if let validId = id { Datadog.setUserInfo(id: validId, name: name, email: email, extraInfo: extraInfo) } else { - Datadog.setUserInfo(name: name, email: email, extraInfo: extraInfo) + // TO DO - log warning message? } + resolve(nil) } diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index bcc3252a8..6be5e0994 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -535,85 +535,6 @@ class DdSdkTests: XCTestCase { XCTAssertEqual(ddConfig.trackFrustrations, false) } - func testSetUser() throws { - let bridge = DdSdkImplementation( - mainDispatchQueue: DispatchQueueMock(), - jsDispatchQueue: DispatchQueueMock(), - jsRefreshRateMonitor: JSRefreshRateMonitor(), - RUMMonitorProvider: { MockRUMMonitor() }, - RUMMonitorInternalProvider: { nil } - ) - bridge.initialize( - configuration: .mockAny(), - resolve: mockResolve, - reject: mockReject - ) - - bridge.setUser( - user: NSDictionary( - dictionary: [ - "id": "id_123", - "name": "John Doe", - "email": "john@doe.com", - "extra-info-1": 123, - "extra-info-2": "abc", - "extra-info-3": true, - ] - ), - resolve: mockResolve, - reject: mockReject - ) - - let ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() - let userInfo = try XCTUnwrap(ddContext.userInfo) - - XCTAssertEqual(userInfo.id, "id_123") - XCTAssertEqual(userInfo.name, "John Doe") - XCTAssertEqual(userInfo.email, "john@doe.com") - XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, 123) - XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, "abc") - XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true) - } - - func testSetUserOptionalId() throws { - let bridge = DdSdkImplementation( - mainDispatchQueue: DispatchQueueMock(), - jsDispatchQueue: DispatchQueueMock(), - jsRefreshRateMonitor: JSRefreshRateMonitor(), - RUMMonitorProvider: { MockRUMMonitor() }, - RUMMonitorInternalProvider: { nil } - ) - bridge.initialize( - configuration: .mockAny(), - resolve: mockResolve, - reject: mockReject - ) - - bridge.setUser( - user: NSDictionary( - dictionary: [ - "name": "John Doe", - "email": "john@doe.com", - "extra-info-1": 123, - "extra-info-2": "abc", - "extra-info-3": true, - ] - ), - resolve: mockResolve, - reject: mockReject - ) - - let ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() - let userInfo = try XCTUnwrap(ddContext.userInfo) - - XCTAssertEqual(userInfo.id, nil) - XCTAssertEqual(userInfo.name, "John Doe") - XCTAssertEqual(userInfo.email, "john@doe.com") - XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, 123) - XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, "abc") - XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true) - } - func testSetUserInfo() throws { let bridge = DdSdkImplementation( mainDispatchQueue: DispatchQueueMock(), @@ -668,59 +589,6 @@ class DdSdkTests: XCTestCase { } } - func testSetUserInfoOptionalId() throws { - let bridge = DdSdkImplementation( - mainDispatchQueue: DispatchQueueMock(), - jsDispatchQueue: DispatchQueueMock(), - jsRefreshRateMonitor: JSRefreshRateMonitor(), - RUMMonitorProvider: { MockRUMMonitor() }, - RUMMonitorInternalProvider: { nil } - ) - bridge.initialize( - configuration: .mockAny(), - resolve: mockResolve, - reject: mockReject - ) - - bridge.setUserInfo( - userInfo: NSDictionary( - dictionary: [ - "name": "John Doe", - "email": "john@doe.com", - "extraInfo": [ - "extra-info-1": 123, - "extra-info-2": "abc", - "extra-info-3": true, - "extra-info-4": [ - "nested-extra-info-1": 456 - ], - ], - ] - ), - resolve: mockResolve, - reject: mockReject - ) - - let ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() - let userInfo = try XCTUnwrap(ddContext.userInfo) - - XCTAssertEqual(userInfo.id, nil) - XCTAssertEqual(userInfo.name, "John Doe") - XCTAssertEqual(userInfo.email, "john@doe.com") - XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, 123) - XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, "abc") - XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true) - - if let extraInfo4Encodable = userInfo.extraInfo["extra-info-4"] - as? DatadogSDKReactNative.AnyEncodable, - let extraInfo4Dict = extraInfo4Encodable.value as? [String: Int] - { - XCTAssertEqual(extraInfo4Dict, ["nested-extra-info-1": 456]) - } else { - XCTFail("extra-info-4 is not of expected type or value") - } - } - func testAddUserExtraInfo() throws { let bridge = DdSdkImplementation( mainDispatchQueue: DispatchQueueMock(), diff --git a/packages/core/ios/Tests/MockRUMMonitor.swift b/packages/core/ios/Tests/MockRUMMonitor.swift index fe17e7748..f0fa03364 100644 --- a/packages/core/ios/Tests/MockRUMMonitor.swift +++ b/packages/core/ios/Tests/MockRUMMonitor.swift @@ -10,6 +10,22 @@ @testable import DatadogSDKReactNative internal class MockRUMMonitor: RUMMonitorProtocol { + func addViewAttribute(forKey key: DatadogInternal.AttributeKey, value: any DatadogInternal.AttributeValue) { + // not implemented + } + + func addViewAttributes(_ attributes: [DatadogInternal.AttributeKey : any DatadogInternal.AttributeValue]) { + // not implemented + } + + func removeViewAttribute(forKey key: DatadogInternal.AttributeKey) { + // not implemented + } + + func removeViewAttributes(forKeys keys: [DatadogInternal.AttributeKey]) { + // not implemented + } + func currentSessionID(completion: @escaping (String?) -> Void) { // not implemented } diff --git a/packages/core/jest/mock.js b/packages/core/jest/mock.js index 9c08f5335..a8161295a 100644 --- a/packages/core/jest/mock.js +++ b/packages/core/jest/mock.js @@ -27,9 +27,6 @@ module.exports = { .fn() .mockImplementation(() => new Promise(resolve => resolve())), isInitialized: jest.fn().mockImplementation(() => true), - setUser: jest - .fn() - .mockImplementation(() => new Promise(resolve => resolve())), setUserInfo: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), diff --git a/packages/core/src/DdSdkReactNative.tsx b/packages/core/src/DdSdkReactNative.tsx index aa7e2ec36..668ae09f3 100644 --- a/packages/core/src/DdSdkReactNative.tsx +++ b/packages/core/src/DdSdkReactNative.tsx @@ -38,7 +38,6 @@ import { DdSdk } from './sdk/DdSdk'; import { FileBasedConfiguration } from './sdk/FileBasedConfiguration/FileBasedConfiguration'; import { GlobalState } from './sdk/GlobalState/GlobalState'; import { UserInfoSingleton } from './sdk/UserInfoSingleton/UserInfoSingleton'; -import type { UserInfo } from './sdk/UserInfoSingleton/types'; import { DdSdkConfiguration } from './types'; import { adaptLongTaskThreshold } from './utils/longTasksUtils'; import { version as sdkVersion } from './version'; @@ -192,22 +191,6 @@ export class DdSdkReactNative { AttributesSingleton.getInstance().setAttributes(attributes); }; - /** - * Set the user information. - * @deprecated UserInfo id property is now mandatory (please user setUserInfo instead) - * @param user: The user object (use builtin attributes: 'id', 'email', 'name', and/or any custom attribute). - * @returns a Promise. - */ - // eslint-disable-next-line @typescript-eslint/ban-types - static setUser = async (user: UserInfo): Promise => { - InternalLog.log( - `Setting user ${JSON.stringify(user)}`, - SdkVerbosity.DEBUG - ); - await DdSdk.setUser(user); - UserInfoSingleton.getInstance().setUserInfo(user); - }; - /** * Sets the user information. * @param id: A mandatory unique user identifier (relevant to your business domain). @@ -245,6 +228,14 @@ export class DdSdkReactNative { ); const userInfo = UserInfoSingleton.getInstance().getUserInfo(); + if (!userInfo) { + InternalLog.log( + 'Skipped adding User Extra Info: User Info is currently undefined. A user ID must be set before adding extra info. Please call setUserInfo() first.', + SdkVerbosity.WARN + ); + + return; + } const updatedUserInfo = { ...userInfo, extraInfo: { diff --git a/packages/core/src/__tests__/DdSdkReactNative.test.tsx b/packages/core/src/__tests__/DdSdkReactNative.test.tsx index 18bf060ce..f9405aa51 100644 --- a/packages/core/src/__tests__/DdSdkReactNative.test.tsx +++ b/packages/core/src/__tests__/DdSdkReactNative.test.tsx @@ -63,7 +63,6 @@ beforeEach(async () => { DdSdkReactNative['wasAutoInstrumented'] = false; NativeModules.DdSdk.initialize.mockClear(); NativeModules.DdSdk.setAttributes.mockClear(); - NativeModules.DdSdk.setUser.mockClear(); NativeModules.DdSdk.setTrackingConsent.mockClear(); NativeModules.DdSdk.onRUMSessionStarted.mockClear(); @@ -1064,21 +1063,6 @@ describe('DdSdkReactNative', () => { }); }); - describe('setUser', () => { - it('calls SDK method when setUser, and sets the user in UserProvider', async () => { - // GIVEN - const user = { id: 'id', foo: 'bar' }; - - // WHEN - await DdSdkReactNative.setUser(user); - - // THEN - expect(DdSdk.setUser).toHaveBeenCalledTimes(1); - expect(DdSdk.setUser).toHaveBeenCalledWith(user); - expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual(user); - }); - }); - describe('setUserInfo', () => { it('calls SDK method when setUserInfo, and sets the user in UserProvider', async () => { // GIVEN diff --git a/packages/core/src/logs/eventMapper.ts b/packages/core/src/logs/eventMapper.ts index eb7b5f22c..939e882a5 100644 --- a/packages/core/src/logs/eventMapper.ts +++ b/packages/core/src/logs/eventMapper.ts @@ -31,13 +31,15 @@ export const formatRawLogToNativeEvent = ( export const formatRawLogToLogEvent = ( rawLog: RawLog | RawLogWithError, additionalInformation: { - userInfo: UserInfo; + userInfo?: UserInfo; attributes: Attributes; } ): LogEvent => { + const userInfo = additionalInformation?.userInfo; + return { ...rawLog, - userInfo: additionalInformation.userInfo, + ...(userInfo !== undefined ? { userInfo } : {}), attributes: additionalInformation.attributes }; }; diff --git a/packages/core/src/sdk/EventMappers/EventMapper.ts b/packages/core/src/sdk/EventMappers/EventMapper.ts index beafcf420..9ca252d72 100644 --- a/packages/core/src/sdk/EventMappers/EventMapper.ts +++ b/packages/core/src/sdk/EventMappers/EventMapper.ts @@ -15,7 +15,7 @@ import type { UserInfo } from '../UserInfoSingleton/types'; import { deepClone } from './utils/deepClone'; export type AdditionalEventDataForMapper = { - userInfo: UserInfo; + userInfo?: UserInfo; attributes: Attributes; }; diff --git a/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts b/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts index c3862aabc..26392d794 100644 --- a/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts +++ b/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts @@ -7,13 +7,13 @@ import type { UserInfo } from './types'; class UserInfoProvider { - private userInfo: UserInfo = {}; + private userInfo: UserInfo | undefined = undefined; setUserInfo = (userInfo: UserInfo) => { this.userInfo = userInfo; }; - getUserInfo = (): UserInfo => { + getUserInfo = (): UserInfo | undefined => { return this.userInfo; }; } diff --git a/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts b/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts index 78a722c01..1f7ae84e7 100644 --- a/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts +++ b/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts @@ -9,6 +9,7 @@ import { UserInfoSingleton } from '../UserInfoSingleton'; describe('UserInfoSingleton', () => { it('sets, returns and resets the user info', () => { UserInfoSingleton.getInstance().setUserInfo({ + id: 'test', email: 'user@mail.com', extraInfo: { loggedIn: true @@ -16,6 +17,7 @@ describe('UserInfoSingleton', () => { }); expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual({ + id: 'test', email: 'user@mail.com', extraInfo: { loggedIn: true @@ -24,6 +26,8 @@ describe('UserInfoSingleton', () => { UserInfoSingleton.reset(); - expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual({}); + expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual( + undefined + ); }); }); diff --git a/packages/core/src/sdk/UserInfoSingleton/types.ts b/packages/core/src/sdk/UserInfoSingleton/types.ts index 97a03ae7f..dd14eb150 100644 --- a/packages/core/src/sdk/UserInfoSingleton/types.ts +++ b/packages/core/src/sdk/UserInfoSingleton/types.ts @@ -5,11 +5,8 @@ */ export type UserInfo = { - readonly id?: string /** @deprecated To be made mandatory when removing DdSdkReactnative.setUser */; + readonly id: string; readonly name?: string; readonly email?: string; readonly extraInfo?: Record; - readonly [ - key: string - ]: unknown /** @deprecated To be removed alongside DdSdkReactnative.setUser */; }; diff --git a/packages/core/src/specs/NativeDdSdk.ts b/packages/core/src/specs/NativeDdSdk.ts index 6f1ce82a5..bbf2572ee 100644 --- a/packages/core/src/specs/NativeDdSdk.ts +++ b/packages/core/src/specs/NativeDdSdk.ts @@ -31,13 +31,6 @@ export interface Spec extends TurboModule { */ setAttributes(attributes: Object): Promise; - /** - * Set the user information. - * @deprecated: Use setUserInfo instead - * @param user: The user object (use builtin attributes: 'id', 'email', 'name', and/or any custom attribute). - */ - setUser(user: Object): Promise; - /** * Set the user information. * @param user: The user object (use builtin attributes: 'id', 'email', 'name', and any custom attribute under extraInfo). diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index e1c5096fb..fe1a5895c 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -5,7 +5,6 @@ */ import type { BatchProcessingLevel } from './DdSdkReactNativeConfiguration'; -import type { UserInfo as UserInfoSingleton } from './sdk/UserInfoSingleton/types'; declare global { // eslint-disable-next-line no-var, vars-on-top @@ -90,13 +89,6 @@ export type DdSdkType = { */ setAttributes(attributes: object): Promise; - /** - * Sets the user information. - * @deprecated UserInfo id property is now mandatory (please user setUserInfo instead) - * @param user: The user object (use builtin attributes: 'id', 'email', 'name', and/or any custom attribute). - */ - setUser(user: object): Promise; - /** * Sets the user information. * @param id: A unique user identifier (relevant to your business domain) @@ -173,7 +165,7 @@ export type LogEvent = { readonly source?: ErrorSource; // readonly date: number; // TODO: RUMM-2446 & RUMM-2447 readonly status: LogStatus; - readonly userInfo: UserInfoSingleton; + readonly userInfo?: UserInfo; readonly attributes?: object; }; diff --git a/packages/react-native-apollo-client/__mocks__/react-native.ts b/packages/react-native-apollo-client/__mocks__/react-native.ts index b35df4e31..046ced2f6 100644 --- a/packages/react-native-apollo-client/__mocks__/react-native.ts +++ b/packages/react-native-apollo-client/__mocks__/react-native.ts @@ -18,9 +18,6 @@ actualRN.NativeModules.DdSdk = { initialize: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, - setUser: jest.fn().mockImplementation( - () => new Promise(resolve => resolve()) - ) as jest.MockedFunction, setAttributes: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, From 75bd308b581d4ba2217625401e414e4209cfdc54 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 12 Sep 2025 17:09:36 +0200 Subject: [PATCH 30/62] Update Tracer imports for Android to remove opentracing dependencies --- .../reactnative/DdTraceImplementation.kt | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTraceImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTraceImplementation.kt index 901ec3f6a..3ed77eb75 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTraceImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdTraceImplementation.kt @@ -6,30 +6,28 @@ package com.datadog.reactnative -import com.datadog.android.trace.AndroidTracer -import com.datadog.android.trace.Trace -import com.datadog.android.trace.TraceConfiguration +import com.datadog.android.Datadog +import com.datadog.android.trace.DatadogTracing import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReadableMap -import io.opentracing.Scope -import io.opentracing.Span -import io.opentracing.Tracer -import io.opentracing.util.GlobalTracer +import com.datadog.android.trace.api.scope.DatadogScope +import com.datadog.android.trace.api.span.DatadogSpan +import com.datadog.android.trace.api.tracer.DatadogTracer +import com.datadog.android.trace.GlobalDatadogTracer import java.util.concurrent.TimeUnit /** * The entry point to use Datadog's Trace feature. */ class DdTraceImplementation( - private val tracerProvider: () -> Tracer = { - val tracer = AndroidTracer.Builder().build() - GlobalTracer.registerIfAbsent(tracer) - - GlobalTracer.get() + private val tracerProvider: () -> DatadogTracer = { + val tracer = DatadogTracing.newTracerBuilder(Datadog.getInstance()).build() + GlobalDatadogTracer.registerIfAbsent(tracer) + GlobalDatadogTracer.get() } ) { - private val spanMap: MutableMap = mutableMapOf() - private val scopeMap: MutableMap = mutableMapOf() + private val spanMap: MutableMap = mutableMapOf() + private val scopeMap: MutableMap = mutableMapOf() // lazy here is on purpose. The thing is that this class will be instantiated even // before Sdk.initialize is called, but Tracer can be created only after SDK is initialized. @@ -47,15 +45,18 @@ class DdTraceImplementation( .start() // This is required for traces to be able to be bundled with logs. - val scope = tracer.scopeManager().activate(span) - + val scope = tracer.activateSpan(span) val spanContext = span.context() span.setTags(context.toHashMap()) span.setTags(GlobalState.globalAttributes) - val spanId = spanContext.toSpanId() + val spanId = spanContext.spanId.toString() + spanMap[spanId] = span - scopeMap[spanId] = scope + if (scope != null) { + scopeMap[spanId] = scope + } + promise.resolve(spanId) } @@ -82,7 +83,7 @@ class DdTraceImplementation( promise.resolve(null) } - private fun Span.setTags(tags: Map) { + private fun DatadogSpan.setTags(tags: Map) { for ((key, value) in tags) { when (value) { is Boolean -> setTag(key, value) From 07bad39940eb9e2ce3ddda7ee5bc52e1be6bd849 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Thu, 18 Sep 2025 10:13:53 +0200 Subject: [PATCH 31/62] Fix android tests --- .../com/datadog/reactnative/DdTraceTest.kt | 84 ++++++++++--------- .../com/datadog/tools/unit/MockRumMonitor.kt | 10 +-- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdTraceTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdTraceTest.kt index 16d459a57..8c22f88e1 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdTraceTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdTraceTest.kt @@ -6,6 +6,12 @@ package com.datadog.reactnative +import com.datadog.android.trace.api.scope.DatadogScope +import com.datadog.android.trace.api.span.DatadogSpan +import com.datadog.android.trace.api.span.DatadogSpanBuilder +import com.datadog.android.trace.api.span.DatadogSpanContext +import com.datadog.android.trace.api.trace.DatadogTraceId +import com.datadog.android.trace.api.tracer.DatadogTracer import com.datadog.tools.unit.toReadableMap import com.facebook.react.bridge.Promise import fr.xgouchet.elmyr.annotation.AdvancedForgery @@ -15,11 +21,6 @@ import fr.xgouchet.elmyr.annotation.MapForgery import fr.xgouchet.elmyr.annotation.StringForgery import fr.xgouchet.elmyr.annotation.StringForgeryType import fr.xgouchet.elmyr.junit5.ForgeExtension -import io.opentracing.Scope -import io.opentracing.ScopeManager -import io.opentracing.Span -import io.opentracing.SpanContext -import io.opentracing.Tracer import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assumptions.assumeTrue @@ -51,22 +52,19 @@ internal class DdTraceTest { lateinit var testedTrace: DdTraceImplementation @Mock - lateinit var mockTracer: Tracer + lateinit var mockTracer: DatadogTracer @Mock - lateinit var mockSpanBuilder: Tracer.SpanBuilder + lateinit var mockSpanBuilder: DatadogSpanBuilder @Mock - lateinit var mockSpanContext: SpanContext + lateinit var mockSpanContext: DatadogSpanContext @Mock - lateinit var mockScopeManager: ScopeManager + lateinit var mockSpan: DatadogSpan @Mock - lateinit var mockSpan: Span - - @Mock - lateinit var mockScope: Scope + lateinit var mockScope: DatadogScope @StringForgery lateinit var fakeOperation: String @@ -74,11 +72,11 @@ internal class DdTraceTest { @DoubleForgery(1000000000000.0, 2000000000000.0) var fakeTimestamp: Double = 0.0 - @StringForgery(type = StringForgeryType.HEXADECIMAL) - lateinit var fakeSpanId: String + @LongForgery(100L, 2000L) + var fakeSpanId: Long = 0 - @StringForgery(type = StringForgeryType.HEXADECIMAL) - lateinit var fakeTraceId: String + @Mock + lateinit var fakeTraceId: DatadogTraceId @MapForgery( key = AdvancedForgery(string = [StringForgery()]), @@ -102,7 +100,6 @@ internal class DdTraceTest { @BeforeEach fun `set up`() { whenever(mockTracer.buildSpan(fakeOperation)) doReturn mockSpanBuilder - whenever(mockTracer.scopeManager()) doReturn mockScopeManager whenever( mockSpanBuilder.withStartTimestamp( fakeTimestamp.toLong() * 1000 @@ -110,9 +107,9 @@ internal class DdTraceTest { ) doReturn mockSpanBuilder whenever(mockSpanBuilder.start()) doReturn mockSpan whenever(mockSpan.context()) doReturn mockSpanContext - whenever(mockSpanContext.toSpanId()) doReturn fakeSpanId - whenever(mockSpanContext.toTraceId()) doReturn fakeTraceId - whenever(mockScopeManager.activate(mockSpan)) doReturn mockScope + whenever(mockSpanContext.spanId) doReturn fakeSpanId + whenever(mockSpanContext.traceId) doReturn fakeTraceId + whenever(mockTracer.activateSpan(mockSpan)) doReturn mockScope testedTrace = DdTraceImplementation(tracerProvider = { mockTracer }) } @@ -133,7 +130,7 @@ internal class DdTraceTest { ) // Then - assertThat(lastResolvedValue).isEqualTo(fakeSpanId) + assertThat(lastResolvedValue.toString()).isEqualTo(fakeSpanId.toString()) } @Test @@ -154,18 +151,20 @@ internal class DdTraceTest { fakeTimestamp, mockPromise ) - val id = lastResolvedValue - testedTrace.finishSpan(id as String, fakeContext.toReadableMap(), endTimestamp, mockPromise) + val id = lastResolvedValue.toString() + testedTrace.finishSpan(id, fakeContext.toReadableMap(), endTimestamp, mockPromise) // Then - assertThat(id).isEqualTo(fakeSpanId) + assertThat(id).isEqualTo(fakeSpanId.toString()) verify(mockSpan).finish(endTimestamp.toLong() * 1000) } @Test fun `M do nothing W startSpan() + finishSpan() with unknown id`( @LongForgery(100L, 2000L) duration: Long, - @StringForgery(type = StringForgeryType.HEXADECIMAL) otherSpanId: String + @StringForgery(type = StringForgeryType.HEXADECIMAL) + @LongForgery(100L, 2000L) + otherSpanId: Long ) { // Given assumeTrue(otherSpanId != fakeSpanId) @@ -178,11 +177,16 @@ internal class DdTraceTest { fakeTimestamp, mockPromise ) - val id = lastResolvedValue - testedTrace.finishSpan(otherSpanId, fakeContext.toReadableMap(), endTimestamp, mockPromise) + val id = lastResolvedValue.toString() + testedTrace.finishSpan( + otherSpanId.toString(), + fakeContext.toReadableMap(), + endTimestamp, + mockPromise + ) // Then - assertThat(id).isEqualTo(fakeSpanId) + assertThat(id).isEqualTo(fakeSpanId.toString()) verify(mockSpan, never()).finish(any()) } @@ -200,7 +204,7 @@ internal class DdTraceTest { fakeTimestamp, mockPromise ) - val id = lastResolvedValue + val id = lastResolvedValue.toString() testedTrace.finishSpan( id as String, emptyMap().toReadableMap(), @@ -209,7 +213,7 @@ internal class DdTraceTest { ) // Then - assertThat(id).isEqualTo(fakeSpanId) + assertThat(id).isEqualTo(fakeSpanId.toString()) verify(mockSpan).context() verify(mockSpan).finish(endTimestamp.toLong() * 1000) fakeContext.forEach { @@ -232,11 +236,11 @@ internal class DdTraceTest { fakeTimestamp, mockPromise ) - val id = lastResolvedValue - testedTrace.finishSpan(id as String, fakeContext.toReadableMap(), endTimestamp, mockPromise) + val id = lastResolvedValue.toString() + testedTrace.finishSpan(id, fakeContext.toReadableMap(), endTimestamp, mockPromise) // Then - assertThat(id).isEqualTo(fakeSpanId) + assertThat(id).isEqualTo(fakeSpanId.toString()) verify(mockSpan).context() verify(mockSpan).finish(endTimestamp.toLong() * 1000) fakeContext.forEach { @@ -262,16 +266,16 @@ internal class DdTraceTest { fakeTimestamp, mockPromise ) - val id = lastResolvedValue + val id = lastResolvedValue.toString() testedTrace.finishSpan( - id as String, + id, emptyMap().toReadableMap(), endTimestamp, mockPromise ) // Then - assertThat(id).isEqualTo(fakeSpanId) + assertThat(id).isEqualTo(fakeSpanId.toString()) verify(mockSpan).context() verify(mockSpan).finish(endTimestamp.toLong() * 1000) fakeContext.forEach { @@ -298,14 +302,14 @@ internal class DdTraceTest { fakeTimestamp, mockPromise ) - val id = lastResolvedValue + val id = lastResolvedValue.toString() fakeGlobalState.forEach { (k, v) -> GlobalState.addAttribute(k, v) } - testedTrace.finishSpan(id as String, fakeContext.toReadableMap(), endTimestamp, mockPromise) + testedTrace.finishSpan(id, fakeContext.toReadableMap(), endTimestamp, mockPromise) // Then - assertThat(id).isEqualTo(fakeSpanId) + assertThat(id).isEqualTo(fakeSpanId.toString()) verify(mockSpan).context() verify(mockSpan).finish(endTimestamp.toLong() * 1000) expectedAttributes.forEach { diff --git a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt index a2e79d630..7c5585edd 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt @@ -29,6 +29,8 @@ class MockRumMonitor : RumMonitor { override fun addAttribute(key: String, value: Any?) {} + override fun addViewAttributes(attributes: Map) {} + override fun addError( message: String, source: RumErrorSource, @@ -61,6 +63,7 @@ class MockRumMonitor : RumMonitor { override fun getCurrentSessionId(callback: (String?) -> Unit) {} override fun removeAttribute(key: String) {} + override fun removeViewAttributes(attributes: Collection) {} override fun startAction( type: RumActionType, @@ -75,13 +78,6 @@ class MockRumMonitor : RumMonitor { attributes: Map ) {} - override fun startResource( - key: String, - method: String, - url: String, - attributes: Map - ) {} - override fun startView( key: Any, name: String, From f3a7954c64e23ac6bd6fb97736acf316bc852c52 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Thu, 18 Sep 2025 10:50:27 +0200 Subject: [PATCH 32/62] Fix iOS tests --- packages/core/ios/Tests/DdSdkTests.swift | 2 +- packages/core/ios/Tests/RUMMocks.swift | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index 6be5e0994..555ce4549 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -738,7 +738,7 @@ class DdSdkTests: XCTestCase { XCTAssertEqual(actualFirstPartyHosts, expectedFirstPartyHosts) XCTAssertEqual(actualTracingSamplingRate, 66) - XCTAssertEqual(actualTraceContextInjection, .all) + XCTAssertEqual(actualTraceContextInjection, .sampled) } func testBuildTelemetrySampleRate() { diff --git a/packages/core/ios/Tests/RUMMocks.swift b/packages/core/ios/Tests/RUMMocks.swift index 6a6fd94e7..01d0f9d0d 100644 --- a/packages/core/ios/Tests/RUMMocks.swift +++ b/packages/core/ios/Tests/RUMMocks.swift @@ -213,14 +213,14 @@ extension RUMActionID: RandomMockable { } } -extension RUMDevice.RUMDeviceType: RandomMockable { - static func mockRandom() -> RUMDevice.RUMDeviceType { +extension Device.DeviceType: RandomMockable { + static func mockRandom() -> Device.DeviceType { return [.mobile, .desktop, .tablet, .tv, .gamingConsole, .bot, .other].randomElement()! } } -extension RUMDevice: RandomMockable { - static func mockRandom() -> RUMDevice { +extension Device: RandomMockable { + static func mockRandom() -> Device { return .init( architecture: .mockRandom(), brand: .mockRandom(), @@ -231,8 +231,8 @@ extension RUMDevice: RandomMockable { } } -extension RUMOperatingSystem: RandomMockable { - static func mockRandom() -> RUMOperatingSystem { +extension OperatingSystem: RandomMockable { + static func mockRandom() -> OperatingSystem { return .init( build: .mockRandom(length: 5), name: .mockRandom(length: 5), From a19a7316fa5953718696b8f9fc92872a22144e08 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 19 Sep 2025 11:45:00 +0200 Subject: [PATCH 33/62] Bump Native SDKs to 3.1.0 --- benchmarks/android/app/build.gradle | 2 +- benchmarks/ios/Podfile.lock | 70 +++++++-------- example-new-architecture/ios/Podfile.lock | 66 +++++++------- example/ios/Podfile.lock | 88 +++++++++---------- packages/core/DatadogSDKReactNative.podspec | 12 +-- packages/core/android/build.gradle | 10 +-- .../com/datadog/tools/unit/MockRumMonitor.kt | 23 +++++ packages/core/ios/Tests/DdLogsTests.swift | 2 + ...DatadogSDKReactNativeSessionReplay.podspec | 2 +- .../android/build.gradle | 4 +- .../DatadogSDKReactNativeWebView.podspec | 4 +- .../react-native-webview/android/build.gradle | 2 +- 12 files changed, 155 insertions(+), 130 deletions(-) diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle index 7dc4b3707..04c240bd0 100644 --- a/benchmarks/android/app/build.gradle +++ b/benchmarks/android/app/build.gradle @@ -129,5 +129,5 @@ dependencies { // Benchmark tools from dd-sdk-android are used for vitals recording // Remember to bump thid alongside the main dd-sdk-android dependencies - implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.0.0") + implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.1.0") } diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 90043a48d..1be186d5f 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogCrashReporting (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogCore (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogCrashReporting (3.1.0): + - DatadogInternal (= 3.1.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.0.0) - - DatadogLogs (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogRUM (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogInternal (3.1.0) + - DatadogLogs (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogRUM (3.1.0): + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -39,7 +39,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.0.0) + - DatadogSessionReplay (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -61,9 +61,9 @@ PODS: - ReactCommon/turbomodule/core - Yoga - DatadogSDKReactNativeWebView (2.12.1): - - DatadogInternal (= 3.0.0) + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.0.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -84,13 +84,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSessionReplay (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogTrace (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogSessionReplay (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogTrace (3.1.0): + - DatadogInternal (= 3.1.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogWebViewTracking (3.1.0): + - DatadogInternal (= 3.1.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.78.2) @@ -2070,17 +2070,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 - DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e - DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 - DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd - DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f - DatadogSDKReactNative: 241bf982c16ceff03d94a58e6d005e55c47b99c6 - DatadogSDKReactNativeSessionReplay: bba36092686e3183e97c1a0c7f4ca8142582ae28 - DatadogSDKReactNativeWebView: 6da060df20e235abac533e582d9fc2b3a5070840 - DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 - DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 - DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 + DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d + DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d + DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc + DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 + DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 + DatadogSDKReactNative: 8e0f39de38621d4d7ed961a74d8a216fd3a38321 + DatadogSDKReactNativeSessionReplay: f9288c8e981dcc65d1f727b01421ee9a7601e75f + DatadogSDKReactNativeWebView: 993527f6c5d38e0fcc4804a6a60c334dd199dc5b + DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 + DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 + DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index cc9913ce3..0378f5d72 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogCrashReporting (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogCore (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogCrashReporting (3.1.0): + - DatadogInternal (= 3.1.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.0.0) - - DatadogLogs (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogRUM (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogInternal (3.1.0) + - DatadogLogs (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogRUM (3.1.0): + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -38,12 +38,12 @@ PODS: - ReactCommon/turbomodule/core - Yoga - DatadogSDKReactNative/Tests (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -64,11 +64,11 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogTrace (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogTrace (3.1.0): + - DatadogInternal (= 3.1.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogWebViewTracking (3.1.0): + - DatadogInternal (= 3.1.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1850,14 +1850,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 - DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e - DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 - DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd - DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f - DatadogSDKReactNative: 0a80aa75958d595a99be54d2838db53eda7a08af - DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 - DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 + DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d + DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d + DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc + DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 + DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 + DatadogSDKReactNative: 069ea9876220b2d09b0f4b180ce571b1b6ecbb35 + DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 + DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f93f0ee07..94d93b3c2 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,34 +1,34 @@ PODS: - boost (1.84.0) - - DatadogCore (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogCrashReporting (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogCore (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogCrashReporting (3.1.0): + - DatadogInternal (= 3.1.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.0.0) - - DatadogLogs (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogRUM (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogInternal (3.1.0) + - DatadogLogs (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogRUM (3.1.0): + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - DatadogSDKReactNative/Tests (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.0.0) + - DatadogSessionReplay (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -51,7 +51,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay/Tests (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.0.0) + - DatadogSessionReplay (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -74,24 +74,24 @@ PODS: - ReactCommon/turbomodule/core - Yoga - DatadogSDKReactNativeWebView (2.12.1): - - DatadogInternal (= 3.0.0) + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.0.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - DatadogSDKReactNativeWebView/Tests (2.12.1): - - DatadogInternal (= 3.0.0) + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.0.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - react-native-webview - React-RCTText - - DatadogSessionReplay (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogTrace (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogSessionReplay (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogTrace (3.1.0): + - DatadogInternal (= 3.1.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogWebViewTracking (3.1.0): + - DatadogInternal (= 3.1.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1988,17 +1988,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 - DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e - DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 - DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd - DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f - DatadogSDKReactNative: e430b3f4d7adb0fac07b61e2fb65ceacdaf82b3e - DatadogSDKReactNativeSessionReplay: 4b2a3d166a79581f18522795b40141c34cf3685d - DatadogSDKReactNativeWebView: 35dc2b9736e1aaa82b366bf6b8a8a959a9b088c5 - DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 - DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 - DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 + DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d + DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d + DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc + DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 + DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 + DatadogSDKReactNative: af351a4e1ce08124c290c52de94b0062a166cc67 + DatadogSDKReactNativeSessionReplay: dcbd55d9d0f2b86026996a8b7ec9654922d5dfe1 + DatadogSDKReactNativeWebView: 096ac87eb753b6a217b93441983264b9837c3b7e + DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 + DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 + DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index a2f41ddd1..c0d235304 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -19,14 +19,14 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the versions in sync with DatadogSDKReactNativeSessionReplay.podspec - s.dependency 'DatadogCore', '3.0.0' - s.dependency 'DatadogLogs', '3.0.0' - s.dependency 'DatadogTrace', '3.0.0' - s.dependency 'DatadogRUM', '3.0.0' - s.dependency 'DatadogCrashReporting', '3.0.0' + s.dependency 'DatadogCore', '3.1.0' + s.dependency 'DatadogLogs', '3.1.0' + s.dependency 'DatadogTrace', '3.1.0' + s.dependency 'DatadogRUM', '3.1.0' + s.dependency 'DatadogCrashReporting', '3.1.0' # DatadogWebViewTracking is not available for tvOS - s.ios.dependency 'DatadogWebViewTracking', '3.0.0' + s.ios.dependency 'DatadogWebViewTracking', '3.1.0' s.test_spec 'Tests' do |test_spec| test_spec.source_files = 'ios/Tests/**/*.{swift,json}' diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index a8d09d4d1..59bb75cc3 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -201,16 +201,16 @@ dependencies { // This breaks builds if the React Native target is below 0.76.0. as it relies on Gradle 8.5.0. // To avoid this, we enforce 1.0.0-beta01 on RN < 0.76.0 if (reactNativeMinorVersion < 76) { - implementation("com.datadoghq:dd-sdk-android-rum:3.0.0") { + implementation("com.datadoghq:dd-sdk-android-rum:3.1.0") { exclude group: "androidx.metrics", module: "metrics-performance" } implementation "androidx.metrics:metrics-performance:1.0.0-beta01" } else { - implementation "com.datadoghq:dd-sdk-android-rum:3.0.0" + implementation "com.datadoghq:dd-sdk-android-rum:3.1.0" } - implementation "com.datadoghq:dd-sdk-android-logs:3.0.0" - implementation "com.datadoghq:dd-sdk-android-trace:3.0.0" - implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" + implementation "com.datadoghq:dd-sdk-android-logs:3.1.0" + implementation "com.datadoghq:dd-sdk-android-trace:3.1.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" implementation "com.google.code.gson:gson:2.10.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt index 7c5585edd..702cc2533 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt @@ -13,6 +13,7 @@ import com.datadog.android.rum.RumMonitor import com.datadog.android.rum.RumResourceKind import com.datadog.android.rum.RumResourceMethod import com.datadog.android.rum._RumInternalProxy +import com.datadog.android.rum.featureoperations.FailureReason class MockRumMonitor : RumMonitor { override var debug = false @@ -123,4 +124,26 @@ class MockRumMonitor : RumMonitor { key: Any, attributes: Map ) {} + + @ExperimentalRumApi + override fun startFeatureOperation( + name: String, + operationKey: String?, + attributes: Map + ) {} + + @ExperimentalRumApi + override fun succeedFeatureOperation( + name: String, + operationKey: String?, + attributes: Map + ) {} + + @ExperimentalRumApi + override fun failFeatureOperation( + name: String, + operationKey: String?, + failureReason: FailureReason, + attributes: Map + ) {} } diff --git a/packages/core/ios/Tests/DdLogsTests.swift b/packages/core/ios/Tests/DdLogsTests.swift index 2d9fdebac..60640e807 100644 --- a/packages/core/ios/Tests/DdLogsTests.swift +++ b/packages/core/ios/Tests/DdLogsTests.swift @@ -463,6 +463,8 @@ private class MockNativeLogger: LoggerProtocol { } extension MockNativeLogger: InternalLoggerProtocol { + func critical(message: String, error: (any Error)?, attributes: [String : any Encodable]?, completionHandler: @escaping DatadogInternal.CompletionHandler) {} + func log(level: DatadogLogs.LogLevel, message: String, errorKind: String?, errorMessage: String?, stackTrace: String?, attributes: [String : Encodable]?) { receivedMethodCalls.append(MethodCall( kind: MockNativeLogger.MethodCall.Kind(from: level), diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 3a2d5ff48..6a5d0b78f 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogSessionReplay', '3.0.0' + s.dependency 'DatadogSessionReplay', '3.1.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index 6d6fe20b1..a0d77f2ff 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -216,8 +216,8 @@ dependencies { api "com.facebook.react:react-android:$reactNativeVersion" } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.datadoghq:dd-sdk-android-session-replay:3.0.0" - implementation "com.datadoghq:dd-sdk-android-internal:3.0.0" + implementation "com.datadoghq:dd-sdk-android-session-replay:3.1.0" + implementation "com.datadoghq:dd-sdk-android-internal:3.1.0" implementation project(path: ':datadog_mobile-react-native') testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 26e160bbc..080a853d8 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -23,8 +23,8 @@ Pod::Spec.new do |s| end # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogWebViewTracking', '3.0.0' - s.dependency 'DatadogInternal', '3.0.0' + s.dependency 'DatadogWebViewTracking', '3.1.0' + s.dependency 'DatadogInternal', '3.1.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-webview/android/build.gradle b/packages/react-native-webview/android/build.gradle index 098eae019..87ca1b7e7 100644 --- a/packages/react-native-webview/android/build.gradle +++ b/packages/react-native-webview/android/build.gradle @@ -190,7 +190,7 @@ dependencies { implementation "com.facebook.react:react-android:$reactNativeVersion" } - implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation project(path: ':datadog_mobile-react-native') From 3821b5b85d1b6b970ee6a2065309c47e4649b77a Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 19 Sep 2025 14:33:51 +0200 Subject: [PATCH 34/62] Fix internaltTestingTools tests --- .../DdInternalTestingImplementation.kt | 45 ++++++++------- .../DdInternalTestingImplementationTest.kt | 55 ++++++++++++------- 2 files changed, 60 insertions(+), 40 deletions(-) diff --git a/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt b/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt index b33bef6de..0d548aa72 100644 --- a/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt +++ b/packages/internal-testing-tools/android/src/main/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementation.kt @@ -6,11 +6,13 @@ package com.datadog.reactnative.internaltesting +import androidx.annotation.WorkerThread import com.datadog.android.api.InternalLogger import com.datadog.android.Datadog import com.datadog.android.api.context.DatadogContext import com.datadog.android.api.context.NetworkInfo import com.datadog.android.api.context.TimeInfo +import com.datadog.android.api.feature.EventWriteScope import com.datadog.android.api.feature.Feature import com.datadog.android.api.feature.FeatureScope import com.datadog.android.api.storage.EventBatchWriter @@ -112,53 +114,54 @@ internal class FeatureScopeInterceptor( private val featureScope: FeatureScope, private val core: InternalSdkCore, ) : FeatureScope by featureScope { - private val eventsBatchInterceptor = EventBatchInterceptor() + private val eventWriteScopeInterceptor = EventWriteScopeInterceptor() fun eventsWritten(): List { - return eventsBatchInterceptor.events + return eventWriteScopeInterceptor.events } fun clearData() { - eventsBatchInterceptor.clearData() + eventWriteScopeInterceptor.clearData() } // region FeatureScope override fun withWriteContext( - forceNewBatch: Boolean, - callback: (DatadogContext, EventBatchWriter) -> Unit + withFeatureContexts: Set, + callback: (datadogContext: DatadogContext, write: EventWriteScope) -> Unit ) { - featureScope.withWriteContext(forceNewBatch, callback) + featureScope.withWriteContext(withFeatureContexts, callback) core.getDatadogContext()?.let { - callback(it, eventsBatchInterceptor) + callback(it, eventWriteScopeInterceptor) } } // endregion } - -internal class EventBatchInterceptor: EventBatchWriter { +internal class EventWriteScopeInterceptor : EventWriteScope { internal val events = mutableListOf() - override fun currentMetadata(): ByteArray? { - return null - } - fun clearData() { events.clear() } - override fun write( - event: RawBatchEvent, - batchMetadata: ByteArray?, - eventType: EventType - ): Boolean { - val eventContent = String(event.data) + private val writer = object : EventBatchWriter { + override fun currentMetadata(): ByteArray? = null - events += eventContent + override fun write( + event: RawBatchEvent, + batchMetadata: ByteArray?, + eventType: EventType + ): Boolean { + events += String(event.data) + return true + } + } - return true + override fun invoke(p1: (EventBatchWriter) -> Unit) { + p1(writer) } } + diff --git a/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt b/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt index 4a6938f9b..d25db9274 100644 --- a/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt +++ b/packages/internal-testing-tools/android/src/test/kotlin/com/datadog/reactnative/internaltesting/DdInternalTestingImplementationTest.kt @@ -10,9 +10,9 @@ import android.content.Context import com.datadog.android.Datadog import com.datadog.android.api.SdkCore import com.datadog.android.api.context.DatadogContext +import com.datadog.android.api.feature.EventWriteScope import com.datadog.android.api.feature.Feature import com.datadog.android.api.feature.FeatureScope -import com.datadog.android.api.storage.EventBatchWriter import com.datadog.android.api.storage.EventType import com.datadog.android.api.storage.RawBatchEvent import com.datadog.android.api.storage.datastore.DataStoreHandler @@ -85,23 +85,27 @@ internal class DdInternalTestingImplementationTest { wrappedCore.registerFeature(mockFeature) requireNotNull(wrappedCore.getFeature(mockFeature.name)) - .withWriteContext { _, eventBatchWriter -> - eventBatchWriter.write( - RawBatchEvent(data = "mock event for test".toByteArray()), - batchMetadata = null, - eventType = EventType.DEFAULT + .withWriteContext { _, writeScope -> + writeScope { + val rawBatchEvent = + RawBatchEvent(data = "mock event for test".toByteArray()) + it.write( + rawBatchEvent, + batchMetadata = null, + eventType = EventType.DEFAULT + ) + } + + // Then + assertThat( + wrappedCore.featureScopes[mockFeature.name] + ?.eventsWritten() + ?.first() ) + .isEqualTo( + "mock event for test" + ) } - - // Then - assertThat( - wrappedCore.featureScopes[mockFeature.name] - ?.eventsWritten() - ?.first() - ) - .isEqualTo( - "mock event for test" - ) } } } @@ -116,10 +120,23 @@ internal class MockFeatureScope(private val feature: Feature) : FeatureScope { return feature as T } + override fun withContext( + withFeatureContexts: Set, + callback: (datadogContext: DatadogContext) -> Unit + ) { + } + override fun withWriteContext( - forceNewBatch: Boolean, - callback: (DatadogContext, EventBatchWriter) -> Unit - ) {} + withFeatureContexts: Set, + callback: (datadogContext: DatadogContext, write: EventWriteScope) -> Unit + ) { + } + + override fun getWriteContextSync( + withFeatureContexts: Set + ): Pair? { + return TODO("Provide the return value") + } } internal class MockFeature(override val name: String) : Feature { From 89ed52e4f98427ef7168846833f4c4caf350a3c6 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 5 Sep 2025 17:47:29 +0200 Subject: [PATCH 35/62] Use native sdk's core instance instead of the one inside RN SDK wrapper --- .../com/datadog/reactnative/DdSdkNativeInitialization.kt | 2 ++ .../src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt | 6 +----- .../src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt | 7 +------ 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt index 4388ad5f6..ee55d08fe 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt @@ -65,7 +65,9 @@ class DdSdkNativeInitialization internal constructor( datadog.initialize(appContext, sdkConfiguration, trackingConsent) Rum.enable(rumConfiguration, Datadog.getInstance()) + Logs.enable(logsConfiguration, Datadog.getInstance()) + Trace.enable(traceConfiguration, Datadog.getInstance()) } diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index 97acb2ebf..3c86e28b4 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -21,11 +21,7 @@ class DdSdk( ddTelemetry: DdTelemetry = DdTelemetry() ) : ReactContextBaseJavaModule(reactContext) { - private val implementation = DdSdkImplementation( - reactContext, - datadog = datadogWrapper, - ddTelemetry - ) + private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper, ddTelemetry) private var lifecycleEventListener: LifecycleEventListener? = null override fun getName(): String = DdSdkImplementation.NAME diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index 8797bcc64..c9f91738f 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -163,12 +163,7 @@ internal class DdSdkTest { answer.getArgument(0).run() true } - testedBridgeSdk = DdSdkImplementation( - mockReactContext, - mockDatadog, - mockDdTelemetry, - TestUiThreadExecutor() - ) + testedBridgeSdk = DdSdkImplementation(mockReactContext, mockDatadog, mockDdTelemetry, TestUiThreadExecutor()) DatadogSDKWrapperStorage.onInitializedListeners.clear() } From 2340b9b77fcf4c307556c859cf2a9c83aa455718 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Mon, 22 Sep 2025 16:20:27 +0200 Subject: [PATCH 36/62] Fixed internal testing tools and unit tests --- .../com/datadog/reactnative/DdSdkNativeInitialization.kt | 2 -- .../src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt | 6 +++++- .../src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt | 7 ++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt index ee55d08fe..4388ad5f6 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt @@ -65,9 +65,7 @@ class DdSdkNativeInitialization internal constructor( datadog.initialize(appContext, sdkConfiguration, trackingConsent) Rum.enable(rumConfiguration, Datadog.getInstance()) - Logs.enable(logsConfiguration, Datadog.getInstance()) - Trace.enable(traceConfiguration, Datadog.getInstance()) } diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index 3c86e28b4..97acb2ebf 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -21,7 +21,11 @@ class DdSdk( ddTelemetry: DdTelemetry = DdTelemetry() ) : ReactContextBaseJavaModule(reactContext) { - private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper, ddTelemetry) + private val implementation = DdSdkImplementation( + reactContext, + datadog = datadogWrapper, + ddTelemetry + ) private var lifecycleEventListener: LifecycleEventListener? = null override fun getName(): String = DdSdkImplementation.NAME diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index c9f91738f..8797bcc64 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -163,7 +163,12 @@ internal class DdSdkTest { answer.getArgument(0).run() true } - testedBridgeSdk = DdSdkImplementation(mockReactContext, mockDatadog, mockDdTelemetry, TestUiThreadExecutor()) + testedBridgeSdk = DdSdkImplementation( + mockReactContext, + mockDatadog, + mockDdTelemetry, + TestUiThreadExecutor() + ) DatadogSDKWrapperStorage.onInitializedListeners.clear() } From e3acea928fad1b4e6085505a9b5ad8028d12d931 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 19 Sep 2025 17:37:31 +0200 Subject: [PATCH 37/62] Expose clearUserInfo API --- packages/core/__mocks__/react-native.ts | 3 + .../datadog/reactnative/DatadogSDKWrapper.kt | 4 ++ .../com/datadog/reactnative/DatadogWrapper.kt | 5 ++ .../reactnative/DdSdkImplementation.kt | 10 ++- .../kotlin/com/datadog/reactnative/DdSdk.kt | 8 +++ .../kotlin/com/datadog/reactnative/DdSdk.kt | 8 +++ .../com/datadog/reactnative/DdSdkTest.kt | 11 +++ packages/core/ios/Sources/DdSdk.mm | 12 +++- .../ios/Sources/DdSdkImplementation.swift | 8 ++- packages/core/ios/Tests/DdSdkTests.swift | 67 +++++++++++++++++++ packages/core/jest/mock.js | 3 + packages/core/src/DdSdkReactNative.tsx | 10 +++ .../src/__tests__/DdSdkReactNative.test.tsx | 26 +++++++ .../UserInfoSingleton/UserInfoSingleton.ts | 4 ++ .../__tests__/UserInfoSingleton.test.ts | 55 ++++++++++++--- packages/core/src/specs/NativeDdSdk.ts | 5 ++ packages/core/src/types.tsx | 5 ++ 17 files changed, 230 insertions(+), 14 deletions(-) diff --git a/packages/core/__mocks__/react-native.ts b/packages/core/__mocks__/react-native.ts index 260fe68a7..0e85e65ae 100644 --- a/packages/core/__mocks__/react-native.ts +++ b/packages/core/__mocks__/react-native.ts @@ -24,6 +24,9 @@ actualRN.NativeModules.DdSdk = { addUserExtraInfo: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, + clearUserInfo: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, setAttributes: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt index 198061d14..f781687eb 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt @@ -86,6 +86,10 @@ internal class DatadogSDKWrapper : DatadogWrapper { Datadog.addUserProperties(extraInfo) } + override fun clearUserInfo() { + Datadog.clearUserInfo() + } + override fun addRumGlobalAttributes(attributes: Map) { val rumMonitor = this.getRumMonitor() for (attribute in attributes) { diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt index 3ae3e6266..49d606b35 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt @@ -86,6 +86,11 @@ interface DatadogWrapper { extraInfo: Map ) + /** + * Clears the user information. + */ + fun clearUserInfo() + /** * Adds global attributes. * diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index 7a5c6848c..7adcf7438 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -102,7 +102,7 @@ class DdSdkImplementation( } /** - * Sets the user information. + * Sets the user extra information. * @param userExtraInfo: The additional information. (To set the id, name or email please user setUserInfo). */ fun addUserExtraInfo( @@ -114,6 +114,14 @@ class DdSdkImplementation( promise.resolve(null) } + /** + * Clears the user information. + */ + fun clearUserInfo(promise: Promise) { + datadog.clearUserInfo() + promise.resolve(null) + } + /** * Set the tracking consent regarding the data collection. * @param trackingConsent Consent, which can take one of the following values: 'pending', diff --git a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt index cfafffffe..4e4668a3e 100644 --- a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -67,6 +67,14 @@ class DdSdk( implementation.addUserExtraInfo(extraInfo, promise) } + /** + * Clears the user information. + */ + @ReactMethod + override fun clearUserInfo(promise: Promise) { + implementation.clearUserInfo(promise) + } + /** * Set the tracking consent regarding the data collection. * @param trackingConsent Consent, which can take one of the following values: 'pending', diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index 97acb2ebf..0ebdd37fb 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -93,6 +93,14 @@ class DdSdk( implementation.addUserExtraInfo(extraInfo, promise) } + /** + * Clears the user information. + */ + @ReactMethod + fun clearUserInfo(promise: Promise) { + implementation.clearUserInfo(promise) + } + /** * Set the tracking consent regarding the data collection. * @param trackingConsent Consent, which can take one of the following values: 'pending', diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index 8797bcc64..f917bb847 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -2954,6 +2954,17 @@ internal class DdSdkTest { } } + @Test + fun `𝕄 clear user info 𝕎 clearUserInfo()`() { + // When + testedBridgeSdk.clearUserInfo(mockPromise) + + // Then + argumentCaptor> { + verify(mockDatadog).clearUserInfo() + } + } + @Test fun `𝕄 set RUM attributes 𝕎 setAttributes`( @MapForgery( diff --git a/packages/core/ios/Sources/DdSdk.mm b/packages/core/ios/Sources/DdSdk.mm index 918a8db03..674cd0fbc 100644 --- a/packages/core/ios/Sources/DdSdk.mm +++ b/packages/core/ios/Sources/DdSdk.mm @@ -51,6 +51,12 @@ + (void)initFromNative { [self addUserExtraInfo:extraInfo resolve:resolve reject:reject]; } +RCT_EXPORT_METHOD(clearUserInfo:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self clearUserInfo:resolve reject:reject]; +} + RCT_REMAP_METHOD(setTrackingConsent, withTrackingConsent:(NSString*)trackingConsent withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) @@ -81,7 +87,7 @@ + (void)initFromNative { [self consumeWebviewEvent:message resolve:resolve reject:reject]; } -RCT_REMAP_METHOD(clearAllData, withResolver:(RCTPromiseResolveBlock)resolve +RCT_EXPORT_METHOD(clearAllData:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) { [self clearAllData:resolve reject:reject]; @@ -143,6 +149,10 @@ - (void)setUserInfo:(NSDictionary *)userInfo resolve:(RCTPromiseResolveBlock)res [self.ddSdkImplementation setUserInfoWithUserInfo:userInfo resolve:resolve reject:reject]; } +- (void)clearUserInfo:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation clearUserInfoWithResolve:resolve reject:reject]; +} + -(void)addUserExtraInfo:(NSDictionary *)extraInfo resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { [self.ddSdkImplementation addUserExtraInfoWithExtraInfo:extraInfo resolve:resolve reject:reject]; } diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index b2e610635..03c630b70 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -108,7 +108,7 @@ public class DdSdkImplementation: NSObject { resolve(nil) } - + @objc public func addUserExtraInfo(extraInfo: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { let castedExtraInfo = castAttributesToSwift(extraInfo) @@ -117,6 +117,12 @@ public class DdSdkImplementation: NSObject { resolve(nil) } + @objc + public func clearUserInfo(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + Datadog.clearUserInfo() + resolve(nil) + } + @objc public func setTrackingConsent(trackingConsent: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { Datadog.set(trackingConsent: (trackingConsent as NSString?).asTrackingConsent()) diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index 555ce4549..efbf57b96 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -651,6 +651,73 @@ class DdSdkTests: XCTestCase { XCTFail("extra-info-4 is not of expected type or value") } } + + func testClearUserInfo() throws { + let bridge = DdSdkImplementation( + mainDispatchQueue: DispatchQueueMock(), + jsDispatchQueue: DispatchQueueMock(), + jsRefreshRateMonitor: JSRefreshRateMonitor(), + RUMMonitorProvider: { MockRUMMonitor() }, + RUMMonitorInternalProvider: { nil } + ) + bridge.initialize( + configuration: .mockAny(), + resolve: mockResolve, + reject: mockReject + ) + + bridge.setUserInfo( + userInfo: NSDictionary( + dictionary: [ + "id": "id_123", + "name": "John Doe", + "email": "john@doe.com", + "extraInfo": [ + "extra-info-1": 123, + "extra-info-2": "abc", + "extra-info-3": true, + "extra-info-4": [ + "nested-extra-info-1": 456 + ], + ], + ] + ), + resolve: mockResolve, + reject: mockReject + ) + + var ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() + var userInfo = try XCTUnwrap(ddContext.userInfo) + + XCTAssertEqual(userInfo.id, "id_123") + XCTAssertEqual(userInfo.name, "John Doe") + XCTAssertEqual(userInfo.email, "john@doe.com") + XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, 123) + XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, "abc") + XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true) + + if let extraInfo4Encodable = userInfo.extraInfo["extra-info-4"] + as? DatadogSDKReactNative.AnyEncodable, + let extraInfo4Dict = extraInfo4Encodable.value as? [String: Int] + { + XCTAssertEqual(extraInfo4Dict, ["nested-extra-info-1": 456]) + } else { + XCTFail("extra-info-4 is not of expected type or value") + } + + bridge.clearUserInfo(resolve: mockResolve, reject: mockReject) + + ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() + userInfo = try XCTUnwrap(ddContext.userInfo) + + XCTAssertEqual(userInfo.id, nil) + XCTAssertEqual(userInfo.name, nil) + XCTAssertEqual(userInfo.email, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-4"] as? [String: Int], nil) + } func testSettingAttributes() { let rumMonitorMock = MockRUMMonitor() diff --git a/packages/core/jest/mock.js b/packages/core/jest/mock.js index a8161295a..8e154c4cd 100644 --- a/packages/core/jest/mock.js +++ b/packages/core/jest/mock.js @@ -33,6 +33,9 @@ module.exports = { addUserExtraInfo: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), + clearUserInfo: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), setAttributes: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), diff --git a/packages/core/src/DdSdkReactNative.tsx b/packages/core/src/DdSdkReactNative.tsx index 668ae09f3..1838542df 100644 --- a/packages/core/src/DdSdkReactNative.tsx +++ b/packages/core/src/DdSdkReactNative.tsx @@ -214,6 +214,16 @@ export class DdSdkReactNative { UserInfoSingleton.getInstance().setUserInfo(userInfo); }; + /** + * Clears the user information. + * @returns a Promise. + */ + static clearUserInfo = async (): Promise => { + InternalLog.log('Clearing user info', SdkVerbosity.DEBUG); + await DdSdk.clearUserInfo(); + UserInfoSingleton.getInstance().clearUserInfo(); + }; + /** * Set the user information. * @param extraUserInfo: The additional information. (To set the id, name or email please user setUserInfo). diff --git a/packages/core/src/__tests__/DdSdkReactNative.test.tsx b/packages/core/src/__tests__/DdSdkReactNative.test.tsx index f9405aa51..57ff5d0ed 100644 --- a/packages/core/src/__tests__/DdSdkReactNative.test.tsx +++ b/packages/core/src/__tests__/DdSdkReactNative.test.tsx @@ -1112,6 +1112,32 @@ describe('DdSdkReactNative', () => { }); }); + describe('clearUserInfo', () => { + it('calls SDK method when clearUserInfo, and clears the user in UserProvider', async () => { + // GIVEN + const userInfo = { + id: 'id', + name: 'name', + email: 'email', + extraInfo: { + foo: 'bar' + } + }; + + await DdSdkReactNative.setUserInfo(userInfo); + + // WHEN + await DdSdkReactNative.clearUserInfo(); + + // THEN + expect(DdSdk.clearUserInfo).toHaveBeenCalledTimes(1); + expect(DdSdk.setUserInfo).toHaveBeenCalled(); + expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual( + undefined + ); + }); + }); + describe('setTrackingConsent', () => { it('calls SDK method when setTrackingConsent', async () => { // GIVEN diff --git a/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts b/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts index 26392d794..3ce23614b 100644 --- a/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts +++ b/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts @@ -16,6 +16,10 @@ class UserInfoProvider { getUserInfo = (): UserInfo | undefined => { return this.userInfo; }; + + clearUserInfo = () => { + this.userInfo = undefined; + }; } export class UserInfoSingleton { diff --git a/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts b/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts index 1f7ae84e7..f8e7276d6 100644 --- a/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts +++ b/packages/core/src/sdk/UserInfoSingleton/__tests__/UserInfoSingleton.test.ts @@ -7,27 +7,60 @@ import { UserInfoSingleton } from '../UserInfoSingleton'; describe('UserInfoSingleton', () => { - it('sets, returns and resets the user info', () => { + beforeEach(() => { + UserInfoSingleton.reset(); + }); + + it('returns undefined by default', () => { + expect(UserInfoSingleton.getInstance().getUserInfo()).toBeUndefined(); + }); + + it('stores and returns user info after setUserInfo', () => { + const info = { + id: 'test', + email: 'user@mail.com', + extraInfo: { loggedIn: true } + }; + + UserInfoSingleton.getInstance().setUserInfo(info); + + expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual(info); + }); + + it('clears user info with clearUserInfo', () => { UserInfoSingleton.getInstance().setUserInfo({ id: 'test', email: 'user@mail.com', - extraInfo: { - loggedIn: true - } + extraInfo: { loggedIn: true } }); - expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual({ + UserInfoSingleton.getInstance().clearUserInfo(); + + expect(UserInfoSingleton.getInstance().getUserInfo()).toBeUndefined(); + }); + + it('reset() replaces the provider and clears stored user info', () => { + const instanceBefore = UserInfoSingleton.getInstance(); + + UserInfoSingleton.getInstance().setUserInfo({ id: 'test', email: 'user@mail.com', - extraInfo: { - loggedIn: true - } + extraInfo: { loggedIn: true } }); UserInfoSingleton.reset(); - expect(UserInfoSingleton.getInstance().getUserInfo()).toEqual( - undefined - ); + const instanceAfter = UserInfoSingleton.getInstance(); + + expect(instanceAfter).not.toBe(instanceBefore); + + expect(instanceAfter.getUserInfo()).toBeUndefined(); + }); + + it('getInstance returns the same provider between calls (singleton behavior)', () => { + const a = UserInfoSingleton.getInstance(); + const b = UserInfoSingleton.getInstance(); + + expect(a).toBe(b); }); }); diff --git a/packages/core/src/specs/NativeDdSdk.ts b/packages/core/src/specs/NativeDdSdk.ts index bbf2572ee..a2ce1120e 100644 --- a/packages/core/src/specs/NativeDdSdk.ts +++ b/packages/core/src/specs/NativeDdSdk.ts @@ -37,6 +37,11 @@ export interface Spec extends TurboModule { */ setUserInfo(user: Object): Promise; + /** + * Clears the user information. + */ + clearUserInfo(): Promise; + /** * Add custom attributes to the current user information * @param extraInfo: The extraInfo object containing additionall custom attributes diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index fe1a5895c..bad19d429 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -98,6 +98,11 @@ export type DdSdkType = { */ setUserInfo(userInfo: UserInfo): Promise; + /** + * Clears the user information. + */ + clearUserInfo(): Promise; + /** * Add additional user information. * @param extraUserInfo: The additional information. (To set the id, name or email please user setUserInfo). From a3fc308332aeaabaf30a8d8e64095cb1c9592fa1 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Mon, 29 Sep 2025 12:20:44 +0200 Subject: [PATCH 38/62] Update attribute API --- benchmarks/src/testSetup/monitor.ts | 5 +- example/src/ddUtils.tsx | 4 +- packages/codepush/__mocks__/react-native.ts | 13 +- packages/core/__mocks__/react-native.ts | 13 +- .../datadog/reactnative/DatadogSDKWrapper.kt | 17 ++- .../com/datadog/reactnative/DatadogWrapper.kt | 22 ++++ .../reactnative/DdSdkImplementation.kt | 51 ++++++- .../kotlin/com/datadog/reactnative/DdSdk.kt | 39 +++++- .../kotlin/com/datadog/reactnative/DdSdk.kt | 37 +++++- .../com/datadog/reactnative/DdSdkTest.kt | 118 ++++++++++++++++- packages/core/ios/Sources/AnyEncodable.swift | 21 ++- packages/core/ios/Sources/DdSdk.mm | 42 +++++- .../ios/Sources/DdSdkImplementation.swift | 31 ++++- packages/core/ios/Sources/GlobalState.swift | 2 +- packages/core/ios/Tests/DdSdkTests.swift | 124 +++++++++++++++++- packages/core/ios/Tests/MockRUMMonitor.swift | 12 +- packages/core/jest/mock.js | 11 +- packages/core/src/DdSdkReactNative.tsx | 53 +++++++- .../src/__tests__/DdSdkReactNative.test.tsx | 68 +++++++++- .../AttributesSingleton.ts | 26 +++- .../__tests__/AttributesSingleton.test.ts | 60 +++++++-- packages/core/src/specs/NativeDdSdk.ts | 23 +++- packages/core/src/types.tsx | 21 ++- .../__mocks__/react-native.ts | 4 +- 24 files changed, 742 insertions(+), 75 deletions(-) diff --git a/benchmarks/src/testSetup/monitor.ts b/benchmarks/src/testSetup/monitor.ts index c7cc23473..93ea0fccd 100644 --- a/benchmarks/src/testSetup/monitor.ts +++ b/benchmarks/src/testSetup/monitor.ts @@ -4,8 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -import { DefaultTimeProvider, RumActionType } from "@datadog/mobile-react-native"; -import { ErrorSource } from "@datadog/mobile-react-native/lib/typescript/rum/types"; +import { DefaultTimeProvider, ErrorSource, RumActionType } from "@datadog/mobile-react-native"; import type { DdRumType, ResourceKind } from "@datadog/mobile-react-native/lib/typescript/rum/types"; import type { GestureResponderEvent } from "react-native/types"; @@ -72,4 +71,4 @@ export const Monitor: Pick { DdLogs.info('The RN Sdk was properly initialized') DdSdkReactNative.setUserInfo({id: "1337", name: "Xavier", email: "xg@example.com", extraInfo: { type: "premium" } }) - DdSdkReactNative.setAttributes({campaign: "ad-network"}) + DdSdkReactNative.addAttributes({campaign: "ad-network"}) }); } diff --git a/packages/codepush/__mocks__/react-native.ts b/packages/codepush/__mocks__/react-native.ts index 046ced2f6..0c8189840 100644 --- a/packages/codepush/__mocks__/react-native.ts +++ b/packages/codepush/__mocks__/react-native.ts @@ -18,9 +18,18 @@ actualRN.NativeModules.DdSdk = { initialize: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, - setAttributes: jest.fn().mockImplementation( + addAttribute: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) - ) as jest.MockedFunction, + ) as jest.MockedFunction, + removeAttribute: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + addAttributes: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + removeAttributes: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, setTrackingConsent: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, diff --git a/packages/core/__mocks__/react-native.ts b/packages/core/__mocks__/react-native.ts index 0e85e65ae..24e3f80c7 100644 --- a/packages/core/__mocks__/react-native.ts +++ b/packages/core/__mocks__/react-native.ts @@ -27,9 +27,18 @@ actualRN.NativeModules.DdSdk = { clearUserInfo: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, - setAttributes: jest.fn().mockImplementation( + addAttribute: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) - ) as jest.MockedFunction, + ) as jest.MockedFunction, + removeAttribute: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + addAttributes: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + removeAttributes: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, setTrackingConsent: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt index f781687eb..06151d834 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt @@ -89,11 +89,24 @@ internal class DatadogSDKWrapper : DatadogWrapper { override fun clearUserInfo() { Datadog.clearUserInfo() } + + override fun addRumGlobalAttribute(key: String, value: Any?) { + this.getRumMonitor().addAttribute(key, value) + } + + override fun removeRumGlobalAttribute(key: String) { + this.getRumMonitor().removeAttribute(key) + } override fun addRumGlobalAttributes(attributes: Map) { - val rumMonitor = this.getRumMonitor() for (attribute in attributes) { - rumMonitor.addAttribute(attribute.key, attribute.value) + this.addRumGlobalAttribute(attribute.key, attribute.value) + } + } + + override fun removeRumGlobalAttributes(keys: Array) { + for (key in keys) { + this.removeRumGlobalAttribute(key) } } diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt index 49d606b35..d6395b18b 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt @@ -91,6 +91,21 @@ interface DatadogWrapper { */ fun clearUserInfo() + + /** Adds a global attribute. + * + * @param key: Key that identifies the attribute. + * @param value: Value linked to the attribute. + */ + fun addRumGlobalAttribute(key: String, value: Any?) + + /** + * Removes a global attribute. + * + * @param key: Key that identifies the attribute. + */ + fun removeRumGlobalAttribute(key: String) + /** * Adds global attributes. * @@ -98,6 +113,13 @@ interface DatadogWrapper { */ fun addRumGlobalAttributes(attributes: Map) + /** + * Removes global attributes. + * + * @param keys Keys linked to the attributes to be removed + */ + fun removeRumGlobalAttributes(keys: Array) + /** * Sets tracking consent. */ diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index 7adcf7438..ed545d9e1 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -14,6 +14,7 @@ import com.datadog.android.rum.configuration.VitalsUpdateFrequency import com.facebook.react.bridge.LifecycleEventListener import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import java.util.Locale import java.util.concurrent.TimeUnit @@ -66,11 +67,35 @@ class DdSdkImplementation( } /** - * Sets the global context (set of attributes) attached with all future Logs, Spans and RUM + * Sets a specific attribute in the global context attached with all future Logs, Spans and RUM. + * + * @param key: Key that identifies the attribute. + * @param value: Value linked to the attribute. + */ + fun addAttribute(key: String, value: ReadableMap, promise: Promise) { + val attributeValue = value.toMap()["value"] + datadog.addRumGlobalAttribute(key, attributeValue) + GlobalState.addAttribute(key, attributeValue) + promise.resolve(null) + } + + /** + * Removes an attribute from the global context attached with all future Logs, Spans and RUM events. + * @param key: They key associated with the attribute to be removed. + */ + fun removeAttribute(key: String, promise: Promise) { + datadog.removeRumGlobalAttribute(key) + GlobalState.removeAttribute(key) + promise.resolve(null) + } + + + /** + * Adds a set of attributes to the global context that is attached with all future Logs, Spans and RUM * events. - * @param attributes The global context attributes. + * @param attributes: The global context attributes. */ - fun setAttributes(attributes: ReadableMap, promise: Promise) { + fun addAttributes(attributes: ReadableMap, promise: Promise) { datadog.addRumGlobalAttributes(attributes.toHashMap()) for ((k,v) in attributes.toHashMap()) { GlobalState.addAttribute(k, v) @@ -78,6 +103,26 @@ class DdSdkImplementation( promise.resolve(null) } + /** + * Removes a set of attributes from the global context that is attached with all future Logs, Spans and RUM + * events. + * @param keys: They keys associated with the attributes to be removed. + */ + fun removeAttributes(keys: ReadableArray, promise: Promise) { + val keysArray = mutableListOf() + for (i in 0 until keys.size()) { + val key: String = keys.getString(i) + keysArray.add(key) + } + val keysStringArray = keysArray.toTypedArray() + + datadog.removeRumGlobalAttributes(keysStringArray) + for (key in keysStringArray) { + GlobalState.removeAttribute(key) + } + promise.resolve(null) + } + /** * Set the user information. * @param userInfo The user object (use builtin attributes: 'id', 'email', 'name', and any custom diff --git a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt index 4e4668a3e..a9d430081 100644 --- a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -12,13 +12,14 @@ import com.facebook.react.bridge.LifecycleEventListener import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import com.facebook.react.modules.core.DeviceEventManagerModule /** The entry point to initialize Datadog's features. */ class DdSdk( reactContext: ReactApplicationContext, - datadogWrapper: DatadogWrapper = DatadogSDKWrapper() + datadogWrapper: DatadogWrapper = DatadogSDKWrapper(), ddTelemetry: DdTelemetry = DdTelemetry() ) : NativeDdSdkSpec(reactContext) { @@ -40,13 +41,43 @@ class DdSdk( } /** - * Sets the global context (set of attributes) attached with all future Logs, Spans and RUM + * Sets a specific attribute in the global context attached with all future Logs, Spans and RUM + * + * @param key: Key that identifies the attribute. + * @param value: Value linked to the attribute. + */ + @ReactMethod + override fun addAttribute(key: String, value: ReadableMap, promise: Promise) { + implementation.addAttribute(key, value, promise) + } + + /** + * Removes an attribute from the context attached with all future Logs, Spans and RUM events. + * @param key: They key associated with the attribute to be removed. + */ + @ReactMethod + override fun removeAttribute(key: String, promise: Promise) { + implementation.removeAttribute(key, promise) + } + + /** + * Adds a set of attributes to the global context that is attached with all future Logs, Spans and RUM * events. * @param attributes The global context attributes. */ @ReactMethod - override fun setAttributes(attributes: ReadableMap, promise: Promise) { - implementation.setAttributes(attributes, promise) + override fun addAttributes(attributes: ReadableMap, promise: Promise) { + implementation.addAttributes(attributes, promise) + } + + /** + * Removes a set of attributes from the global context that is attached with all future Logs, Spans and RUM + * events. + * @param keys: They keys associated with the attributes to be removed. + */ + @ReactMethod + override fun removeAttributes(keys: ReadableArray, promise: Promise) { + implementation.removeAttributes(keys, promise) } /** diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index 0ebdd37fb..958ba521b 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -12,6 +12,7 @@ import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap /** The entry point to initialize Datadog's features. */ @@ -66,13 +67,43 @@ class DdSdk( } /** - * Sets the global context (set of attributes) attached with all future Logs, Spans and RUM + * Sets a specific attribute in the global context attached with all future Logs, Spans and RUM + * + * @param key: Key that identifies the attribute. + * @param value: Value linked to the attribute. + */ + @ReactMethod + fun addAttribute(key: String, value: ReadableMap, promise: Promise) { + implementation.addAttribute(key, value, promise) + } + + /** + * Removes an attribute from the context attached with all future Logs, Spans and RUM events. + * @param key: They key associated with the attribute to be removed. + */ + @ReactMethod + fun removeAttribute(key: String, promise: Promise) { + implementation.removeAttribute(key, promise) + } + + /** + * Adds a set of attributes to the global context that is attached with all future Logs, Spans and RUM * events. * @param attributes The global context attributes. */ @ReactMethod - fun setAttributes(attributes: ReadableMap, promise: Promise) { - implementation.setAttributes(attributes, promise) + fun addAttributes(attributes: ReadableMap, promise: Promise) { + implementation.addAttributes(attributes, promise) + } + + /** + * Removes a set of attributes from the global context that is attached with all future Logs, Spans and RUM + * events. + * @param keys: They keys associated with the attributes to be removed. + */ + @ReactMethod + fun removeAttributes(keys: ReadableArray, promise: Promise) { + implementation.removeAttributes(keys, promise) } /** diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index f917bb847..ae6ded89c 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -40,6 +40,7 @@ import com.datadog.tools.unit.setStaticValue import com.datadog.tools.unit.toReadableArray import com.datadog.tools.unit.toReadableJavaOnlyMap import com.datadog.tools.unit.toReadableMap +import com.facebook.react.bridge.JavaOnlyMap import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReadableMap @@ -78,7 +79,6 @@ import org.mockito.kotlin.doReturn import org.mockito.kotlin.doThrow import org.mockito.kotlin.eq import org.mockito.kotlin.inOrder -import org.mockito.kotlin.isNotNull import org.mockito.kotlin.isNull import org.mockito.kotlin.mock import org.mockito.kotlin.never @@ -2966,28 +2966,96 @@ internal class DdSdkTest { } @Test - fun `𝕄 set RUM attributes 𝕎 setAttributes`( + fun `M set Rum attribute W addAttribute`( + @StringForgery(type = StringForgeryType.NUMERICAL) key: String, + @StringForgery(type = StringForgeryType.ASCII) value: String + ) { + // When + val attributeMap = JavaOnlyMap().apply { + putString("value", value) + } + testedBridgeSdk.addAttribute(key, attributeMap, mockPromise) + + // Then + verify(mockDatadog).addRumGlobalAttribute(key, value) + } + + @Test + fun `M set GlobalState attribute W addAttribute`( + @StringForgery(type = StringForgeryType.NUMERICAL) key: String, + @StringForgery(type = StringForgeryType.ASCII) value: String + ) { + // When + val attributeMap = JavaOnlyMap().apply { + putString("value", value) + } + testedBridgeSdk.addAttribute(key, attributeMap, mockPromise) + + // Then + assertThat(GlobalState.globalAttributes).containsEntry(key, value) + } + + @Test + fun `M remove Rum attribute W removeAttribute`( + @StringForgery(type = StringForgeryType.NUMERICAL) key: String, + @StringForgery(type = StringForgeryType.ASCII) value: String + ) { + // Given + val attributeMap = JavaOnlyMap().apply { + putString("value", value) + } + testedBridgeSdk.addAttribute(key, attributeMap, mockPromise) + assertThat(GlobalState.globalAttributes).containsEntry(key, value) + + // When + testedBridgeSdk.removeAttribute(key, mockPromise) + + // Then + verify(mockDatadog).removeRumGlobalAttribute(key) + } + + @Test + fun `M remove GlobalState attribute W removeAttribute`( + @StringForgery(type = StringForgeryType.NUMERICAL) key: String, + @StringForgery(type = StringForgeryType.ASCII) value: String + ) { + // Given + val attributeMap = JavaOnlyMap().apply { + putString("value", value) + } + testedBridgeSdk.addAttribute(key, attributeMap, mockPromise) + assertThat(GlobalState.globalAttributes).containsEntry(key, value) + + // When + testedBridgeSdk.removeAttribute(key, mockPromise) + + // Then + assertThat(GlobalState.globalAttributes).doesNotContainEntry(key, value) + } + + @Test + fun `𝕄 set RUM attributes 𝕎 addAttributes`( @MapForgery( key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) ) customAttributes: Map ) { // When - testedBridgeSdk.setAttributes(customAttributes.toReadableMap(), mockPromise) + testedBridgeSdk.addAttributes(customAttributes.toReadableMap(), mockPromise) // Then verify(mockDatadog).addRumGlobalAttributes(customAttributes) } @Test - fun `𝕄 set GlobalState attributes 𝕎 setAttributes`( + fun `𝕄 set GlobalState attributes 𝕎 addAttributes`( @MapForgery( key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) ) customAttributes: Map ) { // When - testedBridgeSdk.setAttributes(customAttributes.toReadableMap(), mockPromise) + testedBridgeSdk.addAttributes(customAttributes.toReadableMap(), mockPromise) // Then customAttributes.forEach { (k, v) -> @@ -2995,6 +3063,46 @@ internal class DdSdkTest { } } + @Test + fun `𝕄 remove RUM attributes 𝕎 removeAttributes`( + @MapForgery( + key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), + value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) + ) customAttributes: Map + ) { + // Given + testedBridgeSdk.addAttributes(customAttributes.toReadableMap(), mockPromise) + verify(mockDatadog).addRumGlobalAttributes(customAttributes) + + // When + val keys = customAttributes.keys.toReadableArray() + testedBridgeSdk.removeAttributes(keys, mockPromise) + + // Then + verify(mockDatadog).removeRumGlobalAttributes(customAttributes.keys.toTypedArray()) + } + + @Test + fun `𝕄 remve GlobalState attributes 𝕎 removeAttributes`( + @MapForgery( + key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), + value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) + ) customAttributes: Map + ) { + // Given + testedBridgeSdk.addAttributes(customAttributes.toReadableMap(), mockPromise) + verify(mockDatadog).addRumGlobalAttributes(customAttributes) + + // When + val keys = customAttributes.keys.toReadableArray() + testedBridgeSdk.removeAttributes(keys, mockPromise) + + // Then + customAttributes.forEach { (k, v) -> + assertThat(GlobalState.globalAttributes).doesNotContainEntry(k, v) + } + } + @Test fun `𝕄 build Granted consent 𝕎 buildTrackingConsent {granted}`(forge: Forge) { // When diff --git a/packages/core/ios/Sources/AnyEncodable.swift b/packages/core/ios/Sources/AnyEncodable.swift index 39821af87..7fac7bb3b 100644 --- a/packages/core/ios/Sources/AnyEncodable.swift +++ b/packages/core/ios/Sources/AnyEncodable.swift @@ -14,18 +14,25 @@ internal func castAttributesToSwift(_ attributes: [String: Any]) -> [String: Enc var casted: [String: Encodable] = [:] attributes.forEach { key, value in - if let castedValue = castByPreservingTypeInformation(attributeValue: value) { - // If possible, cast attribute by preserving its type information - casted[key] = castedValue - } else { - // Otherwise, cast by preserving its encoded value (and loosing type information) - casted[key] = castByPreservingEncodedValue(attributeValue: value) - } + casted[key] = castValueToSwift(value) } return casted } +internal func castValueToSwift(_ value: Any) -> Encodable { + var casted: Encodable + if let castedValue = castByPreservingTypeInformation(attributeValue: value) { + // If possible, cast attribute by preserving its type information + casted = castedValue + } else { + // Otherwise, cast by preserving its encoded value (and loosing type information) + casted = castByPreservingEncodedValue(attributeValue: value) + } + + return casted +} + /// Casts `Any` value to `Encodable` by preserving its type information. private func castByPreservingTypeInformation(attributeValue: Any) -> Encodable? { switch attributeValue { diff --git a/packages/core/ios/Sources/DdSdk.mm b/packages/core/ios/Sources/DdSdk.mm index 674cd0fbc..06736a69e 100644 --- a/packages/core/ios/Sources/DdSdk.mm +++ b/packages/core/ios/Sources/DdSdk.mm @@ -30,11 +30,33 @@ + (void)initFromNative { [self initialize:configuration resolve:resolve reject:reject]; } -RCT_REMAP_METHOD(setAttributes, withAttributes:(NSDictionary*)attributes +RCT_EXPORT_METHOD(addAttribute:(NSString*) key + withValue:(NSDictionary*) value + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self addAttribute:key value:value resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(removeAttribute:(NSString*) key + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self removeAttribute:key resolve:resolve reject:reject]; +} + +RCT_REMAP_METHOD(addAttributes, withAttributes:(NSDictionary*)attributes withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) { - [self setAttributes:attributes resolve:resolve reject:reject]; + [self addAttributes:attributes resolve:resolve reject:reject]; +} + +RCT_REMAP_METHOD(removeAttributes, withKeys:(NSArray *)keys + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self removeAttributes:keys resolve:resolve reject:reject]; } RCT_REMAP_METHOD(setUserInfo, withUserInfo:(NSDictionary*)userInfo @@ -137,8 +159,20 @@ - (void)initialize:(NSDictionary *)configuration resolve:(RCTPromiseResolveBlock [self.ddSdkImplementation initializeWithConfiguration:configuration resolve:resolve reject:reject]; } -- (void)setAttributes:(NSDictionary *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - [self.ddSdkImplementation setAttributesWithAttributes:attributes resolve:resolve reject:reject]; +- (void)addAttribute:(NSString *)key value:(NSDictionary *)value resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation addAttributeWithKey:key value:value resolve:resolve reject:reject]; +} + +- (void)removeAttribute:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation removeAttributeWithKey:key resolve:resolve reject:reject]; +} + +- (void)addAttributes:(NSDictionary *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation addAttributesWithAttributes:attributes resolve:resolve reject:reject]; +} + +- (void)removeAttributes:(NSArray *)keys resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation removeAttributesWithKeys:keys resolve:resolve reject:reject]; } - (void)setTrackingConsent:(NSString *)trackingConsent resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 03c630b70..8aae5e10d 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -75,14 +75,43 @@ public class DdSdkImplementation: NSObject { resolve(nil) } + + @objc + public func addAttribute(key: AttributeKey, value: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + if let attributeValue = value.object(forKey: "value") { + let castedValue = castValueToSwift(attributeValue) + RUMMonitorProvider().addAttribute(forKey: key, value: castedValue) + GlobalState.addAttribute(forKey: key, value: castedValue) + } + + resolve(nil) + } + + @objc + public func removeAttribute(key: AttributeKey, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + RUMMonitorProvider().removeAttribute(forKey: key) + GlobalState.removeAttribute(key: key) + + resolve(nil) + } @objc - public func setAttributes(attributes: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func addAttributes(attributes: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { let castedAttributes = castAttributesToSwift(attributes) for (key, value) in castedAttributes { RUMMonitorProvider().addAttribute(forKey: key, value: value) GlobalState.addAttribute(forKey: key, value: value) } + + resolve(nil) + } + + @objc + public func removeAttributes(keys: [AttributeKey], resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + RUMMonitorProvider().removeAttributes(forKeys: keys) + for (key) in keys { + GlobalState.removeAttribute(key: key) + } resolve(nil) } diff --git a/packages/core/ios/Sources/GlobalState.swift b/packages/core/ios/Sources/GlobalState.swift index b932803a1..a758bf0ef 100644 --- a/packages/core/ios/Sources/GlobalState.swift +++ b/packages/core/ios/Sources/GlobalState.swift @@ -15,7 +15,7 @@ internal struct GlobalState { } internal static func removeAttribute(key: String) { - GlobalState.globalAttributes.removeValue(forKey: key) + GlobalState.globalAttributes[key] = nil } } diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index efbf57b96..adbb57da9 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -651,7 +651,7 @@ class DdSdkTests: XCTestCase { XCTFail("extra-info-4 is not of expected type or value") } } - + func testClearUserInfo() throws { let bridge = DdSdkImplementation( mainDispatchQueue: DispatchQueueMock(), @@ -704,12 +704,12 @@ class DdSdkTests: XCTestCase { } else { XCTFail("extra-info-4 is not of expected type or value") } - + bridge.clearUserInfo(resolve: mockResolve, reject: mockReject) - + ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() userInfo = try XCTUnwrap(ddContext.userInfo) - + XCTAssertEqual(userInfo.id, nil) XCTAssertEqual(userInfo.name, nil) XCTAssertEqual(userInfo.email, nil) @@ -719,7 +719,59 @@ class DdSdkTests: XCTestCase { XCTAssertEqual(userInfo.extraInfo["extra-info-4"] as? [String: Int], nil) } - func testSettingAttributes() { + func testRemovingAttribute() { + let rumMonitorMock = MockRUMMonitor() + let bridge = DdSdkImplementation( + mainDispatchQueue: DispatchQueueMock(), + jsDispatchQueue: DispatchQueueMock(), + jsRefreshRateMonitor: JSRefreshRateMonitor(), + RUMMonitorProvider: { rumMonitorMock }, + RUMMonitorInternalProvider: { nil } + ) + + bridge.initialize( + configuration: .mockAny(), + resolve: mockResolve, + reject: mockReject + ) + + bridge.addAttributes( + attributes: NSDictionary( + dictionary: [ + "attribute-1": 123, + "attribute-2": "abc", + ] + ), + resolve: mockResolve, + reject: mockReject + ) + + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-1"] as? Int64, 123) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-2"] as? String, "abc") + + XCTAssertEqual(GlobalState.globalAttributes["attribute-1"] as? Int64, 123) + XCTAssertEqual(GlobalState.globalAttributes["attribute-2"] as? String, "abc") + + bridge.removeAttribute(key: "attribute-1", resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-2"] as? String, "abc") + + XCTAssertEqual(GlobalState.globalAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(GlobalState.globalAttributes["attribute-2"] as? String, "abc") + + bridge.removeAttribute(key: "attribute-2", resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-2"] as? String, nil) + + XCTAssertEqual(GlobalState.globalAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(GlobalState.globalAttributes["attribute-2"] as? String, nil) + + GlobalState.globalAttributes.removeAll() + } + + func testAddingAttributes() { let rumMonitorMock = MockRUMMonitor() let bridge = DdSdkImplementation( mainDispatchQueue: DispatchQueueMock(), @@ -734,7 +786,7 @@ class DdSdkTests: XCTestCase { reject: mockReject ) - bridge.setAttributes( + bridge.addAttributes( attributes: NSDictionary( dictionary: [ "attribute-1": 123, @@ -757,6 +809,66 @@ class DdSdkTests: XCTestCase { GlobalState.globalAttributes.removeAll() } + func testRemovingAttributes() { + let rumMonitorMock = MockRUMMonitor() + let bridge = DdSdkImplementation( + mainDispatchQueue: DispatchQueueMock(), + jsDispatchQueue: DispatchQueueMock(), + jsRefreshRateMonitor: JSRefreshRateMonitor(), + RUMMonitorProvider: { rumMonitorMock }, + RUMMonitorInternalProvider: { nil } + ) + bridge.initialize( + configuration: .mockAny(), + resolve: mockResolve, + reject: mockReject + ) + + bridge.addAttributes( + attributes: NSDictionary( + dictionary: [ + "attribute-1": 123, + "attribute-2": "abc", + "attribute-3": true, + ] + ), + resolve: mockResolve, + reject: mockReject + ) + + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-1"] as? Int64, 123) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-2"] as? String, "abc") + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-3"] as? Bool, true) + + XCTAssertEqual(GlobalState.globalAttributes["attribute-1"] as? Int64, 123) + XCTAssertEqual(GlobalState.globalAttributes["attribute-2"] as? String, "abc") + XCTAssertEqual(GlobalState.globalAttributes["attribute-3"] as? Bool, true) + + bridge.removeAttributes( + keys: ["attribute-1", "attribute-2"], resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-2"] as? String, nil) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-3"] as? Bool, true) + + XCTAssertEqual(GlobalState.globalAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(GlobalState.globalAttributes["attribute-2"] as? String, nil) + XCTAssertEqual(GlobalState.globalAttributes["attribute-3"] as? Bool, true) + + bridge.removeAttributes(keys: ["attribute-3"], resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-2"] as? String, nil) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-3"] as? Bool, nil) + + XCTAssertEqual(GlobalState.globalAttributes["attribute-1"] as? Int64, nil) + XCTAssertEqual(GlobalState.globalAttributes["attribute-2"] as? String, nil) + XCTAssertEqual(GlobalState.globalAttributes["attribute-3"] as? Bool, nil) + + GlobalState.globalAttributes.removeAll() + + } + func testBuildLongTaskThreshold() { let configuration: DdSdkConfiguration = .mockAny(nativeLongTaskThresholdMs: 2500) diff --git a/packages/core/ios/Tests/MockRUMMonitor.swift b/packages/core/ios/Tests/MockRUMMonitor.swift index f0fa03364..3a882ed47 100644 --- a/packages/core/ios/Tests/MockRUMMonitor.swift +++ b/packages/core/ios/Tests/MockRUMMonitor.swift @@ -38,14 +38,20 @@ internal class MockRUMMonitor: RUMMonitorProtocol { addedAttributes[key] = value } - func removeAttribute(forKey key: DatadogInternal.AttributeKey) {} + func removeAttribute(forKey key: DatadogInternal.AttributeKey) { + addedAttributes.removeValue(forKey: key) + } func addAttributes(_ attributes: [DatadogInternal.AttributeKey : any DatadogInternal.AttributeValue]) { - // Not implemented + for (key, value) in attributes { + addAttribute(forKey: key, value: value) + } } func removeAttributes(forKeys keys: [DatadogInternal.AttributeKey]) { - // Not implemented + for key in keys { + removeAttribute(forKey: key) + } } var debug: Bool diff --git a/packages/core/jest/mock.js b/packages/core/jest/mock.js index 8e154c4cd..c49d13f48 100644 --- a/packages/core/jest/mock.js +++ b/packages/core/jest/mock.js @@ -36,7 +36,16 @@ module.exports = { clearUserInfo: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), - setAttributes: jest + addAttribute: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + removeAttribute: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + addAttributes: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + removeAttributes: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), setTrackingConsent: jest diff --git a/packages/core/src/DdSdkReactNative.tsx b/packages/core/src/DdSdkReactNative.tsx index 1838542df..8360a695b 100644 --- a/packages/core/src/DdSdkReactNative.tsx +++ b/packages/core/src/DdSdkReactNative.tsx @@ -175,20 +175,61 @@ export class DdSdkReactNative { ); }; + /** + * Adds a specific attribute to the global context attached with all future Logs, Spans and RUM. + * @param key: Key that identifies the attribute. + * @param value: Value linked to the attribute. + */ + static addAttribute = async ( + key: string, + value: unknown + ): Promise => { + InternalLog.log( + `Adding attribute ${JSON.stringify(value)} for key ${key}`, + SdkVerbosity.DEBUG + ); + await DdSdk.addAttribute(key, { value }); + AttributesSingleton.getInstance().addAttribute(key, value); + }; + + /** + * Removes an attribute from the context attached with all future Logs, Spans and RUM events. + * @param key: They key associated with the attribute to be removed. + */ + static removeAttribute = async (key: string): Promise => { + InternalLog.log( + `Removing attribute for key ${key}`, + SdkVerbosity.DEBUG + ); + await DdSdk.removeAttribute(key); + AttributesSingleton.getInstance().removeAttribute(key); + }; + /** * Adds a set of attributes to the global context attached with all future Logs, Spans and RUM events. - * To remove an attribute, set it to `undefined` in a call to `setAttributes`. * @param attributes: The global context attributes. * @returns a Promise. */ - // eslint-disable-next-line @typescript-eslint/ban-types - static setAttributes = async (attributes: Attributes): Promise => { + static addAttributes = async (attributes: Attributes): Promise => { + InternalLog.log( + `Adding attributes ${JSON.stringify(attributes)}`, + SdkVerbosity.DEBUG + ); + await DdSdk.addAttributes(attributes); + AttributesSingleton.getInstance().addAttributes(attributes); + }; + + /** + * Removes a set of attributes from the context attached with all future Logs, Spans and RUM events. + * @param keys: They keys associated with the attributes to be removed. + */ + static removeAttributes = async (keys: string[]): Promise => { InternalLog.log( - `Setting attributes ${JSON.stringify(attributes)}`, + `Removing attributes for keys ${JSON.stringify(keys)}`, SdkVerbosity.DEBUG ); - await DdSdk.setAttributes(attributes); - AttributesSingleton.getInstance().setAttributes(attributes); + await DdSdk.removeAttributes(keys); + AttributesSingleton.getInstance().removeAttributes(keys); }; /** diff --git a/packages/core/src/__tests__/DdSdkReactNative.test.tsx b/packages/core/src/__tests__/DdSdkReactNative.test.tsx index 57ff5d0ed..5e6f8c447 100644 --- a/packages/core/src/__tests__/DdSdkReactNative.test.tsx +++ b/packages/core/src/__tests__/DdSdkReactNative.test.tsx @@ -62,7 +62,7 @@ beforeEach(async () => { GlobalState.instance.isInitialized = false; DdSdkReactNative['wasAutoInstrumented'] = false; NativeModules.DdSdk.initialize.mockClear(); - NativeModules.DdSdk.setAttributes.mockClear(); + NativeModules.DdSdk.addAttributes.mockClear(); NativeModules.DdSdk.setTrackingConsent.mockClear(); NativeModules.DdSdk.onRUMSessionStarted.mockClear(); @@ -1045,24 +1045,80 @@ describe('DdSdkReactNative', () => { }); }); - describe('setAttributes', () => { - it('calls SDK method when setAttributes', async () => { + describe('addAttribute', () => { + it('calls SDK method when addAttribute', async () => { + // GIVEN + const key = 'foo'; + const value = 'bar'; + + // WHEN + + await DdSdkReactNative.addAttribute(key, value); + + // THEN + expect(DdSdk.addAttribute).toHaveBeenCalledTimes(1); + expect(DdSdk.addAttribute).toHaveBeenCalledWith(key, { value }); + expect(AttributesSingleton.getInstance().getAttribute(key)).toEqual( + value + ); + }); + }); + + describe('removeAttribute', () => { + it('calls SDK method when removeAttribute', async () => { + // GIVEN + const key = 'foo'; + const value = 'bar'; + await DdSdkReactNative.addAttribute(key, value); + + // WHEN + await DdSdkReactNative.removeAttribute(key); + + // THEN + expect(DdSdk.removeAttribute).toHaveBeenCalledTimes(1); + expect(DdSdk.removeAttribute).toHaveBeenCalledWith(key); + expect(AttributesSingleton.getInstance().getAttribute(key)).toEqual( + undefined + ); + }); + }); + + describe('addAttributes', () => { + it('calls SDK method when addAttributes', async () => { // GIVEN const attributes = { foo: 'bar' }; // WHEN - await DdSdkReactNative.setAttributes(attributes); + await DdSdkReactNative.addAttributes(attributes); // THEN - expect(DdSdk.setAttributes).toHaveBeenCalledTimes(1); - expect(DdSdk.setAttributes).toHaveBeenCalledWith(attributes); + expect(DdSdk.addAttributes).toHaveBeenCalledTimes(1); + expect(DdSdk.addAttributes).toHaveBeenCalledWith(attributes); expect(AttributesSingleton.getInstance().getAttributes()).toEqual({ foo: 'bar' }); }); }); + describe('removeAttributes', () => { + it('calls SDK method when removeAttributes', async () => { + // GIVEN + const attributes = { foo: 'bar', baz: 'quux' }; + await DdSdkReactNative.addAttributes(attributes); + + // WHEN + await DdSdkReactNative.removeAttributes(['foo', 'baz']); + + // THEN + expect(DdSdk.removeAttributes).toHaveBeenCalledTimes(1); + expect(DdSdk.removeAttributes).toHaveBeenCalledWith(['foo', 'baz']); + expect(AttributesSingleton.getInstance().getAttributes()).toEqual( + {} + ); + }); + }); + describe('setUserInfo', () => { it('calls SDK method when setUserInfo, and sets the user in UserProvider', async () => { // GIVEN diff --git a/packages/core/src/sdk/AttributesSingleton/AttributesSingleton.ts b/packages/core/src/sdk/AttributesSingleton/AttributesSingleton.ts index a51bb6c99..ac92c2d32 100644 --- a/packages/core/src/sdk/AttributesSingleton/AttributesSingleton.ts +++ b/packages/core/src/sdk/AttributesSingleton/AttributesSingleton.ts @@ -9,13 +9,37 @@ import type { Attributes } from './types'; class AttributesProvider { private attributes: Attributes = {}; - setAttributes = (attributes: Attributes) => { + addAttribute = (key: string, value: unknown) => { + const newAttributes = { ...this.attributes }; + newAttributes[key] = value; + this.attributes = newAttributes; + }; + + removeAttribute = (key: string) => { + const updatedAttributes = { ...this.attributes }; + delete updatedAttributes[key]; + this.attributes = updatedAttributes; + }; + + addAttributes = (attributes: Attributes) => { this.attributes = { ...this.attributes, ...attributes }; }; + removeAttributes = (keys: string[]) => { + const updated = { ...this.attributes }; + for (const k of keys) { + delete updated[k]; + } + this.attributes = updated; + }; + + getAttribute = (key: string): unknown | undefined => { + return this.attributes[key]; + }; + getAttributes = (): Attributes => { return this.attributes; }; diff --git a/packages/core/src/sdk/AttributesSingleton/__tests__/AttributesSingleton.test.ts b/packages/core/src/sdk/AttributesSingleton/__tests__/AttributesSingleton.test.ts index 23fbe5ad7..90d1133b4 100644 --- a/packages/core/src/sdk/AttributesSingleton/__tests__/AttributesSingleton.test.ts +++ b/packages/core/src/sdk/AttributesSingleton/__tests__/AttributesSingleton.test.ts @@ -7,9 +7,12 @@ import { AttributesSingleton } from '../AttributesSingleton'; describe('AttributesSingleton', () => { - it('adds, returns and resets the user info', () => { - // Adding first attributes - AttributesSingleton.getInstance().setAttributes({ + beforeEach(() => { + AttributesSingleton.reset(); + }); + + it('adds, returns and resets the attributes', () => { + AttributesSingleton.getInstance().addAttributes({ appType: 'student', extraInfo: { loggedIn: true @@ -23,11 +26,8 @@ describe('AttributesSingleton', () => { } }); - // Removing and adding new attributes - AttributesSingleton.getInstance().setAttributes({ - appType: undefined, - newAttribute: false - }); + AttributesSingleton.getInstance().removeAttribute('appType'); + AttributesSingleton.getInstance().addAttribute('newAttribute', false); expect(AttributesSingleton.getInstance().getAttributes()).toEqual({ newAttribute: false, @@ -41,4 +41,48 @@ describe('AttributesSingleton', () => { expect(AttributesSingleton.getInstance().getAttributes()).toEqual({}); }); + + it('addAttribute sets a single key and getAttribute returns it', () => { + AttributesSingleton.getInstance().addAttribute('userId', '123'); + expect(AttributesSingleton.getInstance().getAttribute('userId')).toBe( + '123' + ); + expect(AttributesSingleton.getInstance().getAttributes()).toEqual({ + userId: '123' + }); + }); + + it('removeAttribute removes a single key and leaves others intact', () => { + AttributesSingleton.getInstance().addAttributes({ + a: 1, + b: 2 + }); + + AttributesSingleton.getInstance().removeAttribute('a'); + + expect( + AttributesSingleton.getInstance().getAttribute('a') + ).toBeUndefined(); + expect(AttributesSingleton.getInstance().getAttributes()).toEqual({ + b: 2 + }); + }); + + it('removeAttributes removes multiple keys (missing keys are ignored)', () => { + AttributesSingleton.getInstance().addAttributes({ + keyToKeep: 'yes', + keyToRemove1: true, + keyToRemove2: false + }); + + AttributesSingleton.getInstance().removeAttributes([ + 'keyToRemove1', + 'keyToRemove2', + 'keyToIgnore' + ]); + + expect(AttributesSingleton.getInstance().getAttributes()).toEqual({ + keyToKeep: 'yes' + }); + }); }); diff --git a/packages/core/src/specs/NativeDdSdk.ts b/packages/core/src/specs/NativeDdSdk.ts index a2ce1120e..70401fe3c 100644 --- a/packages/core/src/specs/NativeDdSdk.ts +++ b/packages/core/src/specs/NativeDdSdk.ts @@ -26,10 +26,29 @@ export interface Spec extends TurboModule { initialize(configuration: Object): Promise; /** - * Sets the global context (set of attributes) attached with all future Logs, Spans and RUM events. + * Adds a specific attribute to the global context attached with all future Logs, Spans and RUM. + * @param key: Key that identifies the attribute. + * @param value: Value linked to the attribute. + */ + addAttribute(key: string, value: Object): Promise; + + /** + * Removes an attribute from the context attached with all future Logs, Spans and RUM events. + * @param key: They key associated with the attribute to be removed. + */ + removeAttribute(key: string): Promise; + + /** + * Adds the global context (set of attributes) attached with all future Logs, Spans and RUM events. * @param attributes: The global context attributes. */ - setAttributes(attributes: Object): Promise; + addAttributes(attributes: Object): Promise; + + /** + * Removes a set of attributes from the context attached with all future Logs, Spans and RUM events. + * @param keys: They keys associated with the attributes to be removed. + */ + removeAttributes(keys: string[]): Promise; /** * Set the user information. diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index bad19d429..c8d9821cc 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -83,11 +83,30 @@ export type DdSdkType = { */ initialize(configuration: DdSdkConfiguration): Promise; + /** + * Sets a specific attribute in the global context attached with all future Logs, Spans and RUM + * @param key: Key that identifies the attribute. + * @param value: Value linked to the attribute. + */ + addAttribute(key: string, value: object): Promise; + + /** + * Removes an attribute from the context attached with all future Logs, Spans and RUM events. + * @param key: They key associated with the attribute to be removed. + */ + removeAttribute(key: string): Promise; + /** * Sets the global context (set of attributes) attached with all future Logs, Spans and RUM events. * @param attributes: The global context attributes. */ - setAttributes(attributes: object): Promise; + addAttributes(attributes: object): Promise; + + /** + * Removes a set of attributes from the context attached with all future Logs, Spans and RUM events. + * @param keys: They keys associated with the attributes to be removed. + */ + removeAttributes(keys: string[]): Promise; /** * Sets the user information. diff --git a/packages/react-native-apollo-client/__mocks__/react-native.ts b/packages/react-native-apollo-client/__mocks__/react-native.ts index 046ced2f6..bbac607d3 100644 --- a/packages/react-native-apollo-client/__mocks__/react-native.ts +++ b/packages/react-native-apollo-client/__mocks__/react-native.ts @@ -18,9 +18,9 @@ actualRN.NativeModules.DdSdk = { initialize: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, - setAttributes: jest.fn().mockImplementation( + addAttributes: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) - ) as jest.MockedFunction, + ) as jest.MockedFunction, setTrackingConsent: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, From 5b551df190de2fdfe391350dc921a7b60b62ad38 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Thu, 16 Oct 2025 11:01:21 +0200 Subject: [PATCH 39/62] JS refresh rate normalization --- .../reactnative/DdSdkImplementation.kt | 51 ++++++- .../com/datadog/reactnative/DdSdkTest.kt | 127 ++++++++++++++++++ .../ios/Sources/DdSdkImplementation.swift | 21 ++- packages/core/ios/Tests/DdSdkTests.swift | 108 +++++++++++++++ 4 files changed, 305 insertions(+), 2 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index ed545d9e1..574394a36 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -7,7 +7,10 @@ package com.datadog.reactnative import android.content.Context +import android.hardware.display.DisplayManager +import android.os.Build import android.util.Log +import android.view.Display import com.datadog.android.privacy.TrackingConsent import com.datadog.android.rum.RumPerformanceMetric import com.datadog.android.rum.configuration.VitalsUpdateFrequency @@ -19,6 +22,7 @@ import com.facebook.react.bridge.ReadableMap import java.util.Locale import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean +import kotlin.math.max /** The entry point to initialize Datadog's features. */ @Suppress("TooManyFunctions") @@ -293,9 +297,10 @@ class DdSdkImplementation( return { if (jsRefreshRateMonitoringEnabled && it > 0.0) { + val normalizedFrameTimeSeconds = normalizeFrameTime(it, appContext) datadog.getRumMonitor() ._getInternal() - ?.updatePerformanceMetric(RumPerformanceMetric.JS_FRAME_TIME, it) + ?.updatePerformanceMetric(RumPerformanceMetric.JS_FRAME_TIME, normalizedFrameTimeSeconds) } if (jsLongTasksMonitoringEnabled && it > @@ -308,6 +313,49 @@ class DdSdkImplementation( } } + /** + * Normalizes frameTime values so when are turned into FPS metrics they are normalized on a range of zero to 60fps. + * @param frameTimeSeconds: the frame time to normalize. In seconds. + * @param context: The current app context + * @param fpsBudget: The maximum fps under which the frame Time will be normalized [0-fpsBudget]. Defaults to 60Hz. + * @param deviceDisplayFps: The maximum fps supported by the device. If not provided it will be set from the value obtained from the app context. + */ + @Suppress("CyclomaticComplexMethod") + fun normalizeFrameTime( + frameTimeSeconds: Double, + context: Context, + fpsBudget: Double? = null, + deviceDisplayFps: Double? = null, + ) : Double { + val frameTimeMs = frameTimeSeconds * 1000.0 + val frameBudgetHz = fpsBudget ?: DEFAULT_REFRESH_HZ + val maxDeviceDisplayHz = deviceDisplayFps ?: getMaxDisplayRefreshRate(context) + ?: 60.0 + + val maxDeviceFrameTimeMs = 1000.0 / maxDeviceDisplayHz + val budgetFrameTimeMs = 1000.0 / frameBudgetHz + + if (listOf( + maxDeviceDisplayHz, frameTimeMs, frameBudgetHz, budgetFrameTimeMs, maxDeviceFrameTimeMs + ).any { !it.isFinite() || it <= 0.0 } + ) return 1.0 / DEFAULT_REFRESH_HZ + + + var normalizedFrameTimeMs = frameTimeMs / (maxDeviceFrameTimeMs / budgetFrameTimeMs) + + normalizedFrameTimeMs = max(normalizedFrameTimeMs, maxDeviceFrameTimeMs) + + return normalizedFrameTimeMs / 1000.0 // in seconds + } + + @Suppress("CyclomaticComplexMethod") + private fun getMaxDisplayRefreshRate(context: Context?): Double { + val dm = context?.getSystemService(Context.DISPLAY_SERVICE) as? DisplayManager ?: return 60.0 + val display: Display = dm.getDisplay(Display.DEFAULT_DISPLAY) ?: return DEFAULT_REFRESH_HZ + + return display.supportedModes.maxOf { it.refreshRate.toDouble() } + } + // endregion internal companion object { internal const val DEFAULT_APP_VERSION = "?" @@ -317,6 +365,7 @@ class DdSdkImplementation( internal const val DD_DROP_ACTION = "_dd.action.drop_action" internal const val MONITOR_JS_ERROR_MESSAGE = "Error monitoring JS refresh rate" internal const val PACKAGE_INFO_NOT_FOUND_ERROR_MESSAGE = "Error getting package info" + internal const val DEFAULT_REFRESH_HZ = 60.0 internal const val NAME = "DdSdk" } } diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index ae6ded89c..327d8ffc0 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -60,6 +60,7 @@ import java.util.Locale import java.util.stream.Stream import kotlin.time.Duration.Companion.seconds import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.data.Offset import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -3238,6 +3239,132 @@ internal class DdSdkTest { } } + @Test + fun `𝕄 normalize frameTime according to the device's refresh rate`() { + // 10 fps, 60Hz device, 60 fps budget -> 10 fps + var frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.1, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 60.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.1) + + // 30 fps, 60Hz device, 60 fps budget -> 30 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.03, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 60.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.03) + + // 60 fps, 60Hz device, 60 fps budget -> 60 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.016, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 60.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.016, Offset.offset(0.005)) + + // 60 fps, 120Hz device, 60 fps budget -> 30 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.016, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 120.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.032) + + // 120 fps, 120Hz device, 60 fps budget -> 60 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.0083, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 120.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.016, Offset.offset(0.005)) + + // 90 fps, 120Hz device, 60 fps budget -> 45 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.0111, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 120.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.0222, Offset.offset(0.001)) + + // 100 fps, 120Hz device, 60 fps budget -> 50 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.01, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 120.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.02, Offset.offset(0.001)) + + // 120 fps, 120Hz device, 120 fps budget -> 120 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.0083, + context = mockContext, + fpsBudget = 120.0, + deviceDisplayFps = 120.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.0083, Offset.offset(0.001)) + + // 80 fps, 160Hz device, 60 fps budget -> 30 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.0125, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 160.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.033, Offset.offset(0.001)) + + // 160 fps, 160Hz device, 60 fps budget -> 60 fps + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.00625, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 160.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.016, Offset.offset(0.001)) + + // Edge cases + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.0, + context = mockContext, + fpsBudget = 0.0, + deviceDisplayFps = 0.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.016, Offset.offset(0.001)) + + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.016, + context = mockContext, + fpsBudget = 0.0, + deviceDisplayFps = 0.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.016, Offset.offset(0.001)) + + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.016, + context = mockContext, + fpsBudget = 60.0, + deviceDisplayFps = 0.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.016, Offset.offset(0.001)) + + frameTimeSeconds = testedBridgeSdk.normalizeFrameTime( + frameTimeSeconds = 0.016, + context = mockContext, + fpsBudget = 0.0, + deviceDisplayFps = 60.0 + ) + assertThat(frameTimeSeconds).isEqualTo(0.016, Offset.offset(0.001)) + } + // endregion // region Internal diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 8aae5e10d..437b5ee39 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -244,7 +244,8 @@ public class DdSdkImplementation: NSObject { // Leave JS thread ASAP to give as much time to JS engine work. sharedQueue.async { if (shouldRecordFrameTime) { - rumMonitorInternal.updatePerformanceMetric(at: now, metric: .jsFrameTimeSeconds, value: frameTime, attributes: [:]) + let normalizedFrameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(frameTime) + rumMonitorInternal.updatePerformanceMetric(at: now, metric: .jsFrameTimeSeconds, value: normalizedFrameTimeSeconds, attributes: [:]) } if (shouldRecordLongTask) { rumMonitorInternal.addLongTask(at: now, duration: frameTime, attributes: ["long_task.target": "javascript"]) @@ -254,5 +255,23 @@ public class DdSdkImplementation: NSObject { return frameTimeCallback } + + // Normalizes frameTime values so when they are turned into FPS metrics they are normalized on a range between 0 and fpsBudget. If fpsBudget is not provided it will default to 60hz. + public static func normalizeFrameTimeForDeviceRefreshRate(_ frameTime: Double, fpsBudget: Double? = nil, deviceDisplayFps: Double? = nil) -> Double { + let DEFAULT_REFRESH_HZ = 60.0 + let frameTimeMs: Double = frameTime * 1000.0 + let frameBudgetHz: Double = fpsBudget ?? DEFAULT_REFRESH_HZ + let maxDeviceDisplayHz = deviceDisplayFps ?? Double(UIScreen.main.maximumFramesPerSecond) + let maxDeviceFrameTimeMs = 1000.0 / maxDeviceDisplayHz + let budgetFrameTimeMs = 1000.0 / frameBudgetHz + + guard maxDeviceDisplayHz > 0, frameTimeMs.isFinite, frameTimeMs > 0, frameBudgetHz > 0, budgetFrameTimeMs.isFinite, budgetFrameTimeMs > 0, maxDeviceFrameTimeMs.isFinite, maxDeviceFrameTimeMs > 0 else { + return 1.0 / DEFAULT_REFRESH_HZ + } + + var normalizedFrameTimeMs = frameTimeMs / (maxDeviceFrameTimeMs / budgetFrameTimeMs) + normalizedFrameTimeMs = max(normalizedFrameTimeMs, maxDeviceFrameTimeMs) + return normalizedFrameTimeMs / 1000.0 // in seconds + } } diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index adbb57da9..4a5d13f2e 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -1181,6 +1181,114 @@ class DdSdkTests: XCTestCase { XCTAssertEqual(rumMonitorMock.receivedLongTasks.first?.value, 0.25) XCTAssertEqual(rumMonitorMock.lastReceivedPerformanceMetrics[.jsFrameTimeSeconds], 0.25) } + + func testFrameTimeNormalizationFromCallback() { + let mockRefreshRateMonitor = MockJSRefreshRateMonitor() + let rumMonitorMock = MockRUMMonitor() + + DdSdkImplementation( + mainDispatchQueue: DispatchQueueMock(), + jsDispatchQueue: DispatchQueueMock(), + jsRefreshRateMonitor: mockRefreshRateMonitor, + RUMMonitorProvider: { rumMonitorMock }, + RUMMonitorInternalProvider: { rumMonitorMock._internalMock } + ).initialize( + configuration: .mockAny( + longTaskThresholdMs: 200, + vitalsUpdateFrequency: "average" + ), + resolve: mockResolve, + reject: mockReject + ) + + XCTAssertTrue(mockRefreshRateMonitor.isStarted) + + // 10 fps + mockRefreshRateMonitor.executeFrameCallback(frameTime: 0.1) + sharedQueue.sync {} + XCTAssertEqual(rumMonitorMock.lastReceivedPerformanceMetrics[.jsFrameTimeSeconds], 0.1) + + // 30 fps + mockRefreshRateMonitor.executeFrameCallback(frameTime: 0.03) + sharedQueue.sync {} + XCTAssertEqual(rumMonitorMock.lastReceivedPerformanceMetrics[.jsFrameTimeSeconds], 0.03) + + // 45 fps + mockRefreshRateMonitor.executeFrameCallback(frameTime: 0.02) + sharedQueue.sync {} + XCTAssertEqual(rumMonitorMock.lastReceivedPerformanceMetrics[.jsFrameTimeSeconds], 0.02) + + // 60 fps + mockRefreshRateMonitor.executeFrameCallback(frameTime: 0.016) + sharedQueue.sync {} + XCTAssertEqual(rumMonitorMock.lastReceivedPerformanceMetrics[.jsFrameTimeSeconds]!, 0.016, accuracy: 0.001) + + // 90 fps + mockRefreshRateMonitor.executeFrameCallback(frameTime: 0.011) + sharedQueue.sync {} + XCTAssertEqual(rumMonitorMock.lastReceivedPerformanceMetrics[.jsFrameTimeSeconds]!, 0.016, accuracy: 0.001) + + // 120 fps + mockRefreshRateMonitor.executeFrameCallback(frameTime: 0.008) + sharedQueue.sync {} + XCTAssertEqual(rumMonitorMock.lastReceivedPerformanceMetrics[.jsFrameTimeSeconds]!, 0.016, accuracy: 0.001) + } + + func testFrameTimeNormalizationUtilityFunction() { + + // 10 fps, 60fps capable device, 60 fps budget -> Normalized to 10fps + var frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.1, fpsBudget: 60.0, deviceDisplayFps: 60.0) + XCTAssertEqual(frameTimeSeconds, 0.1, accuracy: 0.01) + + // 30 fps, 60fps capable device, 60 fps budget -> Normalized to 30fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.03, fpsBudget: 60.0, deviceDisplayFps: 60.0) + XCTAssertEqual(frameTimeSeconds, 0.03, accuracy: 0.01) + + // 60 fps, 60fps capable device, 60 fps budget-> Normalized to 60fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.016, fpsBudget: 60.0, deviceDisplayFps: 60.0) + XCTAssertEqual(frameTimeSeconds, 0.016, accuracy: 0.01) + + // 60 fps, 120fps capable device, 60 fps budget -> Normalized to 30fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.016, fpsBudget: 60.0, deviceDisplayFps: 120.0) + XCTAssertEqual(frameTimeSeconds, 0.03, accuracy: 0.01) + + // 120 fps, 120fps capable device, 60 fps budget -> Normalized to 60fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.0083, fpsBudget: 60.0, deviceDisplayFps: 120.0) + XCTAssertEqual(frameTimeSeconds, 0.016, accuracy: 0.001) + + // 90 fps, 120fps capable device, 60 fps budget -> Normalized to 45fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.0111, fpsBudget: 60.0, deviceDisplayFps: 120.0) + XCTAssertEqual(frameTimeSeconds, 0.0222, accuracy: 0.001) + + // 100 fps, 120fps capable device, 60 fps budget -> Normalized to 50fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.01, fpsBudget: 60.0, deviceDisplayFps: 120.0) + XCTAssertEqual(frameTimeSeconds, 0.02, accuracy: 0.001) + + // 120 fps, 120fps capable device, 120 fps budget -> Normalized to 120fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.0083, fpsBudget: 120.0, deviceDisplayFps: 120.0) + XCTAssertEqual(frameTimeSeconds, 0.0083, accuracy: 0.001) + + // 80 fps, 160fps capable device, 60 fps budget -> Normalized to 30fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.0125, fpsBudget: 60.0, deviceDisplayFps: 160.0) + XCTAssertEqual(frameTimeSeconds, 0.033, accuracy: 0.001) + + // 160 fps, 160fps capable device, 60 fps budget -> Normalized to 60fps + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.00625, fpsBudget: 60.0, deviceDisplayFps: 160.0) + XCTAssertEqual(frameTimeSeconds, 0.016, accuracy: 0.001) + + // Edge cases + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0, fpsBudget: 0, deviceDisplayFps: 0) + XCTAssertEqual(frameTimeSeconds, 0.016, accuracy: 0.001) + + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.016, fpsBudget: 0, deviceDisplayFps: 0) + XCTAssertEqual(frameTimeSeconds, 0.016, accuracy: 0.001) + + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.016, fpsBudget: 60.0, deviceDisplayFps: 0) + XCTAssertEqual(frameTimeSeconds, 0.016, accuracy: 0.001) + + frameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(0.016, fpsBudget: 0, deviceDisplayFps: 60.0) + XCTAssertEqual(frameTimeSeconds, 0.016, accuracy: 0.001) + } func testSDKInitializationWithCustomEndpoints() throws { let mockRefreshRateMonitor = MockJSRefreshRateMonitor() From 2918733e3d680fa9036ba62218ee400bb47aee98 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 10 Oct 2025 14:52:21 +0200 Subject: [PATCH 40/62] Expose view Attributes API --- packages/core/__mocks__/react-native.ts | 12 ++ .../reactnative/DdRumImplementation.kt | 44 ++++++ .../reactnative/DdSdkImplementation.kt | 2 - .../kotlin/com/datadog/reactnative/DdRum.kt | 38 ++++++ .../kotlin/com/datadog/reactnative/DdRum.kt | 38 ++++++ .../com/datadog/reactnative/DdRumTest.kt | 58 ++++++++ .../com/datadog/tools/unit/MockRumMonitor.kt | 17 +-- packages/core/ios/Sources/DdRum.mm | 47 ++++++- .../ios/Sources/DdRumImplementation.swift | 28 ++++ .../ios/Sources/DdSdkImplementation.swift | 129 ++++++++++++------ packages/core/ios/Tests/DdRumTests.swift | 59 ++++++++ packages/core/ios/Tests/MockRUMMonitor.swift | 38 +++--- packages/core/jest/mock.js | 12 ++ packages/core/src/rum/DdRum.ts | 45 ++++++ packages/core/src/rum/__tests__/DdRum.test.ts | 92 +++++++++++++ packages/core/src/rum/types.ts | 26 ++++ packages/core/src/specs/NativeDdRum.ts | 25 ++++ 17 files changed, 638 insertions(+), 72 deletions(-) diff --git a/packages/core/__mocks__/react-native.ts b/packages/core/__mocks__/react-native.ts index 24e3f80c7..73308f711 100644 --- a/packages/core/__mocks__/react-native.ts +++ b/packages/core/__mocks__/react-native.ts @@ -132,6 +132,18 @@ actualRN.NativeModules.DdRum = { addTiming: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, + addViewAttribute: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + removeViewAttribute: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + addViewAttributes: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + removeViewAttributes: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, addViewLoadingTime: jest.fn().mockImplementation( () => new Promise(resolve => resolve()) ) as jest.MockedFunction, diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt index 013872c08..4e3cd416f 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt @@ -13,6 +13,7 @@ import com.datadog.android.rum.RumErrorSource import com.datadog.android.rum.RumResourceKind import com.datadog.android.rum.RumResourceMethod import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import java.util.Locale @@ -248,6 +249,49 @@ class DdRumImplementation(private val datadog: DatadogWrapper = DatadogSDKWrappe promise.resolve(null) } + /** + * Adds a custom attribute to the active RUM View. It will be propagated to all future RUM events associated with the active View. + * @param key: key for this view attribute. + * @param value: value for this attribute. + */ + fun addViewAttribute(key: String, value: ReadableMap, promise: Promise) { + val attributeValue = value.toMap()["value"] + val attributes = mutableMapOf() + attributes[key] = attributeValue + datadog.getRumMonitor().addViewAttributes(attributes) + promise.resolve(null) + } + + /** + * Removes an attribute from the active RUM View. + * @param key: key for the attribute to be removed from the view. + */ + fun removeViewAttribute(key: String, promise: Promise) { + val keysToDelete: Collection = listOf(key) + datadog.getRumMonitor().removeViewAttributes(keysToDelete) + promise.resolve(null) + } + + /** + * Adds multiple attributes to the active RUM View. They will be propagated to all future RUM events associated with the active View. + * @param attributes: key/value object containing all attributes to be added to the view. + */ + fun addViewAttributes(attributes: ReadableMap, promise: Promise) { + datadog.getRumMonitor().addViewAttributes(attributes.toMap()) + promise.resolve(null) + } + + /** + * Removes multiple attributes from the active RUM View. + * @param keys: keys for the attributes to be removed from the view. + */ + fun removeViewAttributes(keys: ReadableArray, promise: Promise) { + val keysToDelete = (0 until keys.size()) + .mapNotNull { keys.getString(it) } + datadog.getRumMonitor().removeViewAttributes(keysToDelete) + promise.resolve(null) + } + /** * Adds the loading time of the view to the active view. * It is calculated as the difference between the current time and the start time of the view. diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index 574394a36..6741e971e 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -143,8 +143,6 @@ class DdSdkImplementation( if (id != null) { datadog.setUserInfo(id, name, email, extraInfo) - } else { - // TO DO - Log warning? } promise.resolve(null) diff --git a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt index ce8104685..6cb2b385b 100644 --- a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt +++ b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt @@ -9,6 +9,7 @@ package com.datadog.reactnative import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap /** @@ -201,6 +202,43 @@ class DdRum( implementation.addTiming(name, promise) } + /** + * Adds a custom attribute to the active RUM View. It will be propagated to all future RUM events associated with the active View. + * @param key: key for this view attribute. + * @param value: value for this attribute. + */ + @ReactMethod + override fun addViewAttribute(key: String, value: ReadableMap, promise: Promise) { + implementation.addViewAttribute(key, value, promise) + } + + /** + * Removes an attribute from the active RUM View. + * @param key: key for the attribute to be removed from the view. + */ + @ReactMethod + override fun removeViewAttribute(key: String, promise: Promise) { + implementation.removeViewAttribute(key, promise) + } + + /** + * Adds multiple attributes to the active RUM View. They will be propagated to all future RUM events associated with the active View. + * @param attributes: key/value object containing all attributes to be added to the view. + */ + @ReactMethod + override fun addViewAttributes(attributes: ReadableMap, promise: Promise) { + implementation.addViewAttributes(attributes, promise) + } + + /** + * Removes multiple attributes from the active RUM View. + * @param keys: keys for the attributes to be removed from the view. + */ + @ReactMethod + override fun removeViewAttributes(keys: ReadableArray, promise: Promise) { + implementation.removeViewAttributes(keys, promise) + } + /** * Adds the loading time of the view to the active view. * It is calculated as the difference between the current time and the start time of the view. diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt index 79742e854..a6c4965ea 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt @@ -10,6 +10,7 @@ import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap /** @@ -192,6 +193,43 @@ class DdRum( implementation.addTiming(name, promise) } + /** + * Adds a custom attribute to the active RUM View. It will be propagated to all future RUM events associated with the active View. + * @param key: key for this view attribute. + * @param value: value for this attribute. + */ + @ReactMethod + fun addViewAttribute(key: String, value: ReadableMap, promise: Promise) { + implementation.addViewAttribute(key, value, promise) + } + + /** + * Removes an attribute from the active RUM View. + * @param key: key for the attribute to be removed from the view. + */ + @ReactMethod + fun removeViewAttribute(key: String, promise: Promise) { + implementation.removeViewAttribute(key, promise) + } + + /** + * Adds multiple attributes to the active RUM View. They will be propagated to all future RUM events associated with the active View. + * @param attributes: key/value object containing all attributes to be added to the view. + */ + @ReactMethod + fun addViewAttributes(attributes: ReadableMap, promise: Promise) { + implementation.addViewAttributes(attributes, promise) + } + + /** + * Removes multiple attributes from the active RUM View. + * @param keys: keys for the attributes to be removed from the view. + */ + @ReactMethod + fun removeViewAttributes(keys: ReadableArray, promise: Promise) { + implementation.removeViewAttributes(keys, promise) + } + /** * Adds the loading time of the view to the active view. * It is calculated as the difference between the current time and the start time of the view. diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdRumTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdRumTest.kt index be1c57b3a..9619794df 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdRumTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdRumTest.kt @@ -13,13 +13,16 @@ import com.datadog.android.rum.RumMonitor import com.datadog.android.rum.RumResourceKind import com.datadog.android.rum.RumResourceMethod import com.datadog.tools.unit.forge.BaseConfigurator +import com.datadog.tools.unit.toReadableArray import com.datadog.tools.unit.toReadableMap import com.facebook.react.bridge.Promise import fr.xgouchet.elmyr.Forge +import fr.xgouchet.elmyr.annotation.AdvancedForgery import fr.xgouchet.elmyr.annotation.BoolForgery import fr.xgouchet.elmyr.annotation.DoubleForgery import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.IntForgery +import fr.xgouchet.elmyr.annotation.MapForgery import fr.xgouchet.elmyr.annotation.StringForgery import fr.xgouchet.elmyr.annotation.StringForgeryType import fr.xgouchet.elmyr.junit5.ForgeConfiguration @@ -456,6 +459,61 @@ internal class DdRumTest { verify(mockRumMonitor).addTiming(timing) } + @Test + fun `M call addViewAttribute W addViewAttribute()`( + @StringForgery key: String, + @StringForgery value: String + ) { + var attributeMap = mutableMapOf() + attributeMap.put("value", value) + + var attributes = mutableMapOf() + attributes.put(key, value) + + // When + testedDdRum.addViewAttribute(key, attributeMap.toReadableMap(), mockPromise) + + // Then + verify(mockRumMonitor).addViewAttributes(attributes) + } + + @Test + fun `M call removeViewAttribute W removeViewAttribute()`(@StringForgery key: String) { + // When + testedDdRum.removeViewAttribute(key, mockPromise) + + // Then + verify(mockRumMonitor).removeViewAttributes(listOf(key)) + } + + @Test + fun `M call addViewAttributes W addViewAttributes()`( + @MapForgery( + key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), + value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) + ) customAttributes: Map + ) { + // When + testedDdRum.addViewAttributes(customAttributes.toReadableMap(), mockPromise) + + // Then + verify(mockRumMonitor).addViewAttributes(customAttributes) + } + + @Test + fun `𝕄 call removeViewAttributes 𝕎 removeViewAttributes`( + @MapForgery( + key = AdvancedForgery(string = [StringForgery(StringForgeryType.NUMERICAL)]), + value = AdvancedForgery(string = [StringForgery(StringForgeryType.ASCII)]) + ) customAttributes: Map + ) { + // When + testedDdRum.removeViewAttributes(customAttributes.keys.toReadableArray(), mockPromise) + + // Then + verify(mockRumMonitor).removeViewAttributes(customAttributes.keys.toList()) + } + @Test fun `M call addViewLoadingTime w addViewLoadingTime()`(@BoolForgery overwrite: Boolean) { // When diff --git a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt index 702cc2533..13f73d94a 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/MockRumMonitor.kt @@ -30,7 +30,13 @@ class MockRumMonitor : RumMonitor { override fun addAttribute(key: String, value: Any?) {} - override fun addViewAttributes(attributes: Map) {} + override fun removeAttribute(key: String) {} + + override fun clearAttributes() {} + + override fun getAttributes(): Map { + return mapOf() + } override fun addError( message: String, @@ -55,15 +61,10 @@ class MockRumMonitor : RumMonitor { @ExperimentalRumApi override fun addViewLoadingTime(overwrite: Boolean) {} - override fun clearAttributes() {} - - override fun getAttributes(): Map { - return mapOf() - } - override fun getCurrentSessionId(callback: (String?) -> Unit) {} - override fun removeAttribute(key: String) {} + override fun addViewAttributes(attributes: Map) {} + override fun removeViewAttributes(attributes: Collection) {} override fun startAction( diff --git a/packages/core/ios/Sources/DdRum.mm b/packages/core/ios/Sources/DdRum.mm index 5d831942a..f5c324ce8 100644 --- a/packages/core/ios/Sources/DdRum.mm +++ b/packages/core/ios/Sources/DdRum.mm @@ -107,6 +107,35 @@ @implementation DdRum [self addTiming:name resolve:resolve reject:reject]; } +RCT_EXPORT_METHOD(addViewAttribute:(NSString*) key + withValue:(NSDictionary*) value + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self addViewAttribute:key value:value resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(removeViewAttribute:(NSString*) key + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self removeViewAttribute:key resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(addViewAttributes:(NSDictionary*) attributes + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self addViewAttributes:attributes resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(removeViewAttributes:(NSArray *)keys + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self removeViewAttributes:keys resolve:resolve reject:reject]; +} + RCT_REMAP_METHOD(addViewLoadingTime, withOverwrite:(BOOL)overwrite withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) @@ -138,7 +167,7 @@ @implementation DdRum // Thanks to this guard, we won't compile this code when we build for the old architecture. #ifdef RCT_NEW_ARCH_ENABLED - (std::shared_ptr)getTurboModule: - (const facebook::react::ObjCTurboModule::InitParams &)params +(const facebook::react::ObjCTurboModule::InitParams &)params { return std::make_shared(params); } @@ -180,6 +209,22 @@ - (void)addTiming:(NSString *)name resolve:(RCTPromiseResolveBlock)resolve rejec [self.ddRumImplementation addTimingWithName:name resolve:resolve reject:reject]; } +- (void)addViewAttribute:(NSString *)key value:(NSDictionary *)value resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddRumImplementation addViewAttributeWithKey:key value:value resolve:resolve reject:reject]; +} + +- (void)removeViewAttribute:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddRumImplementation removeViewAttributeWithKey:key resolve:resolve reject:reject]; +} + +- (void)addViewAttributes:(NSDictionary *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddRumImplementation addViewAttributesWithAttributes:attributes resolve:resolve reject:reject]; +} + +- (void)removeViewAttributes:(NSArray *)keys resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddRumImplementation removeViewAttributesWithKeys:keys resolve:resolve reject:reject]; +} + - (void)addViewLoadingTime:(BOOL)overwrite resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {\ [self.ddRumImplementation addViewLoadingTimeWithOverwrite:overwrite resolve:resolve reject:reject]; } diff --git a/packages/core/ios/Sources/DdRumImplementation.swift b/packages/core/ios/Sources/DdRumImplementation.swift index 9f8da4c7f..6fac21f82 100644 --- a/packages/core/ios/Sources/DdRumImplementation.swift +++ b/packages/core/ios/Sources/DdRumImplementation.swift @@ -181,6 +181,34 @@ public class DdRumImplementation: NSObject { resolve(nil) } + @objc + public func addViewAttribute(key: AttributeKey, value: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + if let attributeValue = value.object(forKey: "value") { + let castedAttribute = castValueToSwift(attributeValue) + nativeRUM.addViewAttribute(forKey: key, value: castedAttribute) + } + resolve(nil) + } + + @objc + public func removeViewAttribute(key: AttributeKey, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + nativeRUM.removeViewAttribute(forKey: key) + resolve(nil) + } + + @objc + public func addViewAttributes(attributes: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + let castedAttributes = castAttributesToSwift(attributes) + nativeRUM.addViewAttributes(castedAttributes) + resolve(nil) + } + + @objc + public func removeViewAttributes(keys: [AttributeKey], resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + nativeRUM.removeViewAttributes(forKeys: keys) + resolve(nil) + } + @objc public func addViewLoadingTime(overwrite: Bool, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { nativeRUM.addViewLoadingTime(overwrite: overwrite) diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 437b5ee39..9c3fe980f 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -4,13 +4,14 @@ * Copyright 2016-Present Datadog, Inc. */ -import Foundation import DatadogCore -import DatadogRUM -import DatadogLogs -import DatadogTrace import DatadogCrashReporting import DatadogInternal +import DatadogLogs +import DatadogRUM +import DatadogTrace +import DatadogWebViewTracking +import Foundation import React #if os(iOS) @@ -18,7 +19,8 @@ import DatadogWebViewTracking #endif func getDefaultAppVersion() -> String { - let bundleShortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String + let bundleShortVersion = + Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String let bundleVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String return bundleShortVersion ?? bundleVersion ?? "0.0.0" } @@ -35,7 +37,7 @@ public class DdSdkImplementation: NSObject { var webviewMessageEmitter: InternalExtension.AbstractMessageEmitter? #endif - private let jsLongTaskThresholdInSeconds: TimeInterval = 0.1; + private let jsLongTaskThresholdInSeconds: TimeInterval = 0.1 @objc public convenience init(bridge: RCTBridge) { @@ -47,7 +49,7 @@ public class DdSdkImplementation: NSObject { RUMMonitorInternalProvider: { RUMMonitor.shared()._internal } ) } - + init( mainDispatchQueue: DispatchQueueType, jsDispatchQueue: DispatchQueueType, @@ -62,10 +64,13 @@ public class DdSdkImplementation: NSObject { self.RUMMonitorInternalProvider = RUMMonitorInternalProvider super.init() } - + // Using @escaping RCTPromiseResolveBlock type will result in an issue when compiling the Swift header file. @objc - public func initialize(configuration: NSDictionary, resolve:@escaping ((Any?) -> Void), reject:RCTPromiseRejectBlock) -> Void { + public func initialize( + configuration: NSDictionary, resolve: @escaping ((Any?) -> Void), + reject: RCTPromiseRejectBlock + ) { let sdkConfiguration = configuration.asDdSdkConfiguration() let nativeInitialization = DdSdkNativeInitialization() @@ -117,7 +122,9 @@ public class DdSdkImplementation: NSObject { } @objc - public func setUserInfo(userInfo: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func setUserInfo( + userInfo: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { let castedUserInfo = castAttributesToSwift(userInfo) let id = castedUserInfo["id"] as? String let name = castedUserInfo["name"] as? String @@ -125,21 +132,22 @@ public class DdSdkImplementation: NSObject { var extraInfo: [AttributeKey: AttributeValue] = [:] if let extraInfoEncodable = castedUserInfo["extraInfo"] as? AnyEncodable, - let extraInfoDict = extraInfoEncodable.value as? [String: Any] { + let extraInfoDict = extraInfoEncodable.value as? [String: Any] + { extraInfo = castAttributesToSwift(extraInfoDict) } if let validId = id { Datadog.setUserInfo(id: validId, name: name, email: email, extraInfo: extraInfo) - } else { - // TO DO - log warning message? } resolve(nil) } - + @objc - public func addUserExtraInfo(extraInfo: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func addUserExtraInfo( + extraInfo: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { let castedExtraInfo = castAttributesToSwift(extraInfo) Datadog.addUserExtraInfo(castedExtraInfo) @@ -147,35 +155,37 @@ public class DdSdkImplementation: NSObject { } @objc - public func clearUserInfo(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func clearUserInfo(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { Datadog.clearUserInfo() resolve(nil) } @objc - public func setTrackingConsent(trackingConsent: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func setTrackingConsent( + trackingConsent: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { Datadog.set(trackingConsent: (trackingConsent as NSString?).asTrackingConsent()) resolve(nil) } - - + @objc - public func sendTelemetryLog(message: NSString, attributes: NSDictionary, config: NSDictionary, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func sendTelemetryLog( + message: NSString, attributes: NSDictionary, config: NSDictionary, + resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { let castedAttributes = castAttributesToSwift(attributes) let castedConfig = castAttributesToSwift(config) - DdTelemetry.sendTelemetryLog(message: message as String, attributes: castedAttributes, config: castedConfig) + DdTelemetry.sendTelemetryLog( + message: message as String, attributes: castedAttributes, config: castedConfig) resolve(nil) } @objc - public func telemetryDebug(message: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { - DdTelemetry.telemetryDebug(id: "datadog_react_native:\(message)", message: message as String) - resolve(nil) - } - - @objc - public func telemetryError(message: NSString, stack: NSString, kind: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { - DdTelemetry.telemetryError(id: "datadog_react_native:\(String(describing: kind)):\(message)", message: message as String, kind: kind as String, stack: stack as String) + public func telemetryDebug( + message: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { + DdTelemetry.telemetryDebug( + id: "datadog_react_native:\(message)", message: message as String) resolve(nil) } <<<<<<< HEAD @@ -185,27 +195,50 @@ public class DdSdkImplementation: NSObject { >>>>>>> 0443e0ff (iOS: Always use SDK default core instance) @objc - public func consumeWebviewEvent(message: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { - do{ + public func telemetryError( + message: NSString, stack: NSString, kind: NSString, resolve: RCTPromiseResolveBlock, + reject: RCTPromiseRejectBlock + ) { + DdTelemetry.telemetryError( + id: "datadog_react_native:\(String(describing: kind)):\(message)", + message: message as String, kind: kind as String, stack: stack as String) + resolve(nil) + } + + @objc + public func consumeWebviewEvent( + message: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { + do { try DatadogSDKWrapper.shared.sendWebviewMessage(body: message) } catch { - DdTelemetry.telemetryError(id: "datadog_react_native:\(error.localizedDescription)", message: "The message being sent was:\(message)" as String, kind: "WebViewEventBridgeError" as String, stack: String(describing: error) as String) + DdTelemetry.telemetryError( + id: "datadog_react_native:\(error.localizedDescription)", + message: "The message being sent was:\(message)" as String, + kind: "WebViewEventBridgeError" as String, + stack: String(describing: error) as String) } resolve(nil) } +<<<<<<< HEAD #endif +======= + +>>>>>>> 1f781a51 (Expose view Attributes API) @objc - public func clearAllData(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func clearAllData(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { Datadog.clearAllData() resolve(nil) } - func overrideReactNativeTelemetry(rnConfiguration: DdSdkConfiguration) -> Void { + func overrideReactNativeTelemetry(rnConfiguration: DdSdkConfiguration) { DdTelemetry.overrideTelemetryConfiguration( - initializationType: rnConfiguration.configurationForTelemetry?.initializationType as? String, - reactNativeVersion: rnConfiguration.configurationForTelemetry?.reactNativeVersion as? String, + initializationType: rnConfiguration.configurationForTelemetry?.initializationType + as? String, + reactNativeVersion: rnConfiguration.configurationForTelemetry?.reactNativeVersion + as? String, reactVersion: rnConfiguration.configurationForTelemetry?.reactVersion as? String, trackCrossPlatformLongTasks: rnConfiguration.longTaskThresholdMs != 0, trackErrors: rnConfiguration.configurationForTelemetry?.trackErrors, @@ -220,24 +253,28 @@ public class DdSdkImplementation: NSObject { func startJSRefreshRateMonitoring(sdkConfiguration: DdSdkConfiguration) { if let frameTimeCallback = buildFrameTimeCallback(sdkConfiguration: sdkConfiguration) { // Falling back to mainDispatchQueue if bridge is nil is only useful for tests - self.jsRefreshRateMonitor.startMonitoring(jsQueue: jsDispatchQueue, frameTimeCallback: frameTimeCallback) + self.jsRefreshRateMonitor.startMonitoring( + jsQueue: jsDispatchQueue, frameTimeCallback: frameTimeCallback) } } - func buildFrameTimeCallback(sdkConfiguration: DdSdkConfiguration)-> ((Double) -> ())? { + func buildFrameTimeCallback(sdkConfiguration: DdSdkConfiguration) -> ((Double) -> Void)? { let jsRefreshRateMonitoringEnabled = sdkConfiguration.vitalsUpdateFrequency != nil let jsLongTaskMonitoringEnabled = sdkConfiguration.longTaskThresholdMs != 0 - - if (!jsRefreshRateMonitoringEnabled && !jsLongTaskMonitoringEnabled) { + + if !jsRefreshRateMonitoringEnabled && !jsLongTaskMonitoringEnabled { return nil } func frameTimeCallback(frameTime: Double) { // These checks happen before dispatching because they are quick and less overhead than the dispatch itself. let shouldRecordFrameTime = jsRefreshRateMonitoringEnabled && frameTime > 0 - let shouldRecordLongTask = jsLongTaskMonitoringEnabled && frameTime > sdkConfiguration.longTaskThresholdMs / 1_000 + let shouldRecordLongTask = + jsLongTaskMonitoringEnabled + && frameTime > sdkConfiguration.longTaskThresholdMs / 1_000 guard shouldRecordFrameTime || shouldRecordLongTask, - let rumMonitorInternal = RUMMonitorInternalProvider() else { return } + let rumMonitorInternal = RUMMonitorInternalProvider() + else { return } // Record current timestamp, it may change slightly before event is created on background thread. let now = Date() @@ -247,12 +284,14 @@ public class DdSdkImplementation: NSObject { let normalizedFrameTimeSeconds = DdSdkImplementation.normalizeFrameTimeForDeviceRefreshRate(frameTime) rumMonitorInternal.updatePerformanceMetric(at: now, metric: .jsFrameTimeSeconds, value: normalizedFrameTimeSeconds, attributes: [:]) } - if (shouldRecordLongTask) { - rumMonitorInternal.addLongTask(at: now, duration: frameTime, attributes: ["long_task.target": "javascript"]) + if shouldRecordLongTask { + rumMonitorInternal.addLongTask( + at: now, duration: frameTime, attributes: ["long_task.target": "javascript"] + ) } } } - + return frameTimeCallback } diff --git a/packages/core/ios/Tests/DdRumTests.swift b/packages/core/ios/Tests/DdRumTests.swift index 1102b7b6b..5f6adc016 100644 --- a/packages/core/ios/Tests/DdRumTests.swift +++ b/packages/core/ios/Tests/DdRumTests.swift @@ -253,6 +253,65 @@ internal class DdRumTests: XCTestCase { XCTAssertEqual(mockNativeRUM.receivedAttributes.count, 0) } + func testAddViewAttribute() throws { + let viewAttributeKey = "attributeKey" + let viewAttributes = NSDictionary( + dictionary: [ + "value": 123, + ] + ) + + rum.addViewAttribute(key: viewAttributeKey, value: viewAttributes, resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(mockNativeRUM.calledMethods.count, 1) + XCTAssertEqual(mockNativeRUM.calledMethods.last, .addViewAttribute(key: viewAttributeKey)) + XCTAssertEqual(mockNativeRUM.receivedAttributes.count, 1) + let lastAttributes = try XCTUnwrap(mockNativeRUM.receivedAttributes.last) + XCTAssertEqual(lastAttributes.count, 1) + XCTAssertEqual(lastAttributes["attributeKey"] as? Int64, 123) + } + + func testRemoveViewAttribute() throws { + let viewAttributeKey = "attributeKey" + + rum.removeViewAttribute(key: viewAttributeKey, resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(mockNativeRUM.calledMethods.count, 1) + XCTAssertEqual(mockNativeRUM.calledMethods.last, .removeViewAttribute(key: viewAttributeKey)) + } + + func testAddViewAttributes() throws { + let viewAttributes = NSDictionary( + dictionary: [ + "attribute-1": 123, + "attribute-2": "abc", + "attribute-3": true, + ] + ) + + rum.addViewAttributes(attributes: viewAttributes, resolve: mockResolve, reject: mockReject) + + + XCTAssertEqual(mockNativeRUM.calledMethods.count, 1) + XCTAssertEqual(mockNativeRUM.calledMethods.last, .addViewAttributes()) + XCTAssertEqual(mockNativeRUM.receivedAttributes.count, 1) + let lastAttributes = try XCTUnwrap(mockNativeRUM.receivedAttributes.last) + XCTAssertEqual(lastAttributes.count, 3) + XCTAssertEqual(lastAttributes["attribute-1"] as? Int64, 123) + XCTAssertEqual(lastAttributes["attribute-2"] as? String, "abc") + XCTAssertEqual(lastAttributes["attribute-3"] as? Bool, true) + } + + + func testRemoveViewAttributes() throws { + let viewAttributeKeys = ["attributeKey1", "attributeKey2", "attributeKey3"] + + rum.removeViewAttributes(keys: viewAttributeKeys, resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(mockNativeRUM.calledMethods.count, 1) + XCTAssertEqual(mockNativeRUM.calledMethods.last, .removeViewAttributes(keys: viewAttributeKeys)) + } + func testAddViewLoadingTime() throws { rum.addViewLoadingTime(overwrite: true, resolve: mockResolve, reject: mockReject) diff --git a/packages/core/ios/Tests/MockRUMMonitor.swift b/packages/core/ios/Tests/MockRUMMonitor.swift index 3a882ed47..4a1d0cd92 100644 --- a/packages/core/ios/Tests/MockRUMMonitor.swift +++ b/packages/core/ios/Tests/MockRUMMonitor.swift @@ -10,22 +10,6 @@ @testable import DatadogSDKReactNative internal class MockRUMMonitor: RUMMonitorProtocol { - func addViewAttribute(forKey key: DatadogInternal.AttributeKey, value: any DatadogInternal.AttributeValue) { - // not implemented - } - - func addViewAttributes(_ attributes: [DatadogInternal.AttributeKey : any DatadogInternal.AttributeValue]) { - // not implemented - } - - func removeViewAttribute(forKey key: DatadogInternal.AttributeKey) { - // not implemented - } - - func removeViewAttributes(forKeys keys: [DatadogInternal.AttributeKey]) { - // not implemented - } - func currentSessionID(completion: @escaping (String?) -> Void) { // not implemented } @@ -71,6 +55,10 @@ internal class MockRUMMonitor: RUMMonitorProtocol { case stopUserAction(type: RUMActionType, name: String?) case addUserAction(type: RUMActionType, name: String) case addTiming(name: String) + case addViewAttribute(key: String) + case removeViewAttribute(key: String) + case addViewAttributes(_: Int? = nil) // We need an attribute for the case to be Equatable + case removeViewAttributes(keys: [String]) case addViewLoadingTime(overwrite: Bool) case stopSession(_: Int? = nil) // We need an attribute for the case to be Equatable case addResourceMetrics(resourceKey: String, @@ -131,6 +119,24 @@ internal class MockRUMMonitor: RUMMonitorProtocol { func addTiming(name: String) { calledMethods.append(.addTiming(name: name)) } + func addViewAttribute(forKey key: DatadogInternal.AttributeKey, value: any DatadogInternal.AttributeValue) { + calledMethods.append(.addViewAttribute(key: key)) + receivedAttributes.append([key :value]) + } + + func removeViewAttribute(forKey key: DatadogInternal.AttributeKey) { + calledMethods.append(.removeViewAttribute(key: key)) + } + + func addViewAttributes(_ attributes: [DatadogInternal.AttributeKey : any DatadogInternal.AttributeValue]) { + calledMethods.append(.addViewAttributes()) + receivedAttributes.append(attributes) + } + + func removeViewAttributes(forKeys keys: [DatadogInternal.AttributeKey]) { + calledMethods.append(.removeViewAttributes(keys: keys)) + } + func addViewLoadingTime(overwrite: Bool) { calledMethods.append(.addViewLoadingTime(overwrite: overwrite)) } diff --git a/packages/core/jest/mock.js b/packages/core/jest/mock.js index c49d13f48..0dc9ec138 100644 --- a/packages/core/jest/mock.js +++ b/packages/core/jest/mock.js @@ -119,6 +119,18 @@ module.exports = { addTiming: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), + addViewAttribute: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + removeViewAttribute: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + addViewAttributes: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + removeViewAttributes: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), addViewLoadingTime: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), diff --git a/packages/core/src/rum/DdRum.ts b/packages/core/src/rum/DdRum.ts index b32ab410b..bedc6f33a 100644 --- a/packages/core/src/rum/DdRum.ts +++ b/packages/core/src/rum/DdRum.ts @@ -9,6 +9,7 @@ import { DdAttributes } from '../DdAttributes'; import { InternalLog } from '../InternalLog'; import { SdkVerbosity } from '../SdkVerbosity'; import type { DdNativeRumType } from '../nativeModulesTypes'; +import type { Attributes } from '../sdk/AttributesSingleton/types'; import { bufferVoidNativeCall } from '../sdk/DatadogProvider/Buffer/bufferNativeCall'; import { DdSdk } from '../sdk/DdSdk'; import { GlobalState } from '../sdk/GlobalState/GlobalState'; @@ -285,6 +286,50 @@ class DdRumWrapper implements DdRumType { return bufferVoidNativeCall(() => this.nativeRum.addTiming(name)); }; + addViewAttribute = (key: string, value: unknown): Promise => { + InternalLog.log( + `Adding view attribute “${key}" with value “${JSON.stringify( + value + )}” to RUM View`, + SdkVerbosity.DEBUG + ); + return bufferVoidNativeCall(() => + this.nativeRum.addViewAttribute(key, { value }) + ); + }; + + removeViewAttribute = (key: string): Promise => { + InternalLog.log( + `Removing view attribute “${key}" from RUM View`, + SdkVerbosity.DEBUG + ); + return bufferVoidNativeCall(() => + this.nativeRum.removeViewAttribute(key) + ); + }; + + addViewAttributes = (attributes: Attributes): Promise => { + InternalLog.log( + `Adding view attributes "${JSON.stringify( + attributes + )}” to RUM View`, + SdkVerbosity.DEBUG + ); + return bufferVoidNativeCall(() => + this.nativeRum.addViewAttributes(attributes) + ); + }; + + removeViewAttributes = (keys: string[]): Promise => { + InternalLog.log( + `Removing view attributes “${keys}" from RUM View`, + SdkVerbosity.DEBUG + ); + return bufferVoidNativeCall(() => + this.nativeRum.removeViewAttributes(keys) + ); + }; + addViewLoadingTime = (overwrite: boolean): Promise => { InternalLog.log( overwrite diff --git a/packages/core/src/rum/__tests__/DdRum.test.ts b/packages/core/src/rum/__tests__/DdRum.test.ts index 7e5fc24de..41b873fe9 100644 --- a/packages/core/src/rum/__tests__/DdRum.test.ts +++ b/packages/core/src/rum/__tests__/DdRum.test.ts @@ -1091,6 +1091,98 @@ describe('DdRum', () => { }); }); + describe('DdRum.addTiming', () => { + it('calls the native SDK when setting a timing', async () => { + // GIVEN + const timingName = 'testTiming'; + + // WHEN + await DdRum.addTiming(timingName); + + // THEN + expect(NativeModules.DdRum.addTiming).toHaveBeenCalledTimes(1); + expect(NativeModules.DdRum.addTiming).toHaveBeenCalledWith( + timingName + ); + }); + }); + + describe('DdRum.addViewAttribute', () => { + it('calls the native SDK when setting a view attribute', async () => { + // GIVEN + const key = 'testAttribute'; + const value = { test: 'attribute' }; + + // WHEN + + await DdRum.addViewAttribute(key, value); + + // THEN + expect( + NativeModules.DdRum.addViewAttribute + ).toHaveBeenCalledTimes(1); + expect( + NativeModules.DdRum.addViewAttribute + ).toHaveBeenCalledWith(key, { value }); + }); + }); + + describe('DdRum.removViewAttribute', () => { + it('calls the native SDK when removing a view attribute', async () => { + // GIVEN + const key = 'testAttribute'; + + // WHEN + await DdRum.removeViewAttribute(key); + + // THEN + expect( + NativeModules.DdRum.removeViewAttribute + ).toHaveBeenCalledTimes(1); + expect( + NativeModules.DdRum.removeViewAttribute + ).toHaveBeenCalledWith(key); + }); + }); + + describe('DdRum.addViewAttributes', () => { + it('calls the native SDK when setting view attributes', async () => { + // GIVEN + const attributes = { + test: 'attribute' + }; + + // WHEN + await DdRum.addViewAttributes(attributes); + + // THEN + expect( + NativeModules.DdRum.addViewAttributes + ).toHaveBeenCalledTimes(1); + expect( + NativeModules.DdRum.addViewAttributes + ).toHaveBeenCalledWith(attributes); + }); + }); + + describe('DdRum.removViewAttributes', () => { + it('calls the native SDK when removing view attributes', async () => { + // GIVEN + const keysToDelete = ['test1', 'test2']; + + // WHEN + await DdRum.removeViewAttributes(keysToDelete); + + // THEN + expect( + NativeModules.DdRum.removeViewAttributes + ).toHaveBeenCalledTimes(1); + expect( + NativeModules.DdRum.removeViewAttributes + ).toHaveBeenCalledWith(keysToDelete); + }); + }); + describe('DdRum.addAction', () => { test('uses given context when context is valid', async () => { const context = { diff --git a/packages/core/src/rum/types.ts b/packages/core/src/rum/types.ts index fc8d07c02..3def7f0e6 100644 --- a/packages/core/src/rum/types.ts +++ b/packages/core/src/rum/types.ts @@ -4,6 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ +import type { Attributes } from '../sdk/AttributesSingleton/types'; import type { ErrorSource } from '../types'; import type { DatadogTracingContext } from './instrumentation/resourceTracking/distributedTracing/DatadogTracingContext'; @@ -148,6 +149,31 @@ export type DdRumType = { */ addTiming(name: string): Promise; + /** + * Adds a custom attribute to the active RUM View. It will be propagated to all future RUM events associated with the active View. + * @param key: key for this view attribute. + * @param value: value for this attribute. + */ + addViewAttribute(key: string, value: unknown): Promise; + + /** + * Removes an attribute from the active RUM View. + * @param key: key for the attribute to be removed from the view. + */ + removeViewAttribute(key: string): Promise; + + /** + * Adds multiple attributes to the active RUM View. They will be propagated to all future RUM events associated with the active View. + * @param attributes: key/value object containing all attributes to be added to the view. + */ + addViewAttributes(attributes: Attributes): Promise; + + /** + * Removes multiple attributes from the active RUM View. + * @param keys: keys for the attributes to be removed from the view. + */ + removeViewAttributes(keys: string[]): Promise; + /** * Adds the loading time of the view to the active view. * It is calculated as the difference between the current time and the start time of the view. diff --git a/packages/core/src/specs/NativeDdRum.ts b/packages/core/src/specs/NativeDdRum.ts index f6f7b3daa..e31f5b925 100644 --- a/packages/core/src/specs/NativeDdRum.ts +++ b/packages/core/src/specs/NativeDdRum.ts @@ -136,6 +136,31 @@ export interface Spec extends TurboModule { */ addTiming(name: string): Promise; + /** + * Adds a custom attribute to the active RUM View. It will be propagated to all future RUM events associated with the active View. + * @param key: key for this view attribute. + * @param value: value for this attribute. + */ + addViewAttribute(key: string, value: Object): Promise; + + /** + * Removes an attribute from the active RUM View. + * @param key: key for the attribute to be removed from the view. + */ + removeViewAttribute(key: string): Promise; + + /** + * Adds multiple attributes to the active RUM View. They will be propagated to all future RUM events associated with the active View. + * @param attributes: key/value object containing all attributes to be added to the view. + */ + addViewAttributes(attributes: Object): Promise; + + /** + * Removes multiple attributes from the active RUM View. + * @param keys: keys for the attributes to be removed from the view. + */ + removeViewAttributes(keys: string[]): Promise; + /** * Adds the loading time of the view to the active view. * It is calculated as the difference between the current time and the start time of the view. From 96c5f67b6c5c6d4330f691e5d466adbabdd3bf76 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 22 Aug 2025 15:43:01 +0200 Subject: [PATCH 41/62] Fix FileBasedConfiguration related issues --- example/datadog-configuration.json | 20 ++ example/src/App.tsx | 20 +- .../codepush/src/__tests__/index.test.tsx | 4 +- .../FileBasedConfiguration.ts | 54 ++--- .../__tests__/FileBasedConfiguration.test.ts | 192 ++++++++++-------- .../__fixtures__/malformed-configuration.json | 1 - 6 files changed, 157 insertions(+), 134 deletions(-) create mode 100644 example/datadog-configuration.json diff --git a/example/datadog-configuration.json b/example/datadog-configuration.json new file mode 100644 index 000000000..684e60304 --- /dev/null +++ b/example/datadog-configuration.json @@ -0,0 +1,20 @@ +{ + "$schema": "./node_modules/@datadog/mobile-react-native/datadog-configuration.schema.json", + "configuration": { + "applicationId": "APP_ID", + "batchSize": "SMALL", + "clientToken": "CLIENT_TOKEN", + "env": "ENVIRONMENT", + "longTaskThresholdMs": 1000, + "nativeCrashReportEnabled": true, + "sessionSamplingRate": 100, + "site": "US1", + "telemetrySampleRate": 20, + "trackBackgroundEvents": false, + "trackErrors": true, + "trackInteractions": true, + "trackResources": true, + "trackingConsent": "GRANTED", + "verbosity": "DEBUG" + } +} diff --git a/example/src/App.tsx b/example/src/App.tsx index cefcafffe..c29982a97 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -7,7 +7,7 @@ import AboutScreen from './screens/AboutScreen'; import style from './screens/styles'; import { navigationRef } from './NavigationRoot'; import { DdRumReactNavigationTracking, ViewNamePredicate } from '@datadog/mobile-react-navigation'; -import {DatadogProvider} from '@datadog/mobile-react-native' +import {DatadogProvider, FileBasedConfiguration} from '@datadog/mobile-react-native' import { Route } from "@react-navigation/native"; import { NestedNavigator } from './screens/NestedNavigator/NestedNavigator'; import { getDatadogConfig, onDatadogInitialization } from './ddUtils'; @@ -19,9 +19,25 @@ const viewPredicate: ViewNamePredicate = function customViewNamePredicate(route: return "Custom RN " + trackedName; } +// === Datadog Provider Configuration schemes === + +// 1.- Direct configuration +const configuration = getDatadogConfig(TrackingConsent.GRANTED) + +// 2.- File based configuration from .json +// const configuration = new FileBasedConfiguration(require("../datadog-configuration.json")); + +// 3.- File based configuration from .json and custom mapper setup +// const configuration = new FileBasedConfiguration( { +// configuration: require("../datadog-configuration.json").configuration, +// errorEventMapper: (event) => event, +// resourceEventMapper: (event) => event, +// actionEventMapper: (event) => event}); + + export default function App() { return ( - + { DdRumReactNavigationTracking.startTrackingViews(navigationRef.current, viewPredicate) }}> diff --git a/packages/codepush/src/__tests__/index.test.tsx b/packages/codepush/src/__tests__/index.test.tsx index 5c94c16ef..63e1af7d6 100644 --- a/packages/codepush/src/__tests__/index.test.tsx +++ b/packages/codepush/src/__tests__/index.test.tsx @@ -279,7 +279,7 @@ describe('AppCenter Codepush integration', () => { }; const configuration = new FileBasedConfiguration({ - configuration: { configuration: autoInstrumentationConfig } + configuration: autoInstrumentationConfig }); render(); @@ -346,7 +346,7 @@ describe('AppCenter Codepush integration', () => { }; const configuration = new FileBasedConfiguration({ - configuration: { configuration: autoInstrumentationConfig } + configuration: autoInstrumentationConfig }); render(); diff --git a/packages/core/src/sdk/FileBasedConfiguration/FileBasedConfiguration.ts b/packages/core/src/sdk/FileBasedConfiguration/FileBasedConfiguration.ts index ddd1943aa..3fc69f1f3 100644 --- a/packages/core/src/sdk/FileBasedConfiguration/FileBasedConfiguration.ts +++ b/packages/core/src/sdk/FileBasedConfiguration/FileBasedConfiguration.ts @@ -56,44 +56,7 @@ export class FileBasedConfiguration extends DatadogProviderConfiguration { const resolveJSONConfiguration = ( userSpecifiedConfiguration: unknown ): Record => { - if ( - userSpecifiedConfiguration === undefined || - userSpecifiedConfiguration === null - ) { - try { - // This corresponds to a file located at the root of a RN project. - // /!\ We have to write the require this way as dynamic requires are not supported by Hermes. - // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires - const jsonContent = require('../../../../../../datadog-configuration.json'); - - if ( - typeof jsonContent !== 'object' || - !jsonContent['configuration'] - ) { - console.error(`Failed to parse the Datadog configuration file located at the root of the project. -Your configuration must validate the node_modules/@datadog/mobile-react-native/datadog-configuration.schema.json JSON schema. -You can use VSCode to check your configuration by adding the following line to your JSON file: -{ - "$schema": "./node_modules/@datadog/mobile-react-native/datadog-configuration.schema.json", -}`); - - return {}; - } - - return jsonContent.configuration as Record; - } catch (error) { - console.error(`Failed to read Datadog configuration file at the root of the project. -If you don't have a datadog-configuration.json file at the same level as your node_modules directory,\ -please use the following syntax:\n -new FileBasedConfiguration({configuration: require('./file/to/configuration-file.json')}) -`); - return {}; - } - } - if ( - typeof userSpecifiedConfiguration !== 'object' || - !(userSpecifiedConfiguration as any)['configuration'] - ) { + if (typeof userSpecifiedConfiguration !== 'object') { console.error(`Failed to parse the Datadog configuration file you provided. Your configuration must validate the node_modules/@datadog/mobile-react-native/datadog-configuration.schema.json JSON schema. You can use VSCode to check your configuration by adding the following line to your JSON file: @@ -104,10 +67,7 @@ You can use VSCode to check your configuration by adding the following line to y return {}; } - return (userSpecifiedConfiguration as any)['configuration'] as Record< - string, - any - >; + return (userSpecifiedConfiguration as any) as Record; }; export const getJSONConfiguration = ( @@ -130,6 +90,16 @@ export const getJSONConfiguration = ( } => { const configuration = resolveJSONConfiguration(userSpecifiedConfiguration); + if ( + configuration.clientToken === undefined || + configuration.env === undefined || + configuration.applicationId === undefined + ) { + console.warn( + 'DATADOG: Warning: Malformed json configuration file - clientToken, applicationId and env are mandatory properties.' + ); + } + return { clientToken: configuration.clientToken, env: configuration.env, diff --git a/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts b/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts index 716243e86..6d3ee2e44 100644 --- a/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts +++ b/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts @@ -16,35 +16,99 @@ import malformedConfiguration from './__fixtures__/malformed-configuration.json' describe('FileBasedConfiguration', () => { describe('with user-specified configuration', () => { + it('resolves configuration fields', () => { + const configuration = new FileBasedConfiguration( + configurationAllFields + ); + + expect(configuration).toMatchInlineSnapshot(` + FileBasedConfiguration { + "actionEventMapper": null, + "actionNameAttribute": "action-name-attr", + "additionalConfiguration": {}, + "applicationId": "fake-app-id", + "batchProcessingLevel": "MEDIUM", + "batchSize": "MEDIUM", + "bundleLogsWithRum": true, + "bundleLogsWithTraces": true, + "clientToken": "fake-client-token", + "customEndpoints": {}, + "env": "fake-env", + "errorEventMapper": null, + "firstPartyHosts": [ + { + "match": "example.com", + "propagatorTypes": [ + "b3multi", + "tracecontext", + ], + }, + ], + "initializationMode": "SYNC", + "logEventMapper": null, + "longTaskThresholdMs": 44, + "nativeCrashReportEnabled": false, + "nativeInteractionTracking": false, + "nativeLongTaskThresholdMs": 200, + "nativeViewTracking": false, + "proxyConfig": undefined, + "resourceEventMapper": null, + "resourceTracingSamplingRate": 33, + "serviceName": undefined, + "sessionSamplingRate": 100, + "site": "US5", + "telemetrySampleRate": 20, + "trackBackgroundEvents": false, + "trackErrors": true, + "trackFrustrations": true, + "trackInteractions": true, + "trackResources": true, + "trackWatchdogTerminations": false, + "trackingConsent": "not_granted", + "uploadFrequency": "AVERAGE", + "useAccessibilityLabel": false, + "verbosity": "warn", + "vitalsUpdateFrequency": "AVERAGE", + } + `); + }); + + it('prints a warning message when the configuration file cannot be parsed correctly', () => { + const warnSpy = jest.spyOn(console, 'warn'); + getJSONConfiguration(malformedConfiguration); + + expect(warnSpy).toHaveBeenCalledWith( + 'DATADOG: Warning: Malformed json configuration file - clientToken, applicationId and env are mandatory properties.' + ); + }); + it('resolves all properties from a given file path', () => { const config = new FileBasedConfiguration({ configuration: { - configuration: { - applicationId: 'fake-app-id', - env: 'fake-env', - clientToken: 'fake-client-token', - trackInteractions: true, - trackResources: true, - trackErrors: true, - trackingConsent: 'NOT_GRANTED', - longTaskThresholdMs: 44, - site: 'US5', - verbosity: 'WARN', - actionNameAttribute: 'action-name-attr', - useAccessibilityLabel: false, - resourceTracingSamplingRate: 33, - firstPartyHosts: [ - { - match: 'example.com', - propagatorTypes: [ - 'B3MULTI', - 'TRACECONTEXT', - 'B3', - 'DATADOG' - ] - } - ] - } + applicationId: 'fake-app-id', + env: 'fake-env', + clientToken: 'fake-client-token', + trackInteractions: true, + trackResources: true, + trackErrors: true, + trackingConsent: 'NOT_GRANTED', + longTaskThresholdMs: 44, + site: 'US5', + verbosity: 'WARN', + actionNameAttribute: 'action-name-attr', + useAccessibilityLabel: false, + resourceTracingSamplingRate: 33, + firstPartyHosts: [ + { + match: 'example.com', + propagatorTypes: [ + 'B3MULTI', + 'TRACECONTEXT', + 'B3', + 'DATADOG' + ] + } + ] } }); expect(config).toMatchInlineSnapshot(` @@ -103,11 +167,9 @@ describe('FileBasedConfiguration', () => { it('applies default values to configuration from a given file path', () => { const config = new FileBasedConfiguration({ configuration: { - configuration: { - applicationId: 'fake-app-id', - env: 'fake-env', - clientToken: 'fake-client-token' - } + applicationId: 'fake-app-id', + env: 'fake-env', + clientToken: 'fake-client-token' } }); expect(config).toMatchInlineSnapshot(` @@ -159,11 +221,9 @@ describe('FileBasedConfiguration', () => { const resourceEventMapper = () => null; const config = new FileBasedConfiguration({ configuration: { - configuration: { - applicationId: 'fake-app-id', - env: 'fake-env', - clientToken: 'fake-client-token' - } + applicationId: 'fake-app-id', + env: 'fake-env', + clientToken: 'fake-client-token' }, actionEventMapper, errorEventMapper, @@ -188,62 +248,20 @@ describe('FileBasedConfiguration', () => { it('prints a warning message when the first party hosts contain unknown propagator types', () => { const config = new FileBasedConfiguration({ configuration: { - configuration: { - applicationId: 'fake-app-id', - env: 'fake-env', - clientToken: 'fake-client-token', - firstPartyHosts: [ - { - match: 'example.com', - propagatorTypes: ['UNKNOWN'] - } - ] - } + applicationId: 'fake-app-id', + env: 'fake-env', + clientToken: 'fake-client-token', + firstPartyHosts: [ + { + match: 'example.com', + propagatorTypes: ['UNKNOWN'] + } + ] } }); expect(config.firstPartyHosts).toHaveLength(0); }); }); - describe('with resolved file configuration', () => { - it('resolves configuration fields', () => { - const configuration = getJSONConfiguration(configurationAllFields); - - expect(configuration).toMatchInlineSnapshot(` - { - "actionNameAttribute": "action-name-attr", - "applicationId": "fake-app-id", - "clientToken": "fake-client-token", - "env": "fake-env", - "firstPartyHosts": [ - { - "match": "example.com", - "propagatorTypes": [ - "b3multi", - "tracecontext", - ], - }, - ], - "longTaskThresholdMs": 44, - "resourceTracingSamplingRate": 33, - "site": "US5", - "trackErrors": true, - "trackInteractions": true, - "trackResources": true, - "trackingConsent": "not_granted", - "useAccessibilityLabel": false, - "verbosity": "warn", - } - `); - }); - it('prints a warning message when the configuration file is not found', () => { - expect(() => getJSONConfiguration(undefined)).not.toThrow(); - }); - it('prints a warning message when the configuration file cannot be parsed correctly', () => { - expect(() => - getJSONConfiguration(malformedConfiguration) - ).not.toThrow(); - }); - }); describe('formatPropagatorType', () => { it('formats all propagatorTypes correctly', () => { diff --git a/packages/core/src/sdk/FileBasedConfiguration/__tests__/__fixtures__/malformed-configuration.json b/packages/core/src/sdk/FileBasedConfiguration/__tests__/__fixtures__/malformed-configuration.json index 28423084d..0e1b26639 100644 --- a/packages/core/src/sdk/FileBasedConfiguration/__tests__/__fixtures__/malformed-configuration.json +++ b/packages/core/src/sdk/FileBasedConfiguration/__tests__/__fixtures__/malformed-configuration.json @@ -1,5 +1,4 @@ { "clientToken": "clientToken", - "env": "env", "applicationId": "applicationId" } From 71638bf01e812974e9e621294a453cb4de18f990 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Mon, 27 Oct 2025 14:45:54 +0100 Subject: [PATCH 42/62] Bump Android Native SDK to 3.2.0 and regenerate app podfiles --- benchmarks/android/app/build.gradle | 2 +- benchmarks/ios/Podfile.lock | 10 +++++----- example-new-architecture/ios/Podfile.lock | 6 +++--- example/ios/Podfile.lock | 14 +++++++------- packages/core/android/build.gradle | 10 +++++----- .../android/build.gradle | 4 ++-- packages/react-native-webview/android/build.gradle | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle index 04c240bd0..6d9f28764 100644 --- a/benchmarks/android/app/build.gradle +++ b/benchmarks/android/app/build.gradle @@ -129,5 +129,5 @@ dependencies { // Benchmark tools from dd-sdk-android are used for vitals recording // Remember to bump thid alongside the main dd-sdk-android dependencies - implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.1.0") + implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.2.0") } diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 1be186d5f..403441ec6 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 3.1.0) - DatadogRUM (3.1.0): - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.12.1): + - DatadogSDKReactNative (2.13.0): - DatadogCore (= 3.1.0) - DatadogCrashReporting (= 3.1.0) - DatadogLogs (= 3.1.0) @@ -60,7 +60,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.12.1): + - DatadogSDKReactNativeWebView (2.13.0): - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - DatadogWebViewTracking (= 3.1.0) @@ -2075,9 +2075,9 @@ SPEC CHECKSUMS: DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: 8e0f39de38621d4d7ed961a74d8a216fd3a38321 - DatadogSDKReactNativeSessionReplay: f9288c8e981dcc65d1f727b01421ee9a7601e75f - DatadogSDKReactNativeWebView: 993527f6c5d38e0fcc4804a6a60c334dd199dc5b + DatadogSDKReactNative: 620018df2896abcfad6b338c633cc8eccd5de406 + DatadogSDKReactNativeSessionReplay: b2ef22431dd0816adea8d65df13180cf40533f9d + DatadogSDKReactNativeWebView: 299629cf348a5e8f1dabb8289920a00eee625d6a DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 0378f5d72..051f25e11 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 3.1.0) - DatadogRUM (3.1.0): - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.12.1): + - DatadogSDKReactNative (2.13.0): - DatadogCore (= 3.1.0) - DatadogCrashReporting (= 3.1.0) - DatadogLogs (= 3.1.0) @@ -37,7 +37,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (2.12.1): + - DatadogSDKReactNative/Tests (2.13.0): - DatadogCore (= 3.1.0) - DatadogCrashReporting (= 3.1.0) - DatadogLogs (= 3.1.0) @@ -1855,7 +1855,7 @@ SPEC CHECKSUMS: DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: 069ea9876220b2d09b0f4b180ce571b1b6ecbb35 + DatadogSDKReactNative: 2f11191b56e18680f633bfb125ab1832b327d9b4 DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 94d93b3c2..d0ba99782 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - DatadogInternal (= 3.1.0) - DatadogRUM (3.1.0): - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.12.1): + - DatadogSDKReactNative (2.13.0): - DatadogCore (= 3.1.0) - DatadogCrashReporting (= 3.1.0) - DatadogLogs (= 3.1.0) @@ -18,7 +18,7 @@ PODS: - DatadogTrace (= 3.1.0) - DatadogWebViewTracking (= 3.1.0) - React-Core - - DatadogSDKReactNative/Tests (2.12.1): + - DatadogSDKReactNative/Tests (2.13.0): - DatadogCore (= 3.1.0) - DatadogCrashReporting (= 3.1.0) - DatadogLogs (= 3.1.0) @@ -73,12 +73,12 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.12.1): + - DatadogSDKReactNativeWebView (2.13.0): - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - DatadogWebViewTracking (= 3.1.0) - React-Core - - DatadogSDKReactNativeWebView/Tests (2.12.1): + - DatadogSDKReactNativeWebView/Tests (2.13.0): - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - DatadogWebViewTracking (= 3.1.0) @@ -1993,9 +1993,9 @@ SPEC CHECKSUMS: DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: af351a4e1ce08124c290c52de94b0062a166cc67 - DatadogSDKReactNativeSessionReplay: dcbd55d9d0f2b86026996a8b7ec9654922d5dfe1 - DatadogSDKReactNativeWebView: 096ac87eb753b6a217b93441983264b9837c3b7e + DatadogSDKReactNative: 822ff8092666172584d4d5e56f79c3799887d408 + DatadogSDKReactNativeSessionReplay: afc4e2b1db34ba8af3a442b0691359faaf5e586e + DatadogSDKReactNativeWebView: 00affefdaca0cf2375e669fa03925d8fa75263d0 DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index 59bb75cc3..080185d41 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -201,16 +201,16 @@ dependencies { // This breaks builds if the React Native target is below 0.76.0. as it relies on Gradle 8.5.0. // To avoid this, we enforce 1.0.0-beta01 on RN < 0.76.0 if (reactNativeMinorVersion < 76) { - implementation("com.datadoghq:dd-sdk-android-rum:3.1.0") { + implementation("com.datadoghq:dd-sdk-android-rum:3.2.0") { exclude group: "androidx.metrics", module: "metrics-performance" } implementation "androidx.metrics:metrics-performance:1.0.0-beta01" } else { - implementation "com.datadoghq:dd-sdk-android-rum:3.1.0" + implementation "com.datadoghq:dd-sdk-android-rum:3.2.0" } - implementation "com.datadoghq:dd-sdk-android-logs:3.1.0" - implementation "com.datadoghq:dd-sdk-android-trace:3.1.0" - implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" + implementation "com.datadoghq:dd-sdk-android-logs:3.2.0" + implementation "com.datadoghq:dd-sdk-android-trace:3.2.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.2.0" implementation "com.google.code.gson:gson:2.10.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index a0d77f2ff..bea305684 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -216,8 +216,8 @@ dependencies { api "com.facebook.react:react-android:$reactNativeVersion" } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.datadoghq:dd-sdk-android-session-replay:3.1.0" - implementation "com.datadoghq:dd-sdk-android-internal:3.1.0" + implementation "com.datadoghq:dd-sdk-android-session-replay:3.2.0" + implementation "com.datadoghq:dd-sdk-android-internal:3.2.0" implementation project(path: ':datadog_mobile-react-native') testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" diff --git a/packages/react-native-webview/android/build.gradle b/packages/react-native-webview/android/build.gradle index 87ca1b7e7..dbb8d0593 100644 --- a/packages/react-native-webview/android/build.gradle +++ b/packages/react-native-webview/android/build.gradle @@ -190,7 +190,7 @@ dependencies { implementation "com.facebook.react:react-android:$reactNativeVersion" } - implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.2.0" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation project(path: ':datadog_mobile-react-native') From c736fd97a61e334e90ad859a99cfcfc1a893cc5c Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Tue, 9 Sep 2025 12:08:35 +0200 Subject: [PATCH 43/62] iOS: Always use SDK default core instance --- .../core/ios/Sources/DatadogSDKWrapper.swift | 113 +----------------- .../ios/Sources/DdSdkImplementation.swift | 37 ++---- .../Sources/DdSdkNativeInitialization.swift | 3 + 3 files changed, 17 insertions(+), 136 deletions(-) diff --git a/packages/core/ios/Sources/DatadogSDKWrapper.swift b/packages/core/ios/Sources/DatadogSDKWrapper.swift index 3c56688b0..894f0a09f 100644 --- a/packages/core/ios/Sources/DatadogSDKWrapper.swift +++ b/packages/core/ios/Sources/DatadogSDKWrapper.swift @@ -13,15 +13,12 @@ import DatadogCrashReporting import DatadogInternal import Foundation -<<<<<<< HEAD + #if os(iOS) import DatadogWebViewTracking #endif -public typealias OnCoreInitializedListener = (DatadogCoreProtocol) -> Void -======= -public typealias OnSdkInitializedListener = () -> Void ->>>>>>> 0443e0ff (iOS: Always use SDK default core instance) +public typealias OnSdkInitializedListener = (DatadogCoreProtocol) -> Void /// Wrapper around the Datadog SDK. Use DatadogSDKWrapper.shared to access the instance. public class DatadogSDKWrapper { @@ -45,118 +42,16 @@ public class DatadogSDKWrapper { loggerConfiguration: DatadogLogs.Logger.Configuration, trackingConsent: TrackingConsent ) -> Void { - Datadog.initialize(with: coreConfiguration, trackingConsent: trackingConsent) + let core = Datadog.initialize(with: coreConfiguration, trackingConsent: trackingConsent) for listener in onSdkInitializedListeners { - listener() + listener(core) } self.loggerConfiguration = loggerConfiguration } -<<<<<<< HEAD - internal func isInitialized() -> Bool { - return Datadog.isInitialized() - } - - internal func clearAllData() -> Void { - if let core = coreInstance { - Datadog.clearAllData(in: core) - } else { - Datadog.clearAllData() - } - } - - // Features - internal func enableRUM(with configuration: RUM.Configuration) { - if let core = coreInstance { - RUM.enable(with: configuration, in: core) - } else { - consolePrint("Core instance was not found when initializing RUM.", .critical) - } - } - - internal func enableLogs(with configuration: Logs.Configuration) { - if let core = coreInstance { - Logs.enable(with: configuration, in: core) - } else { - consolePrint("Core instance was not found when initializing Logs.", .critical) - } - } - - internal func enableTrace(with configuration: Trace.Configuration) { - if let core = coreInstance { - Trace.enable(with: configuration, in: core) - } else { - consolePrint("Core instance was not found when initializing Trace.", .critical) - } - } - - internal func enableCrashReporting() { - if let core = coreInstance { - CrashReporting.enable(in: core) - } else { - consolePrint("Core instance was not found when initializing CrashReporting.", .critical) - } - } - - internal func createLogger() -> LoggerProtocol { - let core = coreInstance ?? { - consolePrint("Core instance was not found when creating Logger.", .critical) - return CoreRegistry.default - }() - - return DatadogLogs.Logger.create(with: loggerConfiguration, in: core) - } - - // Telemetry - internal func sendTelemetryLog(message: String, attributes: [String: any Encodable], config: [String: any Encodable]) { - if let core = coreInstance { - let id = (config["onlyOnce"] as? Bool) == true ? message : UUID().uuidString - core.telemetry.debug(id: id, message: message, attributes: attributes) - } else { - consolePrint("Core instance was not found when calling sendTelemetryLog.", .warn) - } - } - - internal func telemetryDebug(id: String, message: String) { - return Datadog._internal.telemetry.debug(id: id, message: message) - } - - internal func telemetryError(id: String, message: String, kind: String?, stack: String?) { - return Datadog._internal.telemetry.error(id: id, message: message, kind: kind, stack: stack) - } - - internal func overrideTelemetryConfiguration( - initializationType: String? = nil, - reactNativeVersion: String? = nil, - reactVersion: String? = nil, - trackCrossPlatformLongTasks: Bool? = nil, - trackErrors: Bool? = nil, - trackInteractions: Bool? = nil, - trackLongTask: Bool? = nil, - trackNativeErrors: Bool? = nil, - trackNativeLongTasks: Bool? = nil, - trackNetworkRequests: Bool? = nil - ) { - coreInstance?.telemetry.configuration( - initializationType: initializationType, - reactNativeVersion: reactNativeVersion, - reactVersion: reactVersion, - trackCrossPlatformLongTasks: trackCrossPlatformLongTasks, - trackErrors: trackErrors, - trackLongTask: trackLongTask, - trackNativeErrors: trackNativeErrors, - trackNativeLongTasks: trackNativeLongTasks, - trackNetworkRequests: trackNetworkRequests, - trackUserInteractions: trackInteractions - ) - } - - #if os(iOS) -======= ->>>>>>> 0443e0ff (iOS: Always use SDK default core instance) // Webview private var webviewMessageEmitter: InternalExtension.AbstractMessageEmitter? diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 9c3fe980f..997068ddf 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -175,33 +175,21 @@ public class DdSdkImplementation: NSObject { ) { let castedAttributes = castAttributesToSwift(attributes) let castedConfig = castAttributesToSwift(config) - DdTelemetry.sendTelemetryLog( - message: message as String, attributes: castedAttributes, config: castedConfig) + DdTelemetry.sendTelemetryLog(message: message as String, attributes: castedAttributes, config: castedConfig) resolve(nil) } @objc - public func telemetryDebug( - message: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock - ) { - DdTelemetry.telemetryDebug( - id: "datadog_react_native:\(message)", message: message as String) + + public func telemetryDebug(message: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + DdTelemetry.telemetryDebug(id: "datadog_react_native:\(message)", message: message as String) resolve(nil) } -<<<<<<< HEAD #if os(iOS) -======= - ->>>>>>> 0443e0ff (iOS: Always use SDK default core instance) @objc - public func telemetryError( - message: NSString, stack: NSString, kind: NSString, resolve: RCTPromiseResolveBlock, - reject: RCTPromiseRejectBlock - ) { - DdTelemetry.telemetryError( - id: "datadog_react_native:\(String(describing: kind)):\(message)", - message: message as String, kind: kind as String, stack: stack as String) + public func telemetryError(message: NSString, stack: NSString, kind: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + DdTelemetry.telemetryError(id: "datadog_react_native:\(String(describing: kind)):\(message)", message: message as String, kind: kind as String, stack: stack as String) resolve(nil) } @@ -221,24 +209,19 @@ public class DdSdkImplementation: NSObject { resolve(nil) } -<<<<<<< HEAD #endif -======= ->>>>>>> 1f781a51 (Expose view Attributes API) @objc - public func clearAllData(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { + public func clearAllData(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { Datadog.clearAllData() resolve(nil) } - func overrideReactNativeTelemetry(rnConfiguration: DdSdkConfiguration) { + func overrideReactNativeTelemetry(rnConfiguration: DdSdkConfiguration) -> Void { DdTelemetry.overrideTelemetryConfiguration( - initializationType: rnConfiguration.configurationForTelemetry?.initializationType - as? String, - reactNativeVersion: rnConfiguration.configurationForTelemetry?.reactNativeVersion - as? String, + initializationType: rnConfiguration.configurationForTelemetry?.initializationType as? String, + reactNativeVersion: rnConfiguration.configurationForTelemetry?.reactNativeVersion as? String, reactVersion: rnConfiguration.configurationForTelemetry?.reactVersion as? String, trackCrossPlatformLongTasks: rnConfiguration.longTaskThresholdMs != 0, trackErrors: rnConfiguration.configurationForTelemetry?.trackErrors, diff --git a/packages/core/ios/Sources/DdSdkNativeInitialization.swift b/packages/core/ios/Sources/DdSdkNativeInitialization.swift index 4ea229871..b55f90561 100644 --- a/packages/core/ios/Sources/DdSdkNativeInitialization.swift +++ b/packages/core/ios/Sources/DdSdkNativeInitialization.swift @@ -94,12 +94,15 @@ public class DdSdkNativeInitialization: NSObject { CrashReporting.enable() } <<<<<<< HEAD +<<<<<<< HEAD #if os(iOS) DatadogSDKWrapper.shared.enableWebviewTracking() #endif ======= >>>>>>> 0443e0ff (iOS: Always use SDK default core instance) +======= +>>>>>>> 93aa6125 (iOS: Always use SDK default core instance) } func buildSDKConfiguration(configuration: DdSdkConfiguration, defaultAppVersion: String = getDefaultAppVersion()) -> Datadog.Configuration { From 846118cd8c6271fe976eee53d1b52108718f8c4a Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Mon, 8 Sep 2025 15:27:17 +0200 Subject: [PATCH 44/62] Bump native SDK dependencies to 3.0.0 --- benchmarks/android/app/build.gradle | 2 +- benchmarks/ios/Podfile.lock | 178 ++++++++-------- example-new-architecture/ios/Podfile.lock | 156 +++++++------- example/ios/Podfile.lock | 196 +++++++++--------- packages/core/DatadogSDKReactNative.podspec | 12 +- packages/core/android/build.gradle | 10 +- ...DatadogSDKReactNativeSessionReplay.podspec | 2 +- .../android/build.gradle | 4 +- .../DatadogSDKReactNativeWebView.podspec | 4 +- .../react-native-webview/android/build.gradle | 2 +- 10 files changed, 283 insertions(+), 283 deletions(-) diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle index 6d9f28764..7dc4b3707 100644 --- a/benchmarks/android/app/build.gradle +++ b/benchmarks/android/app/build.gradle @@ -129,5 +129,5 @@ dependencies { // Benchmark tools from dd-sdk-android are used for vitals recording // Remember to bump thid alongside the main dd-sdk-android dependencies - implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.2.0") + implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.0.0") } diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 403441ec6..16194127d 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogCrashReporting (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogCore (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogCrashReporting (3.0.0): + - DatadogInternal (= 3.0.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.1.0) - - DatadogLogs (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogRUM (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.13.0): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogInternal (3.0.0) + - DatadogLogs (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogRUM (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogSDKReactNative (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -39,7 +39,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.1.0) + - DatadogSessionReplay (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -60,10 +60,10 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.0): - - DatadogInternal (= 3.1.0) + - DatadogSDKReactNativeWebView (2.12.1): + - DatadogInternal (= 3.0.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.1.0) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -84,13 +84,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSessionReplay (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogTrace (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogSessionReplay (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogTrace (3.0.0): + - DatadogInternal (= 3.0.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogWebViewTracking (3.0.0): + - DatadogInternal (= 3.0.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.78.2) @@ -2070,17 +2070,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d - DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d - DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc - DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 - DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: 620018df2896abcfad6b338c633cc8eccd5de406 - DatadogSDKReactNativeSessionReplay: b2ef22431dd0816adea8d65df13180cf40533f9d - DatadogSDKReactNativeWebView: 299629cf348a5e8f1dabb8289920a00eee625d6a - DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 - DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 - DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 + DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 + DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e + DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 + DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd + DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f + DatadogSDKReactNative: 241bf982c16ceff03d94a58e6d005e55c47b99c6 + DatadogSDKReactNativeSessionReplay: bba36092686e3183e97c1a0c7f4ca8142582ae28 + DatadogSDKReactNativeWebView: 6da060df20e235abac533e582d9fc2b3a5070840 + DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 + DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 + DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c @@ -2089,70 +2089,70 @@ SPEC CHECKSUMS: hermes-engine: 2771b98fb813fdc6f92edd7c9c0035ecabf9fee7 OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 - RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 + RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 RCTDeprecation: be794de7dc6ed8f9f7fbf525f86e7651b8b68746 RCTRequired: a83787b092ec554c2eb6019ff3f5b8d125472b3b RCTTypeSafety: 48ad3c858926b1c46f46a81a58822b476e178e2c React: 3b5754191f1b65f1dbc52fbea7959c3d2d9e39c9 React-callinvoker: 6beeaf4c7db11b6cc953fac45f2c76e3fb125013 - React-Core: 88e817c42de035378cc71e009193b9a044d3f595 - React-CoreModules: dcf764d71efb4f75d38fcae8d4513b6729f49360 - React-cxxreact: 8cdcc937c5fbc406fe843a381102fd69440ca78a + React-Core: 8a10ac9de53373a3ecb5dfcbcf56df1d3dad0861 + React-CoreModules: af6999b35c7c01b0e12b59d27f3e054e13da43b1 + React-cxxreact: 833f00155ce8c2fda17f6d286f8eaeff2ececc69 React-debug: 440175830c448e7e53e61ebb8d8468c3256b645e - React-defaultsnativemodule: 4824bcd7b96ee2d75c28b1ca21f58976867f5535 - React-domnativemodule: a421118b475618961cf282e8ea85347cc9bb453c - React-Fabric: 6ac7de06009eb96b609a770b17abba6e460b5f45 - React-FabricComponents: e3bc2680a5a9a4917ff0c8d7f390688c30ef753c - React-FabricImage: 8bad558dec7478077974caa96acc79692d6b71f5 + React-defaultsnativemodule: a970effe18fe50bdbbb7115c3297f873b666d0d4 + React-domnativemodule: 45f886342a724e61531b18fba1859bb6782e5d62 + React-Fabric: 69f1881f2177a8512304a64157943548ab6df0cf + React-FabricComponents: f54111c8e2439fc273ab07483e3a7054ca1e75af + React-FabricImage: 9ad2619dfe8c386d79e8aaa87da6e8f018ab9592 React-featureflags: b9cf9b35baca1c7f20c06a104ffc325a02752faa - React-featureflagsnativemodule: dc93d81da9f41f7132e24455ec8b4b60802fd5b0 - React-graphics: aaa5a38bea15d7b895b210d95d554af45a07002a - React-hermes: 08ad9fb832d1b9faef391be17309aa6a69fad23b - React-idlecallbacksnativemodule: aacea33ef6c511a9781f9286cc7cdf93f39bba14 - React-ImageManager: c596c3b658c9c14607f9183ed0f635c8dd77987c - React-jserrorhandler: 987609b2f16b7d79d63fcd621bf0110dd7400b35 - React-jsi: afa286d7e0c102c2478dc420d4f8935e13c973fc - React-jsiexecutor: 08f5b512b4db9e2f147416d60a0a797576b9cfef - React-jsinspector: 5a94bcae66e3637711c4d96a00038ab9ec935bf5 - React-jsinspectortracing: a12589a0adbb2703cbc4380dabe9a58800810923 - React-jsitracing: 0b1a403d7757cec66b7dd8b308d04db85eef75f3 - React-logger: 304814ae37503c8eb54359851cc55bd4f936b39c - React-Mapbuffer: b588d1ca18d2ce626f868f04ab12d8b1f004f12c - React-microtasksnativemodule: 11831d070aa47755bb5739069eb04ec621fec548 - react-native-config: 3367df9c1f25bb96197007ec531c7087ed4554c3 - react-native-safe-area-context: 9b169299f9dc95f1d7fe1dd266fde53bd899cd0c - react-native-slider: 27263d134d55db948a4706f1e47d0ec88fb354dd - react-native-webview: be9957759cb73cb64f2ed5359e32a85f1f5bdff8 - React-NativeModulesApple: 79a4404ac301b40bec3b367879c5e9a9ce81683c - React-perflogger: 0ea25c109dba33d47dec36b2634bf7ea67c1a555 - React-performancetimeline: f74480de6efbcd8541c34317c0baedb433f27296 + React-featureflagsnativemodule: 7f1bc76d1d2c5bede5e753b8d188dbde7c59b12f + React-graphics: 069e0d0b31ed1e80feb023ad4f7e97f00e84f7b9 + React-hermes: 63df5ac5a944889c8758a6213b39ed825863adb7 + React-idlecallbacksnativemodule: 4c700bd7c0012adf904929075a79418b828b5ffc + React-ImageManager: 5d1ba8a7bae44ebba43fc93da64937c713d42941 + React-jserrorhandler: 0defd58f8bb797cdd0a820f733bf42d8bee708ce + React-jsi: 99d6207ec802ad73473a0dad3c9ad48cd98463f6 + React-jsiexecutor: 8c8097b4ba7e7f480582d6e6238b01be5dcc01c0 + React-jsinspector: ea148ec45bc7ff830e443383ea715f9780c15934 + React-jsinspectortracing: 46bb2841982f01e7b63eaab98140fa1de5b2a1db + React-jsitracing: c1063fc2233960d1c8322291e74bca51d25c10d7 + React-logger: 763728cf4eebc9c5dc9bfc3649e22295784f69f3 + React-Mapbuffer: 63278529b5cf531a7eaf8fc71244fabb062ca90c + React-microtasksnativemodule: 6a39463c32ce831c4c2aa8469273114d894b6be9 + react-native-config: 644074ab88db883fcfaa584f03520ec29589d7df + react-native-safe-area-context: afcc2e2b3e78ae8ef90d81e658aacee34ebc27ea + react-native-slider: 310d3f89edd6ca8344a974bfe83a29a3fbb60e5a + react-native-webview: 80ef603d1df42e24fdde765686fbb9b8a6ecd554 + React-NativeModulesApple: fd0545efbb7f936f78edd15a6564a72d2c34bb32 + React-perflogger: 5f8fa36a8e168fb355efe72099efe77213bc2ac6 + React-performancetimeline: 8c0ecfa1ae459cc5678a65f95ac3bf85644d6feb React-RCTActionSheet: 2ef95837e89b9b154f13cd8401f9054fc3076aff - React-RCTAnimation: 33d960d7f58a81779eea6dea47ad0364c67e1517 - React-RCTAppDelegate: 85c13403fd6f6b6cc630428d52bd8bd76a670dc9 - React-RCTBlob: 74c986a02d951931d2f6ed0e07ed5a7eb385bfc0 - React-RCTFabric: 384a8fea4f22fc0f21299d771971862883ba630a - React-RCTFBReactNativeSpec: eb1c3ec5149f76133593a516ff9d5efe32ebcecd - React-RCTImage: 2c58b5ddeb3c65e52f942bbe13ff9c59bd649b09 - React-RCTLinking: b6b14f8a3e62c02fc627ac4f3fb0c7bd941f907c - React-RCTNetwork: 1d050f2466c1541b339587d46f78d5eee218d626 - React-RCTSettings: 8148f6be0ccc0cfe6e313417ebf8a479caaa2146 - React-RCTText: 64114531ad1359e4e02a4a8af60df606dbbabc25 - React-RCTVibration: f4859417a7dd859b6bf18b1aba897e52beb72ef6 + React-RCTAnimation: 46abefd5acfda7e6629f9e153646deecc70babd2 + React-RCTAppDelegate: 7e58e0299e304cceee3f7019fa77bc6990f66b22 + React-RCTBlob: f68c63a801ef1d27e83c4011e3b083cc86a200d7 + React-RCTFabric: c59f41d0c4edbaac8baa232731ca09925ae4dda7 + React-RCTFBReactNativeSpec: 3240b9b8d792aa4be0fb85c9898fc183125ba8de + React-RCTImage: 34e0bba1507e55f1c614bd759eb91d9be48c8c5b + React-RCTLinking: a0b6c9f4871c18b0b81ea952f43e752718bd5f1d + React-RCTNetwork: bdafd661ac2b20d23b779e45bf7ac3e4c8bd1b60 + React-RCTSettings: 98aa5163796f43789314787b584a84eba47787a9 + React-RCTText: 424a274fc9015b29de89cf3cbcdf4dd85dd69f83 + React-RCTVibration: 92d9875a955b0adb34b4b773528fdbbbc5addd6c React-rendererconsistency: 5ac4164ec18cfdd76ed5f864dbfdc56a5a948bc9 - React-rendererdebug: 3dc1d97bbee0c0c13191e501a96ed9325bbd920e + React-rendererdebug: 710dbd7990e355852c786aa6bc7753f6028f357a React-rncore: 0bace3b991d8843bb5b57c5f2301ec6e9c94718b - React-RuntimeApple: 1e1e0a0c6086bc8c3b07e8f1a2f6ca99b50419a0 - React-RuntimeCore: d39322c59bef2a4b343fda663d20649f29f57fcc + React-RuntimeApple: 701ec44a8b5d863ee9b6a2b2447b6a26bb6805a1 + React-RuntimeCore: a82767065b9a936b05e209dc6987bc1ea9eb5d2d React-runtimeexecutor: 876dfc1d8daa819dfd039c40f78f277c5a3e66a6 - React-RuntimeHermes: 44f5f2baf039f249b31ea4f3e224484fd1731e0e - React-runtimescheduler: 3b3c5b50743bb8743ca49b9e5a70c2c385f156e1 + React-RuntimeHermes: e7a051fd91cab8849df56ac917022ef6064ad621 + React-runtimescheduler: c544141f2124ee3d5f3d5bf0d69f4029a61a68b0 React-timing: 1ee3572c398f5579c9df5bf76aacddf5683ff74e - React-utils: 0cfb7c7fb37d4e5f31cc18ffc7426be0ae6bf907 - ReactAppDependencyProvider: b48473fe434569ff8f6cb6ed4421217ebcbda878 - ReactCodegen: 653a0d8532d8c7dab50c391392044d98e20c9f79 - ReactCommon: 547db015202a80a5b3e7e041586ea54c4a087180 - RNCPicker: ffbd7b9fc7c1341929e61dbef6219f7860f57418 - RNScreens: 0f01bbed9bd8045a8d58e4b46993c28c7f498f3c + React-utils: 18703928768cb37e70cf2efff09def12d74a399e + ReactAppDependencyProvider: 4893bde33952f997a323eb1a1ee87a72764018ff + ReactCodegen: da30aff1cea9b5993dcbc33bf1ef47a463c55194 + ReactCommon: 865ebe76504a95e115b6229dd00a31e56d2d4bfe + RNCPicker: cfb51a08c6e10357d9a65832e791825b0747b483 + RNScreens: 790123c4a28783d80a342ce42e8c7381bed62db1 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: e14bad835e12b6c7e2260fc320bd00e0f4b45add diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 051f25e11..281513566 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogCrashReporting (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogCore (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogCrashReporting (3.0.0): + - DatadogInternal (= 3.0.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.1.0) - - DatadogLogs (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogRUM (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.13.0): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogInternal (3.0.0) + - DatadogLogs (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogRUM (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogSDKReactNative (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -37,13 +37,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (2.13.0): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogSDKReactNative/Tests (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -64,11 +64,11 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogTrace (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogTrace (3.0.0): + - DatadogInternal (= 3.0.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogWebViewTracking (3.0.0): + - DatadogInternal (= 3.0.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1850,14 +1850,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d - DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d - DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc - DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 - DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: 2f11191b56e18680f633bfb125ab1832b327d9b4 - DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 - DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 + DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 + DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e + DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 + DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd + DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f + DatadogSDKReactNative: 0a80aa75958d595a99be54d2838db53eda7a08af + DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 + DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 @@ -1866,62 +1866,62 @@ SPEC CHECKSUMS: hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11 OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 - RCT-Folly: 7b4f73a92ad9571b9dbdb05bb30fad927fa971e1 + RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 RCTTypeSafety: e7678bd60850ca5a41df9b8dc7154638cb66871f React: 4641770499c39f45d4e7cde1eba30e081f9d8a3d React-callinvoker: 4bef67b5c7f3f68db5929ab6a4d44b8a002998ea - React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455 - React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0 - React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d + React-Core: a68cea3e762814e60ecc3fa521c7f14c36c99245 + React-CoreModules: d81b1eaf8066add66299bab9d23c9f00c9484c7c + React-cxxreact: 984f8b1feeca37181d4e95301fcd6f5f6501c6ab React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 - React-defaultsnativemodule: 814830ccbc3fb08d67d0190e63b179ee4098c67b - React-domnativemodule: 270acf94bd0960b026bc3bfb327e703665d27fb4 - React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b - React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb - React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f + React-defaultsnativemodule: 18a684542f82ce1897552a1c4b847be414c9566e + React-domnativemodule: 90bdd4ec3ab38c47cfc3461c1e9283a8507d613f + React-Fabric: f6dade7007533daeb785ba5925039d83f343be4b + React-FabricComponents: b0655cc3e1b5ae12a4a1119aa7d8308f0ad33520 + React-FabricImage: 9b157c4c01ac2bf433f834f0e1e5fe234113a576 React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c - React-featureflagsnativemodule: 0d7091ae344d6160c0557048e127897654a5c00f - React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386 - React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3 - React-idlecallbacksnativemodule: 6b84add48971da9c40403bd1860d4896462590f2 - React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2 - React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64 - React-jsi: 95f7676103137861b79b0f319467627bcfa629ee - React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932 - React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2 - React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b - React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20 - React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc - React-microtasksnativemodule: a645237a841d733861c70b69908ab4a1707b52ad + React-featureflagsnativemodule: 742a8325b3c821d2a1ca13a6d2a0fc72d04555e0 + React-graphics: 68969e4e49d73f89da7abef4116c9b5f466aa121 + React-hermes: ac0bcba26a5d288ebc99b500e1097da2d0297ddf + React-idlecallbacksnativemodule: d61d9c9816131bf70d3d80cd04889fc625ee523f + React-ImageManager: e906eec93a9eb6102a06576b89d48d80a4683020 + React-jserrorhandler: ac5dde01104ff444e043cad8f574ca02756e20d6 + React-jsi: 496fa2b9d63b726aeb07d0ac800064617d71211d + React-jsiexecutor: dd22ab48371b80f37a0a30d0e8915b6d0f43a893 + React-jsinspector: 4629ac376f5765e684d19064f2093e55c97fd086 + React-jsitracing: 7a1c9cd484248870cf660733cd3b8114d54c035f + React-logger: c4052eb941cca9a097ef01b59543a656dc088559 + React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de + React-microtasksnativemodule: d80ff86c8902872d397d9622f1a97aadcc12cead React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 - React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22 - React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d - React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9 + React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e + React-perflogger: 72e653eb3aba9122f9e57cf012d22d2486f33358 + React-performancetimeline: cd6a9374a72001165995d2ab632f672df04076dc React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 - React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4 - React-RCTAppDelegate: 1774aa421a29a41a704ecaf789811ef73c4634b6 - React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8 - React-RCTFabric: 731cda82aed592aacce2d32ead69d78cde5d9274 - React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0 - React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a - React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3 - React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40 - React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2 - React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec + React-RCTAnimation: 395ab53fd064dff81507c15efb781c8684d9a585 + React-RCTAppDelegate: 345a6f1b82abc578437df0ce7e9c48740eca827c + React-RCTBlob: 13311e554c1a367de063c10ee7c5e6573b2dd1d6 + React-RCTFabric: 007b1a98201cc49b5bc6e1417d7fe3f6fc6e2b78 + React-RCTImage: 1b1f914bcc12187c49ba5d949dac38c2eb9f5cc8 + React-RCTLinking: 4ac7c42beb65e36fba0376f3498f3cd8dd0be7fa + React-RCTNetwork: 938902773add4381e84426a7aa17a2414f5f94f7 + React-RCTSettings: e848f1ba17a7a18479cf5a31d28145f567da8223 + React-RCTText: 7e98fafdde7d29e888b80f0b35544e0cb07913cf + React-RCTVibration: cd7d80affd97dc7afa62f9acd491419558b64b78 React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 - React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5 + React-rendererdebug: aa181c36dd6cf5b35511d1ed875d6638fd38f0ec React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 - React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655 - React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157 + React-RuntimeApple: d033becbbd1eba6f9f6e3af6f1893030ce203edd + React-RuntimeCore: 38af280bb678e66ba000a3c3d42920b2a138eebb React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549 - React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe + React-RuntimeHermes: 37aad735ff21ca6de2d8450a96de1afe9f86c385 + React-runtimescheduler: 8ec34cc885281a34696ea16c4fd86892d631f38d React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 - React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e - ReactCodegen: 21a52ccddc6479448fc91903a437dd23ddc7366c - ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd + React-utils: ed818f19ab445000d6b5c4efa9d462449326cc9f + ReactCodegen: f853a20cc9125c5521c8766b4b49375fec20648b + ReactCommon: 300d8d9c5cb1a6cd79a67cf5d8f91e4d477195f9 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index d0ba99782..fac339d80 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,34 +1,34 @@ PODS: - boost (1.84.0) - - DatadogCore (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogCrashReporting (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogCore (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogCrashReporting (3.0.0): + - DatadogInternal (= 3.0.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.1.0) - - DatadogLogs (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogRUM (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.13.0): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogInternal (3.0.0) + - DatadogLogs (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogRUM (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogSDKReactNative (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - React-Core - - DatadogSDKReactNative/Tests (2.13.0): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogSDKReactNative/Tests (2.12.1): + - DatadogCore (= 3.0.0) + - DatadogCrashReporting (= 3.0.0) + - DatadogLogs (= 3.0.0) + - DatadogRUM (= 3.0.0) + - DatadogTrace (= 3.0.0) + - DatadogWebViewTracking (= 3.0.0) - React-Core - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.1.0) + - DatadogSessionReplay (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -51,7 +51,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay/Tests (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.1.0) + - DatadogSessionReplay (= 3.0.0) - DoubleConversion - glog - hermes-engine @@ -73,25 +73,25 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.13.0): - - DatadogInternal (= 3.1.0) + - DatadogSDKReactNativeWebView (2.12.1): + - DatadogInternal (= 3.0.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.1.0) + - DatadogWebViewTracking (= 3.0.0) - React-Core - - DatadogSDKReactNativeWebView/Tests (2.13.0): - - DatadogInternal (= 3.1.0) + - DatadogSDKReactNativeWebView/Tests (2.12.1): + - DatadogInternal (= 3.0.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.1.0) + - DatadogWebViewTracking (= 3.0.0) - React-Core - react-native-webview - React-RCTText - - DatadogSessionReplay (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogTrace (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogSessionReplay (3.0.0): + - DatadogInternal (= 3.0.0) + - DatadogTrace (3.0.0): + - DatadogInternal (= 3.0.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogWebViewTracking (3.0.0): + - DatadogInternal (= 3.0.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1988,17 +1988,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d - DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d - DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc - DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 - DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: 822ff8092666172584d4d5e56f79c3799887d408 - DatadogSDKReactNativeSessionReplay: afc4e2b1db34ba8af3a442b0691359faaf5e586e - DatadogSDKReactNativeWebView: 00affefdaca0cf2375e669fa03925d8fa75263d0 - DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 - DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 - DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 + DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 + DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e + DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 + DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd + DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f + DatadogSDKReactNative: e430b3f4d7adb0fac07b61e2fb65ceacdaf82b3e + DatadogSDKReactNativeSessionReplay: 4b2a3d166a79581f18522795b40141c34cf3685d + DatadogSDKReactNativeWebView: 35dc2b9736e1aaa82b366bf6b8a8a959a9b088c5 + DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 + DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 + DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 @@ -2008,69 +2008,69 @@ SPEC CHECKSUMS: HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352 OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 - RCT-Folly: 7b4f73a92ad9571b9dbdb05bb30fad927fa971e1 + RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 RCTTypeSafety: e7678bd60850ca5a41df9b8dc7154638cb66871f React: 4641770499c39f45d4e7cde1eba30e081f9d8a3d React-callinvoker: 4bef67b5c7f3f68db5929ab6a4d44b8a002998ea - React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455 - React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0 - React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d + React-Core: a68cea3e762814e60ecc3fa521c7f14c36c99245 + React-CoreModules: d81b1eaf8066add66299bab9d23c9f00c9484c7c + React-cxxreact: 984f8b1feeca37181d4e95301fcd6f5f6501c6ab React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964 - React-defaultsnativemodule: a965cb39fb0a79276ab611793d39f52e59a9a851 - React-domnativemodule: d647f94e503c62c44f54291334b1aa22a30fa08b - React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b - React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb - React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f + React-defaultsnativemodule: 21f216e8db975897eb32b5f13247f5bbfaa97f41 + React-domnativemodule: 19270ad4b8d33312838d257f24731a0026809d49 + React-Fabric: f6dade7007533daeb785ba5925039d83f343be4b + React-FabricComponents: b0655cc3e1b5ae12a4a1119aa7d8308f0ad33520 + React-FabricImage: 9b157c4c01ac2bf433f834f0e1e5fe234113a576 React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c - React-featureflagsnativemodule: 95a02d895475de8ace78fedd76143866838bb720 - React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386 - React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3 - React-idlecallbacksnativemodule: 0c1ae840cc5587197cd926a3cb76828ad059d116 - React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2 - React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64 - React-jsi: 95f7676103137861b79b0f319467627bcfa629ee - React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932 - React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2 - React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b - React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20 - React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc - React-microtasksnativemodule: 8732b71aa66045da4bb341ddee1bb539f71e5f38 - react-native-crash-tester: 3ffaa64141427ca362079cb53559fe9a532487ae - react-native-safe-area-context: 04803a01f39f31cc6605a5531280b477b48f8a88 - react-native-webview: 1e12de2fad74c17b4f8b1b53ebd1e3baa0148d71 + React-featureflagsnativemodule: 3a8731d8fd9f755be57e00d9fa8a7f92aa77e87d + React-graphics: 68969e4e49d73f89da7abef4116c9b5f466aa121 + React-hermes: ac0bcba26a5d288ebc99b500e1097da2d0297ddf + React-idlecallbacksnativemodule: 9a2c5b5c174c0c476f039bedc1b9497a8272133e + React-ImageManager: e906eec93a9eb6102a06576b89d48d80a4683020 + React-jserrorhandler: ac5dde01104ff444e043cad8f574ca02756e20d6 + React-jsi: 496fa2b9d63b726aeb07d0ac800064617d71211d + React-jsiexecutor: dd22ab48371b80f37a0a30d0e8915b6d0f43a893 + React-jsinspector: 4629ac376f5765e684d19064f2093e55c97fd086 + React-jsitracing: 7a1c9cd484248870cf660733cd3b8114d54c035f + React-logger: c4052eb941cca9a097ef01b59543a656dc088559 + React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de + React-microtasksnativemodule: 5c3d795318c22ab8df55100e50b151384a4a60b3 + react-native-crash-tester: 48bde9d6f5256c61ef2e0c52dfc74256b26e55eb + react-native-safe-area-context: e134b241010ebe2aacdcea013565963d13826faa + react-native-webview: 2ea635bc43fd8a4b89de61133e8cc0607084e9f8 React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678 - React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22 - React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d - React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9 + React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e + React-perflogger: 72e653eb3aba9122f9e57cf012d22d2486f33358 + React-performancetimeline: cd6a9374a72001165995d2ab632f672df04076dc React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342 - React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4 - React-RCTAppDelegate: 6c0377d9c4058773ea7073bb34bb9ebd6ddf5a84 - React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8 - React-RCTFabric: 7eb6dd2c8fda98cb860a572e3f4e4eb60d62c89e - React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0 - React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a - React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3 - React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40 - React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2 - React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec + React-RCTAnimation: 395ab53fd064dff81507c15efb781c8684d9a585 + React-RCTAppDelegate: 1e5b43833e3e36e9fa34eec20be98174bc0e14a2 + React-RCTBlob: 13311e554c1a367de063c10ee7c5e6573b2dd1d6 + React-RCTFabric: bd906861a4e971e21d8df496c2d8f3ca6956f840 + React-RCTImage: 1b1f914bcc12187c49ba5d949dac38c2eb9f5cc8 + React-RCTLinking: 4ac7c42beb65e36fba0376f3498f3cd8dd0be7fa + React-RCTNetwork: 938902773add4381e84426a7aa17a2414f5f94f7 + React-RCTSettings: e848f1ba17a7a18479cf5a31d28145f567da8223 + React-RCTText: 7e98fafdde7d29e888b80f0b35544e0cb07913cf + React-RCTVibration: cd7d80affd97dc7afa62f9acd491419558b64b78 React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6 - React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5 + React-rendererdebug: aa181c36dd6cf5b35511d1ed875d6638fd38f0ec React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74 - React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655 - React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157 + React-RuntimeApple: d033becbbd1eba6f9f6e3af6f1893030ce203edd + React-RuntimeCore: 38af280bb678e66ba000a3c3d42920b2a138eebb React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899 - React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549 - React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe + React-RuntimeHermes: 37aad735ff21ca6de2d8450a96de1afe9f86c385 + React-runtimescheduler: 8ec34cc885281a34696ea16c4fd86892d631f38d React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9 - React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e - ReactCodegen: 21a52ccddc6479448fc91903a437dd23ddc7366c - ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd - ReactNativeNavigation: 50c1eef68b821e7265eff3a391d27ed18fdce459 - RNCAsyncStorage: 23e56519cc41d3bade3c8d4479f7760cb1c11996 - RNGestureHandler: 950dfa674dbf481460ca389c65b9036ac4ab8ada - RNScreens: 606ab1cf68162f7ba0d049a31f2a84089a6fffb4 + React-utils: ed818f19ab445000d6b5c4efa9d462449326cc9f + ReactCodegen: f853a20cc9125c5521c8766b4b49375fec20648b + ReactCommon: 300d8d9c5cb1a6cd79a67cf5d8f91e4d477195f9 + ReactNativeNavigation: 445f86273eb245d15b14023ee4ef9d6e4f891ad6 + RNCAsyncStorage: b44e8a4e798c3e1f56bffccd0f591f674fb9198f + RNGestureHandler: cb711d56ee3b03a5adea1d38324d4459ab55653f + RNScreens: f75b26fd4777848c216e27b0a09e1bf9c9f4760a SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index c0d235304..a2f41ddd1 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -19,14 +19,14 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the versions in sync with DatadogSDKReactNativeSessionReplay.podspec - s.dependency 'DatadogCore', '3.1.0' - s.dependency 'DatadogLogs', '3.1.0' - s.dependency 'DatadogTrace', '3.1.0' - s.dependency 'DatadogRUM', '3.1.0' - s.dependency 'DatadogCrashReporting', '3.1.0' + s.dependency 'DatadogCore', '3.0.0' + s.dependency 'DatadogLogs', '3.0.0' + s.dependency 'DatadogTrace', '3.0.0' + s.dependency 'DatadogRUM', '3.0.0' + s.dependency 'DatadogCrashReporting', '3.0.0' # DatadogWebViewTracking is not available for tvOS - s.ios.dependency 'DatadogWebViewTracking', '3.1.0' + s.ios.dependency 'DatadogWebViewTracking', '3.0.0' s.test_spec 'Tests' do |test_spec| test_spec.source_files = 'ios/Tests/**/*.{swift,json}' diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index 080185d41..a8d09d4d1 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -201,16 +201,16 @@ dependencies { // This breaks builds if the React Native target is below 0.76.0. as it relies on Gradle 8.5.0. // To avoid this, we enforce 1.0.0-beta01 on RN < 0.76.0 if (reactNativeMinorVersion < 76) { - implementation("com.datadoghq:dd-sdk-android-rum:3.2.0") { + implementation("com.datadoghq:dd-sdk-android-rum:3.0.0") { exclude group: "androidx.metrics", module: "metrics-performance" } implementation "androidx.metrics:metrics-performance:1.0.0-beta01" } else { - implementation "com.datadoghq:dd-sdk-android-rum:3.2.0" + implementation "com.datadoghq:dd-sdk-android-rum:3.0.0" } - implementation "com.datadoghq:dd-sdk-android-logs:3.2.0" - implementation "com.datadoghq:dd-sdk-android-trace:3.2.0" - implementation "com.datadoghq:dd-sdk-android-webview:3.2.0" + implementation "com.datadoghq:dd-sdk-android-logs:3.0.0" + implementation "com.datadoghq:dd-sdk-android-trace:3.0.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" implementation "com.google.code.gson:gson:2.10.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 6a5d0b78f..3a2d5ff48 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogSessionReplay', '3.1.0' + s.dependency 'DatadogSessionReplay', '3.0.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index bea305684..6d6fe20b1 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -216,8 +216,8 @@ dependencies { api "com.facebook.react:react-android:$reactNativeVersion" } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.datadoghq:dd-sdk-android-session-replay:3.2.0" - implementation "com.datadoghq:dd-sdk-android-internal:3.2.0" + implementation "com.datadoghq:dd-sdk-android-session-replay:3.0.0" + implementation "com.datadoghq:dd-sdk-android-internal:3.0.0" implementation project(path: ':datadog_mobile-react-native') testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 080a853d8..26e160bbc 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -23,8 +23,8 @@ Pod::Spec.new do |s| end # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogWebViewTracking', '3.1.0' - s.dependency 'DatadogInternal', '3.1.0' + s.dependency 'DatadogWebViewTracking', '3.0.0' + s.dependency 'DatadogInternal', '3.0.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-webview/android/build.gradle b/packages/react-native-webview/android/build.gradle index dbb8d0593..098eae019 100644 --- a/packages/react-native-webview/android/build.gradle +++ b/packages/react-native-webview/android/build.gradle @@ -190,7 +190,7 @@ dependencies { implementation "com.facebook.react:react-android:$reactNativeVersion" } - implementation "com.datadoghq:dd-sdk-android-webview:3.2.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation project(path: ':datadog_mobile-react-native') From 50271fb4c11d3bd084d3dab0df8eedec70bc5a8b Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 12 Sep 2025 14:43:25 +0200 Subject: [PATCH 45/62] Remove setUser --- packages/core/ios/Tests/MockRUMMonitor.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/core/ios/Tests/MockRUMMonitor.swift b/packages/core/ios/Tests/MockRUMMonitor.swift index 4a1d0cd92..c692f6e7c 100644 --- a/packages/core/ios/Tests/MockRUMMonitor.swift +++ b/packages/core/ios/Tests/MockRUMMonitor.swift @@ -10,6 +10,22 @@ @testable import DatadogSDKReactNative internal class MockRUMMonitor: RUMMonitorProtocol { + func addViewAttribute(forKey key: DatadogInternal.AttributeKey, value: any DatadogInternal.AttributeValue) { + // not implemented + } + + func addViewAttributes(_ attributes: [DatadogInternal.AttributeKey : any DatadogInternal.AttributeValue]) { + // not implemented + } + + func removeViewAttribute(forKey key: DatadogInternal.AttributeKey) { + // not implemented + } + + func removeViewAttributes(forKeys keys: [DatadogInternal.AttributeKey]) { + // not implemented + } + func currentSessionID(completion: @escaping (String?) -> Void) { // not implemented } From 6a7b4267c1cc62507d38e6506b65c6dd77332413 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 19 Sep 2025 11:45:00 +0200 Subject: [PATCH 46/62] Bump Native SDKs to 3.1.0 --- benchmarks/android/app/build.gradle | 2 +- benchmarks/ios/Podfile.lock | 70 +++++++-------- example-new-architecture/ios/Podfile.lock | 66 +++++++------- example/ios/Podfile.lock | 88 +++++++++---------- packages/core/DatadogSDKReactNative.podspec | 12 +-- packages/core/android/build.gradle | 10 +-- ...DatadogSDKReactNativeSessionReplay.podspec | 2 +- .../android/build.gradle | 4 +- .../DatadogSDKReactNativeWebView.podspec | 4 +- .../react-native-webview/android/build.gradle | 2 +- 10 files changed, 130 insertions(+), 130 deletions(-) diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle index 7dc4b3707..04c240bd0 100644 --- a/benchmarks/android/app/build.gradle +++ b/benchmarks/android/app/build.gradle @@ -129,5 +129,5 @@ dependencies { // Benchmark tools from dd-sdk-android are used for vitals recording // Remember to bump thid alongside the main dd-sdk-android dependencies - implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.0.0") + implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.1.0") } diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 16194127d..5c91024d5 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogCrashReporting (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogCore (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogCrashReporting (3.1.0): + - DatadogInternal (= 3.1.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.0.0) - - DatadogLogs (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogRUM (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogInternal (3.1.0) + - DatadogLogs (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogRUM (3.1.0): + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -39,7 +39,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.0.0) + - DatadogSessionReplay (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -61,9 +61,9 @@ PODS: - ReactCommon/turbomodule/core - Yoga - DatadogSDKReactNativeWebView (2.12.1): - - DatadogInternal (= 3.0.0) + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.0.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -84,13 +84,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSessionReplay (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogTrace (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogSessionReplay (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogTrace (3.1.0): + - DatadogInternal (= 3.1.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogWebViewTracking (3.1.0): + - DatadogInternal (= 3.1.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.78.2) @@ -2070,17 +2070,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 - DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e - DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 - DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd - DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f - DatadogSDKReactNative: 241bf982c16ceff03d94a58e6d005e55c47b99c6 - DatadogSDKReactNativeSessionReplay: bba36092686e3183e97c1a0c7f4ca8142582ae28 - DatadogSDKReactNativeWebView: 6da060df20e235abac533e582d9fc2b3a5070840 - DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 - DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 - DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 + DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d + DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d + DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc + DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 + DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 + DatadogSDKReactNative: 8e0f39de38621d4d7ed961a74d8a216fd3a38321 + DatadogSDKReactNativeSessionReplay: f9288c8e981dcc65d1f727b01421ee9a7601e75f + DatadogSDKReactNativeWebView: 993527f6c5d38e0fcc4804a6a60c334dd199dc5b + DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 + DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 + DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index 281513566..c0cd90bf6 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogCrashReporting (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogCore (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogCrashReporting (3.1.0): + - DatadogInternal (= 3.1.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.0.0) - - DatadogLogs (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogRUM (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogInternal (3.1.0) + - DatadogLogs (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogRUM (3.1.0): + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -38,12 +38,12 @@ PODS: - ReactCommon/turbomodule/core - Yoga - DatadogSDKReactNative/Tests (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -64,11 +64,11 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogTrace (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogTrace (3.1.0): + - DatadogInternal (= 3.1.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogWebViewTracking (3.1.0): + - DatadogInternal (= 3.1.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1850,14 +1850,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 - DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e - DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 - DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd - DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f - DatadogSDKReactNative: 0a80aa75958d595a99be54d2838db53eda7a08af - DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 - DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 + DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d + DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d + DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc + DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 + DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 + DatadogSDKReactNative: 069ea9876220b2d09b0f4b180ce571b1b6ecbb35 + DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 + DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index fac339d80..8838c9be5 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,34 +1,34 @@ PODS: - boost (1.84.0) - - DatadogCore (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogCrashReporting (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogCore (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogCrashReporting (3.1.0): + - DatadogInternal (= 3.1.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.0.0) - - DatadogLogs (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogRUM (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogInternal (3.1.0) + - DatadogLogs (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogRUM (3.1.0): + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - DatadogSDKReactNative/Tests (2.12.1): - - DatadogCore (= 3.0.0) - - DatadogCrashReporting (= 3.0.0) - - DatadogLogs (= 3.0.0) - - DatadogRUM (= 3.0.0) - - DatadogTrace (= 3.0.0) - - DatadogWebViewTracking (= 3.0.0) + - DatadogCore (= 3.1.0) + - DatadogCrashReporting (= 3.1.0) + - DatadogLogs (= 3.1.0) + - DatadogRUM (= 3.1.0) + - DatadogTrace (= 3.1.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.0.0) + - DatadogSessionReplay (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -51,7 +51,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay/Tests (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.0.0) + - DatadogSessionReplay (= 3.1.0) - DoubleConversion - glog - hermes-engine @@ -74,24 +74,24 @@ PODS: - ReactCommon/turbomodule/core - Yoga - DatadogSDKReactNativeWebView (2.12.1): - - DatadogInternal (= 3.0.0) + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.0.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - DatadogSDKReactNativeWebView/Tests (2.12.1): - - DatadogInternal (= 3.0.0) + - DatadogInternal (= 3.1.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.0.0) + - DatadogWebViewTracking (= 3.1.0) - React-Core - react-native-webview - React-RCTText - - DatadogSessionReplay (3.0.0): - - DatadogInternal (= 3.0.0) - - DatadogTrace (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogSessionReplay (3.1.0): + - DatadogInternal (= 3.1.0) + - DatadogTrace (3.1.0): + - DatadogInternal (= 3.1.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.0.0): - - DatadogInternal (= 3.0.0) + - DatadogWebViewTracking (3.1.0): + - DatadogInternal (= 3.1.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1988,17 +1988,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 0c39ba4ef3dee02071f235f2fb56af7e29f4ceb0 - DatadogCrashReporting: 604e65e524cb2fc22cda39fd9c9ea5fd3bddf24e - DatadogInternal: 442673a7fb5329299b489b91ed705aa2085380f7 - DatadogLogs: 0146a0e3140ba62fd42729593c0910d692aea5fd - DatadogRUM: f97fbd0290ecec5bc952fb03a6a1ae068649243f - DatadogSDKReactNative: e430b3f4d7adb0fac07b61e2fb65ceacdaf82b3e - DatadogSDKReactNativeSessionReplay: 4b2a3d166a79581f18522795b40141c34cf3685d - DatadogSDKReactNativeWebView: 35dc2b9736e1aaa82b366bf6b8a8a959a9b088c5 - DatadogSessionReplay: 0357b911c6ab42c77c93b29761ecc20d9282e971 - DatadogTrace: d714e7c456e612b7f171483d08086a59aa1c4213 - DatadogWebViewTracking: fb9591c09fca82b143f3843a7164a7e782175c53 + DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d + DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d + DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc + DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 + DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 + DatadogSDKReactNative: af351a4e1ce08124c290c52de94b0062a166cc67 + DatadogSDKReactNativeSessionReplay: dcbd55d9d0f2b86026996a8b7ec9654922d5dfe1 + DatadogSDKReactNativeWebView: 096ac87eb753b6a217b93441983264b9837c3b7e + DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 + DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 + DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index a2f41ddd1..c0d235304 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -19,14 +19,14 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the versions in sync with DatadogSDKReactNativeSessionReplay.podspec - s.dependency 'DatadogCore', '3.0.0' - s.dependency 'DatadogLogs', '3.0.0' - s.dependency 'DatadogTrace', '3.0.0' - s.dependency 'DatadogRUM', '3.0.0' - s.dependency 'DatadogCrashReporting', '3.0.0' + s.dependency 'DatadogCore', '3.1.0' + s.dependency 'DatadogLogs', '3.1.0' + s.dependency 'DatadogTrace', '3.1.0' + s.dependency 'DatadogRUM', '3.1.0' + s.dependency 'DatadogCrashReporting', '3.1.0' # DatadogWebViewTracking is not available for tvOS - s.ios.dependency 'DatadogWebViewTracking', '3.0.0' + s.ios.dependency 'DatadogWebViewTracking', '3.1.0' s.test_spec 'Tests' do |test_spec| test_spec.source_files = 'ios/Tests/**/*.{swift,json}' diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index a8d09d4d1..59bb75cc3 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -201,16 +201,16 @@ dependencies { // This breaks builds if the React Native target is below 0.76.0. as it relies on Gradle 8.5.0. // To avoid this, we enforce 1.0.0-beta01 on RN < 0.76.0 if (reactNativeMinorVersion < 76) { - implementation("com.datadoghq:dd-sdk-android-rum:3.0.0") { + implementation("com.datadoghq:dd-sdk-android-rum:3.1.0") { exclude group: "androidx.metrics", module: "metrics-performance" } implementation "androidx.metrics:metrics-performance:1.0.0-beta01" } else { - implementation "com.datadoghq:dd-sdk-android-rum:3.0.0" + implementation "com.datadoghq:dd-sdk-android-rum:3.1.0" } - implementation "com.datadoghq:dd-sdk-android-logs:3.0.0" - implementation "com.datadoghq:dd-sdk-android-trace:3.0.0" - implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" + implementation "com.datadoghq:dd-sdk-android-logs:3.1.0" + implementation "com.datadoghq:dd-sdk-android-trace:3.1.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" implementation "com.google.code.gson:gson:2.10.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 3a2d5ff48..6a5d0b78f 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogSessionReplay', '3.0.0' + s.dependency 'DatadogSessionReplay', '3.1.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index 6d6fe20b1..a0d77f2ff 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -216,8 +216,8 @@ dependencies { api "com.facebook.react:react-android:$reactNativeVersion" } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.datadoghq:dd-sdk-android-session-replay:3.0.0" - implementation "com.datadoghq:dd-sdk-android-internal:3.0.0" + implementation "com.datadoghq:dd-sdk-android-session-replay:3.1.0" + implementation "com.datadoghq:dd-sdk-android-internal:3.1.0" implementation project(path: ':datadog_mobile-react-native') testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 26e160bbc..080a853d8 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -23,8 +23,8 @@ Pod::Spec.new do |s| end # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogWebViewTracking', '3.0.0' - s.dependency 'DatadogInternal', '3.0.0' + s.dependency 'DatadogWebViewTracking', '3.1.0' + s.dependency 'DatadogInternal', '3.1.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-webview/android/build.gradle b/packages/react-native-webview/android/build.gradle index 098eae019..87ca1b7e7 100644 --- a/packages/react-native-webview/android/build.gradle +++ b/packages/react-native-webview/android/build.gradle @@ -190,7 +190,7 @@ dependencies { implementation "com.facebook.react:react-android:$reactNativeVersion" } - implementation "com.datadoghq:dd-sdk-android-webview:3.0.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation project(path: ':datadog_mobile-react-native') From 2a4f7727c8c744c0ae877fbc749e7f36a0e400f6 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 5 Sep 2025 17:47:29 +0200 Subject: [PATCH 47/62] Use native sdk's core instance instead of the one inside RN SDK wrapper --- .../com/datadog/reactnative/DdSdkNativeInitialization.kt | 2 ++ .../src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt | 6 +----- .../src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt | 7 +------ 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt index 4388ad5f6..ee55d08fe 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt @@ -65,7 +65,9 @@ class DdSdkNativeInitialization internal constructor( datadog.initialize(appContext, sdkConfiguration, trackingConsent) Rum.enable(rumConfiguration, Datadog.getInstance()) + Logs.enable(logsConfiguration, Datadog.getInstance()) + Trace.enable(traceConfiguration, Datadog.getInstance()) } diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index 958ba521b..df44a6b5f 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -22,11 +22,7 @@ class DdSdk( ddTelemetry: DdTelemetry = DdTelemetry() ) : ReactContextBaseJavaModule(reactContext) { - private val implementation = DdSdkImplementation( - reactContext, - datadog = datadogWrapper, - ddTelemetry - ) + private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper, ddTelemetry) private var lifecycleEventListener: LifecycleEventListener? = null override fun getName(): String = DdSdkImplementation.NAME diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index 327d8ffc0..f034b292c 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -164,12 +164,7 @@ internal class DdSdkTest { answer.getArgument(0).run() true } - testedBridgeSdk = DdSdkImplementation( - mockReactContext, - mockDatadog, - mockDdTelemetry, - TestUiThreadExecutor() - ) + testedBridgeSdk = DdSdkImplementation(mockReactContext, mockDatadog, mockDdTelemetry, TestUiThreadExecutor()) DatadogSDKWrapperStorage.onInitializedListeners.clear() } From 0fd48f4a916555c82565b25b659c16f2b9c3c837 Mon Sep 17 00:00:00 2001 From: Marco Saia Date: Mon, 22 Sep 2025 16:20:27 +0200 Subject: [PATCH 48/62] Fixed internal testing tools and unit tests --- .../com/datadog/reactnative/DdSdkNativeInitialization.kt | 2 -- .../src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt | 6 +++++- .../src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt | 7 ++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt index ee55d08fe..4388ad5f6 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkNativeInitialization.kt @@ -65,9 +65,7 @@ class DdSdkNativeInitialization internal constructor( datadog.initialize(appContext, sdkConfiguration, trackingConsent) Rum.enable(rumConfiguration, Datadog.getInstance()) - Logs.enable(logsConfiguration, Datadog.getInstance()) - Trace.enable(traceConfiguration, Datadog.getInstance()) } diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index df44a6b5f..958ba521b 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -22,7 +22,11 @@ class DdSdk( ddTelemetry: DdTelemetry = DdTelemetry() ) : ReactContextBaseJavaModule(reactContext) { - private val implementation = DdSdkImplementation(reactContext, datadog = datadogWrapper, ddTelemetry) + private val implementation = DdSdkImplementation( + reactContext, + datadog = datadogWrapper, + ddTelemetry + ) private var lifecycleEventListener: LifecycleEventListener? = null override fun getName(): String = DdSdkImplementation.NAME diff --git a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt index f034b292c..327d8ffc0 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/reactnative/DdSdkTest.kt @@ -164,7 +164,12 @@ internal class DdSdkTest { answer.getArgument(0).run() true } - testedBridgeSdk = DdSdkImplementation(mockReactContext, mockDatadog, mockDdTelemetry, TestUiThreadExecutor()) + testedBridgeSdk = DdSdkImplementation( + mockReactContext, + mockDatadog, + mockDdTelemetry, + TestUiThreadExecutor() + ) DatadogSDKWrapperStorage.onInitializedListeners.clear() } From b4022578509e35294271cbb02731829810d70028 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 19 Sep 2025 17:37:31 +0200 Subject: [PATCH 49/62] Expose clearUserInfo API --- .../ios/Sources/DdSdkImplementation.swift | 8 +-- packages/core/ios/Tests/DdSdkTests.swift | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 997068ddf..2c5d4cdf3 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -143,7 +143,7 @@ public class DdSdkImplementation: NSObject { resolve(nil) } - + @objc public func addUserExtraInfo( extraInfo: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock @@ -155,15 +155,13 @@ public class DdSdkImplementation: NSObject { } @objc - public func clearUserInfo(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { + public func clearUserInfo(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { Datadog.clearUserInfo() resolve(nil) } @objc - public func setTrackingConsent( - trackingConsent: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock - ) { + public func setTrackingConsent(trackingConsent: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { Datadog.set(trackingConsent: (trackingConsent as NSString?).asTrackingConsent()) resolve(nil) } diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index 4a5d13f2e..5d0237530 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -651,6 +651,73 @@ class DdSdkTests: XCTestCase { XCTFail("extra-info-4 is not of expected type or value") } } + + func testClearUserInfo() throws { + let bridge = DdSdkImplementation( + mainDispatchQueue: DispatchQueueMock(), + jsDispatchQueue: DispatchQueueMock(), + jsRefreshRateMonitor: JSRefreshRateMonitor(), + RUMMonitorProvider: { MockRUMMonitor() }, + RUMMonitorInternalProvider: { nil } + ) + bridge.initialize( + configuration: .mockAny(), + resolve: mockResolve, + reject: mockReject + ) + + bridge.setUserInfo( + userInfo: NSDictionary( + dictionary: [ + "id": "id_123", + "name": "John Doe", + "email": "john@doe.com", + "extraInfo": [ + "extra-info-1": 123, + "extra-info-2": "abc", + "extra-info-3": true, + "extra-info-4": [ + "nested-extra-info-1": 456 + ], + ], + ] + ), + resolve: mockResolve, + reject: mockReject + ) + + var ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() + var userInfo = try XCTUnwrap(ddContext.userInfo) + + XCTAssertEqual(userInfo.id, "id_123") + XCTAssertEqual(userInfo.name, "John Doe") + XCTAssertEqual(userInfo.email, "john@doe.com") + XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, 123) + XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, "abc") + XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true) + + if let extraInfo4Encodable = userInfo.extraInfo["extra-info-4"] + as? DatadogSDKReactNative.AnyEncodable, + let extraInfo4Dict = extraInfo4Encodable.value as? [String: Int] + { + XCTAssertEqual(extraInfo4Dict, ["nested-extra-info-1": 456]) + } else { + XCTFail("extra-info-4 is not of expected type or value") + } + + bridge.clearUserInfo(resolve: mockResolve, reject: mockReject) + + ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() + userInfo = try XCTUnwrap(ddContext.userInfo) + + XCTAssertEqual(userInfo.id, nil) + XCTAssertEqual(userInfo.name, nil) + XCTAssertEqual(userInfo.email, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, nil) + XCTAssertEqual(userInfo.extraInfo["extra-info-4"] as? [String: Int], nil) + } func testClearUserInfo() throws { let bridge = DdSdkImplementation( From 1b2baa74a698015b764bf1c57a322c62f473b553 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Mon, 29 Sep 2025 12:20:44 +0200 Subject: [PATCH 50/62] Update attribute API --- packages/core/ios/Tests/DdSdkTests.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index 5d0237530..cba49f84f 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -651,7 +651,7 @@ class DdSdkTests: XCTestCase { XCTFail("extra-info-4 is not of expected type or value") } } - + func testClearUserInfo() throws { let bridge = DdSdkImplementation( mainDispatchQueue: DispatchQueueMock(), @@ -704,12 +704,12 @@ class DdSdkTests: XCTestCase { } else { XCTFail("extra-info-4 is not of expected type or value") } - + bridge.clearUserInfo(resolve: mockResolve, reject: mockReject) - + ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() userInfo = try XCTUnwrap(ddContext.userInfo) - + XCTAssertEqual(userInfo.id, nil) XCTAssertEqual(userInfo.name, nil) XCTAssertEqual(userInfo.email, nil) From 2485aa256d97fb47c3380af2f9a5c84dcd188e06 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Thu, 16 Oct 2025 11:01:21 +0200 Subject: [PATCH 51/62] JS refresh rate normalization --- .../reactnative/DdSdkImplementation.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index 6741e971e..29fdcdce0 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -354,6 +354,32 @@ class DdSdkImplementation( return display.supportedModes.maxOf { it.refreshRate.toDouble() } } + // endregion + + val maxDeviceFrameTimeMs = 1000.0 / maxDeviceDisplayHz + val budgetFrameTimeMs = 1000.0 / frameBudgetHz + + if (listOf( + maxDeviceDisplayHz, frameTimeMs, frameBudgetHz, budgetFrameTimeMs, maxDeviceFrameTimeMs + ).any { !it.isFinite() || it <= 0.0 } + ) return 1.0 / DEFAULT_REFRESH_HZ + + + var normalizedFrameTimeMs = frameTimeMs / (maxDeviceFrameTimeMs / budgetFrameTimeMs) + + normalizedFrameTimeMs = max(normalizedFrameTimeMs, maxDeviceFrameTimeMs) + + return normalizedFrameTimeMs / 1000.0 // in seconds + } + + @Suppress("CyclomaticComplexMethod") + private fun getMaxDisplayRefreshRate(context: Context?): Double { + val dm = context?.getSystemService(Context.DISPLAY_SERVICE) as? DisplayManager ?: return 60.0 + val display: Display = dm.getDisplay(Display.DEFAULT_DISPLAY) ?: return DEFAULT_REFRESH_HZ + + return display.supportedModes.maxOf { it.refreshRate.toDouble() } + } + // endregion internal companion object { internal const val DEFAULT_APP_VERSION = "?" From 7645ae5cf26ac0674e568976e3543c33437d2d93 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 10 Oct 2025 14:52:21 +0200 Subject: [PATCH 52/62] Expose view Attributes API --- .../ios/Sources/DdSdkImplementation.swift | 25 +++++++++++-------- packages/core/ios/Tests/MockRUMMonitor.swift | 16 ------------ 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 2c5d4cdf3..5b91039b3 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -143,7 +143,7 @@ public class DdSdkImplementation: NSObject { resolve(nil) } - + @objc public func addUserExtraInfo( extraInfo: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock @@ -155,13 +155,15 @@ public class DdSdkImplementation: NSObject { } @objc - public func clearUserInfo(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func clearUserInfo(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { Datadog.clearUserInfo() resolve(nil) } @objc - public func setTrackingConsent(trackingConsent: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func setTrackingConsent( + trackingConsent: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { Datadog.set(trackingConsent: (trackingConsent as NSString?).asTrackingConsent()) resolve(nil) } @@ -173,7 +175,8 @@ public class DdSdkImplementation: NSObject { ) { let castedAttributes = castAttributesToSwift(attributes) let castedConfig = castAttributesToSwift(config) - DdTelemetry.sendTelemetryLog(message: message as String, attributes: castedAttributes, config: castedConfig) + DdTelemetry.sendTelemetryLog( + message: message as String, attributes: castedAttributes, config: castedConfig) resolve(nil) } @@ -184,13 +187,13 @@ public class DdSdkImplementation: NSObject { resolve(nil) } -#if os(iOS) @objc public func telemetryError(message: NSString, stack: NSString, kind: NSString, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { DdTelemetry.telemetryError(id: "datadog_react_native:\(String(describing: kind)):\(message)", message: message as String, kind: kind as String, stack: stack as String) resolve(nil) } +#if os(iOS) @objc public func consumeWebviewEvent( message: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock @@ -207,19 +210,21 @@ public class DdSdkImplementation: NSObject { resolve(nil) } + #endif - @objc - public func clearAllData(resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void { + public func clearAllData(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { Datadog.clearAllData() resolve(nil) } - func overrideReactNativeTelemetry(rnConfiguration: DdSdkConfiguration) -> Void { + func overrideReactNativeTelemetry(rnConfiguration: DdSdkConfiguration) { DdTelemetry.overrideTelemetryConfiguration( - initializationType: rnConfiguration.configurationForTelemetry?.initializationType as? String, - reactNativeVersion: rnConfiguration.configurationForTelemetry?.reactNativeVersion as? String, + initializationType: rnConfiguration.configurationForTelemetry?.initializationType + as? String, + reactNativeVersion: rnConfiguration.configurationForTelemetry?.reactNativeVersion + as? String, reactVersion: rnConfiguration.configurationForTelemetry?.reactVersion as? String, trackCrossPlatformLongTasks: rnConfiguration.longTaskThresholdMs != 0, trackErrors: rnConfiguration.configurationForTelemetry?.trackErrors, diff --git a/packages/core/ios/Tests/MockRUMMonitor.swift b/packages/core/ios/Tests/MockRUMMonitor.swift index c692f6e7c..4a1d0cd92 100644 --- a/packages/core/ios/Tests/MockRUMMonitor.swift +++ b/packages/core/ios/Tests/MockRUMMonitor.swift @@ -10,22 +10,6 @@ @testable import DatadogSDKReactNative internal class MockRUMMonitor: RUMMonitorProtocol { - func addViewAttribute(forKey key: DatadogInternal.AttributeKey, value: any DatadogInternal.AttributeValue) { - // not implemented - } - - func addViewAttributes(_ attributes: [DatadogInternal.AttributeKey : any DatadogInternal.AttributeValue]) { - // not implemented - } - - func removeViewAttribute(forKey key: DatadogInternal.AttributeKey) { - // not implemented - } - - func removeViewAttributes(forKeys keys: [DatadogInternal.AttributeKey]) { - // not implemented - } - func currentSessionID(completion: @escaping (String?) -> Void) { // not implemented } From d892763e6263519412ec2e88fb06c431ec22fc89 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Mon, 27 Oct 2025 16:28:37 +0100 Subject: [PATCH 53/62] Handle optional String on removeAttributes --- .../main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index 29fdcdce0..f02395ed8 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -115,8 +115,7 @@ class DdSdkImplementation( fun removeAttributes(keys: ReadableArray, promise: Promise) { val keysArray = mutableListOf() for (i in 0 until keys.size()) { - val key: String = keys.getString(i) - keysArray.add(key) + keys.getString(i)?.let { if (it.isNotBlank()) keysArray.add(it) } } val keysStringArray = keysArray.toTypedArray() From 7f3b5f7353e7a5103e22e6dfbe513c7c30305bbf Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Mon, 27 Oct 2025 11:37:44 +0100 Subject: [PATCH 54/62] Bump minSdkVersion to 23 --- packages/core/android/build.gradle | 20 ++++--------------- packages/core/android/gradle.properties | 2 +- .../android/gradle.properties | 2 +- .../android/gradle.properties | 2 +- .../android/gradle.properties | 2 +- 5 files changed, 8 insertions(+), 20 deletions(-) diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index 59bb75cc3..1344b2531 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -195,22 +195,10 @@ dependencies { } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compileOnly "com.squareup.okhttp3:okhttp:3.12.13" - - // dd-sdk-android-rum requires androidx.metrics:metrics-performance. - // From 2.21.0, it uses 1.0.0-beta02, which requires Gradle 8.6.0. - // This breaks builds if the React Native target is below 0.76.0. as it relies on Gradle 8.5.0. - // To avoid this, we enforce 1.0.0-beta01 on RN < 0.76.0 - if (reactNativeMinorVersion < 76) { - implementation("com.datadoghq:dd-sdk-android-rum:3.1.0") { - exclude group: "androidx.metrics", module: "metrics-performance" - } - implementation "androidx.metrics:metrics-performance:1.0.0-beta01" - } else { - implementation "com.datadoghq:dd-sdk-android-rum:3.1.0" - } - implementation "com.datadoghq:dd-sdk-android-logs:3.1.0" - implementation "com.datadoghq:dd-sdk-android-trace:3.1.0" - implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" + implementation "com.datadoghq:dd-sdk-android-rum:3.2.0" + implementation "com.datadoghq:dd-sdk-android-logs:3.2.0" + implementation "com.datadoghq:dd-sdk-android-trace:3.2.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.2.0" implementation "com.google.code.gson:gson:2.10.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/core/android/gradle.properties b/packages/core/android/gradle.properties index c9f7a205e..65f975c3e 100644 --- a/packages/core/android/gradle.properties +++ b/packages/core/android/gradle.properties @@ -1,5 +1,5 @@ DdSdkReactNative_kotlinVersion=1.8.21 -DdSdkReactNative_minSdkVersion=21 +DdSdkReactNative_minSdkVersion=23 DdSdkReactNative_compileSdkVersion=33 DdSdkReactNative_buildToolsVersion=33.0.0 DdSdkReactNative_targetSdkVersion=33 diff --git a/packages/internal-testing-tools/android/gradle.properties b/packages/internal-testing-tools/android/gradle.properties index 2a3186ab3..7a783c97d 100644 --- a/packages/internal-testing-tools/android/gradle.properties +++ b/packages/internal-testing-tools/android/gradle.properties @@ -1,5 +1,5 @@ DatadogInternalTesting_kotlinVersion=1.8.21 -DatadogInternalTesting_minSdkVersion=21 +DatadogInternalTesting_minSdkVersion=23 DatadogInternalTesting_compileSdkVersion=33 DatadogInternalTesting_buildToolsVersion=33.0.0 DatadogInternalTesting_targetSdkVersion=33 diff --git a/packages/react-native-session-replay/android/gradle.properties b/packages/react-native-session-replay/android/gradle.properties index 9f1573be5..d072f557e 100644 --- a/packages/react-native-session-replay/android/gradle.properties +++ b/packages/react-native-session-replay/android/gradle.properties @@ -1,6 +1,6 @@ DatadogSDKReactNativeSessionReplay_kotlinVersion=1.8.21 DatadogSDKReactNativeSessionReplay_compileSdkVersion=33 -DatadogSDKReactNativeSessionReplay_minSdkVersion=21 +DatadogSDKReactNativeSessionReplay_minSdkVersion=23 DatadogSDKReactNativeSessionReplay_buildToolsVersion=33.0.0 DatadogSDKReactNativeSessionReplay_targetSdkVersion=33 android.useAndroidX=true diff --git a/packages/react-native-webview/android/gradle.properties b/packages/react-native-webview/android/gradle.properties index 622c7b6b9..25112d024 100644 --- a/packages/react-native-webview/android/gradle.properties +++ b/packages/react-native-webview/android/gradle.properties @@ -1,5 +1,5 @@ DatadogSDKReactNativeWebView_kotlinVersion=1.7.21 -DatadogSDKReactNativeWebView_minSdkVersion=21 +DatadogSDKReactNativeWebView_minSdkVersion=23 DatadogSDKReactNativeWebView_compileSdkVersion=33 DatadogSDKReactNativeWebView_buildToolsVersion=33.0.0 DatadogSDKReactNativeWebView_targetSdkVersion=33 From c28e1fcfd61b20b95bc7d9c2f110931d8e1ca2d0 Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Wed, 5 Nov 2025 15:58:05 +0000 Subject: [PATCH 55/62] Expose sdk iOS config option `trackMemoryWarnings` --- packages/core/ios/Sources/DdSdkConfiguration.swift | 5 ++++- .../ios/Sources/DdSdkNativeInitialization.swift | 1 + .../core/ios/Sources/RNDdSdkConfiguration.swift | 9 +++++++-- packages/core/src/DdSdkReactNative.tsx | 3 ++- .../core/src/DdSdkReactNativeConfiguration.tsx | 14 +++++++++++++- .../DdSdkReactNativeConfiguration.test.ts | 3 +++ .../__tests__/initialization.test.tsx | 1 + .../__tests__/FileBasedConfiguration.test.ts | 3 +++ packages/core/src/types.tsx | 3 ++- 9 files changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/core/ios/Sources/DdSdkConfiguration.swift b/packages/core/ios/Sources/DdSdkConfiguration.swift index 7a76cf39d..288e2a539 100644 --- a/packages/core/ios/Sources/DdSdkConfiguration.swift +++ b/packages/core/ios/Sources/DdSdkConfiguration.swift @@ -76,6 +76,7 @@ public class DdSdkConfiguration: NSObject { public var trackWatchdogTerminations: Bool public var batchProcessingLevel: Datadog.Configuration.BatchProcessingLevel public var initialResourceThreshold: Double? = nil + public var trackMemoryWarnings: Bool public init( clientToken: String, @@ -108,7 +109,8 @@ public class DdSdkConfiguration: NSObject { appHangThreshold: Double?, trackWatchdogTerminations: Bool, batchProcessingLevel: Datadog.Configuration.BatchProcessingLevel, - initialResourceThreshold: Double? + initialResourceThreshold: Double?, + trackMemoryWarnings: Bool = true ) { self.clientToken = clientToken self.env = env @@ -141,6 +143,7 @@ public class DdSdkConfiguration: NSObject { self.trackWatchdogTerminations = trackWatchdogTerminations self.batchProcessingLevel = batchProcessingLevel self.initialResourceThreshold = initialResourceThreshold + self.trackMemoryWarnings = trackMemoryWarnings } } diff --git a/packages/core/ios/Sources/DdSdkNativeInitialization.swift b/packages/core/ios/Sources/DdSdkNativeInitialization.swift index b55f90561..969f72abf 100644 --- a/packages/core/ios/Sources/DdSdkNativeInitialization.swift +++ b/packages/core/ios/Sources/DdSdkNativeInitialization.swift @@ -201,6 +201,7 @@ public class DdSdkNativeInitialization: NSObject { }, onSessionStart: DdSdkSessionStartedListener.instance.rumSessionListener, customEndpoint: customRUMEndpointURL, + trackMemoryWarnings: configuration.trackMemoryWarnings, telemetrySampleRate: (configuration.telemetrySampleRate as? NSNumber)?.floatValue ?? Float(DefaultConfiguration.telemetrySampleRate) ) } diff --git a/packages/core/ios/Sources/RNDdSdkConfiguration.swift b/packages/core/ios/Sources/RNDdSdkConfiguration.swift index 66437c481..6869d1711 100644 --- a/packages/core/ios/Sources/RNDdSdkConfiguration.swift +++ b/packages/core/ios/Sources/RNDdSdkConfiguration.swift @@ -43,6 +43,7 @@ extension NSDictionary { let trackWatchdogTerminations = object(forKey: "trackWatchdogTerminations") as? Bool let batchProcessingLevel = object(forKey: "batchProcessingLevel") as? NSString let initialResourceThreshold = object(forKey: "initialResourceThreshold") as? Double + let trackMemoryWarnings = object(forKey: "trackMemoryWarnings") as? Bool return DdSdkConfiguration( clientToken: (clientToken != nil) ? clientToken! : String(), @@ -75,7 +76,8 @@ extension NSDictionary { appHangThreshold: appHangThreshold, trackWatchdogTerminations: trackWatchdogTerminations ?? DefaultConfiguration.trackWatchdogTerminations, batchProcessingLevel: batchProcessingLevel.asBatchProcessingLevel(), - initialResourceThreshold: initialResourceThreshold + initialResourceThreshold: initialResourceThreshold, + trackMemoryWarnings: trackMemoryWarnings ?? DefaultConfiguration.trackMemoryWarnings ) } @@ -206,6 +208,7 @@ internal struct DefaultConfiguration { static let bundleLogsWithRum = true static let bundleLogsWithTraces = true static let trackWatchdogTerminations = false + static let trackMemoryWarnings = true } extension Dictionary where Key == String, Value == AnyObject { @@ -244,6 +247,7 @@ extension Dictionary where Key == String, Value == AnyObject { let trackWatchdogTerminations = configuration["trackWatchdogTerminations"] as? Bool let batchProcessingLevel = configuration["batchProcessingLevel"] as? NSString let initialResourceThreshold = configuration["initialResourceThreshold"] as? Double + let trackMemoryWarnings = configuration["trackMemoryWarnings"] as? Bool return DdSdkConfiguration( clientToken: clientToken ?? String(), @@ -279,7 +283,8 @@ extension Dictionary where Key == String, Value == AnyObject { appHangThreshold: appHangThreshold, trackWatchdogTerminations: trackWatchdogTerminations ?? DefaultConfiguration.trackWatchdogTerminations, batchProcessingLevel: batchProcessingLevel.asBatchProcessingLevel(), - initialResourceThreshold: initialResourceThreshold + initialResourceThreshold: initialResourceThreshold, + trackMemoryWarnings: trackMemoryWarnings ?? DefaultConfiguration.trackMemoryWarnings ) } } diff --git a/packages/core/src/DdSdkReactNative.tsx b/packages/core/src/DdSdkReactNative.tsx index 8360a695b..b1ea4f4c1 100644 --- a/packages/core/src/DdSdkReactNative.tsx +++ b/packages/core/src/DdSdkReactNative.tsx @@ -397,7 +397,8 @@ export class DdSdkReactNative { configuration.resourceTracingSamplingRate, configuration.trackWatchdogTerminations, configuration.batchProcessingLevel, - configuration.initialResourceThreshold + configuration.initialResourceThreshold, + configuration.trackMemoryWarnings ); }; diff --git a/packages/core/src/DdSdkReactNativeConfiguration.tsx b/packages/core/src/DdSdkReactNativeConfiguration.tsx index 44debb2d2..4ec1ef883 100644 --- a/packages/core/src/DdSdkReactNativeConfiguration.tsx +++ b/packages/core/src/DdSdkReactNativeConfiguration.tsx @@ -133,7 +133,8 @@ export const DEFAULTS = { bundleLogsWithTraces: true, useAccessibilityLabel: true, trackWatchdogTerminations: false, - batchProcessingLevel: BatchProcessingLevel.MEDIUM + batchProcessingLevel: BatchProcessingLevel.MEDIUM, + trackMemoryWarnings: true }; /** @@ -328,6 +329,16 @@ export class DdSdkReactNativeConfiguration { public trackWatchdogTerminations: boolean = DEFAULTS.trackWatchdogTerminations; + /** + * Enables tracking of memory warnings as RUM events. + * + * When enabled, the SDK will automatically record a RUM event each time the app + * receives a memory warning from the operating system. + * + * **Note:** This setting is only supported on **iOS**. It has no effect on other platforms. + */ + public trackMemoryWarnings: boolean = DEFAULTS.trackMemoryWarnings; + /** * Specifies a custom prop to name RUM actions on elements having an `onPress` prop. * @@ -469,6 +480,7 @@ export type PartialInitializationConfiguration = { readonly bundleLogsWithTraces?: boolean; readonly batchProcessingLevel?: BatchProcessingLevel; readonly initialResourceThreshold?: number; + readonly trackMemoryWarnings?: boolean; }; const setConfigurationAttribute = < diff --git a/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts b/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts index b1522ef7f..60a9d13ff 100644 --- a/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts +++ b/packages/core/src/__tests__/DdSdkReactNativeConfiguration.test.ts @@ -60,6 +60,7 @@ describe('DdSdkReactNativeConfiguration', () => { "trackErrors": false, "trackFrustrations": true, "trackInteractions": false, + "trackMemoryWarnings": true, "trackResources": false, "trackWatchdogTerminations": false, "trackingConsent": "granted", @@ -170,6 +171,7 @@ describe('DdSdkReactNativeConfiguration', () => { "trackErrors": true, "trackFrustrations": true, "trackInteractions": true, + "trackMemoryWarnings": true, "trackResources": true, "trackWatchdogTerminations": false, "trackingConsent": "pending", @@ -246,6 +248,7 @@ describe('DdSdkReactNativeConfiguration', () => { "trackErrors": false, "trackFrustrations": false, "trackInteractions": false, + "trackMemoryWarnings": true, "trackResources": false, "trackWatchdogTerminations": false, "trackingConsent": "granted", diff --git a/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx b/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx index c654cd24b..8ace4b731 100644 --- a/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx +++ b/packages/core/src/sdk/DatadogProvider/__tests__/initialization.test.tsx @@ -100,6 +100,7 @@ describe('DatadogProvider', () => { "telemetrySampleRate": 20, "trackBackgroundEvents": false, "trackFrustrations": true, + "trackMemoryWarnings": true, "trackNonFatalAnrs": undefined, "trackWatchdogTerminations": false, "trackingConsent": "granted", diff --git a/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts b/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts index 6d3ee2e44..1670e5fe2 100644 --- a/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts +++ b/packages/core/src/sdk/FileBasedConfiguration/__tests__/FileBasedConfiguration.test.ts @@ -62,6 +62,7 @@ describe('FileBasedConfiguration', () => { "trackErrors": true, "trackFrustrations": true, "trackInteractions": true, + "trackMemoryWarnings": true, "trackResources": true, "trackWatchdogTerminations": false, "trackingConsent": "not_granted", @@ -154,6 +155,7 @@ describe('FileBasedConfiguration', () => { "trackErrors": true, "trackFrustrations": true, "trackInteractions": true, + "trackMemoryWarnings": true, "trackResources": true, "trackWatchdogTerminations": false, "trackingConsent": "not_granted", @@ -205,6 +207,7 @@ describe('FileBasedConfiguration', () => { "trackErrors": false, "trackFrustrations": true, "trackInteractions": false, + "trackMemoryWarnings": true, "trackResources": false, "trackWatchdogTerminations": false, "trackingConsent": "granted", diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index c8d9821cc..5c7d64cec 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -69,7 +69,8 @@ export class DdSdkConfiguration { readonly resourceTracingSamplingRate: number, readonly trackWatchdogTerminations: boolean | undefined, readonly batchProcessingLevel: BatchProcessingLevel, // eslint-disable-next-line no-empty-function - readonly initialResourceThreshold: number | undefined + readonly initialResourceThreshold: number | undefined, + readonly trackMemoryWarnings: boolean ) {} } From 87e16e56332e04f0a5ae87671bfb1bfdb242bc9f Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Mon, 3 Nov 2025 18:05:04 +0000 Subject: [PATCH 56/62] Expose `setAccountInfo` API to JS layer add account info to `applyEventMapper` --- .../datadog/reactnative/DatadogSDKWrapper.kt | 20 ++++- .../com/datadog/reactnative/DatadogWrapper.kt | 27 ++++++ .../reactnative/DdSdkImplementation.kt | 41 +++++++++ .../kotlin/com/datadog/reactnative/DdSdk.kt | 26 ++++++ .../kotlin/com/datadog/reactnative/DdSdk.kt | 26 ++++++ packages/core/ios/Sources/DdSdk.mm | 32 +++++++ .../ios/Sources/DdSdkImplementation.swift | 38 ++++++++ packages/core/jest/mock.js | 9 ++ packages/core/src/DdSdkReactNative.tsx | 66 ++++++++++++++ .../AccountInfoSingleton.ts | 46 ++++++++++ .../__tests__/AccountInfoSingleton.test.ts | 90 +++++++++++++++++++ .../src/sdk/AccountInfoSingleton/types.ts | 11 +++ .../core/src/sdk/EventMappers/EventMapper.ts | 5 ++ packages/core/src/specs/NativeDdSdk.ts | 17 ++++ packages/core/src/types.tsx | 27 ++++++ 15 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts create mode 100644 packages/core/src/sdk/AccountInfoSingleton/__tests__/AccountInfoSingleton.test.ts create mode 100644 packages/core/src/sdk/AccountInfoSingleton/types.ts diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt index 06151d834..56a15373c 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogSDKWrapper.kt @@ -89,7 +89,25 @@ internal class DatadogSDKWrapper : DatadogWrapper { override fun clearUserInfo() { Datadog.clearUserInfo() } - + + override fun setAccountInfo( + id: String, + name: String?, + extraInfo: Map + ) { + Datadog.setAccountInfo(id, name, extraInfo) + } + + override fun addAccountExtraInfo( + extraInfo: Map + ) { + Datadog.addAccountExtraInfo(extraInfo) + } + + override fun clearAccountInfo() { + Datadog.clearAccountInfo() + } + override fun addRumGlobalAttribute(key: String, value: Any?) { this.getRumMonitor().addAttribute(key, value) } diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt index d6395b18b..c72f2faef 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DatadogWrapper.kt @@ -91,6 +91,33 @@ interface DatadogWrapper { */ fun clearUserInfo() + /** + * Sets the account information. + * + * @param id a unique account identifier (relevant to your business domain) + * @param name (nullable) the account name + * @param extraInfo additional information. An extra information can be + * nested up to 8 levels deep. Keys using more than 8 levels will be sanitized by SDK. + */ + fun setAccountInfo( + id: String, + name: String?, + extraInfo: Map + ) + + /** + * Sets the account information. + * @param extraInfo: The additional information. (To set the id or name please use setAccountInfo). + */ + fun addAccountExtraInfo( + extraInfo: Map + ) + + /** + * Clears the account information. + */ + fun clearAccountInfo() + /** Adds a global attribute. * diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index f02395ed8..02123ee8f 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -168,6 +168,47 @@ class DdSdkImplementation( promise.resolve(null) } + /** + * Set the account information. + * @param accountInfo The account object (use builtin attributes: 'id', 'name', and any custom + * attribute inside 'extraInfo'). + */ + fun setAccountInfo(accountInfo: ReadableMap, promise: Promise) { + val accountInfoMap = accountInfo.toHashMap().toMutableMap() + val id = accountInfoMap["id"] as? String + val name = accountInfoMap["name"] as? String + val extraInfo = (accountInfoMap["extraInfo"] as? Map<*, *>)?.filterKeys { it is String } + ?.mapKeys { it.key as String } + ?.mapValues { it.value } ?: emptyMap() + + if (id != null) { + datadog.setAccountInfo(id, name, extraInfo) + } + + promise.resolve(null) + } + + /** + * Sets the account extra information. + * @param accountExtraInfo: The additional information. (To set the id or name please use setAccountInfo). + */ + fun addAccountExtraInfo( + accountExtraInfo: ReadableMap, promise: Promise + ) { + val extraInfoMap = accountExtraInfo.toHashMap().toMutableMap() + + datadog.addAccountExtraInfo(extraInfoMap) + promise.resolve(null) + } + + /** + * Clears the account information. + */ + fun clearAccountInfo(promise: Promise) { + datadog.clearAccountInfo() + promise.resolve(null) + } + /** * Set the tracking consent regarding the data collection. * @param trackingConsent Consent, which can take one of the following values: 'pending', diff --git a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt index a9d430081..421812545 100644 --- a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -106,6 +106,32 @@ class DdSdk( implementation.clearUserInfo(promise) } + /** + * Set the account information. + * @param account The account object (use builtin attributes: 'id', 'name', and any custom * attribute inside 'extraInfo'). + */ + @ReactMethod + override fun setAccountInfo(account: ReadableMap, promise: Promise) { + implementation.setAccountInfo(account, promise) + } + + /** + * Sets the account information. + * @param extraAccountInfo: The additional information. (To set the id or name please use setAccountInfo). + */ + @ReactMethod + override fun addAccountExtraInfo(extraInfo: ReadableMap, promise: Promise) { + implementation.addAccountExtraInfo(extraInfo, promise) + } + + /** + * Clears the account information. + */ + @ReactMethod + override fun clearAccountInfo(promise: Promise) { + implementation.clearAccountInfo(promise) + } + /** * Set the tracking consent regarding the data collection. * @param trackingConsent Consent, which can take one of the following values: 'pending', diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt index 958ba521b..ef91ca549 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdSdk.kt @@ -132,6 +132,32 @@ class DdSdk( implementation.clearUserInfo(promise) } + /** + * Set the account information. + * @param account The account object (use builtin attributes: 'id', 'name', and any custom * attribute inside 'extraInfo'). + */ + @ReactMethod + fun setAccountInfo(account: ReadableMap, promise: Promise) { + implementation.setAccountInfo(account, promise) + } + + /** + * Sets the account information. + * @param extraAccountInfo: The additional information. (To set the id or name please use setAccountInfo). + */ + @ReactMethod + fun addAccountExtraInfo(extraInfo: ReadableMap, promise: Promise) { + implementation.addAccountExtraInfo(extraInfo, promise) + } + + /** + * Clears the account information. + */ + @ReactMethod + fun clearAccountInfo(promise: Promise) { + implementation.clearAccountInfo(promise) + } + /** * Set the tracking consent regarding the data collection. * @param trackingConsent Consent, which can take one of the following values: 'pending', diff --git a/packages/core/ios/Sources/DdSdk.mm b/packages/core/ios/Sources/DdSdk.mm index 06736a69e..c05ac6a7c 100644 --- a/packages/core/ios/Sources/DdSdk.mm +++ b/packages/core/ios/Sources/DdSdk.mm @@ -79,6 +79,26 @@ + (void)initFromNative { [self clearUserInfo:resolve reject:reject]; } +RCT_REMAP_METHOD(setAccountInfo, withAccountInfo:(NSDictionary*)accountInfo + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self setAccountInfo:accountInfo resolve:resolve reject:reject]; +} + +RCT_REMAP_METHOD(addAccountExtraInfo, withAccountExtraInfo:(NSDictionary*)extraInfo + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self addAccountExtraInfo:extraInfo resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(clearAccountInfo:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self clearAccountInfo:resolve reject:reject]; +} + RCT_REMAP_METHOD(setTrackingConsent, withTrackingConsent:(NSString*)trackingConsent withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) @@ -191,6 +211,18 @@ -(void)addUserExtraInfo:(NSDictionary *)extraInfo resolve:(RCTPromiseResolveBloc [self.ddSdkImplementation addUserExtraInfoWithExtraInfo:extraInfo resolve:resolve reject:reject]; } +- (void)setAccountInfo:(NSDictionary *)accountInfo resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation setAccountInfoWithAccountInfo:accountInfo resolve:resolve reject:reject]; +} + +- (void)clearAccountInfo:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation clearAccountInfoWithResolve:resolve reject:reject]; +} + +-(void)addAccountExtraInfo:(NSDictionary *)extraInfo resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddSdkImplementation addAccountExtraInfoWithExtraInfo:extraInfo resolve:resolve reject:reject]; +} + - (void)sendTelemetryLog:(NSString *)message attributes:(NSDictionary *)attributes config:(NSDictionary *)config resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { [self.ddSdkImplementation sendTelemetryLogWithMessage:message attributes:attributes config:config resolve:resolve reject:reject]; } diff --git a/packages/core/ios/Sources/DdSdkImplementation.swift b/packages/core/ios/Sources/DdSdkImplementation.swift index 5b91039b3..db8c4e938 100644 --- a/packages/core/ios/Sources/DdSdkImplementation.swift +++ b/packages/core/ios/Sources/DdSdkImplementation.swift @@ -160,6 +160,44 @@ public class DdSdkImplementation: NSObject { resolve(nil) } + @objc + public func setAccountInfo( + accountInfo: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { + let castedAccountInfo = castAttributesToSwift(accountInfo) + let id = castedAccountInfo["id"] as? String + let name = castedAccountInfo["name"] as? String + var extraInfo: [AttributeKey: AttributeValue] = [:] + + if let extraInfoEncodable = castedAccountInfo["extraInfo"] as? AnyEncodable, + let extraInfoDict = extraInfoEncodable.value as? [String: Any] + { + extraInfo = castAttributesToSwift(extraInfoDict) + } + + if let validId = id { + Datadog.setAccountInfo(id: validId, name: name, extraInfo: extraInfo) + } + + resolve(nil) + } + + @objc + public func addAccountExtraInfo( + extraInfo: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock + ) { + let castedExtraInfo = castAttributesToSwift(extraInfo) + + Datadog.addAccountExtraInfo(castedExtraInfo) + resolve(nil) + } + + @objc + public func clearAccountInfo(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { + Datadog.clearAccountInfo() + resolve(nil) + } + @objc public func setTrackingConsent( trackingConsent: NSString, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock diff --git a/packages/core/jest/mock.js b/packages/core/jest/mock.js index 0dc9ec138..9f5ee2c41 100644 --- a/packages/core/jest/mock.js +++ b/packages/core/jest/mock.js @@ -36,6 +36,15 @@ module.exports = { clearUserInfo: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), + setAccountInfo: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + addAccountExtraInfo: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + clearAccountInfo: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), addAttribute: jest .fn() .mockImplementation(() => new Promise(resolve => resolve())), diff --git a/packages/core/src/DdSdkReactNative.tsx b/packages/core/src/DdSdkReactNative.tsx index b1ea4f4c1..e07ba4e34 100644 --- a/packages/core/src/DdSdkReactNative.tsx +++ b/packages/core/src/DdSdkReactNative.tsx @@ -30,6 +30,7 @@ import { DdRumErrorTracking } from './rum/instrumentation/DdRumErrorTracking'; import { DdBabelInteractionTracking } from './rum/instrumentation/interactionTracking/DdBabelInteractionTracking'; import { DdRumUserInteractionTracking } from './rum/instrumentation/interactionTracking/DdRumUserInteractionTracking'; import { DdRumResourceTracking } from './rum/instrumentation/resourceTracking/DdRumResourceTracking'; +import { AccountInfoSingleton } from './sdk/AccountInfoSingleton/AccountInfoSingleton'; import { AttributesSingleton } from './sdk/AttributesSingleton/AttributesSingleton'; import type { Attributes } from './sdk/AttributesSingleton/types'; import { registerNativeBridge } from './sdk/DatadogInternalBridge/DdSdkInternalNativeBridge'; @@ -299,6 +300,71 @@ export class DdSdkReactNative { UserInfoSingleton.getInstance().setUserInfo(updatedUserInfo); }; + /** + * Sets the account information. + * @param id: A mandatory unique account identifier (relevant to your business domain). + * @param name: The account name. + * @param extraInfo: Additional information. + * @returns a Promise. + */ + static setAccountInfo = async (accountInfo: { + id: string; + name?: string; + extraInfo?: Record; + }): Promise => { + InternalLog.log( + `Setting account ${JSON.stringify(accountInfo)}`, + SdkVerbosity.DEBUG + ); + + await DdSdk.setAccountInfo(accountInfo); + AccountInfoSingleton.getInstance().setAccountInfo(accountInfo); + }; + + /** + * Clears the account information. + * @returns a Promise. + */ + static clearAccountInfo = async (): Promise => { + InternalLog.log('Clearing account info', SdkVerbosity.DEBUG); + await DdSdk.clearAccountInfo(); + AccountInfoSingleton.getInstance().clearAccountInfo(); + }; + + /** + * Set the account information. + * @param extraAccountInfo: The additional information. (To set the id or name please use setAccountInfo). + * @returns a Promise. + */ + static addAccountExtraInfo = async ( + extraAccountInfo: Record + ): Promise => { + InternalLog.log( + `Adding extra account info ${JSON.stringify(extraAccountInfo)}`, + SdkVerbosity.DEBUG + ); + + const accountInfo = AccountInfoSingleton.getInstance().getAccountInfo(); + if (!accountInfo) { + InternalLog.log( + 'Skipped adding Account Extra Info: Account Info is currently undefined. An account ID must be set before adding extra info. Please call setAccountInfo() first.', + SdkVerbosity.WARN + ); + + return; + } + + const extraInfo = { + ...accountInfo.extraInfo, + ...extraAccountInfo + }; + + await DdSdk.addAccountExtraInfo(extraInfo); + AccountInfoSingleton.getInstance().addAccountExtraInfo( + extraAccountInfo + ); + }; + /** * Set the tracking consent regarding the data collection. * @param trackingConsent: One of TrackingConsent values. diff --git a/packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts b/packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts new file mode 100644 index 000000000..5f2be8dea --- /dev/null +++ b/packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts @@ -0,0 +1,46 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import type { AccountInfo } from './types'; + +class AccountInfoProvider { + private accountInfo: AccountInfo | undefined = undefined; + + setAccountInfo = (accountInfo: AccountInfo) => { + this.accountInfo = accountInfo; + }; + + addAccountExtraInfo = (extraInfo: AccountInfo['extraInfo']) => { + if (!this.accountInfo) { + return; + } + + this.accountInfo.extraInfo = { + ...this.accountInfo.extraInfo, + ...extraInfo + }; + }; + + getAccountInfo = (): AccountInfo | undefined => { + return this.accountInfo; + }; + + clearAccountInfo = () => { + this.accountInfo = undefined; + }; +} + +export class AccountInfoSingleton { + private static accountInfoProvider = new AccountInfoProvider(); + + static getInstance = (): AccountInfoProvider => { + return AccountInfoSingleton.accountInfoProvider; + }; + + static reset = () => { + AccountInfoSingleton.accountInfoProvider = new AccountInfoProvider(); + }; +} diff --git a/packages/core/src/sdk/AccountInfoSingleton/__tests__/AccountInfoSingleton.test.ts b/packages/core/src/sdk/AccountInfoSingleton/__tests__/AccountInfoSingleton.test.ts new file mode 100644 index 000000000..9af387619 --- /dev/null +++ b/packages/core/src/sdk/AccountInfoSingleton/__tests__/AccountInfoSingleton.test.ts @@ -0,0 +1,90 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import { AccountInfoSingleton } from '../AccountInfoSingleton'; + +describe('AccountInfoSingleton', () => { + beforeEach(() => { + AccountInfoSingleton.reset(); + }); + + it('returns undefined by default', () => { + expect( + AccountInfoSingleton.getInstance().getAccountInfo() + ).toBeUndefined(); + }); + + it('stores and returns account info after `setAccountInfo`', () => { + const info = { + id: 'test', + name: 'test user', + extraInfo: { premium: true } + }; + + AccountInfoSingleton.getInstance().setAccountInfo(info); + + expect(AccountInfoSingleton.getInstance().getAccountInfo()).toEqual( + info + ); + }); + + it('adds extra account info with `addAccountExtraInfo`', () => { + const info = { + id: 'test', + name: 'test user', + extraInfo: { premium: true } + }; + + AccountInfoSingleton.getInstance().setAccountInfo(info); + AccountInfoSingleton.getInstance().addAccountExtraInfo({ + testGroup: 'A' + }); + + expect(AccountInfoSingleton.getInstance().getAccountInfo()).toEqual({ + ...info, + extraInfo: { ...info.extraInfo, testGroup: 'A' } + }); + }); + + it('clears account info with `clearAccountInfo`', () => { + AccountInfoSingleton.getInstance().setAccountInfo({ + id: 'test', + name: 'test user', + extraInfo: { premium: true } + }); + + AccountInfoSingleton.getInstance().clearAccountInfo(); + + expect( + AccountInfoSingleton.getInstance().getAccountInfo() + ).toBeUndefined(); + }); + + it('`reset()` replaces the provider and clears stored account info', () => { + const instanceBefore = AccountInfoSingleton.getInstance(); + + AccountInfoSingleton.getInstance().setAccountInfo({ + id: 'test', + name: 'test user', + extraInfo: { premium: true } + }); + + AccountInfoSingleton.reset(); + + const instanceAfter = AccountInfoSingleton.getInstance(); + + expect(instanceAfter).not.toBe(instanceBefore); + + expect(instanceAfter.getAccountInfo()).toBeUndefined(); + }); + + it('getInstance returns the same provider between calls (singleton behavior)', () => { + const a = AccountInfoSingleton.getInstance(); + const b = AccountInfoSingleton.getInstance(); + + expect(a).toBe(b); + }); +}); diff --git a/packages/core/src/sdk/AccountInfoSingleton/types.ts b/packages/core/src/sdk/AccountInfoSingleton/types.ts new file mode 100644 index 000000000..1dceb0958 --- /dev/null +++ b/packages/core/src/sdk/AccountInfoSingleton/types.ts @@ -0,0 +1,11 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +export type AccountInfo = { + readonly id: string; + readonly name?: string; + extraInfo?: Record; +}; diff --git a/packages/core/src/sdk/EventMappers/EventMapper.ts b/packages/core/src/sdk/EventMappers/EventMapper.ts index 9ca252d72..e1cbaae19 100644 --- a/packages/core/src/sdk/EventMappers/EventMapper.ts +++ b/packages/core/src/sdk/EventMappers/EventMapper.ts @@ -7,6 +7,8 @@ import { InternalLog } from '../../InternalLog'; import { SdkVerbosity } from '../../SdkVerbosity'; import { DdSdk } from '../../sdk/DdSdk'; +import { AccountInfoSingleton } from '../AccountInfoSingleton/AccountInfoSingleton'; +import type { AccountInfo } from '../AccountInfoSingleton/types'; import { AttributesSingleton } from '../AttributesSingleton/AttributesSingleton'; import type { Attributes } from '../AttributesSingleton/types'; import { UserInfoSingleton } from '../UserInfoSingleton/UserInfoSingleton'; @@ -16,6 +18,7 @@ import { deepClone } from './utils/deepClone'; export type AdditionalEventDataForMapper = { userInfo?: UserInfo; + accountInfo?: AccountInfo; attributes: Attributes; }; @@ -66,9 +69,11 @@ export class EventMapper { // formatting const userInfo = UserInfoSingleton.getInstance().getUserInfo(); + const accountInfo = AccountInfoSingleton.getInstance().getAccountInfo(); const attributes = AttributesSingleton.getInstance().getAttributes(); const initialEvent = this.formatRawEventForMapper(rawEvent, { userInfo, + accountInfo, attributes }); diff --git a/packages/core/src/specs/NativeDdSdk.ts b/packages/core/src/specs/NativeDdSdk.ts index 70401fe3c..68c9c4711 100644 --- a/packages/core/src/specs/NativeDdSdk.ts +++ b/packages/core/src/specs/NativeDdSdk.ts @@ -67,6 +67,23 @@ export interface Spec extends TurboModule { */ addUserExtraInfo(extraInfo: Object): Promise; + /** + * Set the account information. + * @param account: The account object (use builtin attributes: 'id', 'name', and any custom attribute under extraInfo). + */ + setAccountInfo(account: Object): Promise; + + /** + * Clears the account information. + */ + clearAccountInfo(): Promise; + + /** + * Add custom attributes to the current account information + * @param extraInfo: The extraInfo object containing additional custom attributes + */ + addAccountExtraInfo(extraInfo: Object): Promise; + /** * Set the tracking consent regarding the data collection. * @param trackingConsent: Consent, which can take one of the following values: 'pending', 'granted', 'not_granted'. diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index 5c7d64cec..7f97779ee 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -129,6 +129,27 @@ export type DdSdkType = { */ addUserExtraInfo(extraUserInfo: Record): Promise; + /** + * Sets the account information. + * @param id: A unique account identifier (relevant to your business domain) + * @param name: The account name. + * @param extraInfo: Additional information. + */ + setAccountInfo(accountInfo: AccountInfo): Promise; + + /** + * Clears the account information. + */ + clearAccountInfo(): Promise; + + /** + * Add additional account information. + * @param extraAccountInfo: The additional information. (To set the id or name please use setAccountInfo). + */ + addAccountExtraInfo( + extraAccountInfo: Record + ): Promise; + /** * Set the tracking consent regarding the data collection. * @param trackingConsent: Consent, which can take one of the following values: 'pending', 'granted', 'not_granted'. @@ -176,6 +197,12 @@ export type UserInfo = { extraInfo?: object; }; +export type AccountInfo = { + id: string; + name?: string; + extraInfo?: object; +}; + // DdLogs export type LogStatus = 'debug' | 'info' | 'warn' | 'error'; From 5174d55b43e0384c8a73dacbabeabe13c1174452 Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Fri, 7 Nov 2025 14:49:40 +0000 Subject: [PATCH 57/62] Add `userId` and `accountId`to baggage headers Preserve user baggage header when setting session ID Enforced W3 specification for 'baggage' header Only inject Session ID header if propagator=Datadog|W3C Additional test for baggage header and minor warn message improvement --- packages/core/src/rum/DdRum.ts | 32 ++++++++------ packages/core/src/rum/__tests__/DdRum.test.ts | 2 +- packages/core/src/rum/helper.ts | 36 +++++++++++++++ .../distributedTracing/distributedTracing.tsx | 21 +++++++-- .../distributedTracingHeaders.ts | 44 ++++++++++++++++--- .../requestProxy/XHRProxy/XHRProxy.ts | 10 ++++- .../XHRProxy/__tests__/XHRProxy.test.ts | 2 +- .../XHRProxy/baggageHeaderUtils.ts | 36 +-------------- .../DdSdkInternalNativeBridge.tsx | 2 +- 9 files changed, 122 insertions(+), 63 deletions(-) create mode 100644 packages/core/src/rum/helper.ts diff --git a/packages/core/src/rum/DdRum.ts b/packages/core/src/rum/DdRum.ts index bedc6f33a..1f3703e63 100644 --- a/packages/core/src/rum/DdRum.ts +++ b/packages/core/src/rum/DdRum.ts @@ -20,12 +20,19 @@ import { getGlobalInstance } from '../utils/singletonUtils'; import { DefaultTimeProvider } from '../utils/time-provider/DefaultTimeProvider'; import type { TimeProvider } from '../utils/time-provider/TimeProvider'; -import { generateActionEventMapper } from './eventMappers/actionEventMapper'; import type { ActionEventMapper } from './eventMappers/actionEventMapper'; -import { generateErrorEventMapper } from './eventMappers/errorEventMapper'; +import { generateActionEventMapper } from './eventMappers/actionEventMapper'; import type { ErrorEventMapper } from './eventMappers/errorEventMapper'; -import { generateResourceEventMapper } from './eventMappers/resourceEventMapper'; +import { generateErrorEventMapper } from './eventMappers/errorEventMapper'; import type { ResourceEventMapper } from './eventMappers/resourceEventMapper'; +import { generateResourceEventMapper } from './eventMappers/resourceEventMapper'; +import { + clearCachedSessionId, + getCachedAccountId, + getCachedSessionId, + getCachedUserId, + setCachedSessionId +} from './helper'; import type { DatadogTracingContext } from './instrumentation/resourceTracking/distributedTracing/DatadogTracingContext'; import { DatadogTracingIdentifier } from './instrumentation/resourceTracking/distributedTracing/DatadogTracingIdentifier'; import { TracingIdentifier } from './instrumentation/resourceTracking/distributedTracing/TracingIdentifier'; @@ -33,17 +40,12 @@ import { getTracingContext, getTracingContextForPropagators } from './instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders'; -import { - clearCachedSessionId, - getCachedSessionId, - setCachedSessionId -} from './sessionId/sessionIdHelper'; import type { DdRumType, - RumActionType, - ResourceKind, FirstPartyHost, - PropagatorType + PropagatorType, + ResourceKind, + RumActionType } from './types'; const RUM_MODULE = 'com.datadog.reactnative.rum'; @@ -383,7 +385,9 @@ class DdRumWrapper implements DdRumType { url, tracingSamplingRate, firstPartyHosts, - getCachedSessionId() + getCachedSessionId(), + getCachedUserId(), + getCachedAccountId() ); }; @@ -394,7 +398,9 @@ class DdRumWrapper implements DdRumType { return getTracingContextForPropagators( propagators, tracingSamplingRate, - getCachedSessionId() + getCachedSessionId(), + getCachedUserId(), + getCachedAccountId() ); }; diff --git a/packages/core/src/rum/__tests__/DdRum.test.ts b/packages/core/src/rum/__tests__/DdRum.test.ts index 41b873fe9..e4318322b 100644 --- a/packages/core/src/rum/__tests__/DdRum.test.ts +++ b/packages/core/src/rum/__tests__/DdRum.test.ts @@ -17,11 +17,11 @@ import { DdRum } from '../DdRum'; import type { ActionEventMapper } from '../eventMappers/actionEventMapper'; import type { ErrorEventMapper } from '../eventMappers/errorEventMapper'; import type { ResourceEventMapper } from '../eventMappers/resourceEventMapper'; +import { setCachedSessionId } from '../helper'; import { DatadogTracingContext } from '../instrumentation/resourceTracking/distributedTracing/DatadogTracingContext'; import { DatadogTracingIdentifier } from '../instrumentation/resourceTracking/distributedTracing/DatadogTracingIdentifier'; import { TracingIdFormat } from '../instrumentation/resourceTracking/distributedTracing/TracingIdentifier'; import { TracingIdentifierUtils } from '../instrumentation/resourceTracking/distributedTracing/__tests__/__utils__/TracingIdentifierUtils'; -import { setCachedSessionId } from '../sessionId/sessionIdHelper'; import type { FirstPartyHost } from '../types'; import { PropagatorType, RumActionType } from '../types'; diff --git a/packages/core/src/rum/helper.ts b/packages/core/src/rum/helper.ts new file mode 100644 index 000000000..a153b79b5 --- /dev/null +++ b/packages/core/src/rum/helper.ts @@ -0,0 +1,36 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ +let _cachedSessionId: string | undefined; +let _cachedUserId: string | undefined; +let _cachedAccountId: string | undefined; + +export const getCachedSessionId = () => { + return _cachedSessionId; +}; + +export const setCachedSessionId = (sessionId: string) => { + _cachedSessionId = sessionId; +}; + +export const clearCachedSessionId = () => { + _cachedSessionId = undefined; +}; + +export const getCachedUserId = () => { + return _cachedUserId; +}; + +export const setCachedUserId = (userId: string) => { + _cachedUserId = userId; +}; + +export const getCachedAccountId = () => { + return _cachedAccountId; +}; + +export const setCachedAccountId = (accountId: string) => { + _cachedAccountId = accountId; +}; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx index 9c4fcbff7..2ebb98233 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracing.tsx @@ -26,6 +26,9 @@ export type DdRumResourceTracingAttributes = rulePsr: number; propagatorTypes: PropagatorType[]; rumSessionId?: string; + userId?: string; + accountId?: string; + baggageHeaders?: Set; } | { tracingStrategy: 'DISCARD'; @@ -43,12 +46,16 @@ export const getTracingAttributes = ({ hostname, firstPartyHostsRegexMap, tracingSamplingRate, - rumSessionId + rumSessionId, + userId, + accountId }: { hostname: Hostname | null; firstPartyHostsRegexMap: RegexMap; tracingSamplingRate: number; rumSessionId?: string; + userId?: string; + accountId?: string; }): DdRumResourceTracingAttributes => { if (hostname === null) { return DISCARDED_TRACE_ATTRIBUTES; @@ -61,7 +68,9 @@ export const getTracingAttributes = ({ return generateTracingAttributesWithSampling( tracingSamplingRate, propagatorsForHost, - rumSessionId + rumSessionId, + userId, + accountId ); } return DISCARDED_TRACE_ATTRIBUTES; @@ -70,7 +79,9 @@ export const getTracingAttributes = ({ export const generateTracingAttributesWithSampling = ( tracingSamplingRate: number, propagatorTypes: PropagatorType[], - rumSessionId?: string + rumSessionId?: string, + userId?: string, + accountId?: string ): DdRumResourceTracingAttributes => { if (!propagatorTypes || propagatorTypes.length === 0) { return DISCARDED_TRACE_ATTRIBUTES; @@ -93,7 +104,9 @@ export const generateTracingAttributesWithSampling = ( tracingStrategy: 'KEEP', rulePsr: tracingSamplingRate / 100, propagatorTypes, - rumSessionId + rumSessionId, + userId, + accountId }; return tracingAttributes; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts index 8bfaec669..8ad9137c7 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/distributedTracing/distributedTracingHeaders.ts @@ -1,6 +1,5 @@ /* - * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. - * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. This product includes software developed at Datadog (https://www.datadoghq.com/). * Copyright 2016-Present Datadog, Inc. */ @@ -29,6 +28,8 @@ export const PARENT_ID_HEADER_KEY = 'x-datadog-parent-id'; export const TAGS_HEADER_KEY = 'x-datadog-tags'; export const DD_TRACE_ID_TAG = '_dd.p.tid'; export const DD_RUM_SESSION_ID_TAG = 'session.id'; +export const DD_RUM_USER_ID_TAG = 'user.id'; +export const DD_RUM_ACCOUNT_ID_TAG = 'account.id'; /** * OTel headers @@ -143,6 +144,29 @@ export const getTracingHeadersFromAttributes = ( } }); + if (hasDatadogOrW3CPropagator) { + if (tracingAttributes.rumSessionId) { + headers.push({ + header: BAGGAGE_HEADER_KEY, + value: `${DD_RUM_SESSION_ID_TAG}=${tracingAttributes.rumSessionId}` + }); + } + + if (tracingAttributes.userId) { + headers.push({ + header: BAGGAGE_HEADER_KEY, + value: `${DD_RUM_USER_ID_TAG}=${tracingAttributes.userId}` + }); + } + + if (tracingAttributes.accountId) { + headers.push({ + header: BAGGAGE_HEADER_KEY, + value: `${DD_RUM_ACCOUNT_ID_TAG}=${tracingAttributes.accountId}` + }); + } + } + if (hasDatadogOrW3CPropagator && tracingAttributes.rumSessionId) { headers.push({ header: BAGGAGE_HEADER_KEY, @@ -157,7 +181,9 @@ export const getTracingContext = ( url: string, tracingSamplingRate: number, firstPartyHosts: FirstPartyHost[], - rumSessionId?: string + rumSessionId?: string, + userId?: string, + accountId?: string ): DatadogTracingContext => { const hostname = URLHostParser(url); const firstPartyHostsRegexMap = firstPartyHostsRegexMapBuilder( @@ -167,7 +193,9 @@ export const getTracingContext = ( hostname, firstPartyHostsRegexMap, tracingSamplingRate, - rumSessionId + rumSessionId, + userId, + accountId }); return getTracingContextForAttributes( @@ -179,13 +207,17 @@ export const getTracingContext = ( export const getTracingContextForPropagators = ( propagators: PropagatorType[], tracingSamplingRate: number, - rumSessionId?: string + rumSessionId?: string, + userId?: string, + accountId?: string ): DatadogTracingContext => { return getTracingContextForAttributes( generateTracingAttributesWithSampling( tracingSamplingRate, propagators, - rumSessionId + rumSessionId, + userId, + accountId ), tracingSamplingRate ); diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts index d48c4f01a..723ace5ed 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts @@ -5,7 +5,11 @@ */ import { Timer } from '../../../../../utils/Timer'; -import { getCachedSessionId } from '../../../../sessionId/sessionIdHelper'; +import { + getCachedAccountId, + getCachedSessionId, + getCachedUserId +} from '../../../../helper'; import { BAGGAGE_HEADER_KEY, getTracingHeadersFromAttributes @@ -115,7 +119,9 @@ const proxyOpen = ( hostname, firstPartyHostsRegexMap, tracingSamplingRate, - rumSessionId: getCachedSessionId() + rumSessionId: getCachedSessionId(), + userId: getCachedUserId(), + accountId: getCachedAccountId() }), baggageHeaderEntries: new Set() }; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts index cfc5e0178..048dbadec 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts @@ -11,7 +11,7 @@ import { InternalLog } from '../../../../../../InternalLog'; import { SdkVerbosity } from '../../../../../../SdkVerbosity'; import { BufferSingleton } from '../../../../../../sdk/DatadogProvider/Buffer/BufferSingleton'; import { DdRum } from '../../../../../DdRum'; -import { setCachedSessionId } from '../../../../../sessionId/sessionIdHelper'; +import { setCachedSessionId } from '../../../../../helper'; import { PropagatorType } from '../../../../../types'; import { XMLHttpRequestMock } from '../../../__tests__/__utils__/XMLHttpRequestMock'; import { TracingIdentifierUtils } from '../../../distributedTracing/__tests__/__utils__/TracingIdentifierUtils'; diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts index dccae9ddf..7094ec4e8 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts @@ -110,7 +110,7 @@ export function formatBaggageHeader(entries: Set): string | null { } const headerValue = formattedParts.join(','); - const byteLength = utf8ByteLength(headerValue); + const byteLength = Buffer.byteLength(headerValue, 'utf8'); if (byteLength > MAX_BYTES) { InternalLog.log( @@ -122,40 +122,6 @@ export function formatBaggageHeader(entries: Set): string | null { return headerValue; } -/** - * Returns the number of bytes needed to encode a string in UTF-8. - * - * Useful as a lightweight alternative to Node.js `Buffer.byteLength()` - * for older environments that do not support it. - * - * @param text - The input string. - * @returns The UTF-8 byte length of the string. - */ -function utf8ByteLength(text: string): number { - let byteLength = text.length; - for (let i = text.length - 1; i >= 0; i--) { - const code = text.charCodeAt(i); - - // 2-byte characters (U+0080 to U+07FF) - if (code > 0x7f && code <= 0x7ff) { - byteLength++; - } - // 3-byte characters (U+0800 to U+FFFF) - else if (code > 0x7ff && code <= 0xffff) { - byteLength += 2; - } - - // Handle surrogate pairs (4-byte characters, e.g. emoji) - // These characters already count as 2 in the initial length - // Encountering the low surrogate already accounts for the full 4 bytes - // (2 from the initial length + 2 for the 3-byte characters logic above) - if (code >= 0xdc00 && code <= 0xdfff) { - i--; // prevents double counting the same character by skipping high surrogate - } - } - return byteLength; -} - /** * Returns a set of valid baggage header characters. */ diff --git a/packages/core/src/sdk/DatadogInternalBridge/DdSdkInternalNativeBridge.tsx b/packages/core/src/sdk/DatadogInternalBridge/DdSdkInternalNativeBridge.tsx index bbae2cd12..34a1e623a 100644 --- a/packages/core/src/sdk/DatadogInternalBridge/DdSdkInternalNativeBridge.tsx +++ b/packages/core/src/sdk/DatadogInternalBridge/DdSdkInternalNativeBridge.tsx @@ -5,7 +5,7 @@ */ import { InternalLog } from '../../InternalLog'; import { SdkVerbosity } from '../../SdkVerbosity'; -import { setCachedSessionId } from '../../rum/sessionId/sessionIdHelper'; +import { setCachedSessionId } from '../../rum/helper'; import { DatadogDefaultEventEmitter } from '../DatadogEventEmitter/DatadogDefaultEventEmitter'; import type { DatadogEventEmitter } from '../DatadogEventEmitter/DatadogEventEmitter'; From 3e8503610f75fba918f7663c3c99a4a72000694c Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Thu, 13 Nov 2025 17:24:34 +0000 Subject: [PATCH 58/62] Cache `userId` and `accountId` when first set --- .../requestProxy/XHRProxy/__tests__/XHRProxy.test.ts | 10 +++++++++- .../sdk/AccountInfoSingleton/AccountInfoSingleton.ts | 3 +++ .../src/sdk/UserInfoSingleton/UserInfoSingleton.ts | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts index 048dbadec..a18825771 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/__tests__/XHRProxy.test.ts @@ -11,7 +11,11 @@ import { InternalLog } from '../../../../../../InternalLog'; import { SdkVerbosity } from '../../../../../../SdkVerbosity'; import { BufferSingleton } from '../../../../../../sdk/DatadogProvider/Buffer/BufferSingleton'; import { DdRum } from '../../../../../DdRum'; -import { setCachedSessionId } from '../../../../../helper'; +import { + setCachedSessionId, + setCachedUserId, + setCachedAccountId +} from '../../../../../helper'; import { PropagatorType } from '../../../../../types'; import { XMLHttpRequestMock } from '../../../__tests__/__utils__/XMLHttpRequestMock'; import { TracingIdentifierUtils } from '../../../distributedTracing/__tests__/__utils__/TracingIdentifierUtils'; @@ -90,6 +94,10 @@ afterEach(() => { (Date.now as jest.MockedFunction).mockClear(); jest.spyOn(global.Math, 'random').mockRestore(); DdRum.unregisterResourceEventMapper(); + + setCachedSessionId(undefined as any); + setCachedUserId(undefined as any); + setCachedAccountId(undefined as any); }); describe('XHRProxy', () => { diff --git a/packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts b/packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts index 5f2be8dea..439c1493a 100644 --- a/packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts +++ b/packages/core/src/sdk/AccountInfoSingleton/AccountInfoSingleton.ts @@ -4,6 +4,8 @@ * Copyright 2016-Present Datadog, Inc. */ +import { setCachedAccountId } from '../../rum/helper'; + import type { AccountInfo } from './types'; class AccountInfoProvider { @@ -11,6 +13,7 @@ class AccountInfoProvider { setAccountInfo = (accountInfo: AccountInfo) => { this.accountInfo = accountInfo; + setCachedAccountId(this.accountInfo.id); }; addAccountExtraInfo = (extraInfo: AccountInfo['extraInfo']) => { diff --git a/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts b/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts index 3ce23614b..2408fdbf2 100644 --- a/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts +++ b/packages/core/src/sdk/UserInfoSingleton/UserInfoSingleton.ts @@ -4,6 +4,8 @@ * Copyright 2016-Present Datadog, Inc. */ +import { setCachedUserId } from '../../rum/helper'; + import type { UserInfo } from './types'; class UserInfoProvider { @@ -11,6 +13,7 @@ class UserInfoProvider { setUserInfo = (userInfo: UserInfo) => { this.userInfo = userInfo; + setCachedUserId(this.userInfo.id); }; getUserInfo = (): UserInfo | undefined => { From fcabd0503266d0a2a8b79e9e4b7dab89a71a4772 Mon Sep 17 00:00:00 2001 From: Carlos Nogueira Date: Fri, 21 Nov 2025 11:20:51 +0000 Subject: [PATCH 59/62] Integrate Feature Operations into `core` SDK --- packages/codepush/__mocks__/react-native.ts | 11 +++- packages/core/__mocks__/react-native.ts | 11 +++- .../reactnative/DdRumImplementation.kt | 54 ++++++++++++++++ .../kotlin/com/datadog/reactnative/DdRum.kt | 63 ++++++++++++++++++- .../kotlin/com/datadog/reactnative/DdRum.kt | 56 +++++++++++++++++ packages/core/ios/Sources/DdRum.mm | 43 +++++++++++++ .../ios/Sources/DdRumImplementation.swift | 51 +++++++++++++++ packages/core/jest/mock.js | 9 +++ packages/core/src/index.tsx | 3 +- packages/core/src/rum/DdRum.ts | 54 +++++++++++++++- packages/core/src/rum/types.ts | 42 ++++++++++++- packages/core/src/specs/NativeDdRum.ts | 40 ++++++++++++ packages/core/src/types.tsx | 6 ++ .../__mocks__/react-native.ts | 11 +++- 14 files changed, 447 insertions(+), 7 deletions(-) diff --git a/packages/codepush/__mocks__/react-native.ts b/packages/codepush/__mocks__/react-native.ts index 0c8189840..a87659170 100644 --- a/packages/codepush/__mocks__/react-native.ts +++ b/packages/codepush/__mocks__/react-native.ts @@ -119,7 +119,16 @@ actualRN.NativeModules.DdRum = { new Promise(resolve => resolve('test-session-id') ) - ) as jest.MockedFunction + ) as jest.MockedFunction, + startFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + succeedFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + failFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction }; module.exports = actualRN; diff --git a/packages/core/__mocks__/react-native.ts b/packages/core/__mocks__/react-native.ts index 73308f711..a4622b6b9 100644 --- a/packages/core/__mocks__/react-native.ts +++ b/packages/core/__mocks__/react-native.ts @@ -155,7 +155,16 @@ actualRN.NativeModules.DdRum = { new Promise(resolve => resolve('test-session-id') ) - ) as jest.MockedFunction + ) as jest.MockedFunction, + startFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + succeedFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + failFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction }; module.exports = actualRN; diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt index 4e3cd416f..67a299f36 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdRumImplementation.kt @@ -12,6 +12,7 @@ import com.datadog.android.rum.RumAttributes import com.datadog.android.rum.RumErrorSource import com.datadog.android.rum.RumResourceKind import com.datadog.android.rum.RumResourceMethod +import com.datadog.android.rum.featureoperations.FailureReason import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap @@ -333,6 +334,59 @@ class DdRumImplementation(private val datadog: DatadogWrapper = DatadogSDKWrappe } } + /** + * Starts a Feature Operation. + * + * @param name Human-readable operation name (e.g., "login_flow"). + * @param operationKey Optional key that uniquely identifies this operation instance. + * @param attributes Additional attributes to attach to the operation. + * @param promise Resolved with `null` when the call completes. + */ + fun startFeatureOperation(name: String, operationKey: String? = null, attributes: ReadableMap, promise: Promise) { + val attributesMap = attributes.toHashMap().toMutableMap() + datadog.getRumMonitor().startFeatureOperation(name, operationKey, attributesMap); + promise.resolve(null) + } + + /** + * Marks a Feature Operation as successfully completed. + * + * @param name The name of the feature operation (for example, `"login_flow"`). + * @param operationKey The key of the operation instance to complete, if one was provided when starting it. + * @param attributes A map of custom attributes to attach to this completion event. + */ + fun succeedFeatureOperation(name: String, operationKey: String? = null, attributes: ReadableMap, promise: Promise) { + val attributesMap = attributes.toHashMap().toMutableMap() + datadog.getRumMonitor().succeedFeatureOperation(name, operationKey, attributesMap) + promise.resolve(null) + } + + + /** + * Marks a Feature Operation as failed. + * + * @param name The name of the feature operation (for example, `"login_flow"`). + * @param operationKey The key of the operation instance to fail, if one was provided when starting it. + * @param failureReason The reason for the failure. Possible values are defined in [FailureReason] + * (e.g., `FailureReason.ERROR`, `FailureReason.ABANDONED`, `FailureReason.OTHER`). + * @param attributes A map of custom attributes to attach to this failure event. + */ + fun failFeatureOperation( + name: String, + operationKey: String? = null, + failureReason: String, + attributes: ReadableMap, + promise: Promise + ) { + val attributesMap = attributes.toHashMap().toMutableMap() + val reason = runCatching { + enumValueOf(failureReason.uppercase()) + }.getOrDefault(FailureReason.OTHER) + + datadog.getRumMonitor().failFeatureOperation(name, operationKey, reason, attributesMap) + promise.resolve(null) + } + // region Internal private fun String.asRumActionType(): RumActionType { diff --git a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt index 6cb2b385b..30788acff 100644 --- a/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt +++ b/packages/core/android/src/newarch/kotlin/com/datadog/reactnative/DdRum.kt @@ -6,6 +6,7 @@ package com.datadog.reactnative +import com.datadog.android.rum.featureoperations.FailureReason import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactMethod @@ -52,7 +53,12 @@ class DdRum( * If not provided, current timestamp will be used. */ @ReactMethod - override fun stopView(key: String, context: ReadableMap, timestampMs: Double, promise: Promise) { + override fun stopView( + key: String, + context: ReadableMap, + timestampMs: Double, + promise: Promise + ) { implementation.stopView(key, context, timestampMs, promise) } @@ -276,4 +282,59 @@ class DdRum( override fun getCurrentSessionId(promise: Promise) { implementation.getCurrentSessionId(promise) } + + /** + * Starts a RUM Feature Operation. + * + * @param name Human-readable operation name (e.g., "login_flow"). + * @param operationKey Optional key that uniquely identifies this operation instance. + * @param attributes Additional attributes to attach to the operation. + * @param promise Resolved with `null` when the call completes. + */ + @ReactMethod + override fun startFeatureOperation( + name: String, + operationKey: String?, + attributes: ReadableMap, + promise: Promise + ) { + implementation.startFeatureOperation(name, operationKey, attributes, promise) + } + + /** + * Marks a Feature Operation as successfully completed. + * + * @param name The name of the feature operation (for example, `"login_flow"`). + * @param operationKey The key of the operation instance to complete, if one was provided when starting it. + * @param attributes A map of custom attributes to attach to this completion event. + */ + @ReactMethod + override fun succeedFeatureOperation( + name: String, + operationKey: String?, + attributes: ReadableMap, + promise: Promise + ) { + implementation.succeedFeatureOperation(name, operationKey, attributes, promise) + } + + /** + * Marks a Feature Operation as failed. + * + * @param name The name of the feature operation (for example, `"login_flow"`). + * @param operationKey The key of the operation instance to fail, if one was provided when starting it. + * @param failureReason The reason for the failure. Possible values are defined in [FailureReason] + * (e.g., `FailureReason.ERROR`, `FailureReason.ABANDONED`, `FailureReason.OTHER`). + * @param attributes A map of custom attributes to attach to this failure event. + */ + @ReactMethod + override fun failFeatureOperation( + name: String, + operationKey: String?, + failureReason: String, + attributes: ReadableMap, + promise: Promise + ) { + implementation.failFeatureOperation(name, operationKey, failureReason, attributes, promise) + } } diff --git a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt index a6c4965ea..4ef8409b2 100644 --- a/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt +++ b/packages/core/android/src/oldarch/kotlin/com/datadog/reactnative/DdRum.kt @@ -6,6 +6,7 @@ package com.datadog.reactnative +import com.datadog.android.rum.featureoperations.FailureReason import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule @@ -266,4 +267,59 @@ class DdRum( fun getCurrentSessionId(promise: Promise) { implementation.getCurrentSessionId(promise) } + + /** + * Starts a RUM Feature Operation. + * + * @param name Human-readable operation name (e.g., "login_flow"). + * @param operationKey Optional key that uniquely identifies this operation instance. + * @param attributes Additional attributes to attach to the operation. + * @param promise Resolved with `null` when the call completes. + */ + @ReactMethod + fun startFeatureOperation( + name: String, + operationKey: String? = null, + attributes: ReadableMap, + promise: Promise + ) { + implementation.startFeatureOperation(name, operationKey, attributes, promise) + } + + /** + * Marks a Feature Operation as successfully completed. + * + * @param name The name of the feature operation (for example, "login_flow"). + * @param operationKey The key of the operation instance to complete, if one was provided. + * @param attributes A map of custom attributes to attach to this completion event. + */ + @ReactMethod + fun succeedFeatureOperation( + name: String, + operationKey: String? = null, + attributes: ReadableMap, + promise: Promise + ) { + implementation.succeedFeatureOperation(name, operationKey, attributes, promise) + } + + /** + * Marks a Feature Operation as failed. + * + * @param name The name of the feature operation (for example, "login_flow"). + * @param operationKey The key of the operation instance to fail, if one was provided. + * @param failureReason The reason for the failure. Values are defined in [FailureReason] + * (e.g., `FailureReason.ERROR`, `FailureReason.ABANDONED`, `FailureReason.OTHER`). + * @param attributes A map of custom attributes to attach to this failure event. + */ + @ReactMethod + fun failFeatureOperation( + name: String, + operationKey: String? = null, + failureReason: String, + attributes: ReadableMap, + promise: Promise + ) { + implementation.failFeatureOperation(name, operationKey, failureReason, attributes, promise) + } } diff --git a/packages/core/ios/Sources/DdRum.mm b/packages/core/ios/Sources/DdRum.mm index f5c324ce8..c891537f3 100644 --- a/packages/core/ios/Sources/DdRum.mm +++ b/packages/core/ios/Sources/DdRum.mm @@ -164,6 +164,37 @@ @implementation DdRum [self getCurrentSessionId:resolve reject:reject]; } +RCT_REMAP_METHOD(startFeatureOperation, + startWithName:(NSString*)name + withOperationKey:(NSString*)operationKey + withAttributes:(NSDictionary*)attributes + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self startFeatureOperation:name operationKey:operationKey attributes:attributes resolve:resolve reject:reject]; +} + +RCT_REMAP_METHOD(succeedFeatureOperation, + succeedWithName:(NSString*)name + withOperationKey:(NSString*)operationKey + withAttributes:(NSDictionary*)attributes + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self succeedFeatureOperation:name operationKey:operationKey attributes:attributes resolve:resolve reject:reject]; +} + +RCT_REMAP_METHOD(failFeatureOperation, + failWithName:(NSString*)name + withOperationKey:(NSString*)operationKey + withReason:(NSString*)reason + withAttributes:(NSDictionary*)attributes + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self failFeatureOperation:name operationKey:operationKey reason:reason attributes:attributes resolve:resolve reject:reject]; +} + // Thanks to this guard, we won't compile this code when we build for the old architecture. #ifdef RCT_NEW_ARCH_ENABLED - (std::shared_ptr)getTurboModule: @@ -257,4 +288,16 @@ - (void)stopView:(NSString *)key context:(NSDictionary *)context timestampMs:(do [self.ddRumImplementation stopViewWithKey:key context:context timestampMs:timestampMs resolve:resolve reject:reject]; } +- (void) startFeatureOperation:(NSString *)name operationKey:(NSString *)operationKey attributes:(NSDictionary *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddRumImplementation startFeatureOperationWithName:name operationKey:operationKey attributes:attributes resolve:resolve reject:reject]; +} + +- (void) succeedFeatureOperation:(NSString *)name operationKey:(NSString *)operationKey attributes:(NSDictionary *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddRumImplementation succeedFeatureOperationWithName:name operationKey:operationKey attributes:attributes resolve:resolve reject:reject]; +} + +- (void) failFeatureOperation:(NSString *)name operationKey:(NSString *)operationKey reason:(NSString *)reason attributes:(NSDictionary *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.ddRumImplementation failFeatureOperationWithName:name operationKey:operationKey reason:reason attributes:attributes resolve:resolve reject:reject]; +} + @end diff --git a/packages/core/ios/Sources/DdRumImplementation.swift b/packages/core/ios/Sources/DdRumImplementation.swift index 6fac21f82..0ac8a19bf 100644 --- a/packages/core/ios/Sources/DdRumImplementation.swift +++ b/packages/core/ios/Sources/DdRumImplementation.swift @@ -63,6 +63,16 @@ private extension RUMMethod { } } +internal extension RUMFeatureOperationFailureReason { + init(from string: String) { + switch string.lowercased() { + case "error": self = .error + case "abandoned": self = .abandoned + default: self = .other + } + } +} + @objc public class DdRumImplementation: NSObject { internal static let timestampKey = "_dd.timestamp" @@ -236,6 +246,47 @@ public class DdRumImplementation: NSObject { resolve(sessionId) } } + + @objc + public func startFeatureOperation( + name: String, + operationKey: String?, + attributes: NSDictionary, + resolve: @escaping (Any?) -> Void, + reject: RCTPromiseRejectBlock + ){ + let castedAttributes = castAttributesToSwift(attributes) + nativeRUM.startFeatureOperation(name: name, operationKey: operationKey, attributes: castedAttributes) + resolve(nil) + } + + @objc + public func succeedFeatureOperation( + name: String, + operationKey: String?, + attributes: NSDictionary, + resolve: @escaping (Any?) -> Void, + reject: RCTPromiseRejectBlock + ){ + let castedAttributes = castAttributesToSwift(attributes) + nativeRUM.succeedFeatureOperation(name: name, operationKey: operationKey, attributes: castedAttributes) + resolve(nil) + } + + @objc + public func failFeatureOperation( + name: String, + operationKey: String?, + reason: String, + attributes: NSDictionary, + resolve: @escaping (Any?) -> Void, + reject: RCTPromiseRejectBlock + ){ + let castedAttributes = castAttributesToSwift(attributes) + nativeRUM.failFeatureOperation(name: name, operationKey: operationKey, + reason: RUMFeatureOperationFailureReason(from: reason), attributes: castedAttributes) + resolve(nil) + } // MARK: - Private methods diff --git a/packages/core/jest/mock.js b/packages/core/jest/mock.js index 9f5ee2c41..aadc79d27 100644 --- a/packages/core/jest/mock.js +++ b/packages/core/jest/mock.js @@ -154,6 +154,15 @@ module.exports = { .mockImplementation( () => new Promise(resolve => resolve('test-session-id')) ), + startFeatureOperation: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + succeedFeatureOperation: jest + .fn() + .mockImplementation(() => new Promise(resolve => resolve())), + failFeatureOperation: jest + .fn() + .mockImplementation(() => new Promise() < (resolve => resolve())), setTimeProvider: jest.fn().mockImplementation(() => {}), timeProvider: jest.fn().mockReturnValue(undefined), getTracingContext: jest.fn().mockReturnValue(undefined), diff --git a/packages/core/src/index.tsx b/packages/core/src/index.tsx index 062fecc90..ce39c9dfa 100644 --- a/packages/core/src/index.tsx +++ b/packages/core/src/index.tsx @@ -42,7 +42,7 @@ import { DatadogProvider } from './sdk/DatadogProvider/DatadogProvider'; import { DdSdk } from './sdk/DdSdk'; import { FileBasedConfiguration } from './sdk/FileBasedConfiguration/FileBasedConfiguration'; import { DdTrace } from './trace/DdTrace'; -import { ErrorSource } from './types'; +import { ErrorSource, FeatureOperationFailure } from './types'; import { DefaultTimeProvider } from './utils/time-provider/DefaultTimeProvider'; import type { Timestamp } from './utils/time-provider/TimeProvider'; import { TimeProvider } from './utils/time-provider/TimeProvider'; @@ -57,6 +57,7 @@ export { DdRum, RumActionType, ErrorSource, + FeatureOperationFailure, DdSdkReactNativeConfiguration, DdSdkReactNative, DdSdk, diff --git a/packages/core/src/rum/DdRum.ts b/packages/core/src/rum/DdRum.ts index 1f3703e63..3ae7c10ce 100644 --- a/packages/core/src/rum/DdRum.ts +++ b/packages/core/src/rum/DdRum.ts @@ -13,7 +13,7 @@ import type { Attributes } from '../sdk/AttributesSingleton/types'; import { bufferVoidNativeCall } from '../sdk/DatadogProvider/Buffer/bufferNativeCall'; import { DdSdk } from '../sdk/DdSdk'; import { GlobalState } from '../sdk/GlobalState/GlobalState'; -import type { ErrorSource } from '../types'; +import type { ErrorSource, FeatureOperationFailure } from '../types'; import { validateContext } from '../utils/argsUtils'; import { getErrorContext } from '../utils/errorUtils'; import { getGlobalInstance } from '../utils/singletonUtils'; @@ -133,6 +133,58 @@ class DdRumWrapper implements DdRumType { return this.callNativeStopAction(...nativeCallArgs); }; + startFeatureOperation( + name: string, + operationKey: string | null, + attributes: object + ): Promise { + InternalLog.log( + `Starting feature operation “${name}” (${operationKey})`, + SdkVerbosity.DEBUG + ); + return bufferVoidNativeCall(() => + this.nativeRum.startFeatureOperation(name, operationKey, attributes) + ); + } + + succeedFeatureOperation( + name: string, + operationKey: string | null, + attributes: object + ): Promise { + InternalLog.log( + `Succeding feature operation “${name}” (${operationKey})`, + SdkVerbosity.DEBUG + ); + return bufferVoidNativeCall(() => + this.nativeRum.succeedFeatureOperation( + name, + operationKey, + attributes + ) + ); + } + + failFeatureOperation( + name: string, + operationKey: string | null, + reason: FeatureOperationFailure, + attributes: object + ): Promise { + InternalLog.log( + `Failing feature operation “${name}” (${operationKey})`, + SdkVerbosity.DEBUG + ); + return bufferVoidNativeCall(() => + this.nativeRum.failFeatureOperation( + name, + operationKey, + reason, + attributes + ) + ); + } + setTimeProvider = (timeProvider: TimeProvider): void => { this.timeProvider = timeProvider; }; diff --git a/packages/core/src/rum/types.ts b/packages/core/src/rum/types.ts index 3def7f0e6..b879010f7 100644 --- a/packages/core/src/rum/types.ts +++ b/packages/core/src/rum/types.ts @@ -5,7 +5,7 @@ */ import type { Attributes } from '../sdk/AttributesSingleton/types'; -import type { ErrorSource } from '../types'; +import type { ErrorSource, FeatureOperationFailure } from '../types'; import type { DatadogTracingContext } from './instrumentation/resourceTracking/distributedTracing/DatadogTracingContext'; import type { DatadogTracingIdentifier } from './instrumentation/resourceTracking/distributedTracing/DatadogTracingIdentifier'; @@ -230,6 +230,46 @@ export type DdRumType = { * Generates a unique 128bit Span ID. */ generateSpanId(): DatadogTracingIdentifier; + + /** + * Starts a Feature Operation, representing a high-level logical flow within your application (e.g., `login_flow`). + * @param name - The name of the feature operation (for example, `"login_flow"`). + * @param operationKey - An optional key to uniquely identify a specific instance of this operation when multiple are running concurrently. + * @param attributes - Custom attributes to attach to this operation. + */ + startFeatureOperation( + name: string, + operationKey: string | null, + attributes: object + ): Promise; + + /** + * Marks a Feature Operation as successfully completed. + * Should be called when a previously started operation (via `startFeatureOperation`) finishes without error. + * @param name - The name of the feature operation (for example, `"login_flow"`). + * @param operationKey - The key for the operation instance to complete, if it was specified when starting it. + * @param attributes - Custom attributes to attach to this operation’s completion event. + */ + succeedFeatureOperation( + name: string, + operationKey: string | null, + attributes: object + ): Promise; + + /** + * Marks a Feature Operation as failed. + * Should be called when a previously started operation (via `startFeatureOperation`) ends with an error. + * @param name - The name of the feature operation (for example, `"login_flow"`). + * @param operationKey - The key for the operation instance to fail, if it was specified when starting it. + * @param reason - The reason for the failure. + * @param attributes - Custom attributes to attach to this operation’s failure event. + */ + failFeatureOperation( + name: string, + operationKey: string | null, + reason: FeatureOperationFailure, + attributes: object + ): Promise; }; /** diff --git a/packages/core/src/specs/NativeDdRum.ts b/packages/core/src/specs/NativeDdRum.ts index e31f5b925..9c0c459b3 100644 --- a/packages/core/src/specs/NativeDdRum.ts +++ b/packages/core/src/specs/NativeDdRum.ts @@ -185,6 +185,46 @@ export interface Spec extends TurboModule { * Get current Session ID, or `undefined` if not available. */ getCurrentSessionId(): Promise; + + /** + * Starts a Feature Operation, representing a high-level logical flow within your application (e.g., `login_flow`). + * @param name - The name of the feature operation (for example, `"login_flow"`). + * @param operationKey - An optional key to uniquely identify a specific instance of this operation when multiple are running concurrently. + * @param attributes - Custom attributes to attach to this operation. + */ + startFeatureOperation( + name: string, + operationKey: string | null, + attributes: Object + ): Promise; + + /** + * Marks a Feature Operation as successfully completed. + * Should be called when a previously started operation (via `startFeatureOperation`) finishes without error. + * @param name - The name of the feature operation (for example, `"login_flow"`). + * @param operationKey - The key for the operation instance to complete, if it was specified when starting it. + * @param attributes - Custom attributes to attach to this operation’s completion event. + */ + succeedFeatureOperation( + name: string, + operationKey: string | null, + attributes: Object + ): Promise; + + /** + * Marks a Feature Operation as failed. + * Should be called when a previously started operation (via `startFeatureOperation`) ends with an error. + * @param name - The name of the feature operation (for example, `"login_flow"`). + * @param operationKey - The key for the operation instance to fail, if it was specified when starting it. + * @param reason - The reason for the failure. + * @param attributes - Custom attributes to attach to this operation’s failure event. + */ + failFeatureOperation( + name: string, + operationKey: string | null, + reason: string, + attributes: Object + ): Promise; } // eslint-disable-next-line import/no-default-export diff --git a/packages/core/src/types.tsx b/packages/core/src/types.tsx index 7f97779ee..cd697c04b 100644 --- a/packages/core/src/types.tsx +++ b/packages/core/src/types.tsx @@ -232,3 +232,9 @@ export enum ErrorSource { WEBVIEW = 'WEBVIEW', CUSTOM = 'CUSTOM' } + +export enum FeatureOperationFailure { + ERROR = 'ERROR', + ABANDONED = 'ABANDONED', + OTHER = 'OTHER' +} diff --git a/packages/react-native-apollo-client/__mocks__/react-native.ts b/packages/react-native-apollo-client/__mocks__/react-native.ts index bbac607d3..ded32499f 100644 --- a/packages/react-native-apollo-client/__mocks__/react-native.ts +++ b/packages/react-native-apollo-client/__mocks__/react-native.ts @@ -110,7 +110,16 @@ actualRN.NativeModules.DdRum = { new Promise(resolve => resolve('test-session-id') ) - ) as jest.MockedFunction + ) as jest.MockedFunction, + startFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + succeedFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction, + failFeatureOperation: jest.fn().mockImplementation( + () => new Promise(resolve => resolve()) + ) as jest.MockedFunction }; module.exports = actualRN; From 68d150aff03bfc8826361751a2bc11faa497b7d1 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Tue, 18 Nov 2025 09:57:58 +0100 Subject: [PATCH 60/62] Remove defaultPrivacyLevel from Session Replay --- ...lemetryConfigurationEventForgeryFactory.kt | 1 - .../src/SessionReplay.ts | 41 +------------------ .../src/__tests__/SessionReplay.test.ts | 38 +---------------- 3 files changed, 2 insertions(+), 78 deletions(-) diff --git a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/TelemetryConfigurationEventForgeryFactory.kt b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/TelemetryConfigurationEventForgeryFactory.kt index 10e894e6e..684d92c21 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/TelemetryConfigurationEventForgeryFactory.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/TelemetryConfigurationEventForgeryFactory.kt @@ -86,7 +86,6 @@ internal class TelemetryConfigurationEventForgeryFactory : ) } }, - defaultPrivacyLevel = forge.aNullable { aString() }, enablePrivacyForActionName = forge.aNullable { aBool() }, useExcludedActivityUrls = forge.aNullable { aBool() }, useWorkerUrl = forge.aNullable { aBool() }, diff --git a/packages/react-native-session-replay/src/SessionReplay.ts b/packages/react-native-session-replay/src/SessionReplay.ts index 60d4e8ff8..516b8ffb4 100644 --- a/packages/react-native-session-replay/src/SessionReplay.ts +++ b/packages/react-native-session-replay/src/SessionReplay.ts @@ -95,15 +95,6 @@ export interface SessionReplayConfiguration { * Default: `true`. */ startRecordingImmediately?: boolean; - - /** - * Defines the way sensitive content (e.g. text) should be masked. - * - * Default `SessionReplayPrivacy.MASK`. - * @deprecated Use {@link imagePrivacyLevel}, {@link touchPrivacyLevel} and {@link textAndInputPrivacyLevel} instead. - * Note: setting this property (`defaultPrivacyLevel`) will override the individual privacy levels. - */ - defaultPrivacyLevel?: SessionReplayPrivacy; } type InternalBaseSessionReplayConfiguration = { @@ -121,11 +112,8 @@ type InternalPrivacySessionReplayConfiguration = { type InternalSessionReplayConfiguration = InternalBaseSessionReplayConfiguration & InternalPrivacySessionReplayConfiguration; -const DEFAULTS: InternalSessionReplayConfiguration & { - defaultPrivacyLevel: SessionReplayPrivacy; -} = { +const DEFAULTS: InternalSessionReplayConfiguration = { replaySampleRate: 100, - defaultPrivacyLevel: SessionReplayPrivacy.MASK, customEndpoint: '', imagePrivacyLevel: ImagePrivacyLevel.MASK_ALL, touchPrivacyLevel: TouchPrivacyLevel.HIDE, @@ -175,33 +163,6 @@ export class SessionReplayWrapper { DEFAULTS.textAndInputPrivacyLevel }; - // Legacy Default Privacy Level property handling - if (configuration.defaultPrivacyLevel) { - switch (configuration.defaultPrivacyLevel) { - case SessionReplayPrivacy.MASK: - privacyConfig.imagePrivacyLevel = - ImagePrivacyLevel.MASK_ALL; - privacyConfig.touchPrivacyLevel = TouchPrivacyLevel.HIDE; - privacyConfig.textAndInputPrivacyLevel = - TextAndInputPrivacyLevel.MASK_ALL; - break; - case SessionReplayPrivacy.MASK_USER_INPUT: - privacyConfig.imagePrivacyLevel = - ImagePrivacyLevel.MASK_NONE; - privacyConfig.touchPrivacyLevel = TouchPrivacyLevel.HIDE; - privacyConfig.textAndInputPrivacyLevel = - TextAndInputPrivacyLevel.MASK_ALL_INPUTS; - break; - case SessionReplayPrivacy.ALLOW: - privacyConfig.imagePrivacyLevel = - ImagePrivacyLevel.MASK_NONE; - privacyConfig.touchPrivacyLevel = TouchPrivacyLevel.SHOW; - privacyConfig.textAndInputPrivacyLevel = - TextAndInputPrivacyLevel.MASK_SENSITIVE_INPUTS; - break; - } - } - return { ...baseConfig, ...privacyConfig }; }; diff --git a/packages/react-native-session-replay/src/__tests__/SessionReplay.test.ts b/packages/react-native-session-replay/src/__tests__/SessionReplay.test.ts index c755fc6e2..43f449cf7 100644 --- a/packages/react-native-session-replay/src/__tests__/SessionReplay.test.ts +++ b/packages/react-native-session-replay/src/__tests__/SessionReplay.test.ts @@ -9,7 +9,6 @@ import { NativeModules } from 'react-native'; import { ImagePrivacyLevel, SessionReplay, - SessionReplayPrivacy, TextAndInputPrivacyLevel, TouchPrivacyLevel } from '../SessionReplay'; @@ -41,27 +40,9 @@ describe('SessionReplay', () => { ); }); - it('calls native session replay with provided configuration { w defaultPrivacyLevel = ALLOW }', () => { + it('calls native session replay with provided configuration { w custom endpoint }', () => { SessionReplay.enable({ replaySampleRate: 100, - defaultPrivacyLevel: SessionReplayPrivacy.ALLOW, - customEndpoint: 'https://session-replay.example.com' - }); - - expect(NativeModules.DdSessionReplay.enable).toHaveBeenCalledWith( - 100, - 'https://session-replay.example.com', - 'MASK_NONE', - 'SHOW', - 'MASK_SENSITIVE_INPUTS', - true - ); - }); - - it('calls native session replay with provided configuration { w defaultPrivacyLevel = MASK }', () => { - SessionReplay.enable({ - replaySampleRate: 100, - defaultPrivacyLevel: SessionReplayPrivacy.MASK, customEndpoint: 'https://session-replay.example.com' }); @@ -75,23 +56,6 @@ describe('SessionReplay', () => { ); }); - it('calls native session replay with provided configuration { w defaultPrivacyLevel = MASK_USER_INPUT }', () => { - SessionReplay.enable({ - replaySampleRate: 100, - defaultPrivacyLevel: SessionReplayPrivacy.MASK_USER_INPUT, - customEndpoint: 'https://session-replay.example.com' - }); - - expect(NativeModules.DdSessionReplay.enable).toHaveBeenCalledWith( - 100, - 'https://session-replay.example.com', - 'MASK_NONE', - 'HIDE', - 'MASK_ALL_INPUTS', - true - ); - }); - it('calls native session replay with provided configuration { w random privacy levels }', () => { const TIMES = 20; From e862322196b352d5832a41e2a68f164adff91132 Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 28 Nov 2025 11:49:29 +0100 Subject: [PATCH 61/62] Bump Native SDKs to 3.3.0 --- benchmarks/android/app/build.gradle | 2 +- benchmarks/ios/Podfile.lock | 74 +++++++------- example-new-architecture/ios/Podfile.lock | 70 +++++++------- example/ios/Podfile.lock | 96 +++++++++---------- packages/core/DatadogSDKReactNative.podspec | 12 +-- packages/core/android/build.gradle | 8 +- ...DatadogSDKReactNativeSessionReplay.podspec | 2 +- .../android/build.gradle | 4 +- .../DatadogSDKReactNativeWebView.podspec | 4 +- .../react-native-webview/android/build.gradle | 2 +- 10 files changed, 137 insertions(+), 137 deletions(-) diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle index 04c240bd0..ba6ae7a53 100644 --- a/benchmarks/android/app/build.gradle +++ b/benchmarks/android/app/build.gradle @@ -129,5 +129,5 @@ dependencies { // Benchmark tools from dd-sdk-android are used for vitals recording // Remember to bump thid alongside the main dd-sdk-android dependencies - implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.1.0") + implementation("com.datadoghq:dd-sdk-android-benchmark-internal:3.3.0") } diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 5c91024d5..4651f040a 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogCrashReporting (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogCore (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogCrashReporting (3.3.0): + - DatadogInternal (= 3.3.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.1.0) - - DatadogLogs (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogRUM (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogInternal (3.3.0) + - DatadogLogs (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogRUM (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogSDKReactNative (2.13.2): + - DatadogCore (= 3.3.0) + - DatadogCrashReporting (= 3.3.0) + - DatadogLogs (= 3.3.0) + - DatadogRUM (= 3.3.0) + - DatadogTrace (= 3.3.0) + - DatadogWebViewTracking (= 3.3.0) - DoubleConversion - glog - hermes-engine @@ -39,7 +39,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.1.0) + - DatadogSessionReplay (= 3.3.0) - DoubleConversion - glog - hermes-engine @@ -60,10 +60,10 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.12.1): - - DatadogInternal (= 3.1.0) + - DatadogSDKReactNativeWebView (2.13.2): + - DatadogInternal (= 3.3.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.1.0) + - DatadogWebViewTracking (= 3.3.0) - DoubleConversion - glog - hermes-engine @@ -84,13 +84,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSessionReplay (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogTrace (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogSessionReplay (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogTrace (3.3.0): + - DatadogInternal (= 3.3.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogWebViewTracking (3.3.0): + - DatadogInternal (= 3.3.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.78.2) @@ -2070,17 +2070,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d - DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d - DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc - DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 - DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: 8e0f39de38621d4d7ed961a74d8a216fd3a38321 - DatadogSDKReactNativeSessionReplay: f9288c8e981dcc65d1f727b01421ee9a7601e75f - DatadogSDKReactNativeWebView: 993527f6c5d38e0fcc4804a6a60c334dd199dc5b - DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 - DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 - DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 + DatadogCore: 9b1256ac9c27a07087d6214c8546acf756e40be7 + DatadogCrashReporting: 89a00886ef40808bffb8ccb4b6531e472f52e213 + DatadogInternal: 21dac5a7db548da6368a096d0714bdbec66deb6c + DatadogLogs: 355a4ac6bce3f0cb8231819e475c03dbbdd7957c + DatadogRUM: 1b3a47a9b9a5a25890f7fb3aa1f2bd86009d1086 + DatadogSDKReactNative: b364ddf133b4d774f3f7bfb5fc98232f960f5331 + DatadogSDKReactNativeSessionReplay: 73b5b7d46abe2ea8ffcaccb0c6232e49c0e27591 + DatadogSDKReactNativeWebView: 0310cc142fb39e185112e79f196f99f856a96c31 + DatadogSessionReplay: 85e63d3c5e5618c3029726d00595750a73c0920a + DatadogTrace: f13e8c09981787d6cb0a4b7fd1991351fab6d64b + DatadogWebViewTracking: 08fe084b5f57da05c1610fab49ce7bc84226141e DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index c0cd90bf6..38e172b0e 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - boost (1.84.0) - - DatadogCore (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogCrashReporting (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogCore (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogCrashReporting (3.3.0): + - DatadogInternal (= 3.3.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.1.0) - - DatadogLogs (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogRUM (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogInternal (3.3.0) + - DatadogLogs (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogRUM (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogSDKReactNative (2.13.2): + - DatadogCore (= 3.3.0) + - DatadogCrashReporting (= 3.3.0) + - DatadogLogs (= 3.3.0) + - DatadogRUM (= 3.3.0) + - DatadogTrace (= 3.3.0) + - DatadogWebViewTracking (= 3.3.0) - DoubleConversion - glog - hermes-engine @@ -37,13 +37,13 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (2.12.1): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogSDKReactNative/Tests (2.13.2): + - DatadogCore (= 3.3.0) + - DatadogCrashReporting (= 3.3.0) + - DatadogLogs (= 3.3.0) + - DatadogRUM (= 3.3.0) + - DatadogTrace (= 3.3.0) + - DatadogWebViewTracking (= 3.3.0) - DoubleConversion - glog - hermes-engine @@ -64,11 +64,11 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogTrace (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogTrace (3.3.0): + - DatadogInternal (= 3.3.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogWebViewTracking (3.3.0): + - DatadogInternal (= 3.3.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1850,14 +1850,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d - DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d - DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc - DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 - DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: 069ea9876220b2d09b0f4b180ce571b1b6ecbb35 - DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 - DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 + DatadogCore: 9b1256ac9c27a07087d6214c8546acf756e40be7 + DatadogCrashReporting: 89a00886ef40808bffb8ccb4b6531e472f52e213 + DatadogInternal: 21dac5a7db548da6368a096d0714bdbec66deb6c + DatadogLogs: 355a4ac6bce3f0cb8231819e475c03dbbdd7957c + DatadogRUM: 1b3a47a9b9a5a25890f7fb3aa1f2bd86009d1086 + DatadogSDKReactNative: 3c756b98ff379907842eb3769d44e6b8b570385f + DatadogTrace: f13e8c09981787d6cb0a4b7fd1991351fab6d64b + DatadogWebViewTracking: 08fe084b5f57da05c1610fab49ce7bc84226141e DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 8838c9be5..2e3655fd9 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,34 +1,34 @@ PODS: - boost (1.84.0) - - DatadogCore (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogCrashReporting (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogCore (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogCrashReporting (3.3.0): + - DatadogInternal (= 3.3.0) - PLCrashReporter (~> 1.12.0) - - DatadogInternal (3.1.0) - - DatadogLogs (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogRUM (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogSDKReactNative (2.12.1): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogInternal (3.3.0) + - DatadogLogs (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogRUM (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogSDKReactNative (2.13.2): + - DatadogCore (= 3.3.0) + - DatadogCrashReporting (= 3.3.0) + - DatadogLogs (= 3.3.0) + - DatadogRUM (= 3.3.0) + - DatadogTrace (= 3.3.0) + - DatadogWebViewTracking (= 3.3.0) - React-Core - - DatadogSDKReactNative/Tests (2.12.1): - - DatadogCore (= 3.1.0) - - DatadogCrashReporting (= 3.1.0) - - DatadogLogs (= 3.1.0) - - DatadogRUM (= 3.1.0) - - DatadogTrace (= 3.1.0) - - DatadogWebViewTracking (= 3.1.0) + - DatadogSDKReactNative/Tests (2.13.2): + - DatadogCore (= 3.3.0) + - DatadogCrashReporting (= 3.3.0) + - DatadogLogs (= 3.3.0) + - DatadogRUM (= 3.3.0) + - DatadogTrace (= 3.3.0) + - DatadogWebViewTracking (= 3.3.0) - React-Core - DatadogSDKReactNativeSessionReplay (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.1.0) + - DatadogSessionReplay (= 3.3.0) - DoubleConversion - glog - hermes-engine @@ -51,7 +51,7 @@ PODS: - Yoga - DatadogSDKReactNativeSessionReplay/Tests (2.13.2): - DatadogSDKReactNative - - DatadogSessionReplay (= 3.1.0) + - DatadogSessionReplay (= 3.3.0) - DoubleConversion - glog - hermes-engine @@ -73,25 +73,25 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.12.1): - - DatadogInternal (= 3.1.0) + - DatadogSDKReactNativeWebView (2.13.2): + - DatadogInternal (= 3.3.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.1.0) + - DatadogWebViewTracking (= 3.3.0) - React-Core - - DatadogSDKReactNativeWebView/Tests (2.12.1): - - DatadogInternal (= 3.1.0) + - DatadogSDKReactNativeWebView/Tests (2.13.2): + - DatadogInternal (= 3.3.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 3.1.0) + - DatadogWebViewTracking (= 3.3.0) - React-Core - react-native-webview - React-RCTText - - DatadogSessionReplay (3.1.0): - - DatadogInternal (= 3.1.0) - - DatadogTrace (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogSessionReplay (3.3.0): + - DatadogInternal (= 3.3.0) + - DatadogTrace (3.3.0): + - DatadogInternal (= 3.3.0) - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (3.1.0): - - DatadogInternal (= 3.1.0) + - DatadogWebViewTracking (3.3.0): + - DatadogInternal (= 3.3.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -1988,17 +1988,17 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: d2f51c7fb4308cf3c25e55e2e7242e5d558ee71d - DatadogCrashReporting: f636f1d1c534572c0b0abcdc59df244c884d825d - DatadogInternal: 7837b2ce3d525d429682532eeda697b181299fdc - DatadogLogs: 250894b5a99da5b924a019049c0d0326823cdbd6 - DatadogRUM: 0d2a60e1abb8aacfb8827ef84f6d5deb4d5026c8 - DatadogSDKReactNative: af351a4e1ce08124c290c52de94b0062a166cc67 - DatadogSDKReactNativeSessionReplay: dcbd55d9d0f2b86026996a8b7ec9654922d5dfe1 - DatadogSDKReactNativeWebView: 096ac87eb753b6a217b93441983264b9837c3b7e - DatadogSessionReplay: 6bc71888e2b41dd0de3325f06f0c0b3cee0e6df4 - DatadogTrace: f59e933074cd285ad7e9f5af991f8fe04b095991 - DatadogWebViewTracking: 9bc92b4147aeed47eb1911451f651094aa6dd6c1 + DatadogCore: 9b1256ac9c27a07087d6214c8546acf756e40be7 + DatadogCrashReporting: 89a00886ef40808bffb8ccb4b6531e472f52e213 + DatadogInternal: 21dac5a7db548da6368a096d0714bdbec66deb6c + DatadogLogs: 355a4ac6bce3f0cb8231819e475c03dbbdd7957c + DatadogRUM: 1b3a47a9b9a5a25890f7fb3aa1f2bd86009d1086 + DatadogSDKReactNative: 96c64d4627096497594113ffb0c86ae72490b17c + DatadogSDKReactNativeSessionReplay: 02ea3eefd261341d2ae839882351be3d209376d0 + DatadogSDKReactNativeWebView: 83cd1a58da38a7a4bd554051d6742138e36e3589 + DatadogSessionReplay: 85e63d3c5e5618c3029726d00595750a73c0920a + DatadogTrace: f13e8c09981787d6cb0a4b7fd1991351fab6d64b + DatadogWebViewTracking: 08fe084b5f57da05c1610fab49ce7bc84226141e DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 diff --git a/packages/core/DatadogSDKReactNative.podspec b/packages/core/DatadogSDKReactNative.podspec index c0d235304..692dd23c8 100644 --- a/packages/core/DatadogSDKReactNative.podspec +++ b/packages/core/DatadogSDKReactNative.podspec @@ -19,14 +19,14 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the versions in sync with DatadogSDKReactNativeSessionReplay.podspec - s.dependency 'DatadogCore', '3.1.0' - s.dependency 'DatadogLogs', '3.1.0' - s.dependency 'DatadogTrace', '3.1.0' - s.dependency 'DatadogRUM', '3.1.0' - s.dependency 'DatadogCrashReporting', '3.1.0' + s.dependency 'DatadogCore', '3.3.0' + s.dependency 'DatadogLogs', '3.3.0' + s.dependency 'DatadogTrace', '3.3.0' + s.dependency 'DatadogRUM', '3.3.0' + s.dependency 'DatadogCrashReporting', '3.3.0' # DatadogWebViewTracking is not available for tvOS - s.ios.dependency 'DatadogWebViewTracking', '3.1.0' + s.ios.dependency 'DatadogWebViewTracking', '3.3.0' s.test_spec 'Tests' do |test_spec| test_spec.source_files = 'ios/Tests/**/*.{swift,json}' diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index 1344b2531..bf7a2ef9c 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -195,10 +195,10 @@ dependencies { } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compileOnly "com.squareup.okhttp3:okhttp:3.12.13" - implementation "com.datadoghq:dd-sdk-android-rum:3.2.0" - implementation "com.datadoghq:dd-sdk-android-logs:3.2.0" - implementation "com.datadoghq:dd-sdk-android-trace:3.2.0" - implementation "com.datadoghq:dd-sdk-android-webview:3.2.0" + implementation "com.datadoghq:dd-sdk-android-rum:3.3.0" + implementation "com.datadoghq:dd-sdk-android-logs:3.3.0" + implementation "com.datadoghq:dd-sdk-android-trace:3.3.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.3.0" implementation "com.google.code.gson:gson:2.10.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec index 6a5d0b78f..e0b032a9e 100644 --- a/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec +++ b/packages/react-native-session-replay/DatadogSDKReactNativeSessionReplay.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.dependency "React-Core" # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogSessionReplay', '3.1.0' + s.dependency 'DatadogSessionReplay', '3.3.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index a0d77f2ff..1b16713db 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -216,8 +216,8 @@ dependencies { api "com.facebook.react:react-android:$reactNativeVersion" } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.datadoghq:dd-sdk-android-session-replay:3.1.0" - implementation "com.datadoghq:dd-sdk-android-internal:3.1.0" + implementation "com.datadoghq:dd-sdk-android-session-replay:3.3.0" + implementation "com.datadoghq:dd-sdk-android-internal:3.3.0" implementation project(path: ':datadog_mobile-react-native') testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" diff --git a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec index 080a853d8..000b35477 100644 --- a/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec +++ b/packages/react-native-webview/DatadogSDKReactNativeWebView.podspec @@ -23,8 +23,8 @@ Pod::Spec.new do |s| end # /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec - s.dependency 'DatadogWebViewTracking', '3.1.0' - s.dependency 'DatadogInternal', '3.1.0' + s.dependency 'DatadogWebViewTracking', '3.3.0' + s.dependency 'DatadogInternal', '3.3.0' s.dependency 'DatadogSDKReactNative' s.test_spec 'Tests' do |test_spec| diff --git a/packages/react-native-webview/android/build.gradle b/packages/react-native-webview/android/build.gradle index 87ca1b7e7..3ff3048d0 100644 --- a/packages/react-native-webview/android/build.gradle +++ b/packages/react-native-webview/android/build.gradle @@ -190,7 +190,7 @@ dependencies { implementation "com.facebook.react:react-android:$reactNativeVersion" } - implementation "com.datadoghq:dd-sdk-android-webview:3.1.0" + implementation "com.datadoghq:dd-sdk-android-webview:3.3.0" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation project(path: ':datadog_mobile-react-native') From 3d42b9b7ba1668f13d179c07436cb82d04456a5e Mon Sep 17 00:00:00 2001 From: Sergio Barrio Date: Fri, 28 Nov 2025 11:49:57 +0100 Subject: [PATCH 62/62] Solve merge issues and fix failing native tests --- .../reactnative/DdSdkImplementation.kt | 34 +------- .../Sources/DdSdkNativeInitialization.swift | 6 -- packages/core/ios/Tests/DdSdkTests.swift | 81 ++++++------------- .../Sources/RCTDatadogWebViewTracking.swift | 4 +- 4 files changed, 31 insertions(+), 94 deletions(-) diff --git a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt index 02123ee8f..8cb165b5f 100644 --- a/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt +++ b/packages/core/android/src/main/kotlin/com/datadog/reactnative/DdSdkImplementation.kt @@ -351,6 +351,7 @@ class DdSdkImplementation( } } + /** * Normalizes frameTime values so when are turned into FPS metrics they are normalized on a range of zero to 60fps. * @param frameTimeSeconds: the frame time to normalize. In seconds. @@ -368,43 +369,16 @@ class DdSdkImplementation( val frameTimeMs = frameTimeSeconds * 1000.0 val frameBudgetHz = fpsBudget ?: DEFAULT_REFRESH_HZ val maxDeviceDisplayHz = deviceDisplayFps ?: getMaxDisplayRefreshRate(context) - ?: 60.0 - - val maxDeviceFrameTimeMs = 1000.0 / maxDeviceDisplayHz - val budgetFrameTimeMs = 1000.0 / frameBudgetHz - - if (listOf( - maxDeviceDisplayHz, frameTimeMs, frameBudgetHz, budgetFrameTimeMs, maxDeviceFrameTimeMs - ).any { !it.isFinite() || it <= 0.0 } - ) return 1.0 / DEFAULT_REFRESH_HZ - - - var normalizedFrameTimeMs = frameTimeMs / (maxDeviceFrameTimeMs / budgetFrameTimeMs) - - normalizedFrameTimeMs = max(normalizedFrameTimeMs, maxDeviceFrameTimeMs) - - return normalizedFrameTimeMs / 1000.0 // in seconds - } - - @Suppress("CyclomaticComplexMethod") - private fun getMaxDisplayRefreshRate(context: Context?): Double { - val dm = context?.getSystemService(Context.DISPLAY_SERVICE) as? DisplayManager ?: return 60.0 - val display: Display = dm.getDisplay(Display.DEFAULT_DISPLAY) ?: return DEFAULT_REFRESH_HZ - - return display.supportedModes.maxOf { it.refreshRate.toDouble() } - } - - // endregion + ?: 60.0 val maxDeviceFrameTimeMs = 1000.0 / maxDeviceDisplayHz val budgetFrameTimeMs = 1000.0 / frameBudgetHz if (listOf( - maxDeviceDisplayHz, frameTimeMs, frameBudgetHz, budgetFrameTimeMs, maxDeviceFrameTimeMs - ).any { !it.isFinite() || it <= 0.0 } + maxDeviceDisplayHz, frameTimeMs, frameBudgetHz, budgetFrameTimeMs, maxDeviceFrameTimeMs + ).any { !it.isFinite() || it <= 0.0 } ) return 1.0 / DEFAULT_REFRESH_HZ - var normalizedFrameTimeMs = frameTimeMs / (maxDeviceFrameTimeMs / budgetFrameTimeMs) normalizedFrameTimeMs = max(normalizedFrameTimeMs, maxDeviceFrameTimeMs) diff --git a/packages/core/ios/Sources/DdSdkNativeInitialization.swift b/packages/core/ios/Sources/DdSdkNativeInitialization.swift index 969f72abf..fc11cd80d 100644 --- a/packages/core/ios/Sources/DdSdkNativeInitialization.swift +++ b/packages/core/ios/Sources/DdSdkNativeInitialization.swift @@ -93,16 +93,10 @@ public class DdSdkNativeInitialization: NSObject { if sdkConfiguration.nativeCrashReportEnabled ?? false { CrashReporting.enable() } -<<<<<<< HEAD -<<<<<<< HEAD #if os(iOS) DatadogSDKWrapper.shared.enableWebviewTracking() #endif -======= ->>>>>>> 0443e0ff (iOS: Always use SDK default core instance) -======= ->>>>>>> 93aa6125 (iOS: Always use SDK default core instance) } func buildSDKConfiguration(configuration: DdSdkConfiguration, defaultAppVersion: String = getDefaultAppVersion()) -> Datadog.Configuration { diff --git a/packages/core/ios/Tests/DdSdkTests.swift b/packages/core/ios/Tests/DdSdkTests.swift index cba49f84f..3f5c0e960 100644 --- a/packages/core/ios/Tests/DdSdkTests.swift +++ b/packages/core/ios/Tests/DdSdkTests.swift @@ -82,7 +82,7 @@ class DdSdkTests: XCTestCase { func testResolvesPromiseAfterInitializationIsDone() throws { let bridge = DispatchQueueMock() let mockJSRefreshRateMonitor = MockJSRefreshRateMonitor() - let mockListener = MockOnCoreInitializedListener() + let mockListener = MockOnSdkInitializedListener() DatadogSDKWrapper.shared.addOnSdkInitializedListener(listener: mockListener.listener) let expectation = self.expectation(description: "Listener is called when promise resolves") @@ -275,7 +275,9 @@ class DdSdkTests: XCTestCase { func testSDKInitializationWithOnInitializedCallback() { var isInitialized = false + var coreFromCallback: DatadogCoreProtocol? = nil DatadogSDKWrapper.shared.addOnSdkInitializedListener(listener: { + core in coreFromCallback = core isInitialized = Datadog.isInitialized() }) @@ -718,13 +720,14 @@ class DdSdkTests: XCTestCase { XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, nil) XCTAssertEqual(userInfo.extraInfo["extra-info-4"] as? [String: Int], nil) } - - func testClearUserInfo() throws { + + func testAddingAttribute() { + let rumMonitorMock = MockRUMMonitor() let bridge = DdSdkImplementation( mainDispatchQueue: DispatchQueueMock(), jsDispatchQueue: DispatchQueueMock(), jsRefreshRateMonitor: JSRefreshRateMonitor(), - RUMMonitorProvider: { MockRUMMonitor() }, + RUMMonitorProvider: { rumMonitorMock }, RUMMonitorInternalProvider: { nil } ) bridge.initialize( @@ -733,57 +736,19 @@ class DdSdkTests: XCTestCase { reject: mockReject ) - bridge.setUserInfo( - userInfo: NSDictionary( - dictionary: [ - "id": "id_123", - "name": "John Doe", - "email": "john@doe.com", - "extraInfo": [ - "extra-info-1": 123, - "extra-info-2": "abc", - "extra-info-3": true, - "extra-info-4": [ - "nested-extra-info-1": 456 - ], - ], - ] - ), - resolve: mockResolve, - reject: mockReject - ) - - var ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() - var userInfo = try XCTUnwrap(ddContext.userInfo) - - XCTAssertEqual(userInfo.id, "id_123") - XCTAssertEqual(userInfo.name, "John Doe") - XCTAssertEqual(userInfo.email, "john@doe.com") - XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, 123) - XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, "abc") - XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true) - - if let extraInfo4Encodable = userInfo.extraInfo["extra-info-4"] - as? DatadogSDKReactNative.AnyEncodable, - let extraInfo4Dict = extraInfo4Encodable.value as? [String: Int] - { - XCTAssertEqual(extraInfo4Dict, ["nested-extra-info-1": 456]) - } else { - XCTFail("extra-info-4 is not of expected type or value") - } - - bridge.clearUserInfo(resolve: mockResolve, reject: mockReject) + bridge.addAttribute(key: "attribute-1", value: NSDictionary(dictionary: ["value": 123]), resolve: mockResolve, reject: mockReject) + bridge.addAttribute(key: "attribute-2", value: NSDictionary(dictionary: ["value": "abc"]), resolve: mockResolve, reject: mockReject) + bridge.addAttribute(key: "attribute-3", value: NSDictionary(dictionary: ["value": true]), resolve: mockResolve, reject: mockReject) + + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-1"] as? Int64, 123) + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-2"] as? String, "abc") + XCTAssertEqual(rumMonitorMock.addedAttributes["attribute-3"] as? Bool, true) - ddContext = try XCTUnwrap(CoreRegistry.default as? DatadogCore).contextProvider.read() - userInfo = try XCTUnwrap(ddContext.userInfo) + XCTAssertEqual(GlobalState.globalAttributes["attribute-1"] as? Int64, 123) + XCTAssertEqual(GlobalState.globalAttributes["attribute-2"] as? String, "abc") + XCTAssertEqual(GlobalState.globalAttributes["attribute-3"] as? Bool, true) - XCTAssertEqual(userInfo.id, nil) - XCTAssertEqual(userInfo.name, nil) - XCTAssertEqual(userInfo.email, nil) - XCTAssertEqual(userInfo.extraInfo["extra-info-1"] as? Int64, nil) - XCTAssertEqual(userInfo.extraInfo["extra-info-2"] as? String, nil) - XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, nil) - XCTAssertEqual(userInfo.extraInfo["extra-info-4"] as? [String: Int], nil) + GlobalState.globalAttributes.removeAll() } func testRemovingAttribute() { @@ -1542,7 +1507,7 @@ class DdSdkTests: XCTestCase { func testCallsOnSdkInitializedListeners() throws { let bridge = DispatchQueueMock() let mockJSRefreshRateMonitor = MockJSRefreshRateMonitor() - let mockListener = MockOnCoreInitializedListener() + let mockListener = MockOnSdkInitializedListener() DatadogSDKWrapper.shared.addOnSdkInitializedListener(listener: mockListener.listener) @@ -1811,9 +1776,13 @@ extension DdSdkImplementation { } } -class MockOnCoreInitializedListener { +class MockOnSdkInitializedListener { var called = false - func listener() { + var receivedCore: DatadogCoreProtocol? + + lazy var listener: OnSdkInitializedListener = { core in self.called = true + self.receivedCore = core } } + diff --git a/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift b/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift index 45f11e452..6d3bc3f8d 100644 --- a/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift +++ b/packages/react-native-webview/ios/Sources/RCTDatadogWebViewTracking.swift @@ -17,14 +17,14 @@ import DatadogInternal public override init() { super.init() - self.onSdkInitializedListener = { [weak self] in + self.onSdkInitializedListener = { [weak self] (core: DatadogCoreProtocol) in guard let strongSelf = self, let webView = strongSelf.webView else { return } strongSelf.enableWebViewTracking( webView: webView, allowedHosts: strongSelf.allowedHosts, - core: CoreRegistry.default + core: core ) } }