From b645aa9988578ade9eed97492ef880d9bbbc44da Mon Sep 17 00:00:00 2001 From: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:47:36 +0200 Subject: [PATCH 1/2] chore: update scripts/update-javascript.sh to 7.118.0 (#4018) --- CHANGELOG.md | 8 +++ package.json | 20 +++--- yarn.lock | 186 +++++++++++++++++++++++++-------------------------- 3 files changed, 111 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afd42f74e..4714b151a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Dependencies + +- Bump JavaScript SDK from v7.117.0 to v7.118.0 ([#4018](https://github.com/getsentry/sentry-react-native/pull/4018)) + - [changelog](https://github.com/getsentry/sentry-javascript/blob/v7/CHANGELOG.md#71180) + - [diff](https://github.com/getsentry/sentry-javascript/compare/7.117.0...7.118.0) + ## 5.28.0 ### Fixes diff --git a/package.json b/package.json index ad6669849..8e334d7d9 100644 --- a/package.json +++ b/package.json @@ -68,22 +68,22 @@ }, "dependencies": { "@sentry/babel-plugin-component-annotate": "2.20.1", - "@sentry/browser": "7.117.0", + "@sentry/browser": "7.118.0", "@sentry/cli": "2.31.2", - "@sentry/core": "7.117.0", - "@sentry/hub": "7.117.0", - "@sentry/integrations": "7.117.0", - "@sentry/react": "7.117.0", - "@sentry/types": "7.117.0", - "@sentry/utils": "7.117.0" + "@sentry/core": "7.118.0", + "@sentry/hub": "7.118.0", + "@sentry/integrations": "7.118.0", + "@sentry/react": "7.118.0", + "@sentry/types": "7.118.0", + "@sentry/utils": "7.118.0" }, "devDependencies": { "@babel/core": "^7.23.5", "@expo/metro-config": "0.17.5", "@mswjs/interceptors": "^0.25.15", - "@sentry-internal/eslint-config-sdk": "7.117.0", - "@sentry-internal/eslint-plugin-sdk": "7.117.0", - "@sentry-internal/typescript": "7.117.0", + "@sentry-internal/eslint-config-sdk": "7.118.0", + "@sentry-internal/eslint-plugin-sdk": "7.118.0", + "@sentry-internal/typescript": "7.118.0", "@sentry/wizard": "3.16.3", "@types/jest": "^29.5.3", "@types/node": "^20.9.3", diff --git a/yarn.lock b/yarn.lock index b81838f27..ba9f03c3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3743,13 +3743,13 @@ component-type "^1.2.1" join-component "^1.1.0" -"@sentry-internal/eslint-config-sdk@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/eslint-config-sdk/-/eslint-config-sdk-7.117.0.tgz#27e9923a727d6ca56060047aab7af60a9d0360f4" - integrity sha512-LBj5oYTbdqCulebIZVeAj4LPs0UhFK2ZrBXyUgtKchZWahTk1L7eioXd2fmtIuJ9pFmvczS2UMJ0oRdtKy08Mg== +"@sentry-internal/eslint-config-sdk@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/eslint-config-sdk/-/eslint-config-sdk-7.118.0.tgz#70a92d99259959ff28e8775c113cd55754660cfd" + integrity sha512-R92oOdu9H9ufeH2xINZ5BEYWxERP2tNDO9Fd6gFv3FmnPWqHKTrsluM9ee6fUuP4HUgH8A2YFi2MSOdv5upQ7A== dependencies: - "@sentry-internal/eslint-plugin-sdk" "7.117.0" - "@sentry-internal/typescript" "7.117.0" + "@sentry-internal/eslint-plugin-sdk" "7.118.0" + "@sentry-internal/typescript" "7.118.0" "@typescript-eslint/eslint-plugin" "^5.48.0" "@typescript-eslint/parser" "^5.48.0" eslint-config-prettier "^6.11.0" @@ -3759,40 +3759,40 @@ eslint-plugin-jsdoc "^30.0.3" eslint-plugin-simple-import-sort "^5.0.3" -"@sentry-internal/eslint-plugin-sdk@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/eslint-plugin-sdk/-/eslint-plugin-sdk-7.117.0.tgz#110aae111143a13f8fdb196b09a1e721bc964dad" - integrity sha512-M6IuQCc+DPP4YqBS8HQI4B5B8+iB0Dwb3YvTO7mIfDOCmRIM//7j8Mn1rvOBpTeb3qwJnYsmlHg15jiSgtiLzQ== +"@sentry-internal/eslint-plugin-sdk@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/eslint-plugin-sdk/-/eslint-plugin-sdk-7.118.0.tgz#8d0262bdd651e545cf00cfeceac923001fdc4b0d" + integrity sha512-/2WlrVyz2J+w0gqStXnobR7RhsNxmG+dsFrFIBjkfvHDtjJLTAed8tf/fWwJE1bI4lWqytjKxy61RbFkW1SjOg== dependencies: requireindex "~1.1.0" -"@sentry-internal/feedback@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.117.0.tgz#4ca62cc469611720e76877a756cf24b792cb178e" - integrity sha512-4X+NnnY17W74TymgLFH7/KPTVYpEtoMMJh8HzVdCmHTOE6j32XKBeBMRaXBhmNYmEgovgyRKKf2KvtSfgw+V1Q== +"@sentry-internal/feedback@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.118.0.tgz#5b4b13ba514452d07a22ec8c66c2e4bc2091d8e6" + integrity sha512-IYOGRcqIqKJJpMwBBv+0JTu0FPpXnakJYvOx/XEa/SNyF5+l7b9gGEjUVWh1ok50kTLW/XPnpnXNAGQcoKHg+w== dependencies: - "@sentry/core" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry/core" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" -"@sentry-internal/replay-canvas@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.117.0.tgz#d6b3b711453c88e040f31ebab1d4bc627b4a6505" - integrity sha512-7hjIhwEcoosr+BIa0AyEssB5xwvvlzUpvD5fXu4scd3I3qfX8gdnofO96a8r+LrQm3bSj+eN+4TfKEtWb7bU5A== +"@sentry-internal/replay-canvas@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.118.0.tgz#d9741962439a85525e660973042c801c569ea9e4" + integrity sha512-XxHlCClvrxmVKpiZetFYyiBaPQNiojoBGFFVgbbWBIAPc+fWeLJ2BMoQEBjn/0NA/8u8T6lErK5YQo/eIx9+XQ== dependencies: - "@sentry/core" "7.117.0" - "@sentry/replay" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry/core" "7.118.0" + "@sentry/replay" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" -"@sentry-internal/tracing@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.117.0.tgz#c7d2357dae8d7ea2bc130e4513ac4ffc8dc7553c" - integrity sha512-fAIyijNvKBZNA12IcKo+dOYDRTNrzNsdzbm3DP37vJRKVQu19ucqP4Y6InvKokffDP2HZPzFPDoGXYuXkDhUZg== +"@sentry-internal/tracing@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.118.0.tgz#1a96ea745db818e20c2f8273d317f284a416a90a" + integrity sha512-dERAshKlQLrBscHSarhHyUeGsu652bDTUN1FK0m4e3X48M3I5/s+0N880Qjpe5MprNLcINlaIgdQ9jkisvxjfw== dependencies: - "@sentry/core" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry/core" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" "@sentry-internal/tracing@7.76.0": version "7.76.0" @@ -3803,29 +3803,29 @@ "@sentry/types" "7.76.0" "@sentry/utils" "7.76.0" -"@sentry-internal/typescript@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/typescript/-/typescript-7.117.0.tgz#bd43fc07a222e98861e6ab8a85ddd60e7399cd47" - integrity sha512-SylReCEo1FiTuir6XiZuV+sWBOBERDL0C3YmdHhczOh0aeu50FUja7uJfoXMx0LTEwaUAXq62dWUvb9WetluOQ== +"@sentry-internal/typescript@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/typescript/-/typescript-7.118.0.tgz#fe35f195bc47b0917a68830042e2654037d8e530" + integrity sha512-SG2HlB+ubtJFJAbZePrjV/zDQH55LL/LtKEgddGK+NIKSy4v8tkFS2Ej5QUMNhBt+AF/KKBzgRpZyv3apI/m3w== "@sentry/babel-plugin-component-annotate@2.20.1": version "2.20.1" resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.20.1.tgz#204c63ed006a048f48f633876e1b8bacf87a9722" integrity sha512-4mhEwYTK00bIb5Y9UWIELVUfru587Vaeg0DQGswv4aIRHIiMKLyNqCEejaaybQ/fNChIZOKmvyqXk430YVd7Qg== -"@sentry/browser@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.117.0.tgz#3030073f360974dadcf5a5f2e1542497b3be2482" - integrity sha512-29X9HlvDEKIaWp6XKlNPPSNND0U6P/ede5WA2nVHfs1zJLWdZ7/ijuMc0sH/CueEkqHe/7gt94hBcI7HOU/wSw== +"@sentry/browser@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.118.0.tgz#2395b47d693f7e49057552997d5125fc1a3d3448" + integrity sha512-8onDOFV1VLEoBuqA5yaJeR3FF1JNuxr5C7p1oN3OwY724iTVqQnOLmZKZaSnHV3RkY67wKDGQkQIie14sc+42g== dependencies: - "@sentry-internal/feedback" "7.117.0" - "@sentry-internal/replay-canvas" "7.117.0" - "@sentry-internal/tracing" "7.117.0" - "@sentry/core" "7.117.0" - "@sentry/integrations" "7.117.0" - "@sentry/replay" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry-internal/feedback" "7.118.0" + "@sentry-internal/replay-canvas" "7.118.0" + "@sentry-internal/tracing" "7.118.0" + "@sentry/core" "7.118.0" + "@sentry/integrations" "7.118.0" + "@sentry/replay" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" "@sentry/cli-darwin@2.31.2": version "2.31.2" @@ -3894,13 +3894,13 @@ proxy-from-env "^1.1.0" which "^2.0.2" -"@sentry/core@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.117.0.tgz#eebdb6e700d5fbdf3102c4abfb4ff92ef79ae9a5" - integrity sha512-1XZ4/d/DEwnfM2zBMloXDwX+W7s76lGKQMgd8bwgPJZjjEztMJ7X0uopKAGwlQcjn242q+hsCBR6C+fSuI5kvg== +"@sentry/core@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.118.0.tgz#1549b49621bc05a8df16c3546793a299b0638559" + integrity sha512-ol0xBdp3/K11IMAYSQE0FMxBOOH9hMsb/rjxXWe0hfM5c72CqYWL3ol7voPci0GELJ5CZG+9ImEU1V9r6gK64g== dependencies: - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" "@sentry/core@7.76.0": version "7.76.0" @@ -3910,23 +3910,23 @@ "@sentry/types" "7.76.0" "@sentry/utils" "7.76.0" -"@sentry/hub@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-7.117.0.tgz#924462cd083b57b45559eb5a25850e5b3004a7f8" - integrity sha512-pQrXnbzsRHCUsVIqz/sZ0vggnxuuHqsmyjoy2Ha1qn1Ya4QbyAWEEGoZTnZx6I/Vt3dzVvRnR3YCywatdkaFxg== +"@sentry/hub@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-7.118.0.tgz#9737530cb5cb962f1f6e6158622cab2fd5ed1bd5" + integrity sha512-Qfd/ZgO6pRd56+IWK942iC4RnL9xP2AYm0S1Ocb8VhZwx88GQCtRGSmmobVnICLquzWnydtZX1EcgHFNTGXNnw== dependencies: - "@sentry/core" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry/core" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" -"@sentry/integrations@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.117.0.tgz#4613dae3bc1d257c3c870461327fd4f70dbda229" - integrity sha512-U3suSZysmU9EiQqg0ga5CxveAyNbi9IVdsapMDq5EQGNcVDvheXtULs+BOc11WYP3Kw2yWB38VDqLepfc/Fg2g== +"@sentry/integrations@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.118.0.tgz#f090db621979785c6dc44406da1f72653fa0617c" + integrity sha512-C2rR4NvIMjokF8jP5qzSf1o2zxDx7IeYnr8u15Kb2+HdZtX559owALR0hfgwnfeElqMhGlJBaKUWZ48lXJMzCQ== dependencies: - "@sentry/core" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry/core" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" localforage "^1.8.1" "@sentry/node@^7.69.0": @@ -3940,43 +3940,43 @@ "@sentry/utils" "7.76.0" https-proxy-agent "^5.0.0" -"@sentry/react@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.117.0.tgz#0a6e729f5d17782a02a48728821536ede569bc8d" - integrity sha512-aK+yaEP2esBhaczGU96Y7wkqB4umSIlRAzobv7ER88EGHzZulRaocTpQO8HJJGDHm4D8rD+E893BHnghkoqp4Q== +"@sentry/react@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.118.0.tgz#88ae04e1abec1fd9a242ad6d852a1fe5e6851ad4" + integrity sha512-oEYe5TGk8S7YzPsFqDf4xDHjfzs35/QFE+dou3S2d24OYpso8Tq4C5f1VzYmnOOyy85T7JNicYLSo0n0NSJvQg== dependencies: - "@sentry/browser" "7.117.0" - "@sentry/core" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry/browser" "7.118.0" + "@sentry/core" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" hoist-non-react-statics "^3.3.2" -"@sentry/replay@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.117.0.tgz#c41844b60ad5d711d663a562e2df77fe14c51bbb" - integrity sha512-V4DfU+x4UsA4BsufbQ8jHYa5H0q5PYUgso2X1PR31g1fpx7yiYguSmCfz1UryM6KkH92dfTnqXapDB44kXOqzQ== +"@sentry/replay@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.118.0.tgz#ae55b7e14b85f22256dcc5a96bf3e63b252c1acf" + integrity sha512-boQfCL+1L/tSZ9Huwi00+VtU+Ih1Lcg8HtxBuAsBCJR9pQgUL5jp7ECYdTeeHyCh/RJO7JqV1CEoGTgohe10mA== dependencies: - "@sentry-internal/tracing" "7.117.0" - "@sentry/core" "7.117.0" - "@sentry/types" "7.117.0" - "@sentry/utils" "7.117.0" + "@sentry-internal/tracing" "7.118.0" + "@sentry/core" "7.118.0" + "@sentry/types" "7.118.0" + "@sentry/utils" "7.118.0" -"@sentry/types@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.117.0.tgz#c4d89aba487c05f4e5cbfa2f1c65180b536393b4" - integrity sha512-5dtdulcUttc3F0Te7ekZmpSp/ebt/CA71ELx0uyqVGjWsSAINwskFD77sdcjqvZWek//WjiYX1+GRKlpJ1QqsA== +"@sentry/types@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.118.0.tgz#ca3ab06912f60bc2a7ccf2d2e5ccf43985851aef" + integrity sha512-2drqrD2+6kgeg+W/ycmiti3G4lJrV3hGjY9PpJ3bJeXrh6T2+LxKPzlgSEnKFaeQWkXdZ4eaUbtTXVebMjb5JA== "@sentry/types@7.76.0": version "7.76.0" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.76.0.tgz#628c9899bfa82ea762708314c50fd82f2138587d" integrity sha512-vj6z+EAbVrKAXmJPxSv/clpwS9QjPqzkraMFk2hIdE/kii8s8kwnkBwTSpIrNc8GnzV3qYC4r3qD+BXDxAGPaw== -"@sentry/utils@7.117.0": - version "7.117.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.117.0.tgz#ac367a6f623bd09440b39d947437009c0ffe52b2" - integrity sha512-KkcLY8643SGBiDyPvMQOubBkwVX5IPknMHInc7jYC8pDVncGp7C65Wi506bCNPpKCWspUd/0VDNWOOen51/qKA== +"@sentry/utils@7.118.0": + version "7.118.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.118.0.tgz#bfc60826fe3d5d2ae7338ec6ac1f06c20beb179e" + integrity sha512-43qItc/ydxZV1Zb3Kn2M54RwL9XXFa3IAYBO8S82Qvq5YUYmU2AmJ1jgg7DabXlVSWgMA1HntwqnOV3JLaEnTQ== dependencies: - "@sentry/types" "7.117.0" + "@sentry/types" "7.118.0" "@sentry/utils@7.76.0": version "7.76.0" From 53f76984e5b52b9952ee9e17396c77404f7ac81c Mon Sep 17 00:00:00 2001 From: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:21:40 +0200 Subject: [PATCH 2/2] fix(ttid): End and measure TTID regardless current active span (#4019) --- CHANGELOG.md | 5 ++ src/js/tracing/reactnavigation.ts | 47 +++++--------- src/js/tracing/utils.ts | 31 ++++++--- test/tracing/reactnavigation.ttid.test.tsx | 73 ++++++++++++++++++++++ 4 files changed, 113 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4714b151a..8b0ba8612 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Fixed + +- fix(ttid): End and measure TTID regardless current active span ([#4019](https://github.com/getsentry/sentry-react-native/pull/4019)) + - Fixes possible missing TTID measurements and spans + ### Dependencies - Bump JavaScript SDK from v7.117.0 to v7.118.0 ([#4018](https://github.com/getsentry/sentry-react-native/pull/4018)) diff --git a/src/js/tracing/reactnavigation.ts b/src/js/tracing/reactnavigation.ts index a25abaa79..f4225d902 100644 --- a/src/js/tracing/reactnavigation.ts +++ b/src/js/tracing/reactnavigation.ts @@ -1,5 +1,5 @@ /* eslint-disable max-lines */ -import { getActiveSpan, setMeasurement, spanToJSON, startInactiveSpan } from '@sentry/core'; +import { getActiveSpan, startInactiveSpan } from '@sentry/core'; import type { Span, Transaction as TransactionType, TransactionContext } from '@sentry/types'; import { logger, timestampInSeconds } from '@sentry/utils'; @@ -11,7 +11,12 @@ import type { OnConfirmRoute, TransactionCreator } from './routingInstrumentatio import { InternalRoutingInstrumentation } from './routingInstrumentation'; import { manualInitialDisplaySpans, startTimeToInitialDisplaySpan } from './timetodisplay'; import type { BeforeNavigate, ReactNavigationTransactionContext, RouteChangeContextData } from './types'; -import { customTransactionSource, defaultTransactionSource, getBlankTransactionContext } from './utils'; +import { + customTransactionSource, + defaultTransactionSource, + getBlankTransactionContext, + setSpanDurationAsMeasurementOnTransaction, +} from './utils'; export interface NavigationRoute { name: string; @@ -224,6 +229,7 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati if (this._latestTransaction) { if (!previousRoute || previousRoute.key !== route.key) { const routeHasBeenSeen = this._recentRouteKeys.includes(route.key); + const latestTransaction = this._latestTransaction; const latestTtidSpan = !routeHasBeenSeen && this._options.enableTimeToInitialDisplay && @@ -233,46 +239,21 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati }); !routeHasBeenSeen && + latestTtidSpan && this._newScreenFrameEventEmitter?.once( NewFrameEventName, ({ newFrameTimestampInSeconds }: NewFrameEvent) => { const activeSpan = getActiveSpan(); - if (!activeSpan) { - logger.warn( - '[ReactNavigationInstrumentation] No active span found to attach ui.load.initial_display to.', - ); - return; - } - - if (manualInitialDisplaySpans.has(activeSpan)) { + if (activeSpan && manualInitialDisplaySpans.has(activeSpan)) { logger.warn( '[ReactNavigationInstrumentation] Detected manual instrumentation for the current active span.', ); return; } - if (!latestTtidSpan) { - return; - } - - if (spanToJSON(latestTtidSpan).parent_span_id !== getActiveSpan()?.spanContext().spanId) { - logger.warn( - '[ReactNavigationInstrumentation] Currently Active Span changed before the new frame was rendered, _latestTtidSpan is not a child of the currently active span.', - ); - return; - } - latestTtidSpan.setStatus('ok'); latestTtidSpan.end(newFrameTimestampInSeconds); - const ttidSpan = spanToJSON(latestTtidSpan); - - const ttidSpanEnd = ttidSpan.timestamp; - const ttidSpanStart = ttidSpan.start_timestamp; - if (!ttidSpanEnd || !ttidSpanStart) { - return; - } - - setMeasurement('time_to_initial_display', (ttidSpanEnd - ttidSpanStart) * 1000, 'millisecond'); + setSpanDurationAsMeasurementOnTransaction(latestTransaction, 'time_to_initial_display', latestTtidSpan); }, ); @@ -281,7 +262,7 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati this._navigationProcessingSpan?.end(stateChangedTimestamp); this._navigationProcessingSpan = undefined; - const originalContext = this._latestTransaction.toContext() as typeof BLANK_TRANSACTION_CONTEXT; + const originalContext = latestTransaction.toContext() as typeof BLANK_TRANSACTION_CONTEXT; const data: RouteChangeContextData = { ...originalContext.data, @@ -313,10 +294,10 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati }; const finalContext = this._prepareFinalContext(updatedContext); - this._latestTransaction.updateWithContext(finalContext); + latestTransaction.updateWithContext(finalContext); const isCustomName = updatedContext.name !== finalContext.name; - this._latestTransaction.setName( + latestTransaction.setName( finalContext.name, isCustomName ? customTransactionSource : defaultTransactionSource, ); diff --git a/src/js/tracing/utils.ts b/src/js/tracing/utils.ts index f154322d1..c426c186e 100644 --- a/src/js/tracing/utils.ts +++ b/src/js/tracing/utils.ts @@ -1,11 +1,6 @@ -import { - type IdleTransaction, - type Span as SpanClass, - type Transaction, - setMeasurement, - spanToJSON, -} from '@sentry/core'; -import type { Span, TransactionContext, TransactionSource } from '@sentry/types'; +import type { Transaction } from '@sentry/core'; +import { type IdleTransaction, type Span as SpanClass, setMeasurement, spanToJSON } from '@sentry/core'; +import type { Span, Transaction as TransactionType, TransactionContext, TransactionSource } from '@sentry/types'; import { logger, timestampInSeconds } from '@sentry/utils'; import { RN_GLOBAL_OBJ } from '../utils/worldwide'; @@ -105,8 +100,7 @@ export function isNearToNow(timestamp: number): boolean { * Uses `setMeasurement` function from @sentry/core. */ export function setSpanDurationAsMeasurement(name: string, span: Span): void { - const spanEnd = spanToJSON(span).timestamp; - const spanStart = spanToJSON(span).start_timestamp; + const { timestamp: spanEnd, start_timestamp: spanStart } = spanToJSON(span); if (!spanEnd || !spanStart) { return; } @@ -114,6 +108,23 @@ export function setSpanDurationAsMeasurement(name: string, span: Span): void { setMeasurement(name, (spanEnd - spanStart) * 1000, 'millisecond'); } +/** + * Sets the duration of the span as a measurement. + * Uses `setMeasurement` function from @sentry/core. + */ +export function setSpanDurationAsMeasurementOnTransaction( + transaction: TransactionType, + name: string, + span: Span, +): void { + const { timestamp: spanEnd, start_timestamp: spanStart } = spanToJSON(span); + if (!spanEnd || !spanStart) { + return; + } + + transaction.setMeasurement(name, (spanEnd - spanStart) * 1000, 'millisecond'); +} + /** * Returns unix timestamp in ms of the bundle start time. * diff --git a/test/tracing/reactnavigation.ttid.test.tsx b/test/tracing/reactnavigation.ttid.test.tsx index df840a3e1..b1357dcdd 100644 --- a/test/tracing/reactnavigation.ttid.test.tsx +++ b/test/tracing/reactnavigation.ttid.test.tsx @@ -6,6 +6,7 @@ jest.mock('../../src/js/utils/environment'); jest.mock('../../src/js/utils/sentryeventemitter', () => mockedSentryEventEmitter); jest.mock('../../src/js/tracing/timetodisplaynative', () => mockedtimetodisplaynative); +import { Span } from '@sentry/core'; import type { SpanJSON, TransactionEvent, Transport } from '@sentry/types'; import { timestampInSeconds } from '@sentry/utils'; import React from "react"; @@ -84,6 +85,78 @@ describe('React Navigation - TTID', () => { ); }); + test('should end ttid with measurements even when active span was removed from the scope', () => { + jest.runOnlyPendingTimers(); // Flush app start transaction + + mockedNavigation.navigateToNewScreen(); + Sentry.getCurrentScope().setSpan(undefined); + mockedEventEmitter.emitNewFrameEvent(); + jest.runOnlyPendingTimers(); // Flush transaction + + const transaction = getLastTransaction(transportSendMock); + expect(transaction).toEqual( + expect.objectContaining({ + type: 'transaction', + spans: expect.arrayContaining([ + expect.objectContaining>({ + data: { + 'sentry.op': 'ui.load.initial_display', + 'sentry.origin': 'manual', + }, + description: 'New Screen initial display', + op: 'ui.load.initial_display', + origin: 'manual', + status: 'ok', + start_timestamp: transaction.start_timestamp, + timestamp: expect.any(Number), + }), + ]), + measurements: expect.objectContaining['measurements']>({ + time_to_initial_display: { + value: expect.any(Number), + unit: 'millisecond', + }, + }), + }), + ); + }); + + test('should end ttid with measurements even when active span on the scope changed', () => { + jest.runOnlyPendingTimers(); // Flush app start transaction + + mockedNavigation.navigateToNewScreen(); + Sentry.getCurrentScope().setSpan(new Span()); + mockedEventEmitter.emitNewFrameEvent(); + jest.runOnlyPendingTimers(); // Flush transaction + + const transaction = getLastTransaction(transportSendMock); + expect(transaction).toEqual( + expect.objectContaining({ + type: 'transaction', + spans: expect.arrayContaining([ + expect.objectContaining>({ + data: { + 'sentry.op': 'ui.load.initial_display', + 'sentry.origin': 'manual', + }, + description: 'New Screen initial display', + op: 'ui.load.initial_display', + origin: 'manual', + status: 'ok', + start_timestamp: transaction.start_timestamp, + timestamp: expect.any(Number), + }), + ]), + measurements: expect.objectContaining['measurements']>({ + time_to_initial_display: { + value: expect.any(Number), + unit: 'millisecond', + }, + }), + }), + ); + }); + test('should add ttid measurement', () => { jest.runOnlyPendingTimers(); // Flush app start transaction