diff --git a/.github/workflows/issue_notification.yml b/.github/workflows/issue_notification.yml new file mode 100644 index 000000000..41731149b --- /dev/null +++ b/.github/workflows/issue_notification.yml @@ -0,0 +1,56 @@ + +name: Github Issue Notification + +on: + # # When a new issue is opened + issues: + types: + - opened + + # When manually triggering the workflow + workflow_dispatch: + inputs: + issue_number: + description: 'Issue number to process' + required: true + type: number + +jobs: + process_issue: + runs-on: ubuntu-latest + environment: protected-dev-env + + steps: + - name: Checkout Repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Set up Python 3.x + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: '3.x' + + - name: Install Dependencies + run: | + cd tools/issue_handler + pip install -r requirements.txt + + - name: Set Issue Number + run: | + if [ "${{ github.event_name }}" = "issues" ]; then + echo "GITHUB_EVENT_NUMBER=${{ github.event.issue.number }}" >> $GITHUB_ENV + else + echo "GITHUB_EVENT_NUMBER=${{ github.event.inputs.issue_number }}" >> $GITHUB_ENV + fi + + - name: Run the Processing Script + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + OPENAI_TOKEN: ${{ secrets.OPENAI_TOKEN }} + OPENAI_SYSTEM_PROMPT: ${{ vars.OPENAI_SYSTEM_PROMPT }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + GITHUB_REPOSITORY: ${{ github.repository }} + run: | + cd tools/issue_handler + # Add timeout to prevent hanging processes (5 minutes) + timeout 300 python -m src.analyze_issue $GITHUB_EVENT_NUMBER diff --git a/.gitignore b/.gitignore index 1e9c16ffd..693bb50a6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ # Xcode # build/ +.build/ *.pbxuser !default.pbxuser *.mode1v3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 84f473f4e..d5254cda4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -142,17 +142,26 @@ use_frameworks! Now you can go back to your `App.js/tsx` and use `@datadog/mobile-react-native` from there Example code: ``` -import { DdSdkReactNative, DdSdkReactNativeConfiguration } from '@datadog/mobile-react-native'; +import { DdSdkReactNative, CoreConfiguration, TrackingConsent } from '@datadog/mobile-react-native'; const App: () => React$Node = () => { - const config = new DdSdkReactNativeConfiguration( + const config = new CoreConfiguration( "", "", - "", - true, // track User interactions (e.g.: Tap on buttons) - true, // track XHR Resources - true // track Errors + TrackingConsent.GRANTED, + { + rumConfiguration: { + applicationId: APPLICATION_ID, + trackInteractions: true, + trackResources: true, + trackFrustrations: true, + trackErrors: true, + }, + logsConfiguration: {}, + traceConfiguration: {} + } ) + DdSdkReactNative.initialize(config); ... ``` diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 2d12ca9ea..3baff5a5f 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -32,6 +32,8 @@ dev,react-native-webview,MIT,"Copyright (c) 2015-present, Facebook, Inc." dev,react-test-renderer,MIT,"Copyright (c) Facebook, Inc. and its affiliates." dev,typescript,Apache-2.0,"Copyright Microsoft Corporation" dev,genversion,MIT,"Copyright (c) 2021 Akseli PalΓ©n" +dev,@openfeature/core,Apache-2.0,"Copyright (c) The OpenFeature Authors" +prod,@openfeature/web-sdk,Apache-2.0,"Copyright (c) The OpenFeature Authors" prod,chokidar,MIT,"Copyright (c) 2012 Paul Miller (https://paulmillr.com), Elan Shanker" prod,fast-glob,MIT,"Copyright (c) Denis Malinochkin" prod,svgo,MIT,"Copyright (c) Kir Belevich" diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 000000000..f37fa23bc --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,239 @@ +# Migration Guide + +This document outlines breaking changes and migration steps between major versions of the project. + +## Migration from 2.x to 3.0 + +This section describes the main changes introduced in SDK `3.0` compared to `2.x`. + +### Core SDK Initialization changes + +The configuration object used to initialize the SDK has seen some changes in its structure. +Feature configuration is now split into feature-specific properties: rumConfiguration, logsConfiguration, traceConfiguration. + +Then, RUM, Logs and Trace can be independently configured via their optional configuration objects that are each represented by a property inside the core configuration object. + +**NOTE: clientToken, environment and trackingConsent are mandatory for the Core SDK initialization. +ApplicationID is mandatory for RUM to work.** + +For instance, to configure the SDK and enable RUM, Logs and Trace you'd do the following: + +``` +const config = new CoreConfiguration( + CLIENT_TOKEN, + ENVIRONMENT, + TrackingConsent.GRANTED, + { + rumConfiguration: { + applicationId: APPLICATION_ID, + trackInteractions: true, + trackResources: true, + trackFrustrations: true, + sessionSampleRate: 100, + telemetrySampleRate: 100 + } + }, + logsConfiguration: { + logEventMapper: (logEvent) => { + logEvent.message = `[CUSTOM] ${logEvent.message}`; + return logEvent; + } + }, + traceConfiguration: {} +); + +... + +await DdSdkReactNative.initialize(config); +``` + +Or if using the DatadogProvider wrapper: + +``` +const configuration = new DatadogProviderConfiguration( + CLIENT_TOKEN, + ENVIRONMENT, + TrackingConsent.GRANTED, + { + batchSize: BatchSize.SMALL, + uploadFrequency: UploadFrequency.FREQUENT, + batchProcessingLevel: BatchProcessingLevel.MEDIUM, + additionalConfiguration: { + customProperty: "sdk-example-app" + }, + rumConfiguration: { + applicationId: APPLICATION_ID, + trackInteractions: true, + trackResources: true, + trackErrors: true, + sessionSampleRate: 100, + nativeCrashReportEnabled: true + }, + logsConfiguration: { + logEventMapper: (logEvent) => { + logEvent.message = `[CUSTOM] ${logEvent.message}`; + return logEvent; + } + }, + traceConfiguration: {} + } +); + +... + + +``` + +**NOTE: Unlike v2.x, which would always enable all feature modules when initializing the SDK, v3 won't initialize nor enable a feature module if there's no configuration for it.** + +### Property renames and relocations + +| Property | New Location | Changes | +| :--- | :--- | :--- | +| `sampleRate` | *Removed* | Deprecated property removed. | +| `sessionSamplingRate` | `RumConfiguration` | Moved and renamed to `sessionSampleRate` | +| `resourceTracingSamplingRate` | `RumConfiguration` | Moved and renamed to `resourceTraceSampleRate`. | +| `proxyConfig` | `CoreConfiguration` | Renamed to `proxyConfiguration`. | +| `serviceName` | `CoreConfiguration` | Renamed to `service`. | +| `customEndpoints` | *Split* | Split into `customEndpoint` within `RumConfiguration`, `LogsConfiguration`, and `TraceConfiguration` | +| *New Property* | `CoreConfiguration` | `attributeEncoders` added. | +| *New Property* | `RumConfiguration` | `trackMemoryWarnings` added. | +| `nativeCrashReportEnabled` | `RumConfiguration` | Moved. | +| `nativeViewTracking` | `RumConfiguration` | Moved. | +| `nativeInteractionTracking` | `RumConfiguration` | Moved. | +| `firstPartyHosts` | `RumConfiguration` | Moved. | +| `telemetrySampleRate` | `RumConfiguration` | Moved. | +| `nativeLongTaskThresholdMs` | `RumConfiguration` | Moved. | +| `longTaskThresholdMs` | `RumConfiguration` | Moved. | +| `vitalsUpdateFrequency` | `RumConfiguration` | Moved. | +| `trackFrustrations` | `RumConfiguration` | Moved. | +| `trackBackgroundEvents` | `RumConfiguration` | Moved. | +| `bundleLogsWithRum` | `LogsConfiguration` | Moved. | +| `bundleLogsWithTraces` | `LogsConfiguration` | Moved. | +| `trackNonFatalAnrs` | `RumConfiguration` | Moved. | +| `appHangThreshold` | `RumConfiguration` | Moved. | +| `initialResourceThreshold` | `RumConfiguration` | Moved. | +| `trackWatchdogTerminations` | `RumConfiguration` | Moved. | +| `actionNameAttribute` | `RumConfiguration` | Moved. | +| `logEventMapper` | `LogsConfiguration` | Moved. | +| `errorEventMapper` | `RumConfiguration` | Moved. | +| `resourceEventMapper` | `RumConfiguration` | Moved. | +| `actionEventMapper` | `RumConfiguration` | Moved. |`TraceConfiguration`. | +| `useAccessibilityLabel` | `RumConfiguration` | Moved. | +| `trackInteractions` | `RumConfiguration` | Moved. | +| `trackResources` | `RumConfiguration` | Moved. | +| `trackErrors` | `RumConfiguration` | Moved. | + +### FileBasedConfiguration changes + +FileBasedConfiguration now requires a path to a configuration JSON file instead of trying to find a default `datadog-configuration.json` at the app's root level like it did on v2. + +### Changes to SessionReplay configuration +defaultPrivacyLevel has been removed in favor of granular options: imagePrivacyLevel, touchPrivacyLevel and textAndInputPrivacyLevel. + +### Fatal Errors are no longer reported as logs + +Fatal Errors are no longer automatically reported as Logs. Fatal crashes will still be captured, but are no longer duplicated in Logs by default. + +### Context / Attribute encoding +Context / attributes encoding is now safe and deterministic + All attributes passed to Datadog SDK APIs are automatically sanitized and encoded: +Unsupported values (functions, symbols, non-finite numbers, etc.) are dropped with a warning to prevent crashes and undefined behavior +Common types (Date, Error, Map) are properly serialized +Nested objects are flattened using dot notation (a.b.c = value) to match native SDK expectations +Root-level primitives and arrays are wrapped under a context key for schema consistency +Custom encoders can be registered via the attributeEncoders configuration option for domain-specific types + +### Android mindSdkVersion bumped to 23 +Android's minSdkVersion has been bumped to 23. + +### Resource Traces sampling aligned with RUM Sessions +Resource traces are now consistently sampled based on the active RUM session. +You may notice changes in the percentage of reported resources. + +### JS Refresh rate normalization changes +JS refresh rate is now normalized to a 0–60 FPS range. + +### RUM Session sampling changes +v3 modifies the logic to determine whether a trace should be sampled or not, by using the RUM Session ID first, before using the Trace sampling if no session can be found. + +Consistent trace sampling based on RUM Session ID allows RUM clients and the backend to come to a the same decision about sampling without relying on randomness for each trace. + +### Removed APIs + +| API | Status | +| :--- | :--- | +| setUser | Removed in favor of setUserInfo. To completely remove userInfo please use the newly added clearUserInfo | +| setAttributes| Removed in favor of addAttributes | + +### Attributes API +The attribute API has been expanded allowing for addition and removal of single or batches of attributes in bulk.This can be performed with the new granular APIs: addAttributes, removeAttributes, addAttribute and removeAttribute. + +### New APIs + +#### ViewAttributes + +RUM View-level attributes are now automatically propagated to all related child events, including resources, user actions, errors, and long tasks. This ensures consistent metadata across events, making it easier to filter and correlate data on Datadog dashboards. + +To manage View level attributes more effectively, new APIs were added: + +``` +addViewAttribute = (key: string, value: unknown) +removeViewAttribute = (key: string) +addViewAttributes = (attributes: Attributes) +removeViewAttributes = (keys: string[]) +``` + +#### AccountInfo +The AccountInfo API from the native Datadog SDKs has been exposed to React Native as well: + +``` +setAccountInfo = async (accountInfo: { + id: string; + name?: string; + extraInfo?: Record; +}) + +clearAccountInfo = async () + +addAccountExtraInfo = async (extraAccountInfo: Record) +``` + +#### Feature Operations + +``` +startFeatureOperation( + name: string, + operationKey: string | null, + attributes: object +): Promise + +succeedFeatureOperation( + name: string, + operationKey: string | null, + attributes: object +): Promise + +failFeatureOperation( + name: string, + operationKey: string | null, + reason: FeatureOperationFailure, + attributes: object +): Promise +``` + +### New Navigation Tracking Options + +v3 modifies the automatic navigation tracking modules for React Navigation and React Native Navigation and exposes a new NavigationTrackingOptions parameter through the startTracking/startTrackingViews function. + +This `options` object allows to customize the view tracking logic via 3 new optional predicate functions: + +- ViewNamePredicate - a custom naming predicates that decide the display name of views tracked by RUM. +- ViewTrackingPredicate - a custom predicate that decides if a view needs to be tracked by RUM or not. +- ParamsTrackingPredicate - a custom predicate that decides which navigation parameters (if any) need to be tracked alongside the view on RUM. + +All of these are optional, and when not set the default behavior will be used for each one of them. The default behaviours are as follows: + +- ViewNamePredicate - directly forwards the view given name to RUM. +- ViewTrackingPredicate - tracks all views on RUM. +- ParamsTrackingPredicate - does not forward any parameters to RUM. diff --git a/NATIVE_SDK_VERSIONS.md b/NATIVE_SDK_VERSIONS.md index 7ba795c56..eeb516488 100644 --- a/NATIVE_SDK_VERSIONS.md +++ b/NATIVE_SDK_VERSIONS.md @@ -1,5 +1,10 @@ | React Native | iOS Bridge / iOS SDK | Android Bridge / Android SDK | |-------------|---------------------|-----------------------------| +| 3.1.0 | 3.5.0 | 3.5.0 | +| 3.0.3 | 3.4.0 | 3.4.0 | +| 3.0.2 | 3.4.0 | 3.4.0 | +| 3.0.1 | 3.4.0 | 3.4.0 | +| 3.0.0 | 3.4.0 | 3.4.0 | | 2.14.1 | 2.30.2 | 2.26.2 | | 2.14.0 | 2.30.2 | 2.26.2 | | 2.13.2 | 2.30.2 | 2.26.2 | diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle index 86d26791f..b64f27c14 100644 --- a/benchmarks/android/app/build.gradle +++ b/benchmarks/android/app/build.gradle @@ -129,5 +129,7 @@ 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.5.0") + // Required for compile-time access to Datadog.getInstance() required by BenchmarkVitalsModuleImpl + implementation("com.datadoghq:dd-sdk-android-core:3.5.0") } diff --git a/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModuleImpl.kt b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModuleImpl.kt index 81ff632e2..669f88b2d 100644 --- a/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModuleImpl.kt +++ b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModuleImpl.kt @@ -10,6 +10,7 @@ import android.content.Context import com.benchmarkrunner.BuildConfig import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReadableMap +import com.datadog.android.Datadog import com.datadog.benchmark.DatadogVitalsMeter import com.datadog.benchmark.DatadogExporterConfiguration @@ -33,7 +34,7 @@ class BenchmarkVitalsModuleImpl(private val context: Context) { .setIntervalInSeconds(METER_INTERVAL_IN_SECONDS) .build() - vitalsMeter = DatadogVitalsMeter.create(exporterConfig) + vitalsMeter = DatadogVitalsMeter.create(exporterConfig, Datadog.getInstance()) vitalsMeter.startMeasuring() promise.resolve(true) diff --git a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj index e8c70650d..c72e63b31 100644 --- a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj +++ b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj @@ -3,11 +3,10 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ - 04066FD52DCCB9D200A9E317 /* DatadogBenchmarks in Frameworks */ = {isa = PBXBuildFile; productRef = 04066FD42DCCB9D200A9E317 /* DatadogBenchmarks */; }; 041FA8A82DCCB7FA00BABC32 /* MetricExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041FA8A62DCCB7FA00BABC32 /* MetricExporter.swift */; }; 041FA8A92DCCB7FA00BABC32 /* BenchmarkVitals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041FA8A52DCCB7FA00BABC32 /* BenchmarkVitals.swift */; }; 041FA8AA2DCCB7FA00BABC32 /* Metrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041FA8A72DCCB7FA00BABC32 /* Metrics.swift */; }; @@ -17,6 +16,7 @@ 043403232DCB9CB200803AF8 /* BenchMarkVitalsImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043403222DCB9CB200803AF8 /* BenchMarkVitalsImplementation.swift */; }; 043403262DCB9CD700803AF8 /* BenchmarkVitals.mm in Sources */ = {isa = PBXBuildFile; fileRef = 043403242DCB9CD700803AF8 /* BenchmarkVitals.mm */; }; 04576C962DCBAF900078DCAB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 04576C952DCBAF900078DCAB /* main.m */; }; + 04726DD72F46402A008D1A48 /* TracerProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04726DD62F46402A008D1A48 /* TracerProvider.swift */; }; 0C80B921A6F3F58F76C31292 /* libPods-BenchmarkRunner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-BenchmarkRunner.a */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 20A397FC280595A8A9851556 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; @@ -25,7 +25,6 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 041FA8A12DCCB7FA00BABC32 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 041FA8A22DCCB7FA00BABC32 /* BenchmarkMeter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkMeter.swift; sourceTree = ""; }; 041FA8A32DCCB7FA00BABC32 /* BenchmarkProfiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkProfiler.swift; sourceTree = ""; }; 041FA8A42DCCB7FA00BABC32 /* Benchmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Benchmarks.swift; sourceTree = ""; }; @@ -36,6 +35,7 @@ 043403242DCB9CD700803AF8 /* BenchmarkVitals.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BenchmarkVitals.mm; sourceTree = ""; }; 043403282DCBA1D100803AF8 /* BenchmarkVitals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BenchmarkVitals.h; sourceTree = ""; }; 04576C952DCBAF900078DCAB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 04726DD62F46402A008D1A48 /* TracerProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracerProvider.swift; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* BenchmarkRunner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BenchmarkRunner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = BenchmarkRunner/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = BenchmarkRunner/Info.plist; sourceTree = ""; }; @@ -54,7 +54,6 @@ buildActionMask = 2147483647; files = ( 0C80B921A6F3F58F76C31292 /* libPods-BenchmarkRunner.a in Frameworks */, - 04066FD52DCCB9D200A9E317 /* DatadogBenchmarks in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -64,6 +63,7 @@ 04066FD22DCCB97400A9E317 /* Sources */ = { isa = PBXGroup; children = ( + 04726DD62F46402A008D1A48 /* TracerProvider.swift */, 041FA8A42DCCB7FA00BABC32 /* Benchmarks.swift */, 041FA8A62DCCB7FA00BABC32 /* MetricExporter.swift */, 041FA8A72DCCB7FA00BABC32 /* Metrics.swift */, @@ -74,7 +74,6 @@ 041FA8A02DCCB7EA00BABC32 /* Vitals */ = { isa = PBXGroup; children = ( - 041FA8A12DCCB7FA00BABC32 /* Package.swift */, 041FA8A52DCCB7FA00BABC32 /* BenchmarkVitals.swift */, 041FA8A22DCCB7FA00BABC32 /* BenchmarkMeter.swift */, 041FA8A32DCCB7FA00BABC32 /* BenchmarkProfiler.swift */, @@ -201,9 +200,6 @@ Base, ); mainGroup = 83CBB9F61A601CBA00E9B192; - packageReferences = ( - 04066FD32DCCB9D200A9E317 /* XCLocalSwiftPackageReference "Vitals" */, - ); productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -251,10 +247,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-frameworks.sh\"\n"; @@ -290,10 +290,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-resources-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-resources-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-resources.sh\"\n"; @@ -316,6 +320,7 @@ 043403232DCB9CB200803AF8 /* BenchMarkVitalsImplementation.swift in Sources */, 04576C962DCBAF900078DCAB /* main.m in Sources */, 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */, + 04726DD72F46402A008D1A48 /* TracerProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -597,10 +602,7 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -669,10 +671,7 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -702,20 +701,6 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - -/* Begin XCLocalSwiftPackageReference section */ - 04066FD32DCCB9D200A9E317 /* XCLocalSwiftPackageReference "Vitals" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = BenchmarkVitals/Vitals; - }; -/* End XCLocalSwiftPackageReference section */ - -/* Begin XCSwiftPackageProductDependency section */ - 04066FD42DCCB9D200A9E317 /* DatadogBenchmarks */ = { - isa = XCSwiftPackageProductDependency; - productName = DatadogBenchmarks; - }; -/* End XCSwiftPackageProductDependency section */ }; rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; } diff --git a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index fefebe144..000000000 --- a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,177 +0,0 @@ -{ - "originHash" : "6080434f841a87c8e7ac3b20dc830d9b44f71d3a779bd2cd618583a99aad2fc9", - "pins" : [ - { - "identity" : "grpc-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift.git", - "state" : { - "revision" : "8c5e99d0255c373e0330730d191a3423c57373fb", - "version" : "1.24.2" - } - }, - { - "identity" : "opentelemetry-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/open-telemetry/opentelemetry-swift", - "state" : { - "revision" : "2ffffae2a027e2159dbf3fd53de1f25ba6d2d11d", - "version" : "1.13.0" - } - }, - { - "identity" : "opentracing-objc", - "kind" : "remoteSourceControl", - "location" : "https://github.com/undefinedlabs/opentracing-objc", - "state" : { - "revision" : "18c1a35ca966236cee0c5a714a51a73ff33384c1", - "version" : "0.5.2" - } - }, - { - "identity" : "swift-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-algorithms.git", - "state" : { - "revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023", - "version" : "1.2.1" - } - }, - { - "identity" : "swift-atomics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-atomics.git", - "state" : { - "revision" : "cd142fd2f64be2100422d658e7411e39489da985", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", - "version" : "1.1.4" - } - }, - { - "identity" : "swift-http-structured-headers", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-structured-headers.git", - "state" : { - "revision" : "f280fc7676b9940ff2c6598642751ea333c6544f", - "version" : "1.2.2" - } - }, - { - "identity" : "swift-http-types", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-types.git", - "state" : { - "revision" : "a0a57e949a8903563aba4615869310c0ebf14c03", - "version" : "1.4.0" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "3d8596ed08bd13520157f0355e35caed215ffbfa", - "version" : "1.6.3" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "4c83e1cdf4ba538ef6e43a9bbd0bcc33a0ca46e3", - "version" : "2.7.0" - } - }, - { - "identity" : "swift-nio", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio.git", - "state" : { - "revision" : "0f54d58bb5db9e064f332e8524150de379d1e51c", - "version" : "2.82.1" - } - }, - { - "identity" : "swift-nio-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-extras.git", - "state" : { - "revision" : "f1f6f772198bee35d99dd145f1513d8581a54f2c", - "version" : "1.26.0" - } - }, - { - "identity" : "swift-nio-http2", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-http2.git", - "state" : { - "revision" : "4281466512f63d1bd530e33f4aa6993ee7864be0", - "version" : "1.36.0" - } - }, - { - "identity" : "swift-nio-ssl", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-ssl.git", - "state" : { - "revision" : "6df102a39c8da5fdc2eae29a0f63546d660866fc", - "version" : "2.30.0" - } - }, - { - "identity" : "swift-nio-transport-services", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-transport-services.git", - "state" : { - "revision" : "cd1e89816d345d2523b11c55654570acd5cd4c56", - "version" : "1.24.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics.git", - "state" : { - "revision" : "e0ec0f5f3af6f3e4d5e7a19d2af26b481acb6ba8", - "version" : "1.0.3" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "d72aed98f8253ec1aa9ea1141e28150f408cf17f", - "version" : "1.29.0" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system.git", - "state" : { - "revision" : "a34201439c74b53f0fd71ef11741af7e7caf01e1", - "version" : "1.4.2" - } - }, - { - "identity" : "thrift-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/undefinedlabs/Thrift-Swift", - "state" : { - "revision" : "18ff09e6b30e589ed38f90a1af23e193b8ecef8e", - "version" : "1.1.2" - } - } - ], - "version" : 3 -} diff --git a/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index fefebe144..000000000 --- a/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,177 +0,0 @@ -{ - "originHash" : "6080434f841a87c8e7ac3b20dc830d9b44f71d3a779bd2cd618583a99aad2fc9", - "pins" : [ - { - "identity" : "grpc-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift.git", - "state" : { - "revision" : "8c5e99d0255c373e0330730d191a3423c57373fb", - "version" : "1.24.2" - } - }, - { - "identity" : "opentelemetry-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/open-telemetry/opentelemetry-swift", - "state" : { - "revision" : "2ffffae2a027e2159dbf3fd53de1f25ba6d2d11d", - "version" : "1.13.0" - } - }, - { - "identity" : "opentracing-objc", - "kind" : "remoteSourceControl", - "location" : "https://github.com/undefinedlabs/opentracing-objc", - "state" : { - "revision" : "18c1a35ca966236cee0c5a714a51a73ff33384c1", - "version" : "0.5.2" - } - }, - { - "identity" : "swift-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-algorithms.git", - "state" : { - "revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023", - "version" : "1.2.1" - } - }, - { - "identity" : "swift-atomics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-atomics.git", - "state" : { - "revision" : "cd142fd2f64be2100422d658e7411e39489da985", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", - "version" : "1.1.4" - } - }, - { - "identity" : "swift-http-structured-headers", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-structured-headers.git", - "state" : { - "revision" : "f280fc7676b9940ff2c6598642751ea333c6544f", - "version" : "1.2.2" - } - }, - { - "identity" : "swift-http-types", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-types.git", - "state" : { - "revision" : "a0a57e949a8903563aba4615869310c0ebf14c03", - "version" : "1.4.0" - } - }, - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "3d8596ed08bd13520157f0355e35caed215ffbfa", - "version" : "1.6.3" - } - }, - { - "identity" : "swift-metrics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-metrics.git", - "state" : { - "revision" : "4c83e1cdf4ba538ef6e43a9bbd0bcc33a0ca46e3", - "version" : "2.7.0" - } - }, - { - "identity" : "swift-nio", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio.git", - "state" : { - "revision" : "0f54d58bb5db9e064f332e8524150de379d1e51c", - "version" : "2.82.1" - } - }, - { - "identity" : "swift-nio-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-extras.git", - "state" : { - "revision" : "f1f6f772198bee35d99dd145f1513d8581a54f2c", - "version" : "1.26.0" - } - }, - { - "identity" : "swift-nio-http2", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-http2.git", - "state" : { - "revision" : "4281466512f63d1bd530e33f4aa6993ee7864be0", - "version" : "1.36.0" - } - }, - { - "identity" : "swift-nio-ssl", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-ssl.git", - "state" : { - "revision" : "6df102a39c8da5fdc2eae29a0f63546d660866fc", - "version" : "2.30.0" - } - }, - { - "identity" : "swift-nio-transport-services", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-transport-services.git", - "state" : { - "revision" : "cd1e89816d345d2523b11c55654570acd5cd4c56", - "version" : "1.24.0" - } - }, - { - "identity" : "swift-numerics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics.git", - "state" : { - "revision" : "e0ec0f5f3af6f3e4d5e7a19d2af26b481acb6ba8", - "version" : "1.0.3" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "d72aed98f8253ec1aa9ea1141e28150f408cf17f", - "version" : "1.29.0" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system.git", - "state" : { - "revision" : "a34201439c74b53f0fd71ef11741af7e7caf01e1", - "version" : "1.4.2" - } - }, - { - "identity" : "thrift-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/undefinedlabs/Thrift-Swift", - "state" : { - "revision" : "18ff09e6b30e589ed38f90a1af23e193b8ecef8e", - "version" : "1.1.2" - } - } - ], - "version" : 3 -} diff --git a/benchmarks/ios/BenchmarkVitals/BenchMarkVitalsImplementation.swift b/benchmarks/ios/BenchmarkVitals/BenchMarkVitalsImplementation.swift index 546973eac..9df4e5ee7 100644 --- a/benchmarks/ios/BenchmarkVitals/BenchMarkVitalsImplementation.swift +++ b/benchmarks/ios/BenchmarkVitals/BenchMarkVitalsImplementation.swift @@ -6,7 +6,6 @@ import Foundation import React -import DatadogBenchmarks struct NativeTestConfig { let scenario: String @@ -14,6 +13,7 @@ struct NativeTestConfig { let clientToken: String let applicationID: String let apiKey: String + let env: String init(from dict: NSDictionary) { self.scenario = dict["scenario"] as? String ?? "" @@ -21,6 +21,7 @@ struct NativeTestConfig { self.clientToken = dict["clientToken"] as? String ?? "" self.applicationID = dict["applicationID"] as? String ?? "" self.apiKey = dict["apiKey"] as? String ?? "" + self.env = dict["env"] as? String ?? "" } } @@ -44,6 +45,7 @@ public class BenchmarkVitalsImplementation: NSObject { applicationIdentifier: appId, applicationName: appName, applicationVersion: appVersion, + env: nativeConfig.env, sdkVersion: "", deviceModel: deviceModel, osName: osName, diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkMeter.swift b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkMeter.swift index 694b6ae07..7108e5f3b 100644 --- a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkMeter.swift +++ b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkMeter.swift @@ -6,48 +6,57 @@ import Foundation import DatadogInternal -import DatadogBenchmarks import OpenTelemetryApi +import OpenTelemetrySdk internal final class Meter: DatadogInternal.BenchmarkMeter { - let meter: OpenTelemetryApi.Meter + let meter: MeterSdk - init(provider: MeterProvider) { - self.meter = provider.get( - instrumentationName: "benchmarks", - instrumentationVersion: nil - ) + init(provider: MeterProviderSdk) { + self.meter = provider.get(name: "benchmarks") } func counter(metric: @autoclosure () -> String) -> DatadogInternal.BenchmarkCounter { - meter.createDoubleCounter(name: metric()) + DoubleCounterWrapper(counter: meter.counterBuilder(name: metric()).ofDoubles().build()) } func gauge(metric: @autoclosure () -> String) -> DatadogInternal.BenchmarkGauge { - meter.createDoubleMeasure(name: metric()) + DoubleGaugeWrapper(gauge: meter.gaugeBuilder(name: metric()).build()) } func observe(metric: @autoclosure () -> String, callback: @escaping (any DatadogInternal.BenchmarkGauge) -> Void) { - _ = meter.createDoubleObserver(name: metric()) { callback(DoubleObserverWrapper(observer: $0)) } + _ = meter.gaugeBuilder(name: metric()).buildWithCallback { callback(ObservableDoubleMeasurementWrapper(measurement: $0)) } } } -extension AnyCounterMetric: DatadogInternal.BenchmarkCounter { - public func add(value: Double, attributes: @autoclosure () -> [String: String]) { - add(value: value, labelset: LabelSet(labels: attributes())) +private final class DoubleCounterWrapper: DatadogInternal.BenchmarkCounter { + var counter: DoubleCounterSdk + + init(counter: DoubleCounterSdk) { + self.counter = counter + } + + func add(value: Double, attributes: @autoclosure () -> [String: String]) { + counter.add(value: value, attributes: attributes().mapValues { AttributeValue.string($0) }) } } -extension AnyMeasureMetric: DatadogInternal.BenchmarkGauge { - public func record(value: Double, attributes: @autoclosure () -> [String: String]) { - record(value: value, labelset: LabelSet(labels: attributes())) +private final class DoubleGaugeWrapper: DatadogInternal.BenchmarkGauge { + let gauge: DoubleGaugeSdk + + init(gauge: DoubleGaugeSdk) { + self.gauge = gauge + } + + func record(value: Double, attributes: @autoclosure () -> [String: String]) { + gauge.record(value: value, attributes: attributes().mapValues { AttributeValue.string($0) }) } } -private struct DoubleObserverWrapper: DatadogInternal.BenchmarkGauge { - let observer: DoubleObserverMetric +private struct ObservableDoubleMeasurementWrapper: DatadogInternal.BenchmarkGauge { + let measurement: ObservableMeasurementSdk func record(value: Double, attributes: @autoclosure () -> [String: String]) { - observer.observe(value: value, labelset: LabelSet(labels: attributes())) + measurement.record(value: value, attributes: attributes().mapValues { AttributeValue.string($0) }) } } diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkProfiler.swift b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkProfiler.swift index e19b6759b..1cfeb1a77 100644 --- a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkProfiler.swift +++ b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkProfiler.swift @@ -6,7 +6,6 @@ import Foundation import DatadogInternal -import DatadogBenchmarks import OpenTelemetryApi internal final class Profiler: DatadogInternal.BenchmarkProfiler { diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkVitals.swift b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkVitals.swift index 772c6b76e..762c11bf2 100644 --- a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkVitals.swift +++ b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkVitals.swift @@ -5,30 +5,30 @@ */ import Foundation -import DatadogBenchmarks import OpenTelemetryApi +import OpenTelemetrySdk /// Collect Vital Metrics such CPU, Memory, and FPS. /// /// The metrics are reported via opentelemetry. internal final class Vitals { - let provider: OpenTelemetryApi.MeterProvider + let provider: MeterProviderSdk - private lazy var meter: OpenTelemetryApi.Meter = provider.get(instrumentationName: "vitals", instrumentationVersion: nil) + private lazy var meter: MeterSdk = provider.get(name: "vitals") let queue = DispatchQueue(label: "com.datadoghq.benchmarks.rn.ios.vitals", target: .global(qos: .utility)) - init(provider: MeterProvider) { + init(provider: MeterProviderSdk) { self.provider = provider } @discardableResult - func observeMemory() -> OpenTelemetryApi.DoubleObserverMetric { + func observeMemory() -> ObservableInstrumentSdk { let memory = Memory(queue: queue) - return meter.createDoubleObservableGauge(name: "rn.ios.benchmark.memory") { metric in + return meter.gaugeBuilder(name: "rn.ios.benchmark.memory").buildWithCallback { measurement in // report the maximum memory footprint that was recorded during push interval if let value = memory.aggregation?.max { - metric.observe(value: value, labelset: .empty) + measurement.record(value: value) } memory.reset() @@ -36,12 +36,12 @@ internal final class Vitals { } @discardableResult - func observeCPU() -> OpenTelemetryApi.DoubleObserverMetric { + func observeCPU() -> ObservableInstrumentSdk { let cpu = CPU(queue: queue) - return meter.createDoubleObservableGauge(name: "rn.ios.benchmark.cpu") { metric in + return meter.gaugeBuilder(name: "rn.ios.benchmark.cpu").buildWithCallback { measurement in // report the average cpu usage that was recorded during push interval if let value = cpu.aggregation?.avg { - metric.observe(value: value, labelset: .empty) + measurement.record(value: value) } cpu.reset() @@ -49,12 +49,12 @@ internal final class Vitals { } @discardableResult - func observeFPS() -> OpenTelemetryApi.IntObserverMetric { + func observeFPS() -> ObservableInstrumentSdk { let fps = FPS() - return meter.createIntObservableGauge(name: "rn.ios.benchmark.fps.min") { metric in + return meter.gaugeBuilder(name: "rn.ios.benchmark.fps.min").ofLongs().buildWithCallback { measurement in // report the minimum frame rate that was recorded during push interval if let value = fps.aggregation?.min { - metric.observe(value: value, labelset: .empty) + measurement.record(value: value) } fps.reset() diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/Package.swift b/benchmarks/ios/BenchmarkVitals/Vitals/Package.swift deleted file mode 100644 index ff099cb82..000000000 --- a/benchmarks/ios/BenchmarkVitals/Vitals/Package.swift +++ /dev/null @@ -1,38 +0,0 @@ -// swift-tools-version: 5.9 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription -import Foundation - -let package = Package( - name: "DatadogBenchmarks", - products: [ - .library( - name: "DatadogBenchmarks", - targets: ["DatadogBenchmarks"] - ) - ] -) - -func addOpenTelemetryDependency(_ version: Version) { - package.platforms = [.iOS(.v13), .tvOS(.v13)] - - package.dependencies = [ - .package(url: "https://github.com/open-telemetry/opentelemetry-swift", exact: version) - ] - - package.targets = [ - .target( - name: "DatadogBenchmarks", - dependencies: [ - .product(name: "OpenTelemetryApi", package: "opentelemetry-swift"), - .product(name: "OpenTelemetrySdk", package: "opentelemetry-swift"), - .product(name: "DatadogExporter", package: "opentelemetry-swift") - ], - swiftSettings: [.define("OTEL_SWIFT")] - ) - ] -} - -addOpenTelemetryDependency("1.13.0") - diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Benchmarks.swift b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Benchmarks.swift index 020c14af6..8cae622e6 100644 --- a/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Benchmarks.swift +++ b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Benchmarks.swift @@ -11,7 +11,6 @@ import Foundation import OpenTelemetryApi import OpenTelemetrySdk -import DatadogExporter /// Benchmark entrypoint to configure opentelemetry with metrics meters /// and tracer. @@ -24,6 +23,7 @@ public enum Benchmarks { var applicationIdentifier: String var applicationName: String var applicationVersion: String + var env: String var sdkVersion: String var deviceModel: String var osName: String @@ -36,6 +36,7 @@ public enum Benchmarks { applicationIdentifier: String, applicationName: String, applicationVersion: String, + env: String, sdkVersion: String, deviceModel: String, osName: String, @@ -47,6 +48,7 @@ public enum Benchmarks { self.applicationIdentifier = applicationIdentifier self.applicationName = applicationName self.applicationVersion = applicationVersion + self.env = env self.sdkVersion = sdkVersion self.deviceModel = deviceModel self.osName = osName @@ -75,7 +77,7 @@ public enum Benchmarks { /// Configure an OpenTelemetry meter provider. /// /// - Parameter configuration: The Benchmark configuration. - public static func meterProvider(with configuration: Configuration) -> MeterProvider { + public static func meterProvider(with configuration: Configuration) -> MeterProviderSdk { let metricExporter = MetricExporter( configuration: MetricExporter.Configuration( apiKey: configuration.apiKey, @@ -83,20 +85,30 @@ public enum Benchmarks { ) ) - return MeterProviderBuilder() - .with(pushInterval: 10) - .with(processor: MetricProcessorSdk()) - .with(exporter: metricExporter) - .with(resource: Resource(attributes: [ + let metricReader = PeriodicMetricReaderBuilder(exporter: metricExporter) + .setInterval(timeInterval: 10) + .build() + + return MeterProviderSdk.builder() + .setResource(resource: Resource(attributes: [ "device_model": .string(configuration.context.deviceModel), "os": .string(configuration.context.osName), "os_version": .string(configuration.context.osVersion), "run": .string(configuration.context.run), "scenario": .string(configuration.context.scenario), + "env": .string(configuration.context.env), "application_id": .string(configuration.context.applicationIdentifier), "sdk_version": .string(configuration.context.sdkVersion), "branch": .string(configuration.context.branch), ])) + .registerMetricReader(reader: metricReader) + // Workaround: register a catch-all view since the SDK doesn't use default views + .registerView( + selector: InstrumentSelector.builder() + .setInstrument(name: ".*") + .build(), + view: View.builder().build() + ) .build() } @@ -104,22 +116,6 @@ public enum Benchmarks { /// /// - Parameter configuration: The Benchmark configuration. public static func tracerProvider(with configuration: Configuration) -> TracerProvider { - let exporterConfiguration = ExporterConfiguration( - serviceName: configuration.context.applicationIdentifier, - resource: "Benchmark Tracer", - applicationName: configuration.context.applicationName, - applicationVersion: configuration.context.applicationVersion, - environment: "benchmarks", - apiKey: configuration.apiKey, - endpoint: .us1, - uploadCondition: { true } - ) - - let exporter = try! DatadogExporter(config: exporterConfiguration) - let processor = SimpleSpanProcessor(spanExporter: exporter) - - return TracerProviderBuilder() - .add(spanProcessor: processor) - .build() + return NOPTracerProvider() } } diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/Sources/MetricExporter.swift b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/MetricExporter.swift index 5109a455c..d034f8d44 100644 --- a/benchmarks/ios/BenchmarkVitals/Vitals/Sources/MetricExporter.swift +++ b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/MetricExporter.swift @@ -8,7 +8,7 @@ import Foundation import OpenTelemetrySdk enum MetricExporterError: Error { - case unsupportedMetric(aggregation: AggregationType, dataType: Any.Type) + case unsupportedMetric(type: MetricDataType, dataType: Any.Type) } /// Replacement of otel `DatadogExporter` for metrics. @@ -68,51 +68,57 @@ final class MetricExporter: OpenTelemetrySdk.MetricExporter { self.configuration = configuration } - func export(metrics: [Metric], shouldCancel: (() -> Bool)?) -> MetricExporterResultCode { + func export(metrics: [MetricData]) -> ExportResult { do { let series = try metrics.map(transform) try submit(series: series) - return.success + return .success } catch { - return .failureNotRetryable + return .failure } } - /// Transforms otel `Metric` to Datadog `serie`. + func flush() -> ExportResult { + return .success + } + + func shutdown() -> ExportResult { + return .success + } + + func getAggregationTemporality(for instrument: InstrumentType) -> AggregationTemporality { + return .cumulative + } + + /// Transforms otel `MetricData` to Datadog `serie`. /// - /// - Parameter metric: The otel metric + /// - Parameter metric: The otel metric data /// - Returns: The timeserie. - func transform(_ metric: Metric) throws -> Serie { + func transform(_ metric: MetricData) throws -> Serie { var tags = Set(metric.resource.attributes.map { "\($0):\($1)" }) - let points: [Serie.Point] = try metric.data.map { data in - let timestamp = Int64(data.timestamp.timeIntervalSince1970) + let points: [Serie.Point] = try metric.data.points.map { point in + let timestamp = Int64(point.endEpochNanos / 1_000_000_000) // Convert nanos to seconds - data.labels.forEach { tags.insert("\($0):\($1)") } + point.attributes.forEach { tags.insert("\($0):\($1)") } - switch data { - case let data as SumData: - return Serie.Point(timestamp: timestamp, value: data.sum) - case let data as SumData: - return Serie.Point(timestamp: timestamp, value: Double(data.sum)) - case let data as SummaryData: + switch point { + case let data as DoublePointData: + return Serie.Point(timestamp: timestamp, value: data.value) + case let data as LongPointData: + return Serie.Point(timestamp: timestamp, value: Double(data.value)) + case let data as SummaryPointData: return Serie.Point(timestamp: timestamp, value: data.sum) - case let data as SummaryData: - return Serie.Point(timestamp: timestamp, value: Double(data.sum)) -// case let data as HistogramData: -// return Serie.Point(timestamp: timestamp, value: Double(data.sum)) -// case let data as HistogramData: -// return Serie.Point(timestamp: timestamp, value: data.sum) default: throw MetricExporterError.unsupportedMetric( - aggregation: metric.aggregationType, - dataType: type(of: data) + type: metric.type, + dataType: type(of: point) ) } } return Serie( - type: MetricType(metric.aggregationType), + type: MetricType(metric.type), interval: nil, metric: metric.name, unit: nil, @@ -149,13 +155,13 @@ final class MetricExporter: OpenTelemetrySdk.MetricExporter { } private extension MetricExporter.MetricType { - init(_ type: OpenTelemetrySdk.AggregationType) { + init(_ type: MetricDataType) { switch type { - case .doubleSum, .intSum: + case .DoubleSum, .LongSum: self = .count - case .intGauge, .doubleGauge: + case .LongGauge, .DoubleGauge: self = .gauge - case .doubleSummary, .intSummary, .doubleHistogram, .intHistogram: + case .Summary, .Histogram, .ExponentialHistogram: self = .unspecified } } diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/Sources/TracerProvider.swift b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/TracerProvider.swift new file mode 100644 index 000000000..c686071a3 --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/TracerProvider.swift @@ -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 2019-Present Datadog, Inc. + */ + +import Foundation +import OpenTelemetryApi + +/// A no-op TracerProvider that crashes if the tracer is actually used. +class NOPTracerProvider: TracerProvider { + func get( + instrumentationName: String, + instrumentationVersion: String?, + schemaUrl: String?, + attributes: [String: AttributeValue]? + ) -> any Tracer { + return NOPTracer() + } +} + +/// A no-op Tracer that crashes if used. +private class NOPTracer: Tracer { + func spanBuilder(spanName: String) -> any SpanBuilder { // swiftlint:disable:this unavailable_function + fatalError("NOPTracer should not be used. Tracing is not implemented in Benchmarks.") + } +} diff --git a/benchmarks/ios/Podfile b/benchmarks/ios/Podfile index 02dc111b0..6adb02df5 100644 --- a/benchmarks/ios/Podfile +++ b/benchmarks/ios/Podfile @@ -25,6 +25,10 @@ target 'BenchmarkRunner' do :app_path => "#{Pod::Config.instance.installation_root}/.." ) + # OpenTelemetrySdk is needed by the BenchmarkVitals code (metrics exporter, meter provider). + # OpenTelemetryApi is already pulled in transitively via DatadogTrace, but OpenTelemetrySdk is not. + pod 'OpenTelemetry-Swift-Sdk', '~> 2.3.0' + post_install do |installer| # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 react_native_post_install( diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock index 771bfab42..f1b8298ba 100644 --- a/benchmarks/ios/Podfile.lock +++ b/benchmarks/ios/Podfile.lock @@ -1,22 +1,26 @@ PODS: - boost (1.84.0) - - DatadogCore (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogCrashReporting (2.30.2): - - DatadogInternal (= 2.30.2) - - 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.14.1): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogCore (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogCrashReporting (3.5.0): + - DatadogInternal (= 3.5.0) + - KSCrash/Filters (= 2.5.0) + - KSCrash/Recording (= 2.5.0) + - DatadogFlags (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogInternal (3.5.0) + - DatadogLogs (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogRUM (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogSDKReactNative (3.1.0): + - DatadogCore (= 3.5.0) + - DatadogCrashReporting (= 3.5.0) + - DatadogFlags (= 3.5.0) + - DatadogLogs (= 3.5.0) + - DatadogRUM (= 3.5.0) + - DatadogTrace (= 3.5.0) + - DatadogWebViewTracking (= 3.5.0) - DoubleConversion - glog - hermes-engine @@ -37,9 +41,9 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeSessionReplay (2.14.1): + - DatadogSDKReactNativeSessionReplay (3.1.0): - DatadogSDKReactNative - - DatadogSessionReplay (= 2.30.2) + - DatadogSessionReplay (= 3.5.0) - DoubleConversion - glog - hermes-engine @@ -60,10 +64,10 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.14.1): - - DatadogInternal (= 2.30.2) + - DatadogSDKReactNativeWebView (3.1.0): + - DatadogInternal (= 3.5.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 2.30.2) + - DatadogWebViewTracking (= 3.5.0) - DoubleConversion - glog - hermes-engine @@ -84,13 +88,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) - - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogSessionReplay (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogTrace (3.5.0): + - DatadogInternal (= 3.5.0) + - OpenTelemetry-Swift-Api (~> 2.3.0) + - DatadogWebViewTracking (3.5.0): + - DatadogInternal (= 3.5.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.78.2) @@ -99,8 +103,20 @@ PODS: - hermes-engine (0.78.2): - hermes-engine/Pre-built (= 0.78.2) - hermes-engine/Pre-built (0.78.2) - - OpenTelemetrySwiftApi (1.13.1) - - PLCrashReporter (1.12.0) + - KSCrash/Core (2.5.0) + - KSCrash/Filters (2.5.0): + - KSCrash/Recording + - KSCrash/RecordingCore + - KSCrash/ReportingCore + - KSCrash/Recording (2.5.0): + - KSCrash/RecordingCore + - KSCrash/RecordingCore (2.5.0): + - KSCrash/Core + - KSCrash/ReportingCore (2.5.0): + - KSCrash/Core + - OpenTelemetry-Swift-Api (2.3.0) + - OpenTelemetry-Swift-Sdk (2.3.0): + - OpenTelemetry-Swift-Api (= 2.3.0) - RCT-Folly (2024.11.18.00): - boost - DoubleConversion @@ -1832,6 +1848,7 @@ DEPENDENCIES: - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - OpenTelemetry-Swift-Sdk (~> 2.3.0) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) @@ -1904,15 +1921,16 @@ SPEC REPOS: https://github.com/CocoaPods/Specs.git: - DatadogCore - DatadogCrashReporting + - DatadogFlags - DatadogInternal - DatadogLogs - DatadogRUM - DatadogSessionReplay - DatadogTrace - DatadogWebViewTracking - - OpenTelemetrySwiftApi - - PLCrashReporter - trunk: + - KSCrash + - OpenTelemetry-Swift-Api + - OpenTelemetry-Swift-Sdk - SocketRocket EXTERNAL SOURCES: @@ -2070,92 +2088,94 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 - DatadogCore: 8e50ad6cb68343f701707f7eeca16e0acb52ed8c - DatadogCrashReporting: 34763d4276d4fce286c7e8729cfcd2ac04dca43b - DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 - DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 - DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 14c7f36115fdd37841dd620f3376848204596909 - DatadogSDKReactNativeSessionReplay: 27bcc3d5280a85fb2a244b84916c1d01a43668e8 - DatadogSDKReactNativeWebView: 1849aa7769bde0a2a2088705e596276631769656 - DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 - DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 - DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be + DatadogCore: 4cbe2646591d2f96fb3188400863ec93ac411235 + DatadogCrashReporting: e48da3f880a59d2aa2d04e5034e56507177e9d64 + DatadogFlags: f8cf88371460d6c672abfd97fdc9af5be208f33b + DatadogInternal: 63308b529cd87fb2f99c5961d9ff13afb300a3aa + DatadogLogs: be538def1d5204e011f7952915ad0261014a0dd5 + DatadogRUM: cffc65659ce29546fcc2639a74003135259548fc + DatadogSDKReactNative: 9544a5f5b34f832a71d313c6edfb627a8e3a71f3 + DatadogSDKReactNativeSessionReplay: c33fe479991c92c8488eb127e7f22d315fdefb94 + DatadogSDKReactNativeWebView: 988ece4ef7dcc4b22c4c8188fd17177e3eb2d0c2 + DatadogSessionReplay: eea291df0135ec792177be1ffc4951750a66a011 + DatadogTrace: 085e35f9e4889f82f8a747922c58ea4b19728720 + DatadogWebViewTracking: 61b8344da898cbaccffc75bc1a17c86175e8573a DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 hermes-engine: 2771b98fb813fdc6f92edd7c9c0035ecabf9fee7 - OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 - PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 - RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 + KSCrash: 80e1e24eaefbe5134934ae11ca8d7746586bc2ed + OpenTelemetry-Swift-Api: 3d77582ab6837a63b65bf7d2eacc57d8f2595edd + OpenTelemetry-Swift-Sdk: 69d60f0242e830366e359481edd575d6776eb983 + 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 -PODFILE CHECKSUM: d7a3ce8590271749fb5b532390908bc3a583be46 +PODFILE CHECKSUM: 977a21a62f5373f05419c7d794a1a33a54f85bf4 COCOAPODS: 1.16.2 diff --git a/benchmarks/src/scenario/RUM/Auto/rumAutoScenario.tsx b/benchmarks/src/scenario/RUM/Auto/rumAutoScenario.tsx index 4e1d7b6df..19669e293 100644 --- a/benchmarks/src/scenario/RUM/Auto/rumAutoScenario.tsx +++ b/benchmarks/src/scenario/RUM/Auto/rumAutoScenario.tsx @@ -10,7 +10,7 @@ import { useNavigationContainerRef } from '@react-navigation/native'; import { DatadogProvider } from "@datadog/mobile-react-native"; import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; import { NavigationContainer } from "@react-navigation/native"; -import { DdRumReactNavigationTracking, type ViewNamePredicate } from '@datadog/mobile-react-navigation'; +import { DdRumReactNavigationTracking, type NavigationTrackingOptions, type ViewNamePredicate } from '@datadog/mobile-react-navigation'; import type { Route } from "@react-navigation/native"; import { RunType } from '../../../testSetup/types/testConfig'; import { getDatadogProviderConfig } from '../../../testSetup/testUtils'; @@ -31,12 +31,17 @@ function RUMAutoScenario(props: RUMAutoScenarioProps): React.JSX.Element { return `RN ${Platform.OS} Benchmark - RUM Auto - ${trackedName} / ${route.name}`; }; + const navigationTrackingOptions: NavigationTrackingOptions = { + viewNamePredicate, + }; + const onDatadogInitialization = () => { console.info("Datadog SDK initialized"); }; const Tab = createBottomTabNavigator(); const RootStack = createNativeStackNavigator(); + function TabNavigatior() { return ( @@ -60,7 +65,7 @@ function RUMAutoScenario(props: RUMAutoScenarioProps): React.JSX.Element { return ( { if (instrumented) { - DdRumReactNavigationTracking.startTrackingViews(navigationRef.current, viewNamePredicate); + DdRumReactNavigationTracking.startTrackingViews(navigationRef.current, navigationTrackingOptions); }; }}> @@ -88,4 +93,4 @@ function RUMAutoScenario(props: RUMAutoScenarioProps): React.JSX.Element { }; } -export default RUMAutoScenario; \ No newline at end of file +export default RUMAutoScenario; diff --git a/benchmarks/src/scenario/RUM/Auto/screens/characterDetail.tsx b/benchmarks/src/scenario/RUM/Auto/screens/characterDetail.tsx index 20329c589..a2445b58f 100644 --- a/benchmarks/src/scenario/RUM/Auto/screens/characterDetail.tsx +++ b/benchmarks/src/scenario/RUM/Auto/screens/characterDetail.tsx @@ -33,9 +33,8 @@ function CharacterDetailScreen(): React.JSX.Element { const onShowEpisodes = async () => { try { - const episodeNames = await Promise.all(episodeURLs.map((url) => - RickMortyService.fetchRequest(url).then(json => json.name) - )); + const episodeData = await RickMortyService.fetchEpisodesByIds(episodeURLs); + const episodeNames = episodeData.map(episode => episode.name); setEpisodes(episodeNames); } catch (_error) { Alert.alert("Something went wrong. Please try again later."); @@ -86,4 +85,4 @@ function CharacterDetailScreen(): React.JSX.Element { ); }; -export default CharacterDetailScreen; \ No newline at end of file +export default CharacterDetailScreen; diff --git a/benchmarks/src/scenario/RUM/Auto/screens/episodeDetail.tsx b/benchmarks/src/scenario/RUM/Auto/screens/episodeDetail.tsx index a6a280af8..fb8d92dcc 100644 --- a/benchmarks/src/scenario/RUM/Auto/screens/episodeDetail.tsx +++ b/benchmarks/src/scenario/RUM/Auto/screens/episodeDetail.tsx @@ -38,10 +38,8 @@ function EpisodeDetailScreen(): React.JSX.Element { const getCharacters = async () => { try { setIsLoading(true); - const charaterList = await Promise.all(characterURLS.map((url) => - RickMortyService.fetchRequest(url).then(json => json as Character) - )); - setCharacters(charaterList); + const characterList = await RickMortyService.fetchCharactersByIds(characterURLS); + setCharacters(characterList as Character[]); } catch (_error) { Alert.alert("Something went wrong. Please try again later."); } finally { @@ -103,4 +101,4 @@ function EpisodeDetailScreen(): React.JSX.Element { ); }; -export default EpisodeDetailScreen; \ No newline at end of file +export default EpisodeDetailScreen; diff --git a/benchmarks/src/scenario/RUM/Auto/screens/locationDetail.tsx b/benchmarks/src/scenario/RUM/Auto/screens/locationDetail.tsx index 263a31c17..cde7a95e6 100644 --- a/benchmarks/src/scenario/RUM/Auto/screens/locationDetail.tsx +++ b/benchmarks/src/scenario/RUM/Auto/screens/locationDetail.tsx @@ -38,10 +38,8 @@ function LocationDetailScreen(): React.JSX.Element { const getCharacters = async () => { try { setIsLoading(true); - const charaterList = await Promise.all(characterURLS.map((url) => - RickMortyService.fetchRequest(url).then(json => json as Character) - )); - setCharacters(charaterList); + const characterList = await RickMortyService.fetchCharactersByIds(characterURLS); + setCharacters(characterList as Character[]); } catch (_error) { Alert.alert("Something went wrong. Please try again later."); } finally { @@ -103,4 +101,4 @@ function LocationDetailScreen(): React.JSX.Element { ); }; -export default LocationDetailScreen; \ No newline at end of file +export default LocationDetailScreen; diff --git a/benchmarks/src/scenario/RUM/Auto/service/rickMorty.ts b/benchmarks/src/scenario/RUM/Auto/service/rickMorty.ts index 2c776dfef..8a15a120b 100644 --- a/benchmarks/src/scenario/RUM/Auto/service/rickMorty.ts +++ b/benchmarks/src/scenario/RUM/Auto/service/rickMorty.ts @@ -10,27 +10,121 @@ const CHARACTERS_ENDPOINT = "character"; const LOCATIONS_ENDPOINT = "location"; const EPISODES_ENDPOINT = "episode"; +const MAX_CONCURRENT_REQUESTS = 1; +const REQUEST_DELAY_MS = 600; +interface QueuedRequest { + url: string; + resolve: (value: any) => void; + reject: (error: any) => void; +} + class RickMortyService { - fetchRequest(url: string, page?: number) { - const fullURL = url + (page ? ("?page=" + page.toString()) : ''); - return fetch(fullURL).then((data) => { - return data.json(); - }).catch((_error) => { - return Promise.reject(); - }) - }; + private requestQueue: QueuedRequest[] = []; + private activeRequests = 0; + private isProcessing = false; + + private delay(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + private async processQueue(): Promise { + if (this.isProcessing) { + return; + } + + this.isProcessing = true; + + while (this.requestQueue.length > 0 && this.activeRequests < MAX_CONCURRENT_REQUESTS) { + const request = this.requestQueue.shift(); + if (!request) break; + + this.activeRequests++; + + try { + await this.delay(REQUEST_DELAY_MS); + + const response = await fetch(request.url); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + const data = await response.json(); + request.resolve(data); + } catch (error) { + request.reject(error); + } finally { + this.activeRequests--; + } + } + + this.isProcessing = false; + + if (this.requestQueue.length > 0) { + this.processQueue(); + } + } + + fetchRequest(url: string, page?: number): Promise { + const fullURL = url + (page ? `?page=${page}` : ''); + + return new Promise((resolve, reject) => { + this.requestQueue.push({ + url: fullURL, + resolve, + reject + }); + + this.processQueue(); + }); + } + + private extractIdFromUrl(url: string): string | null { + const match = url.match(/\/(\d+)$/); + return match ? match[1] : null; + } + + private async fetchByIds(endpoint: string, urls: string[], resourceType: string): Promise { + const ids = urls.map(url => this.extractIdFromUrl(url)).filter(Boolean); + if (ids.length === 0) return []; + + const batchUrl = `${BASE_URL}/${endpoint}/${ids.join(',')}`; + + try { + const response = await fetch(batchUrl); + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + const data = await response.json(); + return Array.isArray(data) ? data : [data]; + } catch (error) { + throw error; + } + } fetchCharacters(page?: number) { return this.fetchRequest(BASE_URL + "/" + CHARACTERS_ENDPOINT, page); - }; + } fetchLocations(page?: number) { return this.fetchRequest(BASE_URL + "/" + LOCATIONS_ENDPOINT, page); - }; + } fetchEpisodes(page?: number) { return this.fetchRequest(BASE_URL + "/" + EPISODES_ENDPOINT, page); - }; + } + + fetchCharactersByIds(urls: string[]): Promise { + return this.fetchByIds(CHARACTERS_ENDPOINT, urls, 'characters'); + } + + fetchEpisodesByIds(urls: string[]): Promise { + return this.fetchByIds(EPISODES_ENDPOINT, urls, 'episodes'); + } + + fetchLocationsByIds(urls: string[]): Promise { + return this.fetchByIds(LOCATIONS_ENDPOINT, urls, 'locations'); + } }; -export default new RickMortyService(); \ No newline at end of file +export default new RickMortyService(); 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 { let config = new DatadogProviderConfiguration( baseConfig.clientToken ?? '', baseConfig.env ?? '', - baseConfig.applicationID ?? '', - true, - true, - true, - TrackingConsent.GRANTED + TrackingConsent.GRANTED, + { + rumConfiguration: { + applicationId: baseConfig.applicationID ?? '', + trackInteractions: true, + trackResources: true, + trackErrors: true, + sessionSampleRate: 100, + nativeCrashReportEnabled: true + }, + logsConfiguration: { + bundleLogsWithRum: true, + bundleLogsWithTraces: true, + }, + traceConfiguration: {} + } ); - - config.nativeCrashReportEnabled = true - config.sessionSamplingRate = 100; - config.serviceName = `com.rn.${platform}.benchmark` + config.service = `com.rn.${platform}.benchmark` config.verbosity = SdkVerbosity.DEBUG; return config; @@ -57,18 +65,27 @@ export const getDatadogProviderConfig = () => { export const initializeDatadog = (clientToken?: string, environment?: string, appId?: string): Promise => { const platform = Platform.OS; - const config = new DdSdkReactNativeConfiguration( + const config = new CoreConfiguration( clientToken ?? '', environment ?? '', - appId ?? '', - true, - true, - true, - TrackingConsent.GRANTED + TrackingConsent.GRANTED, + { + rumConfiguration: { + applicationId: appId ?? "", + trackInteractions: true, + trackResources: true, + trackErrors: true, + sessionSampleRate: 100, + nativeCrashReportEnabled: true, + }, + logsConfiguration: { + bundleLogsWithRum: true, + bundleLogsWithTraces: true, + }, + traceConfiguration: {} + } ); - config.nativeCrashReportEnabled = true - config.sessionSamplingRate = 100; - config.serviceName = `com.rn.${platform}.benchmark` + config.service = `com.rn.${platform}.benchmark` config.verbosity = SdkVerbosity.DEBUG; return DdSdkReactNative.initialize(config); @@ -101,6 +118,7 @@ export const startCollectingVitals = async (testConfig: TestConfig, datadogConfi clientToken: datadogConfig.clientToken, applicationID: datadogConfig.applicationID, apiKey: datadogConfig.apiKey, + env: datadogConfig.env, }; await BenchmarkVitals?.startCollectingVitals(nativeTestConfig); @@ -121,4 +139,4 @@ export const isValidScenario = (scenario?: string): boolean => { export const sleep = (ms: number) => { return new Promise(resolve => setTimeout(resolve, ms)); -}; \ No newline at end of file +}; diff --git a/benchmarks/src/testSetup/types/testConfig.ts b/benchmarks/src/testSetup/types/testConfig.ts index dae7587d1..b60444a6e 100644 --- a/benchmarks/src/testSetup/types/testConfig.ts +++ b/benchmarks/src/testSetup/types/testConfig.ts @@ -48,4 +48,5 @@ export interface NativeTestConfig { clientToken?: string; applicationID?: string; apiKey?: string; + env?: string, } 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/App.tsx b/example-new-architecture/App.tsx index e830aa345..628c90c88 100644 --- a/example-new-architecture/App.tsx +++ b/example-new-architecture/App.tsx @@ -1,5 +1,5 @@ import { - DdSdkReactNativeConfiguration, + CoreConfiguration, SdkVerbosity, UploadFrequency, BatchSize, @@ -8,10 +8,19 @@ import { RumActionType, DdLogs, DdTrace, + TrackingConsent, + DdFlags, } from '@datadog/mobile-react-native'; -import React from 'react'; +import {DatadogOpenFeatureProvider} from '@datadog/mobile-react-native-openfeature'; +import { + OpenFeature, + OpenFeatureProvider, + useObjectFlagDetails, +} from '@openfeature/react-sdk'; +import React, {Suspense} from 'react'; import type {PropsWithChildren} from 'react'; import { + ActivityIndicator, SafeAreaView, ScrollView, StatusBar, @@ -32,63 +41,85 @@ import { import {APPLICATION_ID, CLIENT_TOKEN, ENVIRONMENT} from './ddCredentials'; (async () => { - const config = new DdSdkReactNativeConfiguration( + const config = new CoreConfiguration( CLIENT_TOKEN, ENVIRONMENT, - APPLICATION_ID, - true, - true, - true, + TrackingConsent.GRANTED, + { + rumConfiguration: { + applicationId: APPLICATION_ID, + trackInteractions: true, + trackResources: true, + trackFrustrations: true, + trackErrors: true, + sessionSampleRate: 100, + telemetrySampleRate: 100, + nativeCrashReportEnabled: true + }, + logsConfiguration: {}, + traceConfiguration: {} + } ); - config.sessionSamplingRate = 100; config.verbosity = SdkVerbosity.DEBUG; - config.telemetrySampleRate = 100; config.uploadFrequency = UploadFrequency.FREQUENT; config.batchSize = BatchSize.SMALL; + + // Initialize the Datadog SDK. await DdSdkReactNative.initialize(config); + + // Enable Datadog Flags feature. + await DdFlags.enable(); + + // Set the provider with OpenFeature. + const provider = new DatadogOpenFeatureProvider(); + OpenFeature.setProvider(provider); + + // Datadog SDK usage examples. await DdRum.startView('main', 'Main'); setTimeout(async () => { await DdRum.addTiming('one_second'); }, 1000); await DdRum.addAction(RumActionType.CUSTOM, 'custom action'); + await DdLogs.info('info log'); + const spanId = await DdTrace.startSpan('test span'); await DdTrace.finishSpan(spanId); })(); -type SectionProps = PropsWithChildren<{ - title: string; -}>; +function AppWithProviders() { + React.useEffect(() => { + const user = { + id: 'user-123', + favoriteFruit: 'apple', + }; + + OpenFeature.setContext({ + targetingKey: user.id, + favoriteFruit: user.favoriteFruit, + }); + }, []); -function Section({children, title}: SectionProps): React.JSX.Element { - const isDarkMode = useColorScheme() === 'dark'; return ( - - - {title} - - - {children} - - + + + + }> + + + + ); } function App(): React.JSX.Element { - const isDarkMode = useColorScheme() === 'dark'; + const greetingFlag = useObjectFlagDetails('rn-sdk-test-json-flag', { + greeting: 'Default greeting', + }); + const isDarkMode = useColorScheme() === 'dark'; const backgroundStyle = { backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, }; @@ -99,14 +130,21 @@ function App(): React.JSX.Element { barStyle={isDarkMode ? 'light-content' : 'dark-content'} backgroundColor={backgroundStyle.backgroundColor} /> - +
- + + +
+ The title of this section is based on the{' '} + {greetingFlag.flagKey} feature + flag.{'\n\n'} + If it's different from "Default greeting", then it is coming from + the feature flag evaluation.{'\n\n'} + Evaluation reason is {greetingFlag.reason}.{'\n\n'}Inspect greetingFlag in{' '} + App.tsx for more evaluation + details. +
+
Edit App.tsx to change this screen and then come back to see your edits. @@ -127,6 +165,36 @@ function App(): React.JSX.Element { ); } +type SectionProps = PropsWithChildren<{ + title: string; +}>; + +function Section({children, title}: SectionProps): React.JSX.Element { + const isDarkMode = useColorScheme() === 'dark'; + return ( + + + {title} + + + {children} + + + ); +} + const styles = StyleSheet.create({ sectionContainer: { marginTop: 32, @@ -146,4 +214,4 @@ const styles = StyleSheet.create({ }, }); -export default App; +export default AppWithProviders; diff --git a/example-new-architecture/ios/Podfile b/example-new-architecture/ios/Podfile index f2f0fa09f..3c29ed272 100644 --- a/example-new-architecture/ios/Podfile +++ b/example-new-architecture/ios/Podfile @@ -26,7 +26,7 @@ target 'DdSdkReactNativeExample' do # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) - + post_install do |installer| # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 react_native_post_install( diff --git a/example-new-architecture/ios/Podfile.lock b/example-new-architecture/ios/Podfile.lock index ca3b81b1d..a41be60f4 100644 --- a/example-new-architecture/ios/Podfile.lock +++ b/example-new-architecture/ios/Podfile.lock @@ -1,22 +1,26 @@ PODS: - boost (1.84.0) - - DatadogCore (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogCrashReporting (2.30.2): - - DatadogInternal (= 2.30.2) - - 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.14.1): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogCore (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogCrashReporting (3.5.0): + - DatadogInternal (= 3.5.0) + - KSCrash/Filters (= 2.5.0) + - KSCrash/Recording (= 2.5.0) + - DatadogFlags (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogInternal (3.5.0) + - DatadogLogs (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogRUM (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogSDKReactNative (3.1.0): + - DatadogCore (= 3.5.0) + - DatadogCrashReporting (= 3.5.0) + - DatadogFlags (= 3.5.0) + - DatadogLogs (= 3.5.0) + - DatadogRUM (= 3.5.0) + - DatadogTrace (= 3.5.0) + - DatadogWebViewTracking (= 3.5.0) - DoubleConversion - glog - hermes-engine @@ -37,13 +41,14 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNative/Tests (2.14.1): - - 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 (3.1.0): + - DatadogCore (= 3.5.0) + - DatadogCrashReporting (= 3.5.0) + - DatadogFlags (= 3.5.0) + - DatadogLogs (= 3.5.0) + - DatadogRUM (= 3.5.0) + - DatadogTrace (= 3.5.0) + - DatadogWebViewTracking (= 3.5.0) - DoubleConversion - glog - hermes-engine @@ -64,11 +69,11 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogTrace (2.30.2): - - DatadogInternal (= 2.30.2) - - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogTrace (3.5.0): + - DatadogInternal (= 3.5.0) + - OpenTelemetry-Swift-Api (~> 2.3.0) + - DatadogWebViewTracking (3.5.0): + - DatadogInternal (= 3.5.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -77,8 +82,18 @@ PODS: - hermes-engine (0.76.9): - hermes-engine/Pre-built (= 0.76.9) - hermes-engine/Pre-built (0.76.9) - - OpenTelemetrySwiftApi (1.13.1) - - PLCrashReporter (1.12.0) + - KSCrash/Core (2.5.0) + - KSCrash/Filters (2.5.0): + - KSCrash/Recording + - KSCrash/RecordingCore + - KSCrash/ReportingCore + - KSCrash/Recording (2.5.0): + - KSCrash/RecordingCore + - KSCrash/RecordingCore (2.5.0): + - KSCrash/Core + - KSCrash/ReportingCore (2.5.0): + - KSCrash/Core + - OpenTelemetry-Swift-Api (2.3.0) - RCT-Folly (2024.10.14.00): - boost - DoubleConversion @@ -1706,13 +1721,14 @@ SPEC REPOS: https://github.com/CocoaPods/Specs.git: - DatadogCore - DatadogCrashReporting + - DatadogFlags - DatadogInternal - DatadogLogs - DatadogRUM - DatadogTrace - DatadogWebViewTracking - - OpenTelemetrySwiftApi - - PLCrashReporter + - KSCrash + - OpenTelemetry-Swift-Api - SocketRocket EXTERNAL SOURCES: @@ -1850,22 +1866,23 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 8e50ad6cb68343f701707f7eeca16e0acb52ed8c - DatadogCrashReporting: 34763d4276d4fce286c7e8729cfcd2ac04dca43b - DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 - DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 - DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 3092efeaf685e37afe770740ef058ee3f9f5bf5d - DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 - DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be + DatadogCore: 4cbe2646591d2f96fb3188400863ec93ac411235 + DatadogCrashReporting: e48da3f880a59d2aa2d04e5034e56507177e9d64 + DatadogFlags: f8cf88371460d6c672abfd97fdc9af5be208f33b + DatadogInternal: 63308b529cd87fb2f99c5961d9ff13afb300a3aa + DatadogLogs: be538def1d5204e011f7952915ad0261014a0dd5 + DatadogRUM: cffc65659ce29546fcc2639a74003135259548fc + DatadogSDKReactNative: d4aaed9748851f674fc9fea27e78a788e3c42908 + DatadogTrace: 085e35f9e4889f82f8a747922c58ea4b19728720 + DatadogWebViewTracking: 61b8344da898cbaccffc75bc1a17c86175e8573a DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 fmt: 01b82d4ca6470831d1cc0852a1af644be019e8f6 glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11 - OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 - PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 + KSCrash: 80e1e24eaefbe5134934ae11ca8d7746586bc2ed + OpenTelemetry-Swift-Api: 3d77582ab6837a63b65bf7d2eacc57d8f2595edd RCT-Folly: 7b4f73a92ad9571b9dbdb05bb30fad927fa971e1 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 @@ -1925,6 +1942,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a -PODFILE CHECKSUM: d9d720c99b6fffec4dd489d565a544a358a52b83 +PODFILE CHECKSUM: 2046fc46dd3311048c09b49573c69b7aba2aab81 COCOAPODS: 1.16.2 diff --git a/example-new-architecture/package.json b/example-new-architecture/package.json index b72ce69e4..83a990a29 100644 --- a/example-new-architecture/package.json +++ b/example-new-architecture/package.json @@ -9,6 +9,8 @@ }, "dependencies": { "@datadog/mobile-react-native": "workspace:packages/core", + "@datadog/mobile-react-native-openfeature": "workspace:packages/react-native-openfeature", + "@openfeature/react-sdk": "^1.1.0", "react": "18.3.1", "react-native": "0.76.9" }, diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index aef22ad73..94eff2f60 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -2,6 +2,7 @@ apply plugin: "com.android.application" apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" apply from: "../../node_modules/@datadog/mobile-react-native/datadog-sourcemaps.gradle" +apply from: "../../node_modules/@datadog/mobile-react-native/datadog-configuration.gradle" /** * This is the configuration block to customize your React Native Android app. diff --git a/example/app.json b/example/app.json index f0f0c83d7..70b08eb89 100644 --- a/example/app.json +++ b/example/app.json @@ -1,5 +1,5 @@ { "name": "DdSdkReactNativeExample", "displayName": "DD RN Sample", - "navigation": "react-native-navigation" + "navigation": "react-navigation" } diff --git a/example/datadog-configuration.json b/example/datadog-configuration.json new file mode 100644 index 000000000..117368236 --- /dev/null +++ b/example/datadog-configuration.json @@ -0,0 +1,21 @@ +{ + "$schema": "./node_modules/@datadog/mobile-react-native/datadog-configuration.schema.json", + "configuration": { + "clientToken": "CLIENT_TOKEN", + "env": "ENVIRONMENT", + "site": "US1", + "rumConfiguration": { + "applicationId": "APPLICATION_ID", + "longTaskThresholdMs": 1000, + "sessionSampleRate": 100, + "telemetrySampleRate": 20, + "trackBackgroundEvents": false, + "trackErrors": true, + "trackInteractions": true, + "trackResources": true + }, + "batchSize": "SMALL", + "trackingConsent": "GRANTED", + "verbosity": "DEBUG" + } +} diff --git a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj index f64fe027d..d50783cd5 100644 --- a/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/DdSdkReactNativeExample.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 04ACF1F72ED5D0B600602CDD /* datadog-configuration.json in Resources */ = {isa = PBXBuildFile; fileRef = 04ACF1F62ED5D0B600602CDD /* datadog-configuration.json */; }; 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 */; }; @@ -16,6 +17,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 04ACF1F52ED5D05F00602CDD /* datadog-configuration.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = "datadog-configuration.json"; path = "../datadog-configuration.json"; sourceTree = ""; }; + 04ACF1F62ED5D0B600602CDD /* datadog-configuration.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = "datadog-configuration.json"; path = "../datadog-configuration.json"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* ddSdkReactnativeExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ddSdkReactnativeExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ddSdkReactnativeExample/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = ddSdkReactnativeExample/AppDelegate.mm; sourceTree = ""; }; @@ -59,6 +62,7 @@ 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { isa = PBXGroup; children = ( + 04ACF1F52ED5D05F00602CDD /* datadog-configuration.json */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */, F2F7BC23E08401E57C9E1BD4 /* libPods-ddSdkReactnativeExample.a */, ); @@ -75,6 +79,7 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( + 04ACF1F62ED5D0B600602CDD /* datadog-configuration.json */, 13B07FAE1A68108700A75B9A /* ddSdkReactnativeExample */, 832341AE1AAA6A7D00B99B32 /* Libraries */, 83CBBA001A601CBA00E9B192 /* Products */, @@ -116,8 +121,8 @@ 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 21A29D19EE0D8BA789DB48E2 /* [CP] Embed Pods Frameworks */, CFB529A04D071A5133DC7E2B /* [CP] Copy Pods Resources */, + 93B37AE4FB9A962A472027AF /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -164,6 +169,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 04ACF1F72ED5D0B600602CDD /* datadog-configuration.json in Resources */, 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 7115D38EB0DCB0BDB39D62A2 /* PrivacyInfo.xcprivacy in Resources */, @@ -189,7 +195,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"; }; - 21A29D19EE0D8BA789DB48E2 /* [CP] Embed Pods Frameworks */ = { + 93B37AE4FB9A962A472027AF /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( diff --git a/example/ios/Podfile b/example/ios/Podfile index 1736870c9..7484e6aa7 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -28,7 +28,7 @@ target 'ddSdkReactnativeExample' do # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) - + # pod 'DatadogSDKReactNative', :path => '../../packages/core/DatadogSDKReactNative.podspec', :testspecs => ['Tests'] post_install do |installer| diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 0deeb0a40..b14259e47 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,34 +1,39 @@ PODS: - boost (1.84.0) - - DatadogCore (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogCrashReporting (2.30.2): - - DatadogInternal (= 2.30.2) - - 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.14.1): - - DatadogCore (= 2.30.2) - - DatadogCrashReporting (= 2.30.2) - - DatadogLogs (= 2.30.2) - - DatadogRUM (= 2.30.2) - - DatadogTrace (= 2.30.2) - - DatadogWebViewTracking (= 2.30.2) + - DatadogCore (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogCrashReporting (3.5.0): + - DatadogInternal (= 3.5.0) + - KSCrash/Filters (= 2.5.0) + - KSCrash/Recording (= 2.5.0) + - DatadogFlags (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogInternal (3.5.0) + - DatadogLogs (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogRUM (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogSDKReactNative (3.1.0): + - DatadogCore (= 3.5.0) + - DatadogCrashReporting (= 3.5.0) + - DatadogFlags (= 3.5.0) + - DatadogLogs (= 3.5.0) + - DatadogRUM (= 3.5.0) + - DatadogTrace (= 3.5.0) + - DatadogWebViewTracking (= 3.5.0) - React-Core - - DatadogSDKReactNative/Tests (2.14.1): - - 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 (3.1.0): + - DatadogCore (= 3.5.0) + - DatadogCrashReporting (= 3.5.0) + - DatadogFlags (= 3.5.0) + - DatadogLogs (= 3.5.0) + - DatadogRUM (= 3.5.0) + - DatadogTrace (= 3.5.0) + - DatadogWebViewTracking (= 3.5.0) - React-Core - - DatadogSDKReactNativeSessionReplay (2.14.1): + - DatadogSDKReactNativeSessionReplay (3.1.0): - DatadogSDKReactNative - - DatadogSessionReplay (= 2.30.2) + - DatadogSessionReplay (= 3.5.0) - DoubleConversion - glog - hermes-engine @@ -49,9 +54,9 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeSessionReplay/Tests (2.14.1): + - DatadogSDKReactNativeSessionReplay/Tests (3.1.0): - DatadogSDKReactNative - - DatadogSessionReplay (= 2.30.2) + - DatadogSessionReplay (= 3.5.0) - DoubleConversion - glog - hermes-engine @@ -73,25 +78,25 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - DatadogSDKReactNativeWebView (2.14.1): - - DatadogInternal (= 2.30.2) + - DatadogSDKReactNativeWebView (3.1.0): + - DatadogInternal (= 3.5.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 2.30.2) + - DatadogWebViewTracking (= 3.5.0) - React-Core - - DatadogSDKReactNativeWebView/Tests (2.14.1): - - DatadogInternal (= 2.30.2) + - DatadogSDKReactNativeWebView/Tests (3.1.0): + - DatadogInternal (= 3.5.0) - DatadogSDKReactNative - - DatadogWebViewTracking (= 2.30.2) + - DatadogWebViewTracking (= 3.5.0) - React-Core - react-native-webview - React-RCTText - - DatadogSessionReplay (2.30.2): - - DatadogInternal (= 2.30.2) - - DatadogTrace (2.30.2): - - DatadogInternal (= 2.30.2) - - OpenTelemetrySwiftApi (= 1.13.1) - - DatadogWebViewTracking (2.30.2): - - DatadogInternal (= 2.30.2) + - DatadogSessionReplay (3.5.0): + - DatadogInternal (= 3.5.0) + - DatadogTrace (3.5.0): + - DatadogInternal (= 3.5.0) + - OpenTelemetry-Swift-Api (~> 2.3.0) + - DatadogWebViewTracking (3.5.0): + - DatadogInternal (= 3.5.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - FBLazyVector (0.76.9) @@ -101,8 +106,18 @@ PODS: - hermes-engine/Pre-built (= 0.76.9) - hermes-engine/Pre-built (0.76.9) - HMSegmentedControl (1.5.6) - - OpenTelemetrySwiftApi (1.13.1) - - PLCrashReporter (1.12.0) + - KSCrash/Core (2.5.0) + - KSCrash/Filters (2.5.0): + - KSCrash/Recording + - KSCrash/RecordingCore + - KSCrash/ReportingCore + - KSCrash/Recording (2.5.0): + - KSCrash/RecordingCore + - KSCrash/RecordingCore (2.5.0): + - KSCrash/Core + - KSCrash/ReportingCore (2.5.0): + - KSCrash/Core + - OpenTelemetry-Swift-Api (2.3.0) - RCT-Folly (2024.10.14.00): - boost - DoubleConversion @@ -1824,6 +1839,7 @@ SPEC REPOS: https://github.com/CocoaPods/Specs.git: - DatadogCore - DatadogCrashReporting + - DatadogFlags - DatadogInternal - DatadogLogs - DatadogRUM @@ -1831,8 +1847,8 @@ SPEC REPOS: - DatadogTrace - DatadogWebViewTracking - HMSegmentedControl - - OpenTelemetrySwiftApi - - PLCrashReporter + - KSCrash + - OpenTelemetry-Swift-Api - SocketRocket EXTERNAL SOURCES: @@ -1988,17 +2004,18 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 1dca942403ed9342f98334bf4c3621f011aa7946 - DatadogCore: 8e50ad6cb68343f701707f7eeca16e0acb52ed8c - DatadogCrashReporting: 34763d4276d4fce286c7e8729cfcd2ac04dca43b - DatadogInternal: bd8672d506a7e67936ed5f7ca612169e49029b44 - DatadogLogs: d683aa9e0c9339f5ae679ead70bbdbe41cdc32f6 - DatadogRUM: 8b794aa458e6323ea9b1cef3f820fd3d092cbe27 - DatadogSDKReactNative: 676327b41d63d42172cc3543dbed83a9e5f0e32c - DatadogSDKReactNativeSessionReplay: 65bb7f28d508739d76c939d1e8242100c0d42204 - DatadogSDKReactNativeWebView: dfddb218204ae6eec3c092fd20ed3c9d268b8683 - DatadogSessionReplay: 56a91d799fe34967c5ae79a222364e37d67020f5 - DatadogTrace: 3ba194791267efa09634234749111cac95abd3e5 - DatadogWebViewTracking: 8287d5ad06e992de5e46dd72a17e05c7513344be + DatadogCore: 4cbe2646591d2f96fb3188400863ec93ac411235 + DatadogCrashReporting: e48da3f880a59d2aa2d04e5034e56507177e9d64 + DatadogFlags: f8cf88371460d6c672abfd97fdc9af5be208f33b + DatadogInternal: 63308b529cd87fb2f99c5961d9ff13afb300a3aa + DatadogLogs: be538def1d5204e011f7952915ad0261014a0dd5 + DatadogRUM: cffc65659ce29546fcc2639a74003135259548fc + DatadogSDKReactNative: eea81a5befd0f63288f1041466a23035c0f3e58d + DatadogSDKReactNativeSessionReplay: 60dd18dbb0fad1a2e484f12d90c2698cb5f66786 + DatadogSDKReactNativeWebView: 456e2b0ae7ad00a74da569805b57ad439a113301 + DatadogSessionReplay: eea291df0135ec792177be1ffc4951750a66a011 + DatadogTrace: 085e35f9e4889f82f8a747922c58ea4b19728720 + DatadogWebViewTracking: 61b8344da898cbaccffc75bc1a17c86175e8573a DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 7605ea4810e0e10ae4815292433c09bf4324ba45 @@ -2006,8 +2023,8 @@ SPEC CHECKSUMS: glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11 HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352 - OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 - PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 + KSCrash: 80e1e24eaefbe5134934ae11ca8d7746586bc2ed + OpenTelemetry-Swift-Api: 3d77582ab6837a63b65bf7d2eacc57d8f2595edd RCT-Folly: 7b4f73a92ad9571b9dbdb05bb30fad927fa971e1 RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83 RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716 @@ -2074,6 +2091,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a -PODFILE CHECKSUM: 2be76f6ff2a88869ff51bdbf48edb79d7d863c79 +PODFILE CHECKSUM: 9a1faac3ae43394b0b86e6fcabf63eced6c66dc2 COCOAPODS: 1.16.2 diff --git a/example/package.json b/example/package.json index db38f20b6..f065aab69 100644 --- a/example/package.json +++ b/example/package.json @@ -12,9 +12,11 @@ "dependencies": { "@datadog/mobile-react-native": "workspace:packages/core", "@datadog/mobile-react-native-navigation": "workspace:packages/react-native-navigation", + "@datadog/mobile-react-native-openfeature": "workspace:packages/react-native-openfeature", "@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", + "@openfeature/react-sdk": "^1.2.0", "@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", diff --git a/example/src/App.tsx b/example/src/App.tsx index cefcafffe..897a1a3a8 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -6,36 +6,99 @@ import ErrorScreen from './screens/ErrorScreen'; 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 { DdRumReactNavigationTracking, NavigationTrackingOptions, ParamsTrackingPredicate, ViewNamePredicate, ViewTrackingPredicate } from '@datadog/mobile-react-navigation'; +import { DatadogProvider, TrackingConsent, DdFlags } from '@datadog/mobile-react-native' +import { DatadogOpenFeatureProvider } from '@datadog/mobile-react-native-openfeature'; +import { OpenFeature, OpenFeatureProvider } from '@openfeature/react-sdk'; import { Route } from "@react-navigation/native"; import { NestedNavigator } from './screens/NestedNavigator/NestedNavigator'; import { getDatadogConfig, onDatadogInitialization } from './ddUtils'; -import { TrackingConsent } from '@datadog/mobile-react-native'; const Tab = createBottomTabNavigator(); -const viewPredicate: ViewNamePredicate = function customViewNamePredicate(route: Route, trackedName: string) { +// === Navigation Tracking custom predicates +const viewNamePredicate: ViewNamePredicate = function customViewNamePredicate(route: Route, trackedName: string) { return "Custom RN " + trackedName; } +const viewTrackingPredicate: ViewTrackingPredicate = function customViewTrackingPredicate(route: Route) { + if (route.name === "AlertModal") { + return false; + } + + return true; +} + +const paramsTrackingPredicate: ParamsTrackingPredicate = function customParamsTrackingPredicate(route: Route) { + const filteredParams: any = {}; + if (route.params?.creditCardNumber) { + filteredParams["creditCardNumber"] = "XXXX XXXX XXXX XXXX"; + } + + if (route.params?.username) { + filteredParams["username"] = route.params.username; + } + + return filteredParams; +} + +const navigationTrackingOptions: NavigationTrackingOptions = { + viewNamePredicate, + viewTrackingPredicate, + paramsTrackingPredicate, +} +// === 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}); + +// 4.- File based configuration from the native side (using initFromNative) +// see https://docs.datadoghq.com/real_user_monitoring/guide/initialize-your-native-sdk-before-react-native-starts + +// const configuration = new DatadogProviderConfiguration("fake_value", "fake_value"); + +const handleDatadogInitialization = async () => { + onDatadogInitialization(); + + // Enable Datadog Flags feature. + await DdFlags.enable(); + + // Set the provider with OpenFeature. + const provider = new DatadogOpenFeatureProvider(); + OpenFeature.setProvider(provider); +} + export default function App() { return ( - - { - DdRumReactNavigationTracking.startTrackingViews(navigationRef.current, viewPredicate) - }}> - null + + + { + DdRumReactNavigationTracking.startTrackingViews( + navigationRef.current, + navigationTrackingOptions) }}> - - - - - - + null + }}> + + + + + + + ) } diff --git a/example/src/WixApp.tsx b/example/src/WixApp.tsx index 55e93f6e4..af685b934 100644 --- a/example/src/WixApp.tsx +++ b/example/src/WixApp.tsx @@ -1,5 +1,5 @@ -import React, { useState } from 'react'; -import { View, Text, Button } from 'react-native'; +import React from 'react'; +import { View, Text, Button, ActivityIndicator } from 'react-native'; import MainScreen from './screens/MainScreen'; import ErrorScreen from './screens/ErrorScreen'; import AboutScreen from './screens/AboutScreen'; @@ -11,18 +11,45 @@ import { } from '@datadog/mobile-react-native-navigation'; import styles from './screens/styles'; -import { DdTrace } from '@datadog/mobile-react-native'; +import { DdFlags } from '@datadog/mobile-react-native'; import TraceScreen from './screens/TraceScreen'; +import { NavigationTrackingOptions, ParamsTrackingPredicate, ViewTrackingPredicate } from '@datadog/mobile-react-native-navigation/src/rum/instrumentation/DdRumReactNativeNavigationTracking'; +import { OpenFeatureProvider, useFlag } from '@openfeature/react-sdk'; -const viewPredicate: ViewNamePredicate = ( - _event: ComponentDidAppearEvent, - trackedName: string -) => { - return 'Custom RNN ' + trackedName; -}; +// === Navigation Tracking custom predicates +const viewNamePredicate: ViewNamePredicate = function customViewNamePredicate(_event: ComponentDidAppearEvent, trackedName: string) { + return "Custom RN " + trackedName; +} + +const viewTrackingPredicate: ViewTrackingPredicate = function customViewTrackingPredicate(event: ComponentDidAppearEvent) { + if (event.name === "AlertModal") { + return false; + } + + return true; +} + +const paramsTrackingPredicate: ParamsTrackingPredicate = function customParamsTrackingPredicate(event: ComponentDidAppearEvent) { + const filteredParams: any = {}; + if (event.passProps?.creditCardNumber) { + filteredParams["creditCardNumber"] = "XXXX XXXX XXXX XXXX"; + } + + if (event.passProps?.username) { + filteredParams["username"] = event.passProps.username; + } + + return filteredParams; +} + +const navigationTrackingOptions: NavigationTrackingOptions = { + viewNamePredicate, + viewTrackingPredicate, + paramsTrackingPredicate, +} function startReactNativeNavigation() { - DdRumReactNativeNavigationTracking.startTracking(viewPredicate); + DdRumReactNativeNavigationTracking.startTracking(navigationTrackingOptions); registerScreens(); Navigation.events().registerAppLaunchedListener(async () => { Navigation.setRoot({ @@ -36,14 +63,25 @@ function startReactNativeNavigation() { } function registerScreens() { - Navigation.registerComponent('Home', () => HomeScreen); + Navigation.registerComponent('Home', () => HomeScreenWithProviders); Navigation.registerComponent('Main', () => MainScreen); Navigation.registerComponent('Error', () => ErrorScreen); Navigation.registerComponent('Trace', () => TraceScreen); Navigation.registerComponent('About', () => AboutScreen); } +const HomeScreenWithProviders = () => { + return ( + + + + ) +} + const HomeScreen = props => { + const testFlagKey = 'rn-sdk-test-json-flag'; + const flag = useFlag(testFlagKey, {greeting: "Default greeting"}); + return ( @@ -80,10 +118,16 @@ const HomeScreen = props => { title="About" onPress={() => { Navigation.push(props.componentId, { - component: { name: 'About' } + component: { name: 'About', + passProps: { + username: "test", + creditCardNumber: "4242 4242 4242 4242" + } + } }); }} /> + {testFlagKey}: {JSON.stringify(flag.value)} ); }; diff --git a/example/src/ddUtils.tsx b/example/src/ddUtils.tsx index 2cd64d477..8e2fa8a94 100644 --- a/example/src/ddUtils.tsx +++ b/example/src/ddUtils.tsx @@ -2,27 +2,51 @@ import { DatadogProviderConfiguration, DdLogs, DdSdkReactNative, - DdSdkReactNativeConfiguration, + CoreConfiguration, SdkVerbosity, - TrackingConsent + TrackingConsent, + BatchSize, + UploadFrequency, + DdFlags, } from '@datadog/mobile-react-native'; +import { DatadogOpenFeatureProvider } from '@datadog/mobile-react-native-openfeature'; +import { OpenFeature } from '@openfeature/react-sdk'; import {APPLICATION_ID, CLIENT_TOKEN, ENVIRONMENT} from './ddCredentials'; +import { BatchProcessingLevel } from '@datadog/mobile-react-native/src/config/types'; // New SDK Setup - not available for react-native-navigation export function getDatadogConfig(trackingConsent: TrackingConsent) { const config = new DatadogProviderConfiguration( CLIENT_TOKEN, ENVIRONMENT, - APPLICATION_ID, - true, - true, - true, - trackingConsent - ) - config.nativeCrashReportEnabled = true - config.sessionSamplingRate = 100 - config.serviceName = "com.datadoghq.reactnative.sample" + trackingConsent, + { + batchSize: BatchSize.SMALL, + uploadFrequency: UploadFrequency.FREQUENT, + batchProcessingLevel: BatchProcessingLevel.MEDIUM, + additionalConfiguration: { + customProperty: "sdk-example-app" + }, + rumConfiguration: { + applicationId: APPLICATION_ID, + trackInteractions: true, + trackResources: true, + trackErrors: true, + sessionSampleRate: 100, + nativeCrashReportEnabled: true + }, + logsConfiguration: { + logEventMapper: (logEvent) => { + logEvent.message = `[CUSTOM] ${logEvent.message}`; + return logEvent; + } + }, + traceConfiguration: {} + } + ); + + config.service = "com.datadoghq.reactnative.sample" config.verbosity = SdkVerbosity.DEBUG; return config @@ -31,29 +55,41 @@ export function getDatadogConfig(trackingConsent: TrackingConsent) { export function onDatadogInitialization() { 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"}) } // Legacy SDK Setup export function initializeDatadog(trackingConsent: TrackingConsent) { - const config = new DdSdkReactNativeConfiguration( + const config = new CoreConfiguration( CLIENT_TOKEN, ENVIRONMENT, - APPLICATION_ID, - true, - true, - true, - trackingConsent + trackingConsent, + { + rumConfiguration: { + applicationId: APPLICATION_ID, + trackInteractions: true, + trackResources: true, + trackErrors: true, + sessionSampleRate: 100, + nativeCrashReportEnabled: true + } + } ) - config.nativeCrashReportEnabled = true - config.sampleRate = 100 - config.serviceName = "com.datadoghq.reactnative.sample" + config.verbosity = SdkVerbosity.DEBUG; + config.service = "com.datadoghq.reactnative.sample" DdSdkReactNative.initialize(config).then(() => { 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"}) }); + + // Enable the Flags feature. + DdFlags.enable().then(() => { + // Set the provider with OpenFeature. + const provider = new DatadogOpenFeatureProvider(); + OpenFeature.setProvider(provider); + }) } diff --git a/example/src/screens/MainScreen.tsx b/example/src/screens/MainScreen.tsx index 7f0fbdec2..1616e953d 100644 --- a/example/src/screens/MainScreen.tsx +++ b/example/src/screens/MainScreen.tsx @@ -7,14 +7,14 @@ import React, { Component, RefObject } from 'react'; import { View, Text, Button, TouchableOpacity, - TouchableWithoutFeedback, TouchableNativeFeedback + TouchableWithoutFeedback, TouchableNativeFeedback, ActivityIndicator } from 'react-native'; +import { DdLogs, DdSdkReactNative, TrackingConsent, DdFlags } from '@datadog/mobile-react-native'; +import { FeatureFlag } from '@openfeature/react-sdk'; import styles from './styles'; import { APPLICATION_KEY, API_KEY } from '../../src/ddCredentials'; -import { DdLogs, DdSdkReactNative, TrackingConsent } from '@datadog/mobile-react-native'; import { getTrackingConsent, saveTrackingConsent } from '../utils'; import { ConsentModal } from '../components/consent'; -import { DdRum } from '../../../packages/core/src/rum/DdRum'; const axios = require('../axiosConfig'); @@ -114,7 +114,12 @@ export default class MainScreen extends Component { render() { return - {this.state.welcomeMessage} + Welcome!}> + Greetings from the Feature Flags! + + + The above greeting is being controlled by the{'\n'}`rn-sdk-test-boolean-flag` feature flag. +