diff --git a/.eslintignore b/.eslintignore index 75da15ae8..c0b6b5c6a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,7 @@ node_modules example example-new-architecture +benchmarks dist lib packages/core/android/build/reports/tests diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cd9aebeab..3f655575a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,114 +1,138 @@ include: - - 'https://gitlab-templates.ddbuild.io/slack-notifier/v1/template.yml' + - 'https://gitlab-templates.ddbuild.io/slack-notifier/v1/template.yml' # SETUP variables: - GIT_DEPTH: 5 - - ANDROID_SDK_VERSION: "commandlinetools-mac-11076708_latest" - EMULATOR_NAME: "android_emulator" - ANDROID_ARCH: "arm64-v8a" - ANDROID_API: "35" - ANDROID_EMULATOR_IMAGE: "system-images;android-$ANDROID_API;google_apis;${ANDROID_ARCH}" - ANDROID_PLATFORM: "platforms;android-$ANDROID_API" - ANDROID_BUILD_TOOLS: "build-tools;$ANDROID_API.0.0" - # KUBERNETES_MEMORY_REQUEST: "8Gi" - # KUBERNETES_MEMORY_LIMIT: "13Gi" - + GIT_DEPTH: 5 + DEVELOP_BRANCH: 'develop' + ANDROID_SDK_VERSION: 'commandlinetools-mac-11076708_latest' + EMULATOR_NAME: 'android_emulator' + ANDROID_ARCH: 'arm64-v8a' + ANDROID_API: '35' + ANDROID_EMULATOR_IMAGE: 'system-images;android-$ANDROID_API;google_apis;${ANDROID_ARCH}' + ANDROID_PLATFORM: 'platforms;android-$ANDROID_API' + ANDROID_BUILD_TOOLS: 'build-tools;$ANDROID_API.0.0' + # KUBERNETES_MEMORY_REQUEST: "8Gi" + # KUBERNETES_MEMORY_LIMIT: "13Gi" stages: - - test - - notify - + - benchmark + - test + - notify .snippets: - install-jdk-17: - - brew install openjdk@17 - install-android-sdk: - - curl -sSL -o commandlinetools.zip https://dl.google.com/android/repository/$ANDROID_SDK_VERSION.zip - - rm -rf ~/android_sdk - - rm -rf ~/cmdline-tools - - unzip -q commandlinetools -d ~/ - - mkdir -p ~/android_sdk/cmdline-tools/latest - - mv ~/cmdline-tools/* ~/android_sdk/cmdline-tools/latest - - rm ./commandlinetools.zip - - export ANDROID_HOME="$HOME/android_sdk/" - - export ANDROID_SDK_ROOT="$HOME/android_sdk/" - - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "emulator" - - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "platform-tools" - - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_PLATFORM" - - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_BUILD_TOOLS" - - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_EMULATOR_IMAGE" - - yes | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --licenses || true - - echo "no" | ~/android_sdk/cmdline-tools/latest/bin/avdmanager --verbose create avd --force --name "$EMULATOR_NAME" --package "$ANDROID_EMULATOR_IMAGE" + install-jdk-17: + - brew install openjdk@17 + install-android-sdk: + - curl -sSL -o commandlinetools.zip https://dl.google.com/android/repository/$ANDROID_SDK_VERSION.zip + - rm -rf ~/android_sdk + - rm -rf ~/cmdline-tools + - unzip -q commandlinetools -d ~/ + - mkdir -p ~/android_sdk/cmdline-tools/latest + - mv ~/cmdline-tools/* ~/android_sdk/cmdline-tools/latest + - rm ./commandlinetools.zip + - export ANDROID_HOME="$HOME/android_sdk/" + - export ANDROID_SDK_ROOT="$HOME/android_sdk/" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "emulator" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "platform-tools" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_PLATFORM" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_BUILD_TOOLS" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_EMULATOR_IMAGE" + - yes | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --licenses || true + - echo "no" | ~/android_sdk/cmdline-tools/latest/bin/avdmanager --verbose create avd --force --name "$EMULATOR_NAME" --package "$ANDROID_EMULATOR_IMAGE" # TESTS test:lint: - tags: [ "macos:sonoma", "specific:true" ] - stage: test - timeout: 1h - script: - - yarn - - yarn run lint + tags: ['macos:sonoma', 'specific:true'] + stage: test + rules: + - if: '$BUILD_BENCHMARK != "true"' + timeout: 1h + script: + - yarn + - yarn run lint test:js: - tags: [ "macos:sonoma", "specific:true" ] - stage: test - timeout: 1h - script: - - yarn - - cp jestSetup.js.override node_modules/react-native-gesture-handler/jestSetup.js - - NODE_OPTIONS='-r dd-trace/ci/init' DD_ENV=ci DD_SERVICE=dd-sdk-reactnative yarn test + tags: ['macos:sonoma', 'specific:true'] + stage: test + rules: + - if: '$BUILD_BENCHMARK != "true"' + timeout: 1h + script: + - yarn + - cp jestSetup.js.override node_modules/react-native-gesture-handler/jestSetup.js + - NODE_OPTIONS='-r dd-trace/ci/init' DD_ENV=ci DD_SERVICE=dd-sdk-reactnative yarn test test:build: - tags: [ "macos:sonoma", "specific:true" ] - stage: test - timeout: 1h - script: - - yarn - - yarn prepare + tags: ['macos:sonoma', 'specific:true'] + stage: test + rules: + - if: '$BUILD_BENCHMARK != "true"' + timeout: 1h + script: + - yarn + - yarn prepare test:native-android: - tags: [ "macos:sonoma", "specific:true" ] - stage: test - timeout: 1h - script: - - !reference [.snippets, install-android-sdk] - - !reference [.snippets, install-jdk-17] - - /opt/homebrew/opt/openjdk@17/bin/java --version - - echo "org.gradle.java.home=/opt/homebrew/opt/openjdk@17" >> packages/core/android/gradle.properties - - echo "org.gradle.java.home=/opt/homebrew/opt/openjdk@17" >> packages/react-native-session-replay/android/gradle.properties - - echo "org.gradle.java.home=/opt/homebrew/opt/openjdk@17" >> packages/internal-testing-tools/android/gradle.properties - - yarn - - (cd packages/core/android && ./gradlew build -PDdSdkReactNative_minSdkVersion=24) - - (cd packages/react-native-session-replay/android && ./gradlew build -PDdSdkReactNative_minSdkVersion=24 -PDatadogSDKReactNativeSessionReplay_minSdkVersion=24) - - (cd packages/internal-testing-tools/android && ./gradlew build -PDdSdkReactNative_minSdkVersion=24 -PDatadogInternalTesting_minSdkVersion=24) + tags: ['macos:sonoma', 'specific:true'] + stage: test + rules: + - if: '$BUILD_BENCHMARK != "true"' + timeout: 1h + script: + - !reference [.snippets, install-android-sdk] + - !reference [.snippets, install-jdk-17] + - /opt/homebrew/opt/openjdk@17/bin/java --version + - echo "org.gradle.java.home=/opt/homebrew/opt/openjdk@17" >> packages/core/android/gradle.properties + - echo "org.gradle.java.home=/opt/homebrew/opt/openjdk@17" >> packages/react-native-session-replay/android/gradle.properties + - echo "org.gradle.java.home=/opt/homebrew/opt/openjdk@17" >> packages/internal-testing-tools/android/gradle.properties + - yarn + - (cd packages/core/android && ./gradlew build -PDdSdkReactNative_minSdkVersion=24) + - (cd packages/react-native-session-replay/android && ./gradlew build -PDdSdkReactNative_minSdkVersion=24 -PDatadogSDKReactNativeSessionReplay_minSdkVersion=24) + - (cd packages/internal-testing-tools/android && ./gradlew build -PDdSdkReactNative_minSdkVersion=24 -PDatadogInternalTesting_minSdkVersion=24) test:native-ios: - tags: [ "macos:sonoma", "specific:true" ] - stage: test - timeout: 1h - script: - - yarn - - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNative test -destination "platform=iOS Simulator,OS=17.4,name=iPhone 15 Pro Max" | xcbeautify + tags: ['macos:sonoma', 'specific:true'] + stage: test + rules: + - if: '$BUILD_BENCHMARK != "true"' + timeout: 1h + script: + - yarn + - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) + - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNative test -destination "platform=iOS Simulator,OS=17.4,name=iPhone 15 Pro Max" | xcbeautify test:native-ios-sr: - tags: [ "macos:sonoma", "specific:true" ] - stage: test - timeout: 1h - script: - - yarn - - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) - - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNativeSessionReplay test -destination "platform=iOS Simulator,OS=17.4,name=iPhone 15 Pro Max" | xcbeautify + tags: ['macos:sonoma', 'specific:true'] + stage: test + rules: + - if: '$BUILD_BENCHMARK != "true"' + timeout: 1h + script: + - yarn + - (cd example/ios && RCT_NEW_ARCH_ENABLED=0 pod install --repo-update) + - set -o pipefail && xcodebuild -workspace example/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNativeSessionReplay test -destination "platform=iOS Simulator,OS=17.4,name=iPhone 15 Pro Max" | xcbeautify test:native-ios-newarch: - tags: [ "macos:sonoma", "specific:true" ] - stage: test - timeout: 1h - script: - - yarn - - (cd example-new-architecture/ios && RCT_NEW_ARCH_ENABLED=1 pod install --repo-update) - - set -o pipefail && xcodebuild -workspace example-new-architecture/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNative test -destination "platform=iOS Simulator,OS=17.4,name=iPhone 15 Pro Max" | xcbeautify \ No newline at end of file + tags: ['macos:sonoma', 'specific:true'] + stage: test + rules: + - if: '$BUILD_BENCHMARK != "true"' + timeout: 1h + script: + - yarn + - (cd example-new-architecture/ios && RCT_NEW_ARCH_ENABLED=1 pod install --repo-update) + - set -o pipefail && xcodebuild -workspace example-new-architecture/ios/DdSdkReactNativeExample.xcworkspace -scheme DatadogSDKReactNative test -destination "platform=iOS Simulator,OS=17.4,name=iPhone 15 Pro Max" | xcbeautify + +benchmark: + stage: benchmark + rules: + - if: '$BUILD_BENCHMARK == "true"' + allow_failure: true + - if: '$CI_COMMIT_BRANCH == "$DEVELOP_BRANCH"' + allow_failure: true + trigger: + include: 'benchmarks/.benchmarks-ci.yml' + strategy: depend diff --git a/benchmarks/.benchmarks-ci.yml b/benchmarks/.benchmarks-ci.yml new file mode 100644 index 000000000..5f945f463 --- /dev/null +++ b/benchmarks/.benchmarks-ci.yml @@ -0,0 +1,109 @@ +include: + - 'https://gitlab-templates.ddbuild.io/slack-notifier/v1/template.yml' + +# GLOBAL VARIABLES +variables: + GIT_DEPTH: 5 + NODE_VERSION: '22.5.1' + ANDROID_SDK_VERSION: 'commandlinetools-mac-11076708_latest' + EMULATOR_NAME: 'android_emulator' + ANDROID_ARCH: 'arm64-v8a' + ANDROID_API: '35' + ANDROID_EMULATOR_IMAGE: 'system-images;android-$ANDROID_API;google_apis;${ANDROID_ARCH}' + ANDROID_PLATFORM: 'platforms;android-$ANDROID_API' + ANDROID_BUILD_TOOLS: 'build-tools;$ANDROID_API.0.0' + +stages: + - build-and-upload + - notify + +# SNIPPETS +.snippets: + install-node: + # Install Node Version Manager (NVM) + - echo "Installing nvm..." + - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + - '. ~/.nvm/nvm.sh --no-use' + - nvm --version + - echo "Installing NODE $NODE_VERSION..." + # Change Node version + - nvm install $NODE_VERSION + - nvm use $NODE_VERSION + - nvm alias default $NODE_VERSION + - echo "Node version:" && node -v + - echo "NPM version:" && npm -v + + install-jdk-17: + - brew install openjdk@17 + install-android-sdk: + - curl -sSL -o commandlinetools.zip https://dl.google.com/android/repository/$ANDROID_SDK_VERSION.zip + - rm -rf ~/android_sdk + - rm -rf ~/cmdline-tools + - unzip -q commandlinetools -d ~/ + - mkdir -p ~/android_sdk/cmdline-tools/latest + - mv ~/cmdline-tools/* ~/android_sdk/cmdline-tools/latest + - rm ./commandlinetools.zip + - export ANDROID_HOME="$HOME/android_sdk/" + - export ANDROID_SDK_ROOT="$HOME/android_sdk/" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "emulator" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "platform-tools" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_PLATFORM" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_BUILD_TOOLS" + - echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "$ANDROID_EMULATOR_IMAGE" + - yes | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --licenses || true + - echo "no" | ~/android_sdk/cmdline-tools/latest/bin/avdmanager --verbose create avd --force --name "$EMULATOR_NAME" --package "$ANDROID_EMULATOR_IMAGE" + + check-versions: + - echo "Node version:" && node -v + - echo "Xcode version:" && xcodebuild -version + - echo "CocoaPods version:" && pod --version + +build-and-upload:app: + stage: build-and-upload + tags: ['macos:sonoma', 'specific:true'] + script: + - !reference [.snippets, install-node] + - !reference [.snippets, install-android-sdk] + - !reference [.snippets, install-jdk-17] + - !reference [.snippets, check-versions] + + - echo $(pwd) + + # Datadog SDK - Yarn install + - echo "Installing DDSDK dependencies" + - yarn install + + # Prepare Logs Directory + - cd $(pwd)/benchmarks + - mkdir -p logs + + # Create .env config file + - echo "Creating .env config" + - ./scripts/create-env-config.sh + + # Yarn install + - echo "Installing dependencies" + - yarn install + + # Android Build + - echo "Starting Android build for BenchmarkRunner" + - ./scripts/build-android-benchmark.sh + + # iOS Build + - echo "Starting iOS build for BenchmarkRunner" + - XCODEBUILD_LOG_PATH=$(pwd)/logs/build_ios_benchmark_runner.log + - touch $XCODEBUILD_LOG_PATH + - ./scripts/build-ios-benchmark.sh | tee -a $XCODEBUILD_LOG_PATH + + # Upload builds to synthetics + - echo "Uploading app-release.apk to Synthetics" + - ./scripts/upload.sh android/app/build/outputs/apk/release/app-release.apk ANDROID + - echo "Uploading BenchmarkRunner.ipa to Synthetics" + - ./scripts/upload.sh ios/BenchmarkRunner.ipa/BenchmarkRunner.ipa IOS + + artifacts: + paths: + - ./benchmarks/logs + - ./benchmarks/android/app/build/outputs/apk/release/app-release.apk + - ./benchmarks/ios/BenchmarkRunner.ipa + when: always diff --git a/benchmarks/.bundle/config b/benchmarks/.bundle/config new file mode 100644 index 000000000..848943bb5 --- /dev/null +++ b/benchmarks/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/benchmarks/.env.alternate b/benchmarks/.env.alternate new file mode 100644 index 000000000..2eefe9616 --- /dev/null +++ b/benchmarks/.env.alternate @@ -0,0 +1,7 @@ +DD_CLIENT_TOKEN="ALT_CLIENT_TOKEN" +DD_API_KEY="ALT_API_KEY" +DD_APP_ID="ALT_APP_ID" +DD_SITE="ALT_SITE" +DD_ENV="ALT_ENV" +BENCH_SCENARIO= +BENCH_RUN_TYPE= \ No newline at end of file diff --git a/benchmarks/.eslintrc.js b/benchmarks/.eslintrc.js new file mode 100644 index 000000000..187894b6a --- /dev/null +++ b/benchmarks/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: '@react-native', +}; diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore new file mode 100644 index 000000000..de9995595 --- /dev/null +++ b/benchmarks/.gitignore @@ -0,0 +1,75 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +**/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +*.keystore +!debug.keystore +.kotlin/ + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +**/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage + +# Yarn +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions diff --git a/benchmarks/.prettierrc.js b/benchmarks/.prettierrc.js new file mode 100644 index 000000000..2b540746a --- /dev/null +++ b/benchmarks/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + arrowParens: 'avoid', + bracketSameLine: true, + bracketSpacing: false, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/benchmarks/.watchmanconfig b/benchmarks/.watchmanconfig new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/benchmarks/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/benchmarks/Gemfile b/benchmarks/Gemfile new file mode 100644 index 000000000..03278dd5e --- /dev/null +++ b/benchmarks/Gemfile @@ -0,0 +1,10 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 2.6.10" + +# Exclude problematic versions of cocoapods and activesupport that causes build failures. +gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' +gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' +gem 'xcodeproj', '< 1.26.0' +gem 'concurrent-ruby', '< 1.3.4' diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 000000000..e2bbf063b --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,182 @@ +# Benchmark runner app for Datadog React Native SDK + +## Build and run + +1. From the root benchmark folder, run `yarn install`. +2. From the iOS folder, run `pod install`. +3. From the root folder, run `yarn ios` or `yarn android`. + +## Enable new architcture + +### iOS + +``` +RCT_NEW_ARCH_ENABLED=1 pod install +``` + +### Android + +Set `newArchEnabled=true` in `benchmarks/android/gradle.properties`. + +## ENV config + +The `.env` config file contains configuration for the Datadog API, as well as a test scenario that you can launch when the app boots up. If it doesn't contain a test scenario, the app waits for a deeplink to trigger a test scenario instead. + + DD_CLIENT_TOKEN="CLIENT_TOKEN" + DD_API_KEY="API_KEY" + DD_APP_ID="APP_ID" + DD_SITE="SITE" + DD_ENV="ENV" + BENCH_SCENARIO="" + BENCH_RUN_TYPE="" + +## Changing ENV settings + +### Debug +``` + $ ENVFILE=.env.alternate yarn ios +``` +or: + +``` + $ ENVFILE=.env.alternate yarn android +``` + +### Release +On Android: +``` + $ ENVFILE=.env.alternate ./gradlew assembleRelease +``` + +On iOS: +``` + xcodebuild -scheme alternate +``` + +## Set test scenarios using deeplinks + +You can trigger test scenarios by running a deeplink with a specific set of parameters to the benchmark app. + +## Run a test scenario + +Launch a specific test scenario with a particular configuration: +- **Method**: `start` +- **Parameters**: + - **scenario**: name of the test as defined on `Scenario` enum in `types/testConfig.ts` + - **runType**: `instrumented|baseline|profiling` + +### iOS + +``` +xcrun simctl openurl booted "benchmark://start?scenario=navigation&runType=instrumented" +``` + +### Android + +``` +adb shell am start -W -a android.intent.action.VIEW -d 'benchmark://start?scenario=navigation\&runType=instrumented' com.benchmarkrunner +``` + +## Stop a test scenario + +Stops the scenario currently running. + +- **Method**: `stop` + +### iOS + +``` +xcrun simctl openurl booted "benchmark://stop" +``` + +### Android + +``` +adb shell am start -W -a android.intent.action.VIEW -d 'benchmark://stop' com.benchmarkrunner +``` + +## Adding a New Scenario to Benchmarks + +### Define the New Scenario + +In `benchmarks/src/testSetup/types/testConfig.ts`, add a new entry to the `Scenario` enum: + +```ts +export enum Scenario { + Default = 'default', + NavigationExample = 'navigation', + (...) + NewScenario = 'newScenario' +} +``` + +The string value (`'newScenario'`) is what must be passed using deeplink as the `scenario` parameter. + +Alternatively, if you're using a `.env` file to set the scenario, add: + +```env +BENCH_SCENARIO="newScenario" +``` + +### Create the Scenario Component + +Create a new folder under `benchmarks/src/scenario/` named after your scenario (for example, `NewScenario`). Inside this folder, define your scenario’s main component and its props. + +Create a `types.ts` file: + +```ts +import type { TestConfig } from "benchmarks/src/testSetup/types/testConfig"; + +export type NewScenarioProps = { + testConfig?: TestConfig; +}; +``` + +Then, define the main component: + +```ts +import { NewScenarioProps } from "./types"; + +function NewScenario(props: NewScenarioProps): React.JSX.Element { + (...) +} + +export default NewScenario; +``` + +### Register the Scenario in the App + +In `benchmarks/src/App.tsx`, add a new case to the scenario switch using the enum identifier you just created: + +```tsx +case Scenario.NewScenario: + return ; +``` + +You can now trigger this scenario either through a deeplink or by setting `BENCH_SCENARIO` in the `.env` file. + +## Instrumenting a Scenario + +Depending on the scenario’s structure and flow, the Datadog SDK initialization may vary. Each scenario is responsible for managing its own initialization logic. + +To simplify this, use the `instrument()` helper from `benchmarks/src/testSetup/testUtils`. It initializes the SDK with a default configuration. + +Since your scenario component receives `testConfig` as a prop, you can use it to determine whether instrumentation should occur: + +```ts +useEffect(() => { + if (props.testConfig?.runType !== RunType.BASELINE) { + instrument().then(() => { + // Datadog is initialized + }); + } +}, []); +``` + +## Using the Datadog Provider + +If your scenario uses the `DatadogProvider`, you can retrieve the necessary configuration using `getDatadogProviderConfig()` from the same `testUtils` module: + +```ts +return ... +``` diff --git a/benchmarks/android/app/build.gradle b/benchmarks/android/app/build.gradle new file mode 100644 index 000000000..d14d070b1 --- /dev/null +++ b/benchmarks/android/app/build.gradle @@ -0,0 +1,133 @@ +apply plugin: "com.android.application" +apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: 'com.facebook.react' + +def isNewArchitectureEnabled() { + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js + // cliFile = file("../../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() +} + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' + +android { + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + + namespace "com.benchmarkrunner" + defaultConfig { + applicationId "com.benchmarkrunner" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()) + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } +} + +repositories { + +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } + + // 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.23.0") +} diff --git a/benchmarks/android/app/debug.keystore b/benchmarks/android/app/debug.keystore new file mode 100644 index 000000000..364e105ed Binary files /dev/null and b/benchmarks/android/app/debug.keystore differ diff --git a/benchmarks/android/app/proguard-rules.pro b/benchmarks/android/app/proguard-rules.pro new file mode 100644 index 000000000..0d1bfd1c2 --- /dev/null +++ b/benchmarks/android/app/proguard-rules.pro @@ -0,0 +1,15 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# From react-native-config: +# Proguard may rename the BuildConfig Java class in the minification process +# and prevent React Native Config from referencing it +-keep class com.benchmarkrunner.BuildConfig { *; } \ No newline at end of file diff --git a/benchmarks/android/app/src/debug/AndroidManifest.xml b/benchmarks/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..eb98c01af --- /dev/null +++ b/benchmarks/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/benchmarks/android/app/src/main/AndroidManifest.xml b/benchmarks/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..eaa5b4df0 --- /dev/null +++ b/benchmarks/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + diff --git a/benchmarks/android/app/src/main/java/com/benchmarkrunner/MainActivity.kt b/benchmarks/android/app/src/main/java/com/benchmarkrunner/MainActivity.kt new file mode 100644 index 000000000..ea53f9039 --- /dev/null +++ b/benchmarks/android/app/src/main/java/com/benchmarkrunner/MainActivity.kt @@ -0,0 +1,27 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.benchmarkrunner + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "BenchmarkRunner" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} diff --git a/benchmarks/android/app/src/main/java/com/benchmarkrunner/MainApplication.kt b/benchmarks/android/app/src/main/java/com/benchmarkrunner/MainApplication.kt new file mode 100644 index 000000000..84563b3d8 --- /dev/null +++ b/benchmarks/android/app/src/main/java/com/benchmarkrunner/MainApplication.kt @@ -0,0 +1,51 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.benchmarkrunner + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.soloader.OpenSourceMergedSoMapping +import com.facebook.soloader.SoLoader +import com.benchmarkvitals.BenchmarkVitalsPackage + +class MainApplication : Application(), ReactApplication { + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + add(BenchmarkVitalsPackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, OpenSourceMergedSoMapping) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + } +} diff --git a/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModule.kt b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModule.kt new file mode 100644 index 000000000..1ccd2ad55 --- /dev/null +++ b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModule.kt @@ -0,0 +1,38 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.benchmarkvitals + +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.turbomodule.core.interfaces.TurboModule +import com.facebook.react.bridge.ReactContextBaseJavaModule +import com.facebook.react.bridge.ReadableMap + +@ReactModule(name = BenchmarkVitalsModule.NAME) +class BenchmarkVitalsModule( + reactContext: ReactApplicationContext +) : ReactContextBaseJavaModule(reactContext), TurboModule { + companion object { + const val NAME = "BenchmarkVitals" + } + + private val impl = BenchmarkVitalsModuleImpl(reactContext) + + override fun getName(): String = NAME + + @ReactMethod + fun startCollectingVitals(config: ReadableMap, promise: Promise) { + impl.startCollectingVitals(config, promise) + } + + @ReactMethod + fun stopCollectingVitals(promise: Promise) { + impl.stopCollectingVitals(promise) + } +} diff --git a/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModuleImpl.kt b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModuleImpl.kt new file mode 100644 index 000000000..81ff632e2 --- /dev/null +++ b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsModuleImpl.kt @@ -0,0 +1,46 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.benchmarkvitals + +import android.content.Context +import com.benchmarkrunner.BuildConfig +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReadableMap +import com.datadog.benchmark.DatadogVitalsMeter +import com.datadog.benchmark.DatadogExporterConfiguration + +private const val METER_INTERVAL_IN_SECONDS = 10L +private const val BENCHMARK_APPLICATION_NAME = "Benchmark RN - Android Application" + +class BenchmarkVitalsModuleImpl(private val context: Context) { + internal lateinit var vitalsMeter: DatadogVitalsMeter + + fun startCollectingVitals(config: ReadableMap, promise: Promise) { + val runType = config.getString("runType") ?: "" + val scenario = config.getString("scenario") ?: "" + val apiKey = config.getString("apiKey") ?: "" + + val exporterConfig = DatadogExporterConfiguration.Builder(apiKey) + .setApplicationId(BuildConfig.APPLICATION_ID) + .setApplicationName(BENCHMARK_APPLICATION_NAME) + .setRun(runType) + .setScenario(scenario) + .setApplicationVersion(BuildConfig.VERSION_NAME) + .setIntervalInSeconds(METER_INTERVAL_IN_SECONDS) + .build() + + vitalsMeter = DatadogVitalsMeter.create(exporterConfig) + vitalsMeter.startMeasuring() + + promise.resolve(true) + } + + fun stopCollectingVitals(promise: Promise) { + vitalsMeter.stopMeasuring() + promise.resolve(true) + } +} diff --git a/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsPackage.kt b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsPackage.kt new file mode 100644 index 000000000..53631cbf3 --- /dev/null +++ b/benchmarks/android/app/src/main/java/com/benchmarkvitals/BenchmarkVitalsPackage.kt @@ -0,0 +1,24 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.benchmarkvitals + +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.uimanager.ViewManager + +class BenchmarkVitalsPackage : ReactPackage { + override fun createNativeModules( + reactContext: ReactApplicationContext + ): List { + return listOf(BenchmarkVitalsModule(reactContext)) + } + + override fun createViewManagers( + reactContext: ReactApplicationContext + ): List> = emptyList() +} diff --git a/benchmarks/android/app/src/main/res/drawable/rn_edit_text_material.xml b/benchmarks/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 000000000..5c25e728e --- /dev/null +++ b/benchmarks/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + diff --git a/benchmarks/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/benchmarks/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..a2f590828 Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/benchmarks/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..1b5239980 Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/benchmarks/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..ff10afd6e Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/benchmarks/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..115a4c768 Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/benchmarks/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..dcd3cd808 Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/benchmarks/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..459ca609d Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/benchmarks/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..8ca12fe02 Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/benchmarks/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..8e19b410a Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/benchmarks/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..b824ebdd4 Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/benchmarks/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/benchmarks/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..4c19a13c2 Binary files /dev/null and b/benchmarks/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/benchmarks/android/app/src/main/res/values/strings.xml b/benchmarks/android/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..8aa7b5f60 --- /dev/null +++ b/benchmarks/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + BenchmarkRunner + diff --git a/benchmarks/android/app/src/main/res/values/styles.xml b/benchmarks/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..7ba83a2ad --- /dev/null +++ b/benchmarks/android/app/src/main/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/benchmarks/android/build.gradle b/benchmarks/android/build.gradle new file mode 100644 index 000000000..976694691 --- /dev/null +++ b/benchmarks/android/build.gradle @@ -0,0 +1,21 @@ +buildscript { + ext { + buildToolsVersion = "35.0.0" + minSdkVersion = 24 + compileSdkVersion = 35 + targetSdkVersion = 35 + ndkVersion = "27.1.12297006" + kotlinVersion = "2.0.21" + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") + } +} + +apply plugin: "com.facebook.react.rootproject" diff --git a/benchmarks/android/gradle.properties b/benchmarks/android/gradle.properties new file mode 100644 index 000000000..9fb15664b --- /dev/null +++ b/benchmarks/android/gradle.properties @@ -0,0 +1,39 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/benchmarks/android/gradle/wrapper/gradle-wrapper.jar b/benchmarks/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..a4b76b953 Binary files /dev/null and b/benchmarks/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/benchmarks/android/gradle/wrapper/gradle-wrapper.properties b/benchmarks/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..e0fd02028 --- /dev/null +++ b/benchmarks/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/benchmarks/android/gradlew b/benchmarks/android/gradlew new file mode 100755 index 000000000..f3b75f3b0 --- /dev/null +++ b/benchmarks/android/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/benchmarks/android/gradlew.bat b/benchmarks/android/gradlew.bat new file mode 100644 index 000000000..9b42019c7 --- /dev/null +++ b/benchmarks/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/benchmarks/android/settings.gradle b/benchmarks/android/settings.gradle new file mode 100644 index 000000000..aa89e3f77 --- /dev/null +++ b/benchmarks/android/settings.gradle @@ -0,0 +1,6 @@ +pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } +plugins { id("com.facebook.react.settings") } +extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } +rootProject.name = 'BenchmarkRunner' +include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/benchmarks/app.json b/benchmarks/app.json new file mode 100644 index 000000000..0c24f2271 --- /dev/null +++ b/benchmarks/app.json @@ -0,0 +1,4 @@ +{ + "name": "BenchmarkRunner", + "displayName": "BenchmarkRunner" +} diff --git a/benchmarks/babel.config.js b/benchmarks/babel.config.js new file mode 100644 index 000000000..f7b3da3b3 --- /dev/null +++ b/benchmarks/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:@react-native/babel-preset'], +}; diff --git a/benchmarks/index.js b/benchmarks/index.js new file mode 100644 index 000000000..69303b34d --- /dev/null +++ b/benchmarks/index.js @@ -0,0 +1,9 @@ +/** + * @format + */ + +import {AppRegistry} from 'react-native'; +import App from './src/App'; +import {name as appName} from './app.json'; + +AppRegistry.registerComponent(appName, () => App); diff --git a/benchmarks/ios/.xcode.env b/benchmarks/ios/.xcode.env new file mode 100644 index 000000000..3d5782c71 --- /dev/null +++ b/benchmarks/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..e8c70650d --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.pbxproj @@ -0,0 +1,721 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + 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 */; }; + 041FA8AB2DCCB7FA00BABC32 /* BenchmarkMeter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041FA8A22DCCB7FA00BABC32 /* BenchmarkMeter.swift */; }; + 041FA8AD2DCCB7FA00BABC32 /* BenchmarkProfiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041FA8A32DCCB7FA00BABC32 /* BenchmarkProfiler.swift */; }; + 041FA8AE2DCCB7FA00BABC32 /* Benchmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041FA8A42DCCB7FA00BABC32 /* Benchmarks.swift */; }; + 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 */; }; + 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 */; }; + 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; +/* 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 = ""; }; + 041FA8A52DCCB7FA00BABC32 /* BenchmarkVitals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkVitals.swift; sourceTree = ""; }; + 041FA8A62DCCB7FA00BABC32 /* MetricExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricExporter.swift; sourceTree = ""; }; + 041FA8A72DCCB7FA00BABC32 /* Metrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metrics.swift; sourceTree = ""; }; + 043403222DCB9CB200803AF8 /* BenchMarkVitalsImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchMarkVitalsImplementation.swift; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = BenchmarkRunner/PrivacyInfo.xcprivacy; sourceTree = ""; }; + 3B4392A12AC88292D35C810B /* Pods-BenchmarkRunner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenchmarkRunner.debug.xcconfig"; path = "Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-BenchmarkRunner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenchmarkRunner.release.xcconfig"; path = "Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner.release.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-BenchmarkRunner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BenchmarkRunner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = BenchmarkRunner/AppDelegate.swift; sourceTree = ""; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = BenchmarkRunner/LaunchScreen.storyboard; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-BenchmarkRunner.a in Frameworks */, + 04066FD52DCCB9D200A9E317 /* DatadogBenchmarks in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 04066FD22DCCB97400A9E317 /* Sources */ = { + isa = PBXGroup; + children = ( + 041FA8A42DCCB7FA00BABC32 /* Benchmarks.swift */, + 041FA8A62DCCB7FA00BABC32 /* MetricExporter.swift */, + 041FA8A72DCCB7FA00BABC32 /* Metrics.swift */, + ); + path = Sources; + sourceTree = ""; + }; + 041FA8A02DCCB7EA00BABC32 /* Vitals */ = { + isa = PBXGroup; + children = ( + 041FA8A12DCCB7FA00BABC32 /* Package.swift */, + 041FA8A52DCCB7FA00BABC32 /* BenchmarkVitals.swift */, + 041FA8A22DCCB7FA00BABC32 /* BenchmarkMeter.swift */, + 041FA8A32DCCB7FA00BABC32 /* BenchmarkProfiler.swift */, + 04066FD22DCCB97400A9E317 /* Sources */, + ); + path = Vitals; + sourceTree = ""; + }; + 0434031E2DCB70D200803AF8 /* BenchmarkVitals */ = { + isa = PBXGroup; + children = ( + 043403282DCBA1D100803AF8 /* BenchmarkVitals.h */, + 043403242DCB9CD700803AF8 /* BenchmarkVitals.mm */, + 043403222DCB9CB200803AF8 /* BenchMarkVitalsImplementation.swift */, + 041FA8A02DCCB7EA00BABC32 /* Vitals */, + ); + path = BenchmarkVitals; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* BenchmarkRunner */ = { + isa = PBXGroup; + children = ( + 04576C952DCBAF900078DCAB /* main.m */, + 761780EC2CA45674006654EE /* AppDelegate.swift */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */, + ); + name = BenchmarkRunner; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-BenchmarkRunner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 0434031E2DCB70D200803AF8 /* BenchmarkVitals */, + 13B07FAE1A68108700A75B9A /* BenchmarkRunner */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* BenchmarkRunner.app */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-BenchmarkRunner.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-BenchmarkRunner.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 13B07F861A680F5B00A75B9A /* BenchmarkRunner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "BenchmarkRunner" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BenchmarkRunner; + productName = BenchmarkRunner; + productReference = 13B07F961A680F5B00A75B9A /* BenchmarkRunner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1620; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "BenchmarkRunner" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + packageReferences = ( + 04066FD32DCCB9D200A9E317 /* XCLocalSwiftPackageReference "Vitals" */, + ); + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* BenchmarkRunner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 20A397FC280595A8A9851556 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-BenchmarkRunner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BenchmarkRunner/Pods-BenchmarkRunner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 041FA8A82DCCB7FA00BABC32 /* MetricExporter.swift in Sources */, + 041FA8A92DCCB7FA00BABC32 /* BenchmarkVitals.swift in Sources */, + 041FA8AA2DCCB7FA00BABC32 /* Metrics.swift in Sources */, + 041FA8AB2DCCB7FA00BABC32 /* BenchmarkMeter.swift in Sources */, + 041FA8AD2DCCB7FA00BABC32 /* BenchmarkProfiler.swift in Sources */, + 041FA8AE2DCCB7FA00BABC32 /* Benchmarks.swift in Sources */, + 043403262DCB9CD700803AF8 /* BenchmarkVitals.mm in Sources */, + 043403232DCB9CB200803AF8 /* BenchMarkVitalsImplementation.swift in Sources */, + 04576C962DCBAF900078DCAB /* main.m in Sources */, + 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-BenchmarkRunner.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = JKFCB4CN7C; + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"${PODS_ROOT}/Headers/Public\"", + "\"${PODS_ROOT}/Headers/Public/DatadogCore\"", + "\"${PODS_ROOT}/Headers/Public/DatadogSDKReactNative\"", + "\"${PODS_ROOT}/Headers/Public/DoubleConversion\"", + "\"${PODS_ROOT}/Headers/Public/FBLazyVector\"", + "\"${PODS_ROOT}/Headers/Public/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/RCTDeprecation\"", + "\"${PODS_ROOT}/Headers/Public/RCTRequired\"", + "\"${PODS_ROOT}/Headers/Public/RCTTypeSafety\"", + "\"${PODS_ROOT}/Headers/Public/RNScreens\"", + "\"${PODS_ROOT}/Headers/Public/React-Core\"", + "\"${PODS_ROOT}/Headers/Public/React-Fabric\"", + "\"${PODS_ROOT}/Headers/Public/React-FabricComponents\"", + "\"${PODS_ROOT}/Headers/Public/React-FabricImage\"", + "\"${PODS_ROOT}/Headers/Public/React-ImageManager\"", + "\"${PODS_ROOT}/Headers/Public/React-Mapbuffer\"", + "\"${PODS_ROOT}/Headers/Public/React-NativeModulesApple\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTAnimation\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTAppDelegate\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTBlob\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTFBReactNativeSpec\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTFabric\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTText\"", + "\"${PODS_ROOT}/Headers/Public/React-RuntimeApple\"", + "\"${PODS_ROOT}/Headers/Public/React-RuntimeCore\"", + "\"${PODS_ROOT}/Headers/Public/React-RuntimeHermes\"", + "\"${PODS_ROOT}/Headers/Public/React-callinvoker\"", + "\"${PODS_ROOT}/Headers/Public/React-cxxreact\"", + "\"${PODS_ROOT}/Headers/Public/React-debug\"", + "\"${PODS_ROOT}/Headers/Public/React-defaultsnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-domnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-featureflags\"", + "\"${PODS_ROOT}/Headers/Public/React-featureflagsnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-graphics\"", + "\"${PODS_ROOT}/Headers/Public/React-hermes\"", + "\"${PODS_ROOT}/Headers/Public/React-idlecallbacksnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-jserrorhandler\"", + "\"${PODS_ROOT}/Headers/Public/React-jsi\"", + "\"${PODS_ROOT}/Headers/Public/React-jsiexecutor\"", + "\"${PODS_ROOT}/Headers/Public/React-jsinspector\"", + "\"${PODS_ROOT}/Headers/Public/React-jsinspectortracing\"", + "\"${PODS_ROOT}/Headers/Public/React-logger\"", + "\"${PODS_ROOT}/Headers/Public/React-microtasksnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-perflogger\"", + "\"${PODS_ROOT}/Headers/Public/React-performancetimeline\"", + "\"${PODS_ROOT}/Headers/Public/React-rendererconsistency\"", + "\"${PODS_ROOT}/Headers/Public/React-rendererdebug\"", + "\"${PODS_ROOT}/Headers/Public/React-runtimeexecutor\"", + "\"${PODS_ROOT}/Headers/Public/React-runtimescheduler\"", + "\"${PODS_ROOT}/Headers/Public/React-timing\"", + "\"${PODS_ROOT}/Headers/Public/React-utils\"", + "\"${PODS_ROOT}/Headers/Public/ReactAppDependencyProvider\"", + "\"${PODS_ROOT}/Headers/Public/ReactCodegen\"", + "\"${PODS_ROOT}/Headers/Public/ReactCommon\"", + "\"${PODS_ROOT}/Headers/Public/SocketRocket\"", + "\"${PODS_ROOT}/Headers/Public/Yoga\"", + "\"${PODS_ROOT}/Headers/Public/boost\"", + "\"${PODS_ROOT}/Headers/Public/fast_float\"", + "\"${PODS_ROOT}/Headers/Public/fmt\"", + "\"${PODS_ROOT}/Headers/Public/glog\"", + "\"${PODS_ROOT}/Headers/Public/hermes-engine\"", + "\"${PODS_ROOT}/Headers/Public/react-native-config\"", + "\"${PODS_ROOT}/Headers/Public/react-native-safe-area-context\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_ROOT)/Headers/Private/React-Core\"", + "\"$(PODS_ROOT)/Headers/Private/React-Core\"", + "\"$(PODS_ROOT)/Headers/Private/Yoga\"", + "$(PROJECT_DIR)/build/generated/ios/**", + ); + INFOPLIST_FILE = BenchmarkRunner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.datadog.react.native.--PRODUCT-NAME-rfc1034identifier-"; + "PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.datadog.react.native.BenchmarkRunner; + PRODUCT_NAME = BenchmarkRunner; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-BenchmarkRunner.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = JKFCB4CN7C; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"${PODS_ROOT}/Headers/Public\"", + "\"${PODS_ROOT}/Headers/Public/DatadogCore\"", + "\"${PODS_ROOT}/Headers/Public/DatadogSDKReactNative\"", + "\"${PODS_ROOT}/Headers/Public/DoubleConversion\"", + "\"${PODS_ROOT}/Headers/Public/FBLazyVector\"", + "\"${PODS_ROOT}/Headers/Public/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/RCTDeprecation\"", + "\"${PODS_ROOT}/Headers/Public/RCTRequired\"", + "\"${PODS_ROOT}/Headers/Public/RCTTypeSafety\"", + "\"${PODS_ROOT}/Headers/Public/RNScreens\"", + "\"${PODS_ROOT}/Headers/Public/React-Core\"", + "\"${PODS_ROOT}/Headers/Public/React-Fabric\"", + "\"${PODS_ROOT}/Headers/Public/React-FabricComponents\"", + "\"${PODS_ROOT}/Headers/Public/React-FabricImage\"", + "\"${PODS_ROOT}/Headers/Public/React-ImageManager\"", + "\"${PODS_ROOT}/Headers/Public/React-Mapbuffer\"", + "\"${PODS_ROOT}/Headers/Public/React-NativeModulesApple\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTAnimation\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTAppDelegate\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTBlob\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTFBReactNativeSpec\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTFabric\"", + "\"${PODS_ROOT}/Headers/Public/React-RCTText\"", + "\"${PODS_ROOT}/Headers/Public/React-RuntimeApple\"", + "\"${PODS_ROOT}/Headers/Public/React-RuntimeCore\"", + "\"${PODS_ROOT}/Headers/Public/React-RuntimeHermes\"", + "\"${PODS_ROOT}/Headers/Public/React-callinvoker\"", + "\"${PODS_ROOT}/Headers/Public/React-cxxreact\"", + "\"${PODS_ROOT}/Headers/Public/React-debug\"", + "\"${PODS_ROOT}/Headers/Public/React-defaultsnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-domnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-featureflags\"", + "\"${PODS_ROOT}/Headers/Public/React-featureflagsnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-graphics\"", + "\"${PODS_ROOT}/Headers/Public/React-hermes\"", + "\"${PODS_ROOT}/Headers/Public/React-idlecallbacksnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-jserrorhandler\"", + "\"${PODS_ROOT}/Headers/Public/React-jsi\"", + "\"${PODS_ROOT}/Headers/Public/React-jsiexecutor\"", + "\"${PODS_ROOT}/Headers/Public/React-jsinspector\"", + "\"${PODS_ROOT}/Headers/Public/React-jsinspectortracing\"", + "\"${PODS_ROOT}/Headers/Public/React-logger\"", + "\"${PODS_ROOT}/Headers/Public/React-microtasksnativemodule\"", + "\"${PODS_ROOT}/Headers/Public/React-perflogger\"", + "\"${PODS_ROOT}/Headers/Public/React-performancetimeline\"", + "\"${PODS_ROOT}/Headers/Public/React-rendererconsistency\"", + "\"${PODS_ROOT}/Headers/Public/React-rendererdebug\"", + "\"${PODS_ROOT}/Headers/Public/React-runtimeexecutor\"", + "\"${PODS_ROOT}/Headers/Public/React-runtimescheduler\"", + "\"${PODS_ROOT}/Headers/Public/React-timing\"", + "\"${PODS_ROOT}/Headers/Public/React-utils\"", + "\"${PODS_ROOT}/Headers/Public/ReactAppDependencyProvider\"", + "\"${PODS_ROOT}/Headers/Public/ReactCodegen\"", + "\"${PODS_ROOT}/Headers/Public/ReactCommon\"", + "\"${PODS_ROOT}/Headers/Public/SocketRocket\"", + "\"${PODS_ROOT}/Headers/Public/Yoga\"", + "\"${PODS_ROOT}/Headers/Public/boost\"", + "\"${PODS_ROOT}/Headers/Public/fast_float\"", + "\"${PODS_ROOT}/Headers/Public/fmt\"", + "\"${PODS_ROOT}/Headers/Public/glog\"", + "\"${PODS_ROOT}/Headers/Public/hermes-engine\"", + "\"${PODS_ROOT}/Headers/Public/react-native-config\"", + "\"${PODS_ROOT}/Headers/Public/react-native-safe-area-context\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_ROOT)/Headers/Private/React-Core\"", + "\"$(PODS_ROOT)/Headers/Private/React-Core\"", + "\"$(PODS_ROOT)/Headers/Private/Yoga\"", + "$(PROJECT_DIR)/build/generated/ios/**", + ); + INFOPLIST_FILE = BenchmarkRunner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.datadog.react.native.--PRODUCT-NAME-rfc1034identifier-"; + "PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.datadog.react.native.BenchmarkRunner; + PRODUCT_NAME = BenchmarkRunner; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + "-DFOLLY_HAVE_CLOCK_GETTIME=1", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; + USE_HERMES = true; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + "-DFOLLY_HAVE_CLOCK_GETTIME=1", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + USE_HERMES = true; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "BenchmarkRunner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "BenchmarkRunner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + 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 new file mode 100644 index 000000000..fefebe144 --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,177 @@ +{ + "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.xcodeproj/xcshareddata/xcschemes/BenchmarkRunner.xcscheme b/benchmarks/ios/BenchmarkRunner.xcodeproj/xcshareddata/xcschemes/BenchmarkRunner.xcscheme new file mode 100644 index 000000000..ae3025f76 --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner.xcodeproj/xcshareddata/xcschemes/BenchmarkRunner.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmarks/ios/BenchmarkRunner.xcworkspace/contents.xcworkspacedata b/benchmarks/ios/BenchmarkRunner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..1411fce3d --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..fefebe144 --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,177 @@ +{ + "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/AppDelegate.swift b/benchmarks/ios/BenchmarkRunner/AppDelegate.swift new file mode 100644 index 000000000..8ca5d31fd --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/AppDelegate.swift @@ -0,0 +1,45 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import React +import ReactAppDependencyProvider +import React_RCTAppDelegate +import UIKit + +@objc(AppDelegate) +class AppDelegate: RCTAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil + ) -> Bool { + self.moduleName = "BenchmarkRunner" + self.dependencyProvider = RCTAppDependencyProvider() + + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = [:] + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + override func sourceURL(for bridge: RCTBridge) -> URL? { + self.bundleURL() + } + + override func bundleURL() -> URL? { + #if DEBUG + RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") + #else + Bundle.main.url(forResource: "main", withExtension: "jsbundle") + #endif + } + + override func application( + _ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:] + ) -> Bool { + return RCTLinkingManager.application(app, open: url, options: options) + } +} diff --git a/benchmarks/ios/BenchmarkRunner/BenchmarkVitalsModule.m b/benchmarks/ios/BenchmarkRunner/BenchmarkVitalsModule.m new file mode 100644 index 000000000..89fbb0ca1 --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/BenchmarkVitalsModule.m @@ -0,0 +1,12 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +#import + +@interface RCT_EXTERN_MODULE(BenchmarkVitalsModule, NSObject) +RCT_EXTERN_METHOD(startCollectingVitals:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(stopCollectingVitals:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +@end diff --git a/benchmarks/ios/BenchmarkRunner/BenchmarkVitalsModule.swift b/benchmarks/ios/BenchmarkRunner/BenchmarkVitalsModule.swift new file mode 100644 index 000000000..5848fe310 --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/BenchmarkVitalsModule.swift @@ -0,0 +1,22 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import Foundation +import React + +@objc(BenchmarkVitals) +class BenchmarkVitalsModule: NSObject { +// var vitals: Vitals? + + @objc + func startCollectingVitals(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { + resolve(true) + } + + @objc func stopCollectingVitals(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { + resolve(true) + } +} diff --git a/benchmarks/ios/BenchmarkRunner/Images.xcassets/AppIcon.appiconset/Contents.json b/benchmarks/ios/BenchmarkRunner/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..81213230d --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/benchmarks/ios/BenchmarkRunner/Images.xcassets/Contents.json b/benchmarks/ios/BenchmarkRunner/Images.xcassets/Contents.json new file mode 100644 index 000000000..2d92bd53f --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/benchmarks/ios/BenchmarkRunner/Info.plist b/benchmarks/ios/BenchmarkRunner/Info.plist new file mode 100644 index 000000000..6a4199cab --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + BenchmarkRunner + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleURLSchemes + + benchmark + + + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/benchmarks/ios/BenchmarkRunner/LaunchScreen.storyboard b/benchmarks/ios/BenchmarkRunner/LaunchScreen.storyboard new file mode 100644 index 000000000..a3c16a42c --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmarks/ios/BenchmarkRunner/PrivacyInfo.xcprivacy b/benchmarks/ios/BenchmarkRunner/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..bad327615 --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/PrivacyInfo.xcprivacy @@ -0,0 +1,37 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/benchmarks/ios/BenchmarkRunner/main.m b/benchmarks/ios/BenchmarkRunner/main.m new file mode 100644 index 000000000..f3348bc1f --- /dev/null +++ b/benchmarks/ios/BenchmarkRunner/main.m @@ -0,0 +1,8 @@ +#import +#import "BenchmarkRunner-Swift.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/benchmarks/ios/BenchmarkVitals/BenchMarkVitalsImplementation.swift b/benchmarks/ios/BenchmarkVitals/BenchMarkVitalsImplementation.swift new file mode 100644 index 000000000..546973eac --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/BenchMarkVitalsImplementation.swift @@ -0,0 +1,75 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import Foundation +import React +import DatadogBenchmarks + +struct NativeTestConfig { + let scenario: String + let runType: String + let clientToken: String + let applicationID: String + let apiKey: String + + init(from dict: NSDictionary) { + self.scenario = dict["scenario"] as? String ?? "" + self.runType = dict["runType"] as? String ?? "" + self.clientToken = dict["clientToken"] as? String ?? "" + self.applicationID = dict["applicationID"] as? String ?? "" + self.apiKey = dict["apiKey"] as? String ?? "" + } +} + +@objc +public class BenchmarkVitalsImplementation: NSObject { + + var vitals: Vitals? + + @objc + public func startCollectingVitals(config: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void { + let nativeConfig = NativeTestConfig(from: config) + + let appId = Bundle.main.bundleIdentifier ?? "unknown.bundle.id" + let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleExecutable") as! String + let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String + let osName = UIDevice.current.systemName + let osVersion = UIDevice.current.systemVersion + let deviceModel = UIDevice.current.model + + let context = Benchmarks.Configuration.Context( + applicationIdentifier: appId, + applicationName: appName, + applicationVersion: appVersion, + sdkVersion: "", + deviceModel: deviceModel, + osName: osName, + osVersion: osVersion, + run: nativeConfig.runType, + scenario: nativeConfig.scenario, + branch: "") + let configuration = Benchmarks.Configuration(clientToken: nativeConfig.clientToken, apiKey: nativeConfig.apiKey, context: context) + let vitals = Vitals( + provider: Benchmarks.meterProvider( + with: configuration + ) + ) + + vitals.observeCPU() + vitals.observeMemory() + vitals.observeFPS() + + + self.vitals = vitals + resolve(true) + } + + @objc + public func stopCollectingVitals(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void { + vitals = nil + resolve(true) + } +} diff --git a/benchmarks/ios/BenchmarkVitals/BenchmarkVitals.h b/benchmarks/ios/BenchmarkVitals/BenchmarkVitals.h new file mode 100644 index 000000000..0df654a46 --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/BenchmarkVitals.h @@ -0,0 +1,23 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +#import +@class BenchmarkVitalsImplementation; + +#ifdef RCT_NEW_ARCH_ENABLED +#import "BenchmarkVitalsSpec.h" +@interface BenchmarkVitals: NSObject + +#else + +#import +@interface BenchmarkVitals : NSObject + +#endif + +@property (nonatomic, strong) BenchmarkVitalsImplementation* benchmarkVitalsImplementation; + +@end diff --git a/benchmarks/ios/BenchmarkVitals/BenchmarkVitals.mm b/benchmarks/ios/BenchmarkVitals/BenchmarkVitals.mm new file mode 100644 index 000000000..c2a011ff1 --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/BenchmarkVitals.mm @@ -0,0 +1,56 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +#if __has_include("BenchmarkRunner-Swift.h") +#import "BenchmarkRunner-Swift.h" +#else +#import +#endif +#import "BenchmarkVitals.h" + +@implementation BenchmarkVitals + +RCT_EXPORT_MODULE() + +RCT_REMAP_METHOD(startCollectingVitals, startCollectingVitalswithConfig:(NSDictionary *)config + withResolve: (RCTPromiseResolveBlock)resolve + withRejecter: (RCTPromiseRejectBlock)reject) +{ + [self startCollectingVitals:config resolve:resolve reject:reject]; +} + +RCT_REMAP_METHOD(stopCollectingVitals, stopCollectingVitalswithResolve: (RCTPromiseResolveBlock)resolve + withRejecter: (RCTPromiseRejectBlock)reject) +{ + [self stopCollectingVitals:resolve reject:reject]; +} + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif + +- (BenchmarkVitalsImplementation*)benchmarkVitalsImplementation +{ + if (_benchmarkVitalsImplementation == nil) { + _benchmarkVitalsImplementation = [[BenchmarkVitalsImplementation alloc] init]; + } + return _benchmarkVitalsImplementation; +} + + +- (void)startCollectingVitals:(NSDictionary *)config resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.benchmarkVitalsImplementation startCollectingVitalsWithConfig:config resolve:resolve reject:reject]; +} + +- (void)stopCollectingVitals:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + [self.benchmarkVitalsImplementation stopCollectingVitalsWithResolve:resolve reject:reject]; +} + +@end diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkMeter.swift b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkMeter.swift new file mode 100644 index 000000000..694b6ae07 --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkMeter.swift @@ -0,0 +1,53 @@ +/* + * 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 DatadogInternal +import DatadogBenchmarks +import OpenTelemetryApi + +internal final class Meter: DatadogInternal.BenchmarkMeter { + let meter: OpenTelemetryApi.Meter + + init(provider: MeterProvider) { + self.meter = provider.get( + instrumentationName: "benchmarks", + instrumentationVersion: nil + ) + } + + func counter(metric: @autoclosure () -> String) -> DatadogInternal.BenchmarkCounter { + meter.createDoubleCounter(name: metric()) + } + + func gauge(metric: @autoclosure () -> String) -> DatadogInternal.BenchmarkGauge { + meter.createDoubleMeasure(name: metric()) + } + + func observe(metric: @autoclosure () -> String, callback: @escaping (any DatadogInternal.BenchmarkGauge) -> Void) { + _ = meter.createDoubleObserver(name: metric()) { callback(DoubleObserverWrapper(observer: $0)) } + } +} + +extension AnyCounterMetric: DatadogInternal.BenchmarkCounter { + public func add(value: Double, attributes: @autoclosure () -> [String: String]) { + add(value: value, labelset: LabelSet(labels: attributes())) + } +} + +extension AnyMeasureMetric: DatadogInternal.BenchmarkGauge { + public func record(value: Double, attributes: @autoclosure () -> [String: String]) { + record(value: value, labelset: LabelSet(labels: attributes())) + } +} + +private struct DoubleObserverWrapper: DatadogInternal.BenchmarkGauge { + let observer: DoubleObserverMetric + + func record(value: Double, attributes: @autoclosure () -> [String: String]) { + observer.observe(value: value, labelset: LabelSet(labels: attributes())) + } +} diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkProfiler.swift b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkProfiler.swift new file mode 100644 index 000000000..e19b6759b --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkProfiler.swift @@ -0,0 +1,56 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. + */ + +import Foundation +import DatadogInternal +import DatadogBenchmarks +import OpenTelemetryApi + +internal final class Profiler: DatadogInternal.BenchmarkProfiler { + let provider: TracerProvider + + init(provider: TracerProvider) { + self.provider = provider + } + + func tracer(operation: @autoclosure () -> String) -> any DatadogInternal.BenchmarkTracer { + TracerWrapper( + tracer: provider.get( + instrumentationName: operation(), + instrumentationVersion: nil + ) + ) + } +} + +private final class TracerWrapper: DatadogInternal.BenchmarkTracer { + let tracer: OpenTelemetryApi.Tracer + + init(tracer: OpenTelemetryApi.Tracer) { + self.tracer = tracer + } + + func startSpan(named: @autoclosure () -> String) -> any DatadogInternal.BenchmarkSpan { + SpanWrapper( + span: tracer + .spanBuilder(spanName: named()) + .setActive(true) + .startSpan() + ) + } +} + +private final class SpanWrapper: DatadogInternal.BenchmarkSpan { + let span: OpenTelemetryApi.Span + + init(span: OpenTelemetryApi.Span) { + self.span = span + } + + func stop() { + span.end() + } +} diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkVitals.swift b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkVitals.swift new file mode 100644 index 000000000..772c6b76e --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/BenchmarkVitals.swift @@ -0,0 +1,63 @@ +/* + * 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 DatadogBenchmarks +import OpenTelemetryApi + +/// Collect Vital Metrics such CPU, Memory, and FPS. +/// +/// The metrics are reported via opentelemetry. +internal final class Vitals { + let provider: OpenTelemetryApi.MeterProvider + + private lazy var meter: OpenTelemetryApi.Meter = provider.get(instrumentationName: "vitals", instrumentationVersion: nil) + + let queue = DispatchQueue(label: "com.datadoghq.benchmarks.rn.ios.vitals", target: .global(qos: .utility)) + + init(provider: MeterProvider) { + self.provider = provider + } + + @discardableResult + func observeMemory() -> OpenTelemetryApi.DoubleObserverMetric { + let memory = Memory(queue: queue) + return meter.createDoubleObservableGauge(name: "rn.ios.benchmark.memory") { metric in + // report the maximum memory footprint that was recorded during push interval + if let value = memory.aggregation?.max { + metric.observe(value: value, labelset: .empty) + } + + memory.reset() + } + } + + @discardableResult + func observeCPU() -> OpenTelemetryApi.DoubleObserverMetric { + let cpu = CPU(queue: queue) + return meter.createDoubleObservableGauge(name: "rn.ios.benchmark.cpu") { metric in + // report the average cpu usage that was recorded during push interval + if let value = cpu.aggregation?.avg { + metric.observe(value: value, labelset: .empty) + } + + cpu.reset() + } + } + + @discardableResult + func observeFPS() -> OpenTelemetryApi.IntObserverMetric { + let fps = FPS() + return meter.createIntObservableGauge(name: "rn.ios.benchmark.fps.min") { metric in + // report the minimum frame rate that was recorded during push interval + if let value = fps.aggregation?.min { + metric.observe(value: value, labelset: .empty) + } + + fps.reset() + } + } +} diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/Package.swift b/benchmarks/ios/BenchmarkVitals/Vitals/Package.swift new file mode 100644 index 000000000..ff099cb82 --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/Package.swift @@ -0,0 +1,38 @@ +// 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 new file mode 100644 index 000000000..020c14af6 --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Benchmarks.swift @@ -0,0 +1,125 @@ +/* + * 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. + */ + +#if OTEL_API +#error("Benchmarks depends on opentelemetry-swift. Please open the project with 'make benchmark-tests-open'.") +#endif + +import Foundation +import OpenTelemetryApi +import OpenTelemetrySdk +import DatadogExporter + +/// Benchmark entrypoint to configure opentelemetry with metrics meters +/// and tracer. +public enum Benchmarks { + /// Configuration of the Benchmarks library. + public struct Configuration { + /// Context of Benchmarks measures. + /// The context properties will be added to metrics as tags. + public struct Context { + var applicationIdentifier: String + var applicationName: String + var applicationVersion: String + var sdkVersion: String + var deviceModel: String + var osName: String + var osVersion: String + var run: String + var scenario: String + var branch: String + + public init( + applicationIdentifier: String, + applicationName: String, + applicationVersion: String, + sdkVersion: String, + deviceModel: String, + osName: String, + osVersion: String, + run: String, + scenario: String, + branch: String + ) { + self.applicationIdentifier = applicationIdentifier + self.applicationName = applicationName + self.applicationVersion = applicationVersion + self.sdkVersion = sdkVersion + self.deviceModel = deviceModel + self.osName = osName + self.osVersion = osVersion + self.run = run + self.scenario = scenario + self.branch = branch + } + } + + var clientToken: String + var apiKey: String + var context: Context + + public init( + clientToken: String, + apiKey: String, + context: Context + ) { + self.clientToken = clientToken + self.apiKey = apiKey + self.context = context + } + } + + /// Configure an OpenTelemetry meter provider. + /// + /// - Parameter configuration: The Benchmark configuration. + public static func meterProvider(with configuration: Configuration) -> MeterProvider { + let metricExporter = MetricExporter( + configuration: MetricExporter.Configuration( + apiKey: configuration.apiKey, + version: configuration.context.applicationVersion + ) + ) + + return MeterProviderBuilder() + .with(pushInterval: 10) + .with(processor: MetricProcessorSdk()) + .with(exporter: metricExporter) + .with(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), + "application_id": .string(configuration.context.applicationIdentifier), + "sdk_version": .string(configuration.context.sdkVersion), + "branch": .string(configuration.context.branch), + ])) + .build() + } + + /// Configure an OpenTelemetry tracer provider. + /// + /// - 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() + } +} diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/Sources/MetricExporter.swift b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/MetricExporter.swift new file mode 100644 index 000000000..5109a455c --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/MetricExporter.swift @@ -0,0 +1,162 @@ +/* + * 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 OpenTelemetrySdk + +enum MetricExporterError: Error { + case unsupportedMetric(aggregation: AggregationType, dataType: Any.Type) +} + +/// Replacement of otel `DatadogExporter` for metrics. +/// +/// This version does not store data to disk, it uploads to the intake directly. +/// Additionally, it does not crash. +final class MetricExporter: OpenTelemetrySdk.MetricExporter { + struct Configuration { + let apiKey: String + let version: String + } + + /// The type of metric. The available types are 0 (unspecified), 1 (count), 2 (rate), and 3 (gauge). Allowed enum values: 0,1,2,3 + enum MetricType: Int, Codable { + case unspecified = 0 + case count = 1 + case rate = 2 + case gauge = 3 + } + + /// https://docs.datadoghq.com/api/latest/metrics/#submit-metrics + internal struct Serie: Codable { + struct Point: Codable { + let timestamp: Int64 + let value: Double + } + + struct Resource: Codable { + let name: String + let type: String + } + + let type: MetricType + let interval: Int64? + let metric: String + let unit: String? + let points: [Point] + let resources: [Resource] + let tags: [String] + } + + let session: URLSession + let encoder = JSONEncoder() + let configuration: Configuration + + // swiftlint:disable force_unwrapping + let intake = URL(string: "https://api.datadoghq.com/api/v2/series")! + let prefix = "{ \"series\": [".data(using: .utf8)! + let separator = ",".data(using: .utf8)! + let suffix = "]}".data(using: .utf8)! + // swiftlint:enable force_unwrapping + + required init(configuration: Configuration) { + let sessionConfiguration: URLSessionConfiguration = .ephemeral + sessionConfiguration.urlCache = nil + self.session = URLSession(configuration: sessionConfiguration) + self.configuration = configuration + } + + func export(metrics: [Metric], shouldCancel: (() -> Bool)?) -> MetricExporterResultCode { + do { + let series = try metrics.map(transform) + try submit(series: series) + return.success + } catch { + return .failureNotRetryable + } + } + + /// Transforms otel `Metric` to Datadog `serie`. + /// + /// - Parameter metric: The otel metric + /// - Returns: The timeserie. + func transform(_ metric: Metric) 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) + + data.labels.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: + 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) + ) + } + } + + return Serie( + type: MetricType(metric.aggregationType), + interval: nil, + metric: metric.name, + unit: nil, + points: points, + resources: [], + tags: Array(tags) + ) + } + + /// Submit timeseries to the Metrics intake. + /// + /// - Parameter series: The timeseries. + func submit(series: [Serie]) throws { + var data = try series.reduce(Data()) { data, serie in + try data + encoder.encode(serie) + separator + } + + // remove last separator + data.removeLast(separator.count) + + var request = URLRequest(url: intake) + request.httpMethod = "POST" + request.allHTTPHeaderFields = [ + "Content-Type": "application/json", + "DD-API-KEY": configuration.apiKey, + "DD-EVP-ORIGIN": "ios", + "DD-EVP-ORIGIN-VERSION": configuration.version, + "DD-REQUEST-ID": UUID().uuidString, + ] + + request.httpBody = prefix + data + suffix + session.dataTask(with: request).resume() + } +} + +private extension MetricExporter.MetricType { + init(_ type: OpenTelemetrySdk.AggregationType) { + switch type { + case .doubleSum, .intSum: + self = .count + case .intGauge, .doubleGauge: + self = .gauge + case .doubleSummary, .intSummary, .doubleHistogram, .intHistogram: + self = .unspecified + } + } +} diff --git a/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Metrics.swift b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Metrics.swift new file mode 100644 index 000000000..184c54f46 --- /dev/null +++ b/benchmarks/ios/BenchmarkVitals/Vitals/Sources/Metrics.swift @@ -0,0 +1,275 @@ +/* + * 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 QuartzCore + +// The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too +// complex for the Swift C importer, so we have to define them ourselves. +let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) +let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout.size) + +public enum MachError: Error { + case task_info(return: kern_return_t) + case task_threads(return: kern_return_t) + case thread_info(return: kern_return_t) +} + +/// Aggregate metric values and compute `min`, `max`, `sum`, `avg`, and `count`. +public class MetricAggregator where T: Numeric { + public struct Aggregation { + public let min: T + public let max: T + public let sum: T + public let count: Int + public let avg: Double + } + + private var mutex = pthread_mutex_t() + private var _aggregation: Aggregation? + + public var aggregation: Aggregation? { + pthread_mutex_lock(&mutex) + defer { pthread_mutex_unlock(&mutex) } + return _aggregation + } + + /// Resets the minimum frame rate to `nil`. + public func reset() { + pthread_mutex_lock(&mutex) + _aggregation = nil + pthread_mutex_unlock(&mutex) + } + + deinit { + pthread_mutex_destroy(&mutex) + } +} + +extension MetricAggregator where T: BinaryInteger { + /// Records a `BinaryInteger` value. + /// + /// - Parameter value: The value to record. + public func record(value: T) { + pthread_mutex_lock(&mutex) + _aggregation = _aggregation.map { + let sum = $0.sum + value + let count = $0.count + 1 + return Aggregation( + min: Swift.min($0.min, value), + max: Swift.max($0.max, value), + sum: sum, + count: count, + avg: Double(sum) / Double(count) + ) + } ?? Aggregation(min: value, max: value, sum: value, count: 1, avg: Double(value)) + pthread_mutex_unlock(&mutex) + } +} + +extension MetricAggregator where T: BinaryFloatingPoint { + /// Records a `BinaryFloatingPoint` value. + /// + /// - Parameter value: The value to record. + internal func record(value: T) { + pthread_mutex_lock(&mutex) + _aggregation = _aggregation.map { + let sum = $0.sum + value + let count = $0.count + 1 + return Aggregation( + min: Swift.min($0.min, value), + max: Swift.max($0.max, value), + sum: sum, + count: count, + avg: Double(sum) / Double(count) + ) + } ?? Aggregation(min: value, max: value, sum: value, count: 1, avg: Double(value)) + pthread_mutex_unlock(&mutex) + } +} + +/// Collect Memory footprint metric. +/// +/// Based on a timer, the `Memory` aggregator will periodically record the memory footprint. +public final class Memory: MetricAggregator { + /// Dispatch source object for monitoring timer events. + private let timer: DispatchSourceTimer + + /// Create a `Memory` aggregator to periodically record the memory footprint on the + /// provided queue. + /// + /// By default, the timer is scheduled with 100 ms interval with 10 ms leeway. + /// + /// - Parameters: + /// - queue: The queue on which to execute the timer handler. + /// - interval: The timer interval, default to 100 ms. + /// - leeway: The timer leeway, default to 10 ms. + public required init( + queue: DispatchQueue, + every interval: DispatchTimeInterval = .milliseconds(100), + leeway: DispatchTimeInterval = .milliseconds(10) + ) { + timer = DispatchSource.makeTimerSource(queue: queue) + super.init() + + timer.setEventHandler { [weak self] in + guard let self, let footprint = try? self.footprint() else { + return + } + + self.record(value: footprint) + } + + timer.schedule(deadline: .now(), repeating: interval, leeway: leeway) + timer.activate() + } + + deinit { + timer.cancel() + } + + /// Collects single sample of current memory footprint. + /// + /// The computation is based on https://developer.apple.com/forums/thread/105088 + /// It leverages recommended `phys_footprint` value, which returns values that are close to Xcode's _Memory Use_ + /// gauge and _Allocations Instrument_. + /// + /// - Returns: Current memory footprint in bytes, `throws` if failed to read. + private func footprint() throws -> Double { + var info = task_vm_info_data_t() + var count = TASK_VM_INFO_COUNT + let kr = withUnsafeMutablePointer(to: &info) { + $0.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { + task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), $0, &count) + } + } + + guard kr == KERN_SUCCESS, count >= TASK_VM_INFO_REV1_COUNT else { + throw MachError.task_info(return: kr) + } + + return Double(info.phys_footprint) + } +} + +/// Collect CPU usage metric. +/// +/// Based on a timer, the `CPU` aggregator will periodically record the CPU usage. +public final class CPU: MetricAggregator { + /// Dispatch source object for monitoring timer events. + private let timer: DispatchSourceTimer + + /// Create a `CPU` aggregator to periodically record the CPU usage on the + /// provided queue. + /// + /// By default, the timer is scheduled with 100 ms interval with 10 ms leeway. + /// + /// - Parameters: + /// - queue: The queue on which to execute the timer handler. + /// - interval: The timer interval, default to 100 ms. + /// - leeway: The timer leeway, default to 10 ms. + public required init( + queue: DispatchQueue, + every interval: DispatchTimeInterval = .milliseconds(100), + leeway: DispatchTimeInterval = .milliseconds(10) + ) { + self.timer = DispatchSource.makeTimerSource(queue: queue) + super.init() + + timer.setEventHandler { [weak self] in + guard let self, let usage = try? self.usage() else { + return + } + + self.record(value: usage) + } + + timer.schedule(deadline: .now(), repeating: interval, leeway: leeway) + timer.activate() + } + + deinit { + timer.cancel() + } + + /// Collect single sample of current cpu usage. + /// + /// The computation is based on https://gist.github.com/hisui/10004131#file-cpu-usage-cpp + /// It reads the `cpu_usage` from all thread to compute the application usage percentage. + /// + /// - Returns: The cpu usage of all threads. + private func usage() throws -> Double { + var threads_list: thread_act_array_t? + var threads_count = mach_msg_type_number_t() + let kr = withUnsafeMutablePointer(to: &threads_list) { + $0.withMemoryRebound(to: thread_act_array_t?.self, capacity: 1) { + task_threads(mach_task_self_, $0, &threads_count) + } + } + + guard kr == KERN_SUCCESS, let threads_list = threads_list else { + throw MachError.task_threads(return: kr) + } + + defer { + vm_deallocate(mach_task_self_, vm_address_t(bitPattern: threads_list), vm_size_t(Int(threads_count) * MemoryLayout.stride)) + } + + return try (0.. { + private class CADisplayLinker { + weak var fps: FPS? + + init() { } + + @objc + func tick(link: CADisplayLink) { + guard let fps else { + return + } + + let rate = 1 / (link.targetTimestamp - link.timestamp) + fps.record(value: lround(rate)) + } + } + + private var displayLink: CADisplayLink + + override public init() { + let linker = CADisplayLinker() + displayLink = CADisplayLink(target: linker, selector: #selector(CADisplayLinker.tick(link:))) + super.init() + + linker.fps = self + displayLink.add(to: RunLoop.main, forMode: .common) + } + + deinit { + displayLink.invalidate() + } +} diff --git a/benchmarks/ios/Podfile b/benchmarks/ios/Podfile new file mode 100644 index 000000000..059b1eae4 --- /dev/null +++ b/benchmarks/ios/Podfile @@ -0,0 +1,35 @@ +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip + +platform :ios, min_ios_version_supported +prepare_react_native_project! + +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + +target 'BenchmarkRunner' do + config = use_native_modules! + + use_react_native!( + :path => config[:reactNativePath], + # 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( + installer, + config[:reactNativePath], + :mac_catalyst_enabled => false, + # :ccache_enabled => true + ) + end +end diff --git a/benchmarks/ios/Podfile.lock b/benchmarks/ios/Podfile.lock new file mode 100644 index 000000000..c9a471204 --- /dev/null +++ b/benchmarks/ios/Podfile.lock @@ -0,0 +1,2160 @@ +PODS: + - boost (1.84.0) + - DatadogCore (2.29.0): + - DatadogInternal (= 2.29.0) + - DatadogCrashReporting (2.29.0): + - DatadogInternal (= 2.29.0) + - PLCrashReporter (~> 1.12.0) + - DatadogInternal (2.29.0) + - DatadogLogs (2.29.0): + - DatadogInternal (= 2.29.0) + - DatadogRUM (2.29.0): + - DatadogInternal (= 2.29.0) + - DatadogSDKReactNative (2.10.1): + - DatadogCore (= 2.29.0) + - DatadogCrashReporting (= 2.29.0) + - DatadogLogs (= 2.29.0) + - DatadogRUM (= 2.29.0) + - DatadogTrace (= 2.29.0) + - DatadogWebViewTracking (= 2.29.0) + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - DatadogSDKReactNativeSessionReplay (2.10.1): + - DatadogSDKReactNative + - DatadogSessionReplay (= 2.29.0) + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - DatadogSDKReactNativeWebView (2.10.1): + - DatadogInternal (= 2.29.0) + - DatadogSDKReactNative + - DatadogWebViewTracking (= 2.29.0) + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - DatadogSessionReplay (2.29.0): + - DatadogInternal (= 2.29.0) + - DatadogTrace (2.29.0): + - DatadogInternal (= 2.29.0) + - OpenTelemetrySwiftApi (= 1.13.1) + - DatadogWebViewTracking (2.29.0): + - DatadogInternal (= 2.29.0) + - DoubleConversion (1.1.6) + - fast_float (6.1.4) + - FBLazyVector (0.78.2) + - fmt (11.0.2) + - glog (0.3.5) + - 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) + - RCT-Folly (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Default (= 2024.11.18.00) + - RCT-Folly/Default (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Fabric (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - RCTDeprecation (0.78.2) + - RCTRequired (0.78.2) + - RCTTypeSafety (0.78.2): + - FBLazyVector (= 0.78.2) + - RCTRequired (= 0.78.2) + - React-Core (= 0.78.2) + - React (0.78.2): + - React-Core (= 0.78.2) + - React-Core/DevSupport (= 0.78.2) + - React-Core/RCTWebSocket (= 0.78.2) + - React-RCTActionSheet (= 0.78.2) + - React-RCTAnimation (= 0.78.2) + - React-RCTBlob (= 0.78.2) + - React-RCTImage (= 0.78.2) + - React-RCTLinking (= 0.78.2) + - React-RCTNetwork (= 0.78.2) + - React-RCTSettings (= 0.78.2) + - React-RCTText (= 0.78.2) + - React-RCTVibration (= 0.78.2) + - React-callinvoker (0.78.2) + - React-Core (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default (= 0.78.2) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/CoreModulesHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/Default (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/DevSupport (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default (= 0.78.2) + - React-Core/RCTWebSocket (= 0.78.2) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTActionSheetHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTAnimationHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTBlobHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTImageHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTLinkingHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTNetworkHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTSettingsHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTTextHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTVibrationHeaders (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-Core/RCTWebSocket (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTDeprecation + - React-Core/Default (= 0.78.2) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket (= 0.7.1) + - Yoga + - React-CoreModules (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - RCT-Folly (= 2024.11.18.00) + - RCTTypeSafety (= 0.78.2) + - React-Core/CoreModulesHeaders (= 0.78.2) + - React-jsi (= 0.78.2) + - React-jsinspector + - React-NativeModulesApple + - React-RCTBlob + - React-RCTFBReactNativeSpec + - React-RCTImage (= 0.78.2) + - ReactCommon + - SocketRocket (= 0.7.1) + - React-cxxreact (0.78.2): + - boost + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-callinvoker (= 0.78.2) + - React-debug (= 0.78.2) + - React-jsi (= 0.78.2) + - React-jsinspector + - React-logger (= 0.78.2) + - React-perflogger (= 0.78.2) + - React-runtimeexecutor (= 0.78.2) + - React-timing (= 0.78.2) + - React-debug (0.78.2) + - React-defaultsnativemodule (0.78.2): + - hermes-engine + - RCT-Folly + - React-domnativemodule + - React-featureflagsnativemodule + - React-idlecallbacksnativemodule + - React-jsi + - React-jsiexecutor + - React-microtasksnativemodule + - React-RCTFBReactNativeSpec + - React-domnativemodule (0.78.2): + - hermes-engine + - RCT-Folly + - React-Fabric + - React-FabricComponents + - React-graphics + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - Yoga + - React-Fabric (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/animations (= 0.78.2) + - React-Fabric/attributedstring (= 0.78.2) + - React-Fabric/componentregistry (= 0.78.2) + - React-Fabric/componentregistrynative (= 0.78.2) + - React-Fabric/components (= 0.78.2) + - React-Fabric/consistency (= 0.78.2) + - React-Fabric/core (= 0.78.2) + - React-Fabric/dom (= 0.78.2) + - React-Fabric/imagemanager (= 0.78.2) + - React-Fabric/leakchecker (= 0.78.2) + - React-Fabric/mounting (= 0.78.2) + - React-Fabric/observers (= 0.78.2) + - React-Fabric/scheduler (= 0.78.2) + - React-Fabric/telemetry (= 0.78.2) + - React-Fabric/templateprocessor (= 0.78.2) + - React-Fabric/uimanager (= 0.78.2) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/animations (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/attributedstring (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/componentregistry (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/componentregistrynative (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/components/legacyviewmanagerinterop (= 0.78.2) + - React-Fabric/components/root (= 0.78.2) + - React-Fabric/components/view (= 0.78.2) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components/legacyviewmanagerinterop (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components/root (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/components/view (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-Fabric/consistency (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/core (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/dom (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/imagemanager (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/leakchecker (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/mounting (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/observers (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events (= 0.78.2) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/observers/events (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/scheduler (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-performancetimeline + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/telemetry (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/templateprocessor (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/uimanager (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/uimanager/consistency (= 0.78.2) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-Fabric/uimanager/consistency (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - React-FabricComponents (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components (= 0.78.2) + - React-FabricComponents/textlayoutmanager (= 0.78.2) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components/inputaccessory (= 0.78.2) + - React-FabricComponents/components/iostextinput (= 0.78.2) + - React-FabricComponents/components/modal (= 0.78.2) + - React-FabricComponents/components/rncore (= 0.78.2) + - React-FabricComponents/components/safeareaview (= 0.78.2) + - React-FabricComponents/components/scrollview (= 0.78.2) + - React-FabricComponents/components/text (= 0.78.2) + - React-FabricComponents/components/textinput (= 0.78.2) + - React-FabricComponents/components/unimplementedview (= 0.78.2) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/inputaccessory (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/iostextinput (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/modal (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/rncore (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/safeareaview (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/scrollview (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/text (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/textinput (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/components/unimplementedview (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricComponents/textlayoutmanager (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - Yoga + - React-FabricImage (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - RCTRequired (= 0.78.2) + - RCTTypeSafety (= 0.78.2) + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-jsiexecutor (= 0.78.2) + - React-logger + - React-rendererdebug + - React-utils + - ReactCommon + - Yoga + - React-featureflags (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - React-featureflagsnativemodule (0.78.2): + - hermes-engine + - RCT-Folly + - React-featureflags + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - React-graphics (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - React-jsi + - React-jsiexecutor + - React-utils + - React-hermes (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-cxxreact (= 0.78.2) + - React-jsi + - React-jsiexecutor (= 0.78.2) + - React-jsinspector + - React-perflogger (= 0.78.2) + - React-runtimeexecutor + - React-idlecallbacksnativemodule (0.78.2): + - glog + - hermes-engine + - RCT-Folly + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimescheduler + - ReactCommon/turbomodule/core + - React-ImageManager (0.78.2): + - glog + - RCT-Folly/Fabric + - React-Core/Default + - React-debug + - React-Fabric + - React-graphics + - React-rendererdebug + - React-utils + - React-jserrorhandler (0.78.2): + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - ReactCommon/turbomodule/bridging + - React-jsi (0.78.2): + - boost + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-jsiexecutor (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-cxxreact (= 0.78.2) + - React-jsi (= 0.78.2) + - React-jsinspector + - React-perflogger (= 0.78.2) + - React-jsinspector (0.78.2): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly + - React-featureflags + - React-jsi + - React-jsinspectortracing + - React-perflogger (= 0.78.2) + - React-runtimeexecutor (= 0.78.2) + - React-jsinspectortracing (0.78.2): + - RCT-Folly + - React-jsitracing (0.78.2): + - React-jsi + - React-logger (0.78.2): + - glog + - React-Mapbuffer (0.78.2): + - glog + - React-debug + - React-microtasksnativemodule (0.78.2): + - hermes-engine + - RCT-Folly + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - react-native-config (1.5.5): + - react-native-config/App (= 1.5.5) + - react-native-config/App (1.5.5): + - React-Core + - react-native-safe-area-context (5.4.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - react-native-safe-area-context/common (= 5.4.0) + - react-native-safe-area-context/fabric (= 5.4.0) + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - react-native-safe-area-context/common (5.4.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - react-native-safe-area-context/fabric (5.4.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - react-native-safe-area-context/common + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - react-native-slider (4.5.7): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - react-native-slider/common (= 4.5.7) + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - react-native-slider/common (4.5.7): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - react-native-webview (13.15.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - React-NativeModulesApple (0.78.2): + - glog + - hermes-engine + - React-callinvoker + - React-Core + - React-cxxreact + - React-jsi + - React-jsinspector + - React-runtimeexecutor + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - React-perflogger (0.78.2): + - DoubleConversion + - RCT-Folly (= 2024.11.18.00) + - React-performancetimeline (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - React-cxxreact + - React-featureflags + - React-jsinspectortracing + - React-timing + - React-RCTActionSheet (0.78.2): + - React-Core/RCTActionSheetHeaders (= 0.78.2) + - React-RCTAnimation (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - RCTTypeSafety + - React-Core/RCTAnimationHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - React-RCTAppDelegate (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-CoreModules + - React-debug + - React-defaultsnativemodule + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RCTImage + - React-RCTNetwork + - React-rendererdebug + - React-RuntimeApple + - React-RuntimeCore + - React-RuntimeHermes + - React-runtimescheduler + - React-utils + - ReactCommon + - React-RCTBlob (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-Core/RCTBlobHeaders + - React-Core/RCTWebSocket + - React-jsi + - React-jsinspector + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - React-RCTFabric (0.78.2): + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - React-Core + - React-debug + - React-Fabric + - React-FabricComponents + - React-FabricImage + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-jsinspector + - React-jsinspectortracing + - React-performancetimeline + - React-RCTImage + - React-RCTText + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler + - React-utils + - Yoga + - React-RCTFBReactNativeSpec (0.78.2): + - hermes-engine + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-Core + - React-jsi + - React-jsiexecutor + - React-NativeModulesApple + - ReactCommon + - React-RCTImage (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - RCTTypeSafety + - React-Core/RCTImageHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - React-RCTLinking (0.78.2): + - React-Core/RCTLinkingHeaders (= 0.78.2) + - React-jsi (= 0.78.2) + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - ReactCommon/turbomodule/core (= 0.78.2) + - React-RCTNetwork (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - RCTTypeSafety + - React-Core/RCTNetworkHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - React-RCTSettings (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - RCTTypeSafety + - React-Core/RCTSettingsHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - React-RCTText (0.78.2): + - React-Core/RCTTextHeaders (= 0.78.2) + - Yoga + - React-RCTVibration (0.78.2): + - RCT-Folly (= 2024.11.18.00) + - React-Core/RCTVibrationHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - React-rendererconsistency (0.78.2) + - React-rendererdebug (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - RCT-Folly (= 2024.11.18.00) + - React-debug + - React-rncore (0.78.2) + - React-RuntimeApple (0.78.2): + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - React-callinvoker + - React-Core/Default + - React-CoreModules + - React-cxxreact + - React-featureflags + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-Mapbuffer + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RuntimeCore + - React-runtimeexecutor + - React-RuntimeHermes + - React-runtimescheduler + - React-utils + - React-RuntimeCore (0.78.2): + - glog + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - React-cxxreact + - React-Fabric + - React-featureflags + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-performancetimeline + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - React-runtimeexecutor (0.78.2): + - React-jsi (= 0.78.2) + - React-RuntimeHermes (0.78.2): + - hermes-engine + - RCT-Folly/Fabric (= 2024.11.18.00) + - React-featureflags + - React-hermes + - React-jsi + - React-jsinspector + - React-jsitracing + - React-RuntimeCore + - React-utils + - React-runtimescheduler (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-callinvoker + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - React-performancetimeline + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-timing + - React-utils + - React-timing (0.78.2) + - React-utils (0.78.2): + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-debug + - React-jsi (= 0.78.2) + - ReactAppDependencyProvider (0.78.2): + - ReactCodegen + - ReactCodegen (0.78.2): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-FabricImage + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-NativeModulesApple + - React-RCTAppDelegate + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - ReactCommon (0.78.2): + - ReactCommon/turbomodule (= 0.78.2) + - ReactCommon/turbomodule (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-callinvoker (= 0.78.2) + - React-cxxreact (= 0.78.2) + - React-jsi (= 0.78.2) + - React-logger (= 0.78.2) + - React-perflogger (= 0.78.2) + - ReactCommon/turbomodule/bridging (= 0.78.2) + - ReactCommon/turbomodule/core (= 0.78.2) + - ReactCommon/turbomodule/bridging (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-callinvoker (= 0.78.2) + - React-cxxreact (= 0.78.2) + - React-jsi (= 0.78.2) + - React-logger (= 0.78.2) + - React-perflogger (= 0.78.2) + - ReactCommon/turbomodule/core (0.78.2): + - DoubleConversion + - fast_float (= 6.1.4) + - fmt (= 11.0.2) + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - React-callinvoker (= 0.78.2) + - React-cxxreact (= 0.78.2) + - React-debug (= 0.78.2) + - React-featureflags (= 0.78.2) + - React-jsi (= 0.78.2) + - React-logger (= 0.78.2) + - React-perflogger (= 0.78.2) + - React-utils (= 0.78.2) + - RNCPicker (2.11.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNScreens (4.10.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNScreens/common (= 4.10.0) + - Yoga + - RNScreens/common (4.10.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - SocketRocket (0.7.1) + - Yoga (0.0.0) + +DEPENDENCIES: + - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - "DatadogSDKReactNative (from `../node_modules/@datadog/mobile-react-native`)" + - "DatadogSDKReactNativeSessionReplay (from `../node_modules/@datadog/mobile-react-native-session-replay`)" + - "DatadogSDKReactNativeWebView (from `../node_modules/@datadog/mobile-react-native-webview`)" + - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) + - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - 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`) + - 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`) + - RCTRequired (from `../node_modules/react-native/Libraries/Required`) + - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../node_modules/react-native/`) + - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) + - React-Core (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) + - React-defaultsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) + - React-domnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/dom`) + - React-Fabric (from `../node_modules/react-native/ReactCommon`) + - React-FabricComponents (from `../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../node_modules/react-native/ReactCommon/react/featureflags`) + - React-featureflagsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) + - React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`) + - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) + - React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) + - React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`) + - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsinspectortracing (from `../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`) + - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) + - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) + - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - react-native-config (from `../../node_modules/react-native-config`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - "react-native-slider (from `../../node_modules/@react-native-community/slider`)" + - react-native-webview (from `../node_modules/react-native-webview`) + - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) + - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) + - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../node_modules/react-native/React`) + - React-RCTFBReactNativeSpec (from `../node_modules/react-native/React`) + - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-rncore (from `../node_modules/react-native/ReactCommon`) + - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - React-timing (from `../node_modules/react-native/ReactCommon/react/timing`) + - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) + - ReactAppDependencyProvider (from `build/generated/ios`) + - ReactCodegen (from `build/generated/ios`) + - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "RNCPicker (from `../node_modules/@react-native-picker/picker`)" + - RNScreens (from `../node_modules/react-native-screens`) + - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + +SPEC REPOS: + trunk: + - DatadogCore + - DatadogCrashReporting + - DatadogInternal + - DatadogLogs + - DatadogRUM + - DatadogSessionReplay + - DatadogTrace + - DatadogWebViewTracking + - OpenTelemetrySwiftApi + - PLCrashReporter + - SocketRocket + +EXTERNAL SOURCES: + boost: + :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + DatadogSDKReactNative: + :path: "../node_modules/@datadog/mobile-react-native" + DatadogSDKReactNativeSessionReplay: + :path: "../node_modules/@datadog/mobile-react-native-session-replay" + DatadogSDKReactNativeWebView: + :path: "../node_modules/@datadog/mobile-react-native-webview" + DoubleConversion: + :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + fast_float: + :podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec" + FBLazyVector: + :path: "../node_modules/react-native/Libraries/FBLazyVector" + fmt: + :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" + glog: + :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + hermes-engine: + :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :tag: hermes-2025-01-13-RNv0.78.0-a942ef374897d85da38e9c8904574f8376555388 + RCT-Folly: + :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTDeprecation: + :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + RCTRequired: + :path: "../node_modules/react-native/Libraries/Required" + RCTTypeSafety: + :path: "../node_modules/react-native/Libraries/TypeSafety" + React: + :path: "../node_modules/react-native/" + React-callinvoker: + :path: "../node_modules/react-native/ReactCommon/callinvoker" + React-Core: + :path: "../node_modules/react-native/" + React-CoreModules: + :path: "../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-debug: + :path: "../node_modules/react-native/ReactCommon/react/debug" + React-defaultsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/defaults" + React-domnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/dom" + React-Fabric: + :path: "../node_modules/react-native/ReactCommon" + React-FabricComponents: + :path: "../node_modules/react-native/ReactCommon" + React-FabricImage: + :path: "../node_modules/react-native/ReactCommon" + React-featureflags: + :path: "../node_modules/react-native/ReactCommon/react/featureflags" + React-featureflagsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" + React-graphics: + :path: "../node_modules/react-native/ReactCommon/react/renderer/graphics" + React-hermes: + :path: "../node_modules/react-native/ReactCommon/hermes" + React-idlecallbacksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" + React-ImageManager: + :path: "../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + React-jserrorhandler: + :path: "../node_modules/react-native/ReactCommon/jserrorhandler" + React-jsi: + :path: "../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" + React-jsinspectortracing: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/tracing" + React-jsitracing: + :path: "../node_modules/react-native/ReactCommon/hermes/executor/" + React-logger: + :path: "../node_modules/react-native/ReactCommon/logger" + React-Mapbuffer: + :path: "../node_modules/react-native/ReactCommon" + React-microtasksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + react-native-config: + :path: "../../node_modules/react-native-config" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" + react-native-slider: + :path: "../../node_modules/@react-native-community/slider" + react-native-webview: + :path: "../node_modules/react-native-webview" + React-NativeModulesApple: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + React-perflogger: + :path: "../node_modules/react-native/ReactCommon/reactperflogger" + React-performancetimeline: + :path: "../node_modules/react-native/ReactCommon/react/performance/timeline" + React-RCTActionSheet: + :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../node_modules/react-native/Libraries/NativeAnimation" + React-RCTAppDelegate: + :path: "../node_modules/react-native/Libraries/AppDelegate" + React-RCTBlob: + :path: "../node_modules/react-native/Libraries/Blob" + React-RCTFabric: + :path: "../node_modules/react-native/React" + React-RCTFBReactNativeSpec: + :path: "../node_modules/react-native/React" + React-RCTImage: + :path: "../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../node_modules/react-native/Libraries/Network" + React-RCTSettings: + :path: "../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../node_modules/react-native/Libraries/Vibration" + React-rendererconsistency: + :path: "../node_modules/react-native/ReactCommon/react/renderer/consistency" + React-rendererdebug: + :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" + React-rncore: + :path: "../node_modules/react-native/ReactCommon" + React-RuntimeApple: + :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + React-RuntimeCore: + :path: "../node_modules/react-native/ReactCommon/react/runtime" + React-runtimeexecutor: + :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + React-RuntimeHermes: + :path: "../node_modules/react-native/ReactCommon/react/runtime" + React-runtimescheduler: + :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + React-timing: + :path: "../node_modules/react-native/ReactCommon/react/timing" + React-utils: + :path: "../node_modules/react-native/ReactCommon/react/utils" + ReactAppDependencyProvider: + :path: build/generated/ios + ReactCodegen: + :path: build/generated/ios + ReactCommon: + :path: "../node_modules/react-native/ReactCommon" + RNCPicker: + :path: "../node_modules/@react-native-picker/picker" + RNScreens: + :path: "../node_modules/react-native-screens" + Yoga: + :path: "../node_modules/react-native/ReactCommon/yoga" + +SPEC CHECKSUMS: + boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 + DatadogCore: 919080d4ba0bf172f42e8cf49a6ea33a79bdeb9a + DatadogCrashReporting: 3de14c873c0492803eca0373769791fde30639f6 + DatadogInternal: f98c60cc5b44db688692e2b560ea273182cde022 + DatadogLogs: c314b15a97bfc7e0728ea253d3638b0513032d88 + DatadogRUM: 6ec371f477a1022fd5aad6ccb5407b85a04db399 + DatadogSDKReactNative: dc3487e1416597865b3e0a6190e3860af27b7c91 + DatadogSDKReactNativeSessionReplay: a2a2731423054420cc070d2caf0c20d69a328109 + DatadogSDKReactNativeWebView: af8ad5fecbed66d2cd1498cbc0466e577e51d511 + DatadogSessionReplay: 1f2f70afa2fc5870ce7304a02749f73529d3e6cb + DatadogTrace: f0de55334db1630938ef980b5e054964652c4606 + DatadogWebViewTracking: f637f0e36cf62b713cd6673690d94072e6223570 + DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb + fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 + FBLazyVector: e32d34492c519a2194ec9d7f5e7a79d11b73f91c + fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd + glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 + hermes-engine: 2771b98fb813fdc6f92edd7c9c0035ecabf9fee7 + OpenTelemetrySwiftApi: aaee576ed961e0c348af78df58b61300e95bd104 + PLCrashReporter: db59ef96fa3d25f3650040d02ec2798cffee75f2 + RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 + RCTDeprecation: be794de7dc6ed8f9f7fbf525f86e7651b8b68746 + RCTRequired: a83787b092ec554c2eb6019ff3f5b8d125472b3b + RCTTypeSafety: 48ad3c858926b1c46f46a81a58822b476e178e2c + React: 3b5754191f1b65f1dbc52fbea7959c3d2d9e39c9 + React-callinvoker: 6beeaf4c7db11b6cc953fac45f2c76e3fb125013 + React-Core: 8a10ac9de53373a3ecb5dfcbcf56df1d3dad0861 + React-CoreModules: af6999b35c7c01b0e12b59d27f3e054e13da43b1 + React-cxxreact: 833f00155ce8c2fda17f6d286f8eaeff2ececc69 + React-debug: 440175830c448e7e53e61ebb8d8468c3256b645e + React-defaultsnativemodule: a970effe18fe50bdbbb7115c3297f873b666d0d4 + React-domnativemodule: 45f886342a724e61531b18fba1859bb6782e5d62 + React-Fabric: 69f1881f2177a8512304a64157943548ab6df0cf + React-FabricComponents: f54111c8e2439fc273ab07483e3a7054ca1e75af + React-FabricImage: 9ad2619dfe8c386d79e8aaa87da6e8f018ab9592 + React-featureflags: b9cf9b35baca1c7f20c06a104ffc325a02752faa + React-featureflagsnativemodule: 7f1bc76d1d2c5bede5e753b8d188dbde7c59b12f + React-graphics: 069e0d0b31ed1e80feb023ad4f7e97f00e84f7b9 + React-hermes: 63df5ac5a944889c8758a6213b39ed825863adb7 + React-idlecallbacksnativemodule: 4c700bd7c0012adf904929075a79418b828b5ffc + React-ImageManager: 5d1ba8a7bae44ebba43fc93da64937c713d42941 + React-jserrorhandler: 0defd58f8bb797cdd0a820f733bf42d8bee708ce + React-jsi: 99d6207ec802ad73473a0dad3c9ad48cd98463f6 + React-jsiexecutor: 8c8097b4ba7e7f480582d6e6238b01be5dcc01c0 + React-jsinspector: ea148ec45bc7ff830e443383ea715f9780c15934 + React-jsinspectortracing: 46bb2841982f01e7b63eaab98140fa1de5b2a1db + React-jsitracing: c1063fc2233960d1c8322291e74bca51d25c10d7 + React-logger: 763728cf4eebc9c5dc9bfc3649e22295784f69f3 + React-Mapbuffer: 63278529b5cf531a7eaf8fc71244fabb062ca90c + React-microtasksnativemodule: 6a39463c32ce831c4c2aa8469273114d894b6be9 + react-native-config: 644074ab88db883fcfaa584f03520ec29589d7df + react-native-safe-area-context: afcc2e2b3e78ae8ef90d81e658aacee34ebc27ea + react-native-slider: 310d3f89edd6ca8344a974bfe83a29a3fbb60e5a + react-native-webview: 80ef603d1df42e24fdde765686fbb9b8a6ecd554 + React-NativeModulesApple: fd0545efbb7f936f78edd15a6564a72d2c34bb32 + React-perflogger: 5f8fa36a8e168fb355efe72099efe77213bc2ac6 + React-performancetimeline: 8c0ecfa1ae459cc5678a65f95ac3bf85644d6feb + React-RCTActionSheet: 2ef95837e89b9b154f13cd8401f9054fc3076aff + React-RCTAnimation: 46abefd5acfda7e6629f9e153646deecc70babd2 + React-RCTAppDelegate: 7e58e0299e304cceee3f7019fa77bc6990f66b22 + React-RCTBlob: f68c63a801ef1d27e83c4011e3b083cc86a200d7 + React-RCTFabric: c59f41d0c4edbaac8baa232731ca09925ae4dda7 + React-RCTFBReactNativeSpec: 3240b9b8d792aa4be0fb85c9898fc183125ba8de + React-RCTImage: 34e0bba1507e55f1c614bd759eb91d9be48c8c5b + React-RCTLinking: a0b6c9f4871c18b0b81ea952f43e752718bd5f1d + React-RCTNetwork: bdafd661ac2b20d23b779e45bf7ac3e4c8bd1b60 + React-RCTSettings: 98aa5163796f43789314787b584a84eba47787a9 + React-RCTText: 424a274fc9015b29de89cf3cbcdf4dd85dd69f83 + React-RCTVibration: 92d9875a955b0adb34b4b773528fdbbbc5addd6c + React-rendererconsistency: 5ac4164ec18cfdd76ed5f864dbfdc56a5a948bc9 + React-rendererdebug: 710dbd7990e355852c786aa6bc7753f6028f357a + React-rncore: 0bace3b991d8843bb5b57c5f2301ec6e9c94718b + React-RuntimeApple: 701ec44a8b5d863ee9b6a2b2447b6a26bb6805a1 + React-RuntimeCore: a82767065b9a936b05e209dc6987bc1ea9eb5d2d + React-runtimeexecutor: 876dfc1d8daa819dfd039c40f78f277c5a3e66a6 + React-RuntimeHermes: e7a051fd91cab8849df56ac917022ef6064ad621 + React-runtimescheduler: c544141f2124ee3d5f3d5bf0d69f4029a61a68b0 + React-timing: 1ee3572c398f5579c9df5bf76aacddf5683ff74e + React-utils: 18703928768cb37e70cf2efff09def12d74a399e + ReactAppDependencyProvider: 4893bde33952f997a323eb1a1ee87a72764018ff + ReactCodegen: da30aff1cea9b5993dcbc33bf1ef47a463c55194 + ReactCommon: 865ebe76504a95e115b6229dd00a31e56d2d4bfe + RNCPicker: cfb51a08c6e10357d9a65832e791825b0747b483 + RNScreens: 790123c4a28783d80a342ce42e8c7381bed62db1 + SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 + Yoga: e14bad835e12b6c7e2260fc320bd00e0f4b45add + +PODFILE CHECKSUM: 4410ec48cbe9f00cc7dce5aa595affed6a14ea0d + +COCOAPODS: 1.16.2 diff --git a/benchmarks/ios/exportOptions.plist b/benchmarks/ios/exportOptions.plist new file mode 100644 index 000000000..52aa90a21 --- /dev/null +++ b/benchmarks/ios/exportOptions.plist @@ -0,0 +1,15 @@ + + + + + provisioningProfiles + + com.datadog.react.native.BenchmarkRunner + React Native Benchmark App + + uploadBitcode + + uploadSymbols + + + diff --git a/benchmarks/ios/main.m b/benchmarks/ios/main.m new file mode 100644 index 000000000..51ae013f8 --- /dev/null +++ b/benchmarks/ios/main.m @@ -0,0 +1,11 @@ +#import +#import "BenchmarkRunner-Swift.h" + +@interface AppDelegate : UIResponder +@end + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/benchmarks/jest.config.js b/benchmarks/jest.config.js new file mode 100644 index 000000000..8eb675e9b --- /dev/null +++ b/benchmarks/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + preset: 'react-native', +}; diff --git a/benchmarks/metro.config.js b/benchmarks/metro.config.js new file mode 100644 index 000000000..84b107529 --- /dev/null +++ b/benchmarks/metro.config.js @@ -0,0 +1,45 @@ +const path = require('path'); +const pakCore = require('../packages/core/package.json'); +const exclusionList = require('metro-config/src/defaults/exclusionList'); +const escape = require('escape-string-regexp'); +const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); + +const root = path.resolve(__dirname, '..'); +const modules = Object.keys({ + ...pakCore.peerDependencies +}); + +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const config = { + projectRoot: __dirname, + watchFolders: [ + root + ], + resetCache: true, + // We need to make sure that only one version is loaded for peerDependencies + // So we denylist them at the root, and alias them to the versions in example's node_modules + // This block is very important, because otherwise things like React can be packed multiple times + // while it should be only one React instance in the runtime. exclusionList relies on the modules which are + // declared as peer dependencies in the core package. + resolver: { + blacklistRE: exclusionList( + modules.map( + m => + new RegExp( + `^${escape(path.join(root, 'node_modules', m))}\\/.*$` + ) + ) + ), + extraNodeModules: modules.reduce((acc, name) => { + acc[name] = path.join(__dirname, 'node_modules', name); + return acc; + }, {}) + }, +}; + +module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/benchmarks/package.json b/benchmarks/package.json new file mode 100644 index 000000000..7425dad49 --- /dev/null +++ b/benchmarks/package.json @@ -0,0 +1,62 @@ +{ + "name": "benchmark-runner", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios", + "lint": "eslint .", + "start": "react-native start", + "test": "jest" + }, + "codegenConfig": { + "name": "BenchmarkVitalsSpec", + "type": "modules", + "jsSrcsDir": "src/specs", + "android": { + "javaPackageName": "com.benchmarkvitals" + }, + "library": "BenchmarkRunner" + }, + "dependencies": { + "@datadog/mobile-react-native": "workspace:packages/core", + "@datadog/mobile-react-native-session-replay": "workspace:packages/react-native-session-replay", + "@datadog/mobile-react-native-webview": "workspace:packages/react-native-webview", + "@datadog/mobile-react-navigation": "workspace:packages/react-navigation", + "@react-native-community/slider": "4.5.7", + "@react-native-picker/picker": "2.11.0", + "@react-navigation/bottom-tabs": "7.3.12", + "@react-navigation/native": "7.1.8", + "@react-navigation/native-stack": "7.3.12", + "query-string": "9.1.1", + "react": "19.0.0", + "react-native": "0.78.2", + "react-native-config": "1.5.5", + "react-native-safe-area-context": "5.4.0", + "react-native-screens": "4.10.0", + "react-native-webview": "13.15.0" + }, + "devDependencies": { + "@babel/core": "7.25.2", + "@babel/preset-env": "7.25.3", + "@babel/runtime": "7.25.0", + "@datadog/datadog-ci": "3.12.0", + "@react-native-community/cli": "15.0.1", + "@react-native-community/cli-platform-android": "15.0.1", + "@react-native-community/cli-platform-ios": "15.0.1", + "@react-native/babel-preset": "0.78.2", + "@react-native/eslint-config": "0.78.2", + "@react-native/metro-config": "0.78.2", + "@react-native/typescript-config": "0.78.2", + "@types/jest": "29.5.13", + "@types/react-test-renderer": "19.0.0", + "eslint": "8.19.0", + "jest": "29.6.3", + "prettier": "2.8.8", + "react-test-renderer": "19.0.0", + "typescript": "5.0.4" + }, + "engines": { + "node": ">=18" + } +} diff --git a/benchmarks/react-native-config.d.ts b/benchmarks/react-native-config.d.ts new file mode 100644 index 000000000..0de73ed3d --- /dev/null +++ b/benchmarks/react-native-config.d.ts @@ -0,0 +1,16 @@ +import { RunType, Scenario } from "./src/testSetup/types/testConfig"; + +declare module 'react-native-config' { + export interface NativeConfig { + DD_CLIENT_TOKEN?: string; + DD_API_KEY?: string; + DD_APP_ID?: string; + DD_SITE?: string; + DD_ENV?: string; + BENCH_SCENARIO?: Scenario; + BENCH_RUN_TYPE?: RunType; + } + + export const Config: NativeConfig; + export default Config; + } diff --git a/benchmarks/scripts/build-android-benchmark.sh b/benchmarks/scripts/build-android-benchmark.sh new file mode 100755 index 000000000..ad06246e5 --- /dev/null +++ b/benchmarks/scripts/build-android-benchmark.sh @@ -0,0 +1,37 @@ +set -e +source ./scripts/secrets/config.sh + +# Builds the Android Benchmark app +# +# Usage: ./scripts/build-android-benchmark.sh + +function build_android_app { + + if [ ! -d "./android/app/src/main/assets" ]; then + mkdir ./android/app/src/main/assets + fi + + touch ./android/app/src/main/assets/index.android + + # Generate bundle + echo "Generating bundle..." + + npx react-native bundle \ + --platform android \ + --dev false \ + --entry-file index.js \ + --bundle-output android/app/src/main/assets/index.android.bundle \ + --assets-dest android/app/build/intermediates/res/merged/release/ \ + + rm -rf android/app/src/main/res/drawable-* + rm -rf android/app/src/main/res/raw/* + echo "Building Android App in release mode..." + echo "Assembling Release APK..." + cd android + ./gradlew assembleRelease || exit 1 +} + +# run_checks +build_android_app + +cd $ROOT diff --git a/benchmarks/scripts/build-ios-benchmark.sh b/benchmarks/scripts/build-ios-benchmark.sh new file mode 100755 index 000000000..e5f811a79 --- /dev/null +++ b/benchmarks/scripts/build-ios-benchmark.sh @@ -0,0 +1,72 @@ +#!/bin/bash +set -eo pipefail +source ./scripts/secrets/config.sh +source ./scripts/secrets/get-secret.sh + +# Builds the iOS Benchmark app +# +# Usage: ./build-ios-benhchmark.sh + +CODE_SIGN_STYLE="${CODE_SIGN_STYLE:-Manual}" +CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY:-Apple Development: Sergio Barrio (64DLL4SMU9)}" +PROVISIONING_PROFILE_SPECIFIER="${PROVISIONING_PROFILE_SPECIFIER:-React Native Benchmark App}" +DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM:-JKFCB4CN7C}" + +function setup_ios_singing { + mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles" + + get_secret $DD_RN_BENCHMARK_E2E_PROVISIONING_PROFILE_BASE64 | base64 --decode > "$HOME/Library/MobileDevice/Provisioning Profiles/datadog.mobileprovision" + + export KEYCHAIN_PASSWORD="$(openssl rand -base64 32)" + export KEYCHAIN="datadog.keychain" + security delete-keychain "$KEYCHAIN" || true + security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" + security set-keychain-settings -lut 21600 "$KEYCHAIN" + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" + security list-keychain -d user -s "$KEYCHAIN" "login.keychain" "System.keychain" + + get_secret $DD_RN_BENCHMARK_E2E_CERTIFICATE_P12_BASE64 | base64 --decode > "datadog.certificate.p12" + export P12_PASSWORD="$(get_secret $DD_RN_BENCHMARK_E2E_CERTIFICATE_PASSWORD)" + + security import "datadog.certificate.p12" -P $P12_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN + security set-key-partition-list -S "apple-tool:,apple:" -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN" +} + +function build_ios_app { + cd ${ROOT}/ios + + echo export NODE_BINARY=$(command -v node) > ${ROOT}/ios/.xcode.env + rm Podfile.lock || true + pod install --repo-update + + # Build & Archive + LOG_PATH="${XCODEBUILD_LOG_PATH:-logs/xcodebuild_full_output_benchmark_runner.log}" + mkdir -p logs + touch "$LOG_PATH" + echo "=== Creating iOS archive ===" | tee -a "$LOG_PATH" + + xcodebuild -workspace BenchmarkRunner.xcworkspace \ + -scheme BenchmarkRunner clean archive \ + -configuration release \ + -sdk iphoneos \ + -archivePath BenchmarkRunner.xcarchive \ + CODE_SIGN_STYLE="$CODE_SIGN_STYLE" \ + CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" \ + PROVISIONING_PROFILE_SPECIFIER="$PROVISIONING_PROFILE_SPECIFIER" \ + DEVELOPMENT_TEAM="$DEVELOPMENT_TEAM" \ + 2>&1 | tee -a "$LOG_PATH" | xcbeautify || exit 1 + + # Export IPA + echo "=== Exporting iOS ipa ===" | tee -a "$LOG_PATH" + + xcodebuild -exportArchive \ + -archivePath BenchmarkRunner.xcarchive \ + -exportOptionsPlist ./exportOptions.plist \ + -exportPath BenchmarkRunner.ipa \ + 2>&1 | tee -a "$LOG_PATH" | xcbeautify || exit 1 +} + +setup_ios_singing +build_ios_app + +cd $ROOT \ No newline at end of file diff --git a/benchmarks/scripts/create-env-config.sh b/benchmarks/scripts/create-env-config.sh new file mode 100755 index 000000000..be0a8cb30 --- /dev/null +++ b/benchmarks/scripts/create-env-config.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -eo pipefail +source ./scripts/secrets/get-secret.sh + +cd $ROOT +ENV_FILENAME=".env" + +DD_CLIENT_TOKEN="$(get_secret $DD_RN_BENCHMARK_CLIENT_TOKEN)" +DD_API_KEY="$(get_secret $DD_RN_BENCHMARK_API_KEY)" +DD_APP_ID="$(get_secret $DD_RN_BENCHMARK_APP_ID)" +DD_SITE="us1" +DD_ENV="dev" + +cat > "$ENV_FILENAME" </dev/null; then + echo "Reading '$secret_name' secret in local env. You are already authenticated with 'vault'." >&2 + else + echo "Reading '$secret_name' secret in local env. You will now be authenticated with OIDC in your web browser." >&2 + vault login -method=oidc -no-print + fi + fi + + local secret_value=$(vault kv get -field=value "$DD_SDK_RN_SECRETS_PATH_PREFIX/$secret_name") + + if [[ -z "$secret_value" ]]; then + echo "Error" "Failed to retrieve the '$secret_name' secret or the secret is empty." >&2 + exit 1 + fi + + echo "$secret_value" +} diff --git a/benchmarks/scripts/upload.sh b/benchmarks/scripts/upload.sh new file mode 100755 index 000000000..ca7b1b276 --- /dev/null +++ b/benchmarks/scripts/upload.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Upload app binary to synthetics to be used on tests +# +# Usage: ./upload.sh FILE_PATH PLATFORM + +set -e +source ./scripts/secrets/get-secret.sh + + +FILE_PATH=$1 # Path to app binary (.ipa/.apk) +PLATFORM=$2 # IOS/ANDROID + +API_KEY="$(get_secret $DD_RN_BENCHMARK_API_KEY)" +APP_KEY="$(get_secret $DD_RN_BENCHMARK_APP_KEY)" + +if [ "$PLATFORM" = "ANDROID" ]; then + SYNTHETICS_APP_ID="$(get_secret "$DD_RN_BENCHMARK_SYNTHETICS_ANDROID_APP_ID")" +elif [ "$PLATFORM" = "IOS" ]; then + SYNTHETICS_APP_ID="$(get_secret "$DD_RN_BENCHMARK_SYNTHETICS_IOS_APP_ID")" +else + echo "Can't upload - Unknown platform ${PLATFORM}" + exit 1 +fi + +timestamp=$(date +"%Y/%m/%d-%H:%M:%S") + +yarn datadog-ci synthetics upload-application --apiKey $API_KEY --appKey $APP_KEY --mobileApplicationId $SYNTHETICS_APP_ID --mobileApplicationVersionFilePath $FILE_PATH --versionName "benchmark_${PLATFORM}_${timestamp}" --latest diff --git a/benchmarks/src/App.tsx b/benchmarks/src/App.tsx new file mode 100644 index 000000000..4a3bc0255 --- /dev/null +++ b/benchmarks/src/App.tsx @@ -0,0 +1,98 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import React, { useEffect, useState } from 'react'; +import { + Linking, + Text, + View, +} from 'react-native'; +import { DEFAULT_ENV_TEST_CONFIG, getDatadogConfig, getTestConfigFromDeeplink, isValidScenario, startCollectingVitals, stopCollectingVitals } from './testSetup/testUtils'; +import { Command, Scenario } from './testSetup/types/testConfig'; +import type { TestConfig } from './testSetup/types/testConfig'; +import DefaultScenario from './scenario/Default/defaultScenario'; +import NavigationExampleScenario from './scenario/NavigationExample/navigationExampleScenario'; +import LogsCustomScenario from './scenario/Logs/Custom/logsCustomScenario'; +import LogsHeavyTrafficScenario from './scenario/Logs/HeavyTraffic/logsHeavyTraffic'; +import TracesScenario from './scenario/Traces/tracesScenario'; +import RUMManualScenario from './scenario/RUM/Manual/rumManualScenario'; +import RUMAutoScenario from './scenario/RUM/Auto/rumAutoScenario'; +import SessionReplayScenario from './scenario/SessionReplay/sessionReplayScenario'; + +function App(): React.JSX.Element { + const [testConfig, setTestConfig] = useState(); + + useEffect(() => { + setupFromTestConfig(DEFAULT_ENV_TEST_CONFIG); + + Linking.getInitialURL().then(url => { + setupFromUrl(url); + }); + + const deeplinkListener = Linking.addEventListener('url', ({ url }) => { + setupFromUrl(url); + }) + + return () => { + deeplinkListener.remove(); + } + }, []); + + const setupFromTestConfig = async (testConfig: TestConfig | undefined) => { + switch (testConfig?.command) { + case Command.Start: + if (isValidScenario(testConfig?.scenario)) { + const datadogConfig = getDatadogConfig(); + testConfig.datadogConfig = datadogConfig; + + await startCollectingVitals(testConfig, datadogConfig); + + // Starts running the Scenario + setTestConfig(testConfig); + } + break; + case Command.Stop: + setTestConfig(undefined); + await stopCollectingVitals(); + break; + } + } + + const setupFromUrl = (url: string | null | undefined) => { + if (url) { + const newTestConfig = getTestConfigFromDeeplink(url); + setupFromTestConfig(newTestConfig); + } + } + + switch(testConfig?.scenario) { + case Scenario.Default: + return ; + case Scenario.NavigationExample: + return ; + case Scenario.LogsCustom: + return ; + case Scenario.LogsHeavyTraffic: + return ; + case Scenario.Traces: + return ; + case Scenario.RUMManual: + return ; + case Scenario.RUMAuto: + return ; + case Scenario.SessionReplay: + return ; + // Add new scenarios here + default: + return ( + + No scenario loaded + + ); + } +} + +export default App; diff --git a/benchmarks/src/common/styles.ts b/benchmarks/src/common/styles.ts new file mode 100644 index 000000000..7b4a24d33 --- /dev/null +++ b/benchmarks/src/common/styles.ts @@ -0,0 +1,315 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import { Dimensions, StyleSheet } from "react-native"; + +const SCR_WIDTH = Dimensions.get('screen').width; +const SCR_HEIGHT = Dimensions.get('screen').height; + +export enum Colors { + White = '#FFFFFF', + Black = '#000000', + Grey = '#EEEEEF', + DarkGrey = '#9E9E9F', + DatadogPurple = '#BC72E4', + Background = '#F2F2F7', + Title = '#AFAFA0', +} + +export const CommonStyles = StyleSheet.create({ + safeAreaContainer: { + flex: 1, + backgroundColor: Colors.Grey, + }, + container: { + flex: 1, + paddingHorizontal: 20, + paddingVertical: 20, + }, + uiItemsContainer: { + flex: 1, + backgroundColor: Colors.White, + paddingHorizontal: 10, + }, + lightContainer: { + flex: 1, + paddingHorizontal: 10, + paddingVertical: 10, + backgroundColor: Colors.White, + }, + title: { + paddingLeft: 20, + fontSize: 13, + color: Colors.Title, + }, + holder: { + backgroundColor: Colors.White, + borderRadius: 15, + padding: 15, + marginTop: 5, + marginBottom: 20, + }, + fullScreenHolder: { + flex: 1, + justifyContent: 'space-around', + alignItems: 'center', + backgroundColor: Colors.White, + }, + separator: { + height: 1, + width: '100%', + backgroundColor: Colors.Background, + }, + input: { + flex: 1, + }, + smallInput: { + flex: 0.5, + maxWidth: '25%', + }, + inputBorder: { + padding: 5, + borderColor: Colors.Grey, + borderWidth: 1, + }, + row: { + minHeight: '5%', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + label: { + color: Colors.Black, + fontSize: 15, + marginRight: 20, + }, + buttonWrapper: { + backgroundColor: Colors.DatadogPurple, + borderRadius: 10, + padding: 5, + marginBottom: 20, + }, + greyButton: { + backgroundColor: Colors.Grey, + }, + logEntry: { + padding: 5, + borderBottomColor: Colors.Grey, + borderBottomWidth: 1, + fontSize: 12, + }, + image: { + height: 150, + padding: 10, + borderRadius: 10, + backgroundColor: Colors.White, + }, + resultTitle: { + fontSize: 16, + color: Colors.Black, + marginTop: 15, + textAlign: 'center', + }, + listContainer: { + flex: 1, + paddingHorizontal: 10, + }, + resultList: { + borderRadius: 10, + }, + resultCell: { + flex: 1, + padding: 10, + backgroundColor: Colors.White, + flexDirection: 'row', + justifyContent: 'flex-start', + }, + cellImage: { + height: 60, + width: 60, + borderRadius: 5, + marginRight: 10, + }, + cellTitle: { + fontSize: 18, + fontWeight: 500, + }, + cellContent: { + flex: 1, + borderBottomWidth: 1, + borderBottomColor: Colors.Background, + paddingBottom: 10, + }, + cellArrow: { + color: Colors.DarkGrey, + lineHeight: 60, + fontSize: 20, + paddingHorizontal: 10, + }, + detailImage: { + height: 120, + width: 120, + }, + detailTitle: { + marginVertical: 10, + fontSize: 18, + fontWeight: 500, + }, + detailRow: { + flexDirection: 'row', + justifyContent: 'space-between', + }, + detailLabel: { + color: Colors.DarkGrey, + }, + detailField: { + + }, + expandedContentEntry: { + paddingVertical: 10, + }, + gridItem: { + padding: 10, + }, + gridItemLabel: { + width: 100, + marginVertical: 10, + fontSize: 16, + fontWeight: 500, + textAlign: 'center', + }, + gridImage: { + height: 100, + width: 100, + }, + uiElementCell: { + padding: 15, + flex: 1, + backgroundColor: Colors.White, + flexDirection: 'row', + justifyContent: 'space-around', + alignContent: 'space-around', + borderBottomWidth: 1, + borderBottomColor: Colors.Grey, + }, + uiElementTitle: { + flex: 0.9, + fontSize: 25, + }, + uiElementArrow: { + flex: 0.1, + color: Colors.DatadogPurple, + fontSize: 25, + }, + sessionReplayView: { + height: 250, + width: 250, + backgroundColor: 'green', + marginVertical: 30, + }, + sessionReplayRotatedView: { + backgroundColor: 'blue', + transform: [{ rotate: '30deg' }], + }, + sessionReplayOpacityView:{ + backgroundColor: 'yellow', + }, + sessionReplayOpacityViewChild:{ + backgroundColor: 'blue', + opacity: 0.2, + height: 100, + width: 100, + }, + sessionReplayContainerView:{ + backgroundColor: 'purple', + borderRadius: 30, + justifyContent: 'center', + alignItems: 'center', + }, + sessionReplayContainerViewText:{ + color: Colors.White, + fontSize: 20, + }, + sessionReplayImage: { + width: 350, + height: 350, + }, + sessionReplayText: { + color: Colors.DatadogPurple, + fontSize: 16, + textAlign: 'left', + marginVertical: 10, + }, + sessionReplayTextCursive: { + color: Colors.Black, + fontStyle: 'italic', + textAlign: 'center', + }, + sessionReplayTextBold: { + color: Colors.DarkGrey, + fontWeight: '900', + textAlign: 'right', + }, + sessionReplayTextSpaced: { + color: Colors.DatadogPurple, + letterSpacing: 10, + lineHeight: 25, + }, + sessionReplayTextInput: { + marginVertical: 15, + backgroundColor: Colors.Grey, + width: '80%', + fontSize: 20, + padding: 10, + borderRadius: 10, + }, + sessionReplaySwitch: { + marginVertical: 30, + }, + sessionReplayButton: { + marginVertical: 20, + backgroundColor: Colors.DatadogPurple, + width: '80%', + padding: 20, + borderRadius: 15, + color: Colors.White, + }, + sessionReplayButtonLabel: { + color: Colors.White, + textAlign: 'center', + fontSize: 20, + }, + sessionReplayActivityIndicator : { + marginVertical: 50, + }, + sessionReplayPicker: { + + }, + sessionReplaySlider: { + width: 200, + height: 40, + marginVertical: 40, + }, + sessionReplayWebView: { + height: SCR_HEIGHT, + width: SCR_WIDTH, + }, + sessionReplaySectionList: { + width: SCR_WIDTH, + }, + sessionReplaySectionListItem: { + backgroundColor: Colors.DatadogPurple, + padding: 20, + marginVertical: 8, + }, + sessionReplaySectionListItemTitle: { + color: Colors.White, + }, + sessionReplaySectionListHeader: { + fontSize: 32, + backgroundColor: Colors.White, + }, +}) diff --git a/benchmarks/src/component/Picker/Picker.tsx b/benchmarks/src/component/Picker/Picker.tsx new file mode 100644 index 000000000..531c3bc81 --- /dev/null +++ b/benchmarks/src/component/Picker/Picker.tsx @@ -0,0 +1,64 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import React, {useState} from 'react'; +import {Platform, Pressable, Text } from 'react-native'; +import {Picker as RNPicker, PickerIOS as RNPickerIOS} from '@react-native-picker/picker'; +import type {PickerProps} from './types'; +import styles from './styles'; + +const isIOS = Platform.OS === 'ios'; + +function Picker(props: PickerProps): React.JSX.Element { + const [isOpen, setIsOpen] = useState(false); + + const openPicker = () => { + setIsOpen(true); + }; + + const onValueChange = (newValue: unknown) => { + setIsOpen(false); + props?.onValueChange(newValue); + }; + + if (isIOS) { + if (isOpen) { + return ( + + {props.values.map(({label, value}, index) => ( + + ))} + + ) + } else { + return ( + + {props.label.toUpperCase()} + + ) + } + } else { + return ( + + {props.values.map(({label, value}, index) => ( + + ))} + + ) + }; +} + +export default Picker; diff --git a/benchmarks/src/component/Picker/styles.ts b/benchmarks/src/component/Picker/styles.ts new file mode 100644 index 000000000..358f36814 --- /dev/null +++ b/benchmarks/src/component/Picker/styles.ts @@ -0,0 +1,16 @@ +import { StyleSheet } from "react-native"; +import { Colors } from "../../common/styles"; + +export default StyleSheet.create({ + pickerButton: { + padding: 10, + }, + picker: { + width: '40%', + backgroundColor: Colors.White, + }, + pickerLabel: { + color: Colors.DarkGrey, + fontSize: 15, + }, +}); \ No newline at end of file diff --git a/benchmarks/src/component/Picker/types.ts b/benchmarks/src/component/Picker/types.ts new file mode 100644 index 000000000..fdc58beee --- /dev/null +++ b/benchmarks/src/component/Picker/types.ts @@ -0,0 +1,11 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +export interface PickerProps { + onValueChange: (newValue: unknown) => void, + label: string; + values: {label: string, value: string}[]; +}; \ No newline at end of file diff --git a/benchmarks/src/component/Stepper/Stepper.tsx b/benchmarks/src/component/Stepper/Stepper.tsx new file mode 100644 index 000000000..4a342b7b6 --- /dev/null +++ b/benchmarks/src/component/Stepper/Stepper.tsx @@ -0,0 +1,30 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import React from 'react'; +import { + Pressable, + Text, + View, +} from 'react-native'; +import type { StepperProps } from "./types"; +import styles from "./styles"; + +function Stepper(props: StepperProps): React.JSX.Element { + return ( + + + {'-'} + + + + {'+'} + + + ); +} + +export default Stepper; \ No newline at end of file diff --git a/benchmarks/src/component/Stepper/styles.ts b/benchmarks/src/component/Stepper/styles.ts new file mode 100644 index 000000000..b2d57ca48 --- /dev/null +++ b/benchmarks/src/component/Stepper/styles.ts @@ -0,0 +1,31 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import { StyleSheet } from "react-native"; +import { Colors } from "../../common/styles"; + +export default StyleSheet.create({ + container: { + backgroundColor: Colors.Grey, + flexDirection: 'row', + justifyContent: 'space-between', + borderRadius: 10, + maxWidth: '30%', + }, + separator: { + backgroundColor: Colors.DarkGrey, + width: 1, + height: 20, + marginTop: 5, + marginBottom: 5, + }, + buttonLabel: { + color: Colors.Black, + minWidth: '45%', + textAlign: 'center', + fontSize: 24, + }, +}) \ No newline at end of file diff --git a/benchmarks/src/component/Stepper/types.ts b/benchmarks/src/component/Stepper/types.ts new file mode 100644 index 000000000..99d025127 --- /dev/null +++ b/benchmarks/src/component/Stepper/types.ts @@ -0,0 +1,10 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +export interface StepperProps { + onDecreasePressed: () => void, + onIncreasePressed: () => void, +}; \ No newline at end of file diff --git a/benchmarks/src/scenario/Default/defaultScenario.tsx b/benchmarks/src/scenario/Default/defaultScenario.tsx new file mode 100644 index 000000000..c1d85a27b --- /dev/null +++ b/benchmarks/src/scenario/Default/defaultScenario.tsx @@ -0,0 +1,30 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import React, { useEffect } from 'react'; +import { + Text, + View, +} from 'react-native'; +import type { DefaultScenarioProps } from './types'; +import { RunType } from '../../testSetup/types/testConfig'; +import { instrument } from '../../testSetup/testUtils'; + +function DefaultScenario(props: DefaultScenarioProps): React.JSX.Element { + useEffect(() => { + if (props.testConfig?.runType !== RunType.BASELINE) { + instrument(); + } + }, []); + + return ( + + {'Default Scenario'} + + ); +} + +export default DefaultScenario; diff --git a/benchmarks/src/scenario/Default/types.ts b/benchmarks/src/scenario/Default/types.ts new file mode 100644 index 000000000..d74aa5935 --- /dev/null +++ b/benchmarks/src/scenario/Default/types.ts @@ -0,0 +1,11 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import type { TestConfig } from "../../testSetup/types/testConfig" + +export type DefaultScenarioProps = { + testConfig?: TestConfig, +} \ No newline at end of file diff --git a/benchmarks/src/scenario/Logs/Custom/logsCustomScenario.tsx b/benchmarks/src/scenario/Logs/Custom/logsCustomScenario.tsx new file mode 100644 index 000000000..dd846f770 --- /dev/null +++ b/benchmarks/src/scenario/Logs/Custom/logsCustomScenario.tsx @@ -0,0 +1,267 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import React, {useEffect, useRef, useState} from 'react'; +import { + Button, + Platform, + Pressable, + SafeAreaView, + ScrollView, + Switch, + Text, + TextInput, + View, +} from 'react-native'; +import { LogLevel, PAYLOADS_BY_SIZE, PayloadSize } from '../types'; +import type {LogsCustomScenarioProps} from '../types'; +import { RunType } from '../../../testSetup/types/testConfig'; +import { instrument } from '../../../testSetup/testUtils'; +import { Colors, CommonStyles as styles } from '../../../common/styles'; +import Stepper from '../../../component/Stepper/Stepper'; +import { DdLogs } from '@datadog/mobile-react-native'; +import { Logger } from '../../../testSetup/logger'; +import Picker from '../../../component/Picker/Picker'; +import { DEFAULT_LOGS_PER_SECOND, DEFAULT_LOG_INTERVAL, DEFAULT_LOG_MESSAGE, LOG_LEVELS, MAX_LOG_OUTPUT_ENTRIES, PAYLOAD_SIZES } from '../constants'; + +function LogsCustomScenario(props: LogsCustomScenarioProps): React.JSX.Element { + const logger = useRef(Logger); + const [logMessage, setLogMessage] = useState(DEFAULT_LOG_MESSAGE); + const [logLevel, setLogLevel] = useState(LogLevel.INFO); + const [payloadSize, setPayloadSize] = useState( + PayloadSize.Small, + ); + const [logsPerSecond, setLogsPerSecond] = useState( + DEFAULT_LOGS_PER_SECOND, + ); + const [logInterval, setLogInterval] = useState(DEFAULT_LOG_INTERVAL); + const [isRepeatLogging, setIsRepeatLogging] = useState(false); + const isLogging = useRef(false); + const [isLoggingState, setIsLoggingState] = useState(isLogging.current); + + const logOutputBuffer = useRef([]); + const [logOutput, setLogOutput] = useState(logOutputBuffer.current); + const logOutPutScrollViewRef = useRef(null); + + useEffect(() => { + if (props.testConfig?.runType !== RunType.BASELINE) { + instrument().then(() => { + logger.current = DdLogs; + }); + } + }, []); + + // UI Management + const onLogLevelChanged = (newLogLevel: LogLevel | unknown) => { + setLogLevel(newLogLevel as LogLevel); + }; + + const onPayloadSizeChanged = (newPayloadSize: PayloadSize | unknown) => { + setPayloadSize(newPayloadSize as PayloadSize); + }; + + const onLogsPerSecondChanged = (newLogsPerSecond: string) => { + const newLogsPerSecondNumber = parseInt(newLogsPerSecond, 10); + if (!Number.isNaN(newLogsPerSecondNumber)) { + setLogsPerSecond(newLogsPerSecondNumber); + } + }; + + const onLogsPerSecondDecrease = () => { + const newLogsPerSecond = logsPerSecond > 1 ? logsPerSecond - 1 : 1; + setLogsPerSecond(newLogsPerSecond); + }; + + const onLogsPerSecondIncrease = () => { + setLogsPerSecond(logsPerSecond + 1); + }; + + const onLogIntervalChanged = (newLogInterval: string) => { + const newLogsIntervalNumber = parseInt(newLogInterval, 10); + if (!Number.isNaN(newLogsIntervalNumber)) { + setLogInterval(newLogsIntervalNumber); + } + }; + + const onLogIntervalDecrease = () => { + const newLogInterval = logInterval > 1 ? logInterval - 1 : 1; + setLogInterval(newLogInterval); + }; + + const onLogIntervalIncrease = () => { + setLogInterval(logInterval + 1); + }; + + const onToggleIsRepeatLogging = () => { + setIsRepeatLogging(!isRepeatLogging); + }; + + // Logging + const startLogging = () => { + isLogging.current = true; + setIsLoggingState(true); + clearLogOutput(); + + if (isRepeatLogging) { + const interval = setInterval(() => { + if (!isLogging.current) { + clearInterval(interval); + } else { + logBatch(logsPerSecond, logMessage, logLevel, payloadSize); + } + }, logInterval * 1000); // in ms + } else { + logBatch(logsPerSecond, logMessage, logLevel, payloadSize); + stopLogging(); + } + }; + + const stopLogging = () => { + isLogging.current = false; + setIsLoggingState(false); + }; + + const clearLogOutput = () => { + logOutputBuffer.current = []; + setLogOutput(logOutputBuffer.current); + } + + const logBatch = ( + amount: number, + message: string, + level: LogLevel, + size: PayloadSize, + ) => { + for (let i = 0; i < amount; i++) { + logOutputBuffer.current = [ + ...logOutputBuffer.current, + `${new Date().toISOString()} - ${level} - ${size}: ${message}`, + ]; + + if (logOutputBuffer.current.length > MAX_LOG_OUTPUT_ENTRIES) { + logOutputBuffer.current.shift(); + }; + + setLogOutput(logOutputBuffer.current); + + switch (level) { + case LogLevel.DEBUG: + logger.current.debug(message, PAYLOADS_BY_SIZE[size]); + break; + case LogLevel.ERROR: + logger.current.error(message, PAYLOADS_BY_SIZE[size]); + break; + case LogLevel.INFO: + logger.current.info(message, PAYLOADS_BY_SIZE[size]); + break; + case LogLevel.WARN: + logger.current.warn(message, PAYLOADS_BY_SIZE[size]); + break; + } + } + }; + + return ( + + + LOG CONFIGURATION + + + + + + + {'Log Level'} + + + + + {'Payload size'} + + + + LOGGING FREQUENCY + + + {'Logs per Second:'} + + + + + + {'Interval (sec):'} + + + + + + + {'Repeat logging'} + + + + + +