From 6c83718264e9a0459104db92bc530d548ffa4695 Mon Sep 17 00:00:00 2001
From: Andrew Liu <159852527+aliu39@users.noreply.github.com>
Date: Tue, 30 Jul 2024 11:04:04 -0700
Subject: [PATCH 01/26] Initial start, stop, and link w/project platform
---
.../devtoolbar/components/navigation.tsx | 2 +
.../devtoolbar/components/panelRouter.tsx | 3 +
.../components/replay/replayPanel.tsx | 147 ++++++++++++++++++
.../devtoolbar/hooks/useToolbarRoute.tsx | 9 +-
4 files changed, 160 insertions(+), 1 deletion(-)
create mode 100644 static/app/components/devtoolbar/components/replay/replayPanel.tsx
diff --git a/static/app/components/devtoolbar/components/navigation.tsx b/static/app/components/devtoolbar/components/navigation.tsx
index 24607c54b3750f..0f6e1a7601d316 100644
--- a/static/app/components/devtoolbar/components/navigation.tsx
+++ b/static/app/components/devtoolbar/components/navigation.tsx
@@ -6,6 +6,7 @@ import {
IconFlag,
IconIssues,
IconMegaphone,
+ IconPlay,
IconReleases,
IconSiren,
} from 'sentry/icons';
@@ -58,6 +59,7 @@ export default function Navigation({
}>
+ } />
);
}
diff --git a/static/app/components/devtoolbar/components/panelRouter.tsx b/static/app/components/devtoolbar/components/panelRouter.tsx
index 9eea23f360e6ff..af2e389bcf1145 100644
--- a/static/app/components/devtoolbar/components/panelRouter.tsx
+++ b/static/app/components/devtoolbar/components/panelRouter.tsx
@@ -7,6 +7,7 @@ const PanelFeedback = lazy(() => import('./feedback/feedbackPanel'));
const PanelIssues = lazy(() => import('./issues/issuesPanel'));
const PanelFeatureFlags = lazy(() => import('./featureFlags/featureFlagsPanel'));
const PanelReleases = lazy(() => import('./releases/releasesPanel'));
+const PanelReplay = lazy(() => import('./replay/replayPanel'));
export default function PanelRouter() {
const {state} = useToolbarRoute();
@@ -22,6 +23,8 @@ export default function PanelRouter() {
return ;
case 'releases':
return ;
+ case 'replay':
+ return ;
default:
return null;
}
diff --git a/static/app/components/devtoolbar/components/replay/replayPanel.tsx b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
new file mode 100644
index 00000000000000..42ad0340938f39
--- /dev/null
+++ b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
@@ -0,0 +1,147 @@
+import {Fragment, useState} from 'react';
+import {css} from '@emotion/react';
+
+import {Button} from 'sentry/components/button';
+import SentryAppLink from 'sentry/components/devtoolbar/components/sentryAppLink';
+import {listItemPlaceholderWrapperCss} from 'sentry/components/devtoolbar/styles/listItem';
+import {
+ resetFlexColumnCss,
+ resetFlexRowCss,
+} from 'sentry/components/devtoolbar/styles/reset';
+import ProjectBadge from 'sentry/components/idBadge/projectBadge';
+import Placeholder from 'sentry/components/placeholder';
+import TextOverflow from 'sentry/components/textOverflow';
+import TimeSince from 'sentry/components/timeSince';
+import {IconPause, IconPlay} from 'sentry/icons';
+import {t} from 'sentry/locale';
+import type {PlatformKey} from 'sentry/types/project';
+
+import useConfiguration from '../../hooks/useConfiguration';
+import {panelInsetContentCss, panelSectionCss} from '../../styles/panel';
+import {smallCss} from '../../styles/typography';
+import PanelLayout from '../panelLayout';
+
+export function StartReplayButton({
+ setReplayId,
+}: {
+ setReplayId: React.Dispatch>;
+}) {
+ const {SentrySDK} = useConfiguration();
+ const replay = SentrySDK && 'getReplay' in SentrySDK && SentrySDK.getReplay();
+
+ const [isStarted, setIsStarted] = useState(false);
+
+ return (
+ : }
+ disabled={!replay}
+ onClick={() => {
+ if (replay) {
+ try {
+ isStarted ? replay.stop() : replay.start();
+ } catch (err) {
+ console.error(err);
+ }
+ setIsStarted(!isStarted);
+
+ let replayId: string | undefined;
+ try {
+ console.log('getting replay id');
+ replayId = replay.getReplayId();
+ } catch (err) {
+ console.error(err);
+ }
+ setReplayId(replayId); // always sets/refreshes
+ }
+ }}
+ >
+ {isStarted
+ ? t('A replay recording is in progress.')
+ : t('Start recording the current session')}
+
+ );
+}
+
+const TRUNC_ID_LENGTH = 10; // TODO: import this from somewhere else? Wrap/make dynamic?
+
+export default function ReleasesPanel() {
+ // const {data, isLoading, isError} = useToolbarRelease();
+ const [isLoading, isError] = [false, false];
+
+ const {organizationSlug, projectSlug, projectId, projectPlatform, trackAnalytics} =
+ useConfiguration();
+
+ const estimateSize = 515;
+ const placeholderHeight = `${estimateSize - 8}px`; // The real height of the items, minus the padding-block value
+
+ const [replayId, setReplayId] = useState(undefined); // b7908c02c0ea40f081077a84d887d1f6
+ console.log(replayId);
+
+ return (
+
+ {isLoading || isError ? (
+
+
+
+ ) : (
+
+
+
+ {replayId !== undefined ? (
+
+ {'Replay of current session: '}
+ {
+ trackAnalytics?.({
+ eventKey: `devtoolbar.current-replay-link.click`,
+ eventName: `devtoolbar: Current replay link clicked`,
+ });
+ }}
+ >
+
+
+ {/* TODO: can truncate if too 32 char is too long */}
+ {replayId.slice(0, TRUNC_ID_LENGTH)}
+
+
+
+ ) : null}
+
+ {/* TODO: add DURATION and start time, similar to replay index page */}
+ {/* {'1 min ago 01:12'} */}
+
+ )}
+
+ );
+}
diff --git a/static/app/components/devtoolbar/hooks/useToolbarRoute.tsx b/static/app/components/devtoolbar/hooks/useToolbarRoute.tsx
index 6ff627611fb668..5e0a65f8bf8550 100644
--- a/static/app/components/devtoolbar/hooks/useToolbarRoute.tsx
+++ b/static/app/components/devtoolbar/hooks/useToolbarRoute.tsx
@@ -1,7 +1,14 @@
import {createContext, useCallback, useContext, useState} from 'react';
type State = {
- activePanel: null | 'alerts' | 'feedback' | 'issues' | 'featureFlags' | 'releases';
+ activePanel:
+ | null
+ | 'alerts'
+ | 'feedback'
+ | 'issues'
+ | 'featureFlags'
+ | 'releases'
+ | 'replay';
};
const context = createContext<{
From 72868f613987a11806060fc833c6917af2bce887 Mon Sep 17 00:00:00 2001
From: Andrew Liu <159852527+aliu39@users.noreply.github.com>
Date: Wed, 31 Jul 2024 17:17:17 -0700
Subject: [PATCH 02/26] more progress to MVP + improve comments
---
package.json | 16 +-
static/app/bootstrap/initializeSdk.tsx | 2 +
.../components/replay/replayPanel.tsx | 68 +++---
yarn.lock | 195 +++++++++---------
4 files changed, 156 insertions(+), 125 deletions(-)
diff --git a/package.json b/package.json
index dfb7b1535ebab8..8b46ff9921c839 100644
--- a/package.json
+++ b/package.json
@@ -59,13 +59,13 @@
"@sentry-internal/rrweb-player": "2.25.0",
"@sentry-internal/rrweb-snapshot": "2.25.0",
"@sentry/babel-plugin-component-annotate": "^2.16.1",
- "@sentry/core": "^8.18.0",
- "@sentry/node": "^8.18.0",
- "@sentry/react": "^8.18.0",
+ "@sentry/core": "^8.20.0",
+ "@sentry/node": "^8.20.0",
+ "@sentry/react": "^8.20.0",
"@sentry/release-parser": "^1.3.1",
"@sentry/status-page-list": "^0.3.0",
- "@sentry/types": "^8.18.0",
- "@sentry/utils": "^8.18.0",
+ "@sentry/types": "^8.20.0",
+ "@sentry/utils": "^8.20.0",
"@spotlightjs/spotlight": "^2.0.0-alpha.1",
"@tanstack/react-query": "^4.29.7",
"@tanstack/react-query-devtools": "^4.36.1",
@@ -180,7 +180,7 @@
"@codecov/webpack-plugin": "^0.0.1-beta.8",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.11",
"@sentry/jest-environment": "6.0.0",
- "@sentry/profiling-node": "^8.18.0",
+ "@sentry/profiling-node": "^8.20.0",
"@styled/typescript-styled-plugin": "^1.0.1",
"@testing-library/dom": "10.1.0",
"@testing-library/jest-dom": "6.4.5",
@@ -263,9 +263,7 @@
"last 3 iOS major versions",
"Firefox ESR"
],
- "test": [
- "current node"
- ]
+ "test": ["current node"]
},
"volta": {
"extends": ".volta.json"
diff --git a/static/app/bootstrap/initializeSdk.tsx b/static/app/bootstrap/initializeSdk.tsx
index a1c09c2dc1d49f..f5999191713d3c 100644
--- a/static/app/bootstrap/initializeSdk.tsx
+++ b/static/app/bootstrap/initializeSdk.tsx
@@ -175,6 +175,8 @@ export function initializeSdk(config: Config, {routes}: {routes?: Function} = {}
return event;
},
+
+ debug: true,
});
if (process.env.NODE_ENV !== 'production') {
diff --git a/static/app/components/devtoolbar/components/replay/replayPanel.tsx b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
index 42ad0340938f39..711f3e27e31f67 100644
--- a/static/app/components/devtoolbar/components/replay/replayPanel.tsx
+++ b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
@@ -1,5 +1,6 @@
import {Fragment, useState} from 'react';
import {css} from '@emotion/react';
+import type {replayIntegration} from '@sentry/react';
import {Button} from 'sentry/components/button';
import SentryAppLink from 'sentry/components/devtoolbar/components/sentryAppLink';
@@ -10,8 +11,6 @@ import {
} from 'sentry/components/devtoolbar/styles/reset';
import ProjectBadge from 'sentry/components/idBadge/projectBadge';
import Placeholder from 'sentry/components/placeholder';
-import TextOverflow from 'sentry/components/textOverflow';
-import TimeSince from 'sentry/components/timeSince';
import {IconPause, IconPlay} from 'sentry/icons';
import {t} from 'sentry/locale';
import type {PlatformKey} from 'sentry/types/project';
@@ -22,37 +21,48 @@ import {smallCss} from '../../styles/typography';
import PanelLayout from '../panelLayout';
export function StartReplayButton({
+ replay,
setReplayId,
}: {
+ replay: ReturnType | undefined | false;
setReplayId: React.Dispatch>;
}) {
- const {SentrySDK} = useConfiguration();
- const replay = SentrySDK && 'getReplay' in SentrySDK && SentrySDK.getReplay();
-
const [isStarted, setIsStarted] = useState(false);
+ // isStarted is not always accurate, since we don't have an API fx to check if we're currently recording.
+ // _replay.recordingMode == "session" is how we'd check w/ the internal API.
return (
: }
- disabled={!replay}
+ disabled={!replay} // TODO: tooltip on why this could be disabled
onClick={() => {
if (replay) {
try {
- isStarted ? replay.stop() : replay.start();
+ if (isStarted) {
+ replay.stop(); // stop should call flush
+ } else {
+ // If we're sampling errors, there's a chance the replay will be in buffering mode.
+ // In this case start() will do nothing, while flush() will switch to session mode/start recording.
+ // However if we're not buffering, flush() will not start a replay (needs more testing).
+ // To improve this code we need an API fx to get the recording mode (see above)
+ replay.flush();
+ replay.start();
+ }
} catch (err) {
console.error(err);
+ } finally {
+ setIsStarted(!isStarted); // TODO: improve
}
- setIsStarted(!isStarted);
let replayId: string | undefined;
try {
- console.log('getting replay id');
replayId = replay.getReplayId();
} catch (err) {
console.error(err);
}
- setReplayId(replayId); // always sets/refreshes
+ console.log('Replay ID=', replayId);
+ setReplayId(replayId); // always set/refresh regardless of error
}
}}
>
@@ -63,20 +73,29 @@ export function StartReplayButton({
);
}
-const TRUNC_ID_LENGTH = 10; // TODO: import this from somewhere else? Wrap/make dynamic?
-
-export default function ReleasesPanel() {
- // const {data, isLoading, isError} = useToolbarRelease();
- const [isLoading, isError] = [false, false];
-
- const {organizationSlug, projectSlug, projectId, projectPlatform, trackAnalytics} =
- useConfiguration();
+const TRUNC_ID_LENGTH = 10; // TODO: import this from somewhere else? Make it more dynamic?
+export default function ReplayPanel() {
+ // TODO: re-estimate. This is from releasesPanel
const estimateSize = 515;
const placeholderHeight = `${estimateSize - 8}px`; // The real height of the items, minus the padding-block value
- const [replayId, setReplayId] = useState(undefined); // b7908c02c0ea40f081077a84d887d1f6
- console.log(replayId);
+ const {projectSlug, projectId, projectPlatform, trackAnalytics, SentrySDK} =
+ useConfiguration();
+ const replay = SentrySDK && 'getReplay' in SentrySDK && SentrySDK.getReplay();
+ const [replayId, setReplayId] = useState(() => {
+ try {
+ if (replay) {
+ return replay.getReplayId();
+ }
+ } catch {
+ return undefined;
+ }
+ return undefined;
+ });
+ console.log('Replay ID=', replayId);
+
+ const [isLoading, isError] = [false, false]; // TODO: use if we query an endpoint for data like time started
return (
@@ -93,14 +112,14 @@ export default function ReleasesPanel() {
) : (
-
+
{replayId !== undefined ? (
{'Replay of current session: '}
{
@@ -131,12 +150,13 @@ export default function ReleasesPanel() {
hideName
avatarProps={{hasTooltip: false}}
/>
- {/* TODO: can truncate if too 32 char is too long */}
{replayId.slice(0, TRUNC_ID_LENGTH)}
- ) : null}
+ ) : (
+ 'No replay'
+ )}
{/* TODO: add DURATION and start time, similar to replay index page */}
{/* {'1 min ago 01:12'} */}
diff --git a/yarn.lock b/yarn.lock
index 756930196eca28..4e2e7059cd7413 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2292,10 +2292,10 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64"
integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==
-"@prisma/instrumentation@5.16.1":
- version "5.16.1"
- resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.16.1.tgz#93f996f9c95874156badbb5edbb97994667f7c3f"
- integrity sha512-4m5gRFWnQb8s/yTyGbMZkL7A5uJgqOWcWJxapwcAD0T0kh5sGPEVSQl/zTQvE9aduXhFAxOtC3gO+R8Hb5xO1Q==
+"@prisma/instrumentation@5.17.0":
+ version "5.17.0"
+ resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.17.0.tgz#f741ff517f54b1a896fb8605e0d702f29855c6cb"
+ integrity sha512-c1Sle4ji8aasMcYfBBHFM56We4ljfenVtRmS8aY06BllS7SoU6SmJBwG7vil+GHiR0Yrh+t9iBwt4AY0Jr4KNQ==
dependencies:
"@opentelemetry/api" "^1.8"
"@opentelemetry/instrumentation" "^0.49 || ^0.50 || ^0.51 || ^0.52.0"
@@ -3020,23 +3020,23 @@
fs-extra "^11.1.1"
lodash "^4.17.21"
-"@sentry-internal/browser-utils@8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.18.0.tgz#b3d06a77bf80e8d00e4cd8fc11a242cb4e9fa534"
- integrity sha512-1R7QXp7Gu6ovJGWvGjbgHcDcvDstsQba3miHtUCyDSH9kXtnAVLCAItDkseetFh+JLsjBXf3QFi2H3HPY4hRCw==
+"@sentry-internal/browser-utils@8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.20.0.tgz#26837f889cff1caf09ddfd6ca7f0adad9256b981"
+ integrity sha512-GGYNiELnT4ByidHyS4/M8UF8Oxagm5R13QyTncQGq8nZcQhcFZ9mdxLnf1/R4+j44Fph2Cgzafe8jGP/AMA9zw==
dependencies:
- "@sentry/core" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
-"@sentry-internal/feedback@8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.18.0.tgz#8055e7fcffe2c09505b0df66590859b7e59e3239"
- integrity sha512-on6+4ZRkfdnsNgXecGQ6ME8aO26VTzkuM6y/kNN+bG2hSdxsmuU957B4x1Z5wEXiOWswuf3rhqGepg8JIdPkMQ==
+"@sentry-internal/feedback@8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.20.0.tgz#8e4ab43bb4048951f6670bd48b2af04deb75eff4"
+ integrity sha512-mFvAoVpVShkDB2AgEr/dE96NSTPKI/lGMBznZMg7ZEcwZhLfH7HvLYCadIskRfzqFTLOUpbm9ciIO4SyR/4bDA==
dependencies:
- "@sentry/core" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
"@sentry-internal/global-search@^1.0.0":
version "1.0.0"
@@ -3057,25 +3057,25 @@
resolved "https://registry.yarnpkg.com/@sentry-internal/react-inspector/-/react-inspector-6.0.1-4.tgz#10758f3461cf2cf48df8c80f0514c55ca18872c5"
integrity sha512-uL2RyvW8EqDEchnbo8Hu/c4IpBqM3LLxUpZPHs8o40kynerzPset6bC/m5SU124gEhy4PqjdvJ7DhTYR75NetQ==
-"@sentry-internal/replay-canvas@8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.18.0.tgz#8b5aa194de1d2dc688c71803066e22276d33cdb3"
- integrity sha512-fcuLJBrhw3Ql8sU8veUgDCRYo6toQldFU807cpYphQ0uEw2oVZwNNPDQSu1651Ykvp0P/x+9hk/jjJxMohrO9g==
+"@sentry-internal/replay-canvas@8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.20.0.tgz#abaa845278dd397670fb01baed505f751b1c9989"
+ integrity sha512-LXV/pMH9KMw6CtImenMsiBkYIFIc97pDJ/rC7mVImKIROQ45fxGp/JBXM4Id0GENyA2+SySMWVQCAAapSfHZTw==
dependencies:
- "@sentry-internal/replay" "8.18.0"
- "@sentry/core" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry-internal/replay" "8.20.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
-"@sentry-internal/replay@8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.18.0.tgz#338ef7ce3d1ae1629d80315b293b5991b2886ba4"
- integrity sha512-cCLib/HjD8UR0fB2F5hV6KsFBD6yTOEsi67RBllm5gT5vJt87VYoPliF6O7mmMNw8TWkQ0uc5laKld3q9ph+ug==
+"@sentry-internal/replay@8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.20.0.tgz#1e1b514651a6c499609cb90cf8df3ee18a1df157"
+ integrity sha512-sCiI7SOAHq5XsxkixtoMofeSyKd/hVgDV+4145f6nN9m7nLzig4PBQwh2SgK2piJ2mfaXfqcdzA1pShPYldaJA==
dependencies:
- "@sentry-internal/browser-utils" "8.18.0"
- "@sentry/core" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry-internal/browser-utils" "8.20.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
"@sentry-internal/rrdom@2.25.0":
version "2.25.0"
@@ -3124,36 +3124,36 @@
resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.16.1.tgz#da3bf4ec1c1dc68a97d6a7e27bd710001d6b07fb"
integrity sha512-pJka66URsqQbk6hTs9H1XFpUeI0xxuqLYf9Dy5pRGNHSJMtfv91U+CaYSWt03aRRMGDXMduh62zAAY7Wf0HO+A==
-"@sentry/browser@8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.18.0.tgz#26840a95750f7b239af0cb350868acba536ba872"
- integrity sha512-E2w9u76JcjxcmgvroJrB7bcbG5oBCYI/pME1CtprBgZSS9mMYDsyBe6JKqGHdw2wvT3xNxNtkm7hf1O6+3NWUQ==
+"@sentry/browser@8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.20.0.tgz#6644d3223f891b031684210d89511275a5d6c657"
+ integrity sha512-JDZbCreY44/fHYN28QzsAwEHXa2rc1hzM6GE4RSlXCdAhNfrjVxyYDxhw/50pVEHZg1WXxf7ZmERjocV5VJHsw==
dependencies:
- "@sentry-internal/browser-utils" "8.18.0"
- "@sentry-internal/feedback" "8.18.0"
- "@sentry-internal/replay" "8.18.0"
- "@sentry-internal/replay-canvas" "8.18.0"
- "@sentry/core" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry-internal/browser-utils" "8.20.0"
+ "@sentry-internal/feedback" "8.20.0"
+ "@sentry-internal/replay" "8.20.0"
+ "@sentry-internal/replay-canvas" "8.20.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
-"@sentry/core@8.18.0", "@sentry/core@^8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.18.0.tgz#65fd100edc9ff6ba96f9ae1c24c960b54cf9e6a1"
- integrity sha512-8moEMC3gp4W6mH9w5amb/zrYk6bNW8WGgcLRMCs5rguxny8YP5i8ISOJ0T0LP9x/RxSK/6xix5D2bzI/5ECzlw==
+"@sentry/core@8.20.0", "@sentry/core@^8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.20.0.tgz#c50d082033a44295d2fe9140319f912ba1f946d3"
+ integrity sha512-R81snuw+67VT4aCxr6ShST/s0Y6FlwN2YczhDwaGyzumn5rlvA6A4JtQDeExduNoDDyv4T3LrmW8wlYZn3CJJw==
dependencies:
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
"@sentry/jest-environment@6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@sentry/jest-environment/-/jest-environment-6.0.0.tgz#7d77ac2e18e3fe4f0da2c143bc0985ad3d3c2dcb"
integrity sha512-e4ZTE/h1/wNITyIzZUqka3KOmLMICVYXLxGiM7OdQy8zS7J7j/HCKbUPIZ9ozk5RVQJDwG68U2pNB4YX2Ka3xQ==
-"@sentry/node@8.18.0", "@sentry/node@^8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/node/-/node-8.18.0.tgz#61280cc885c9b1d0c6ef086a4ef902ee8cd4fe45"
- integrity sha512-a+W477bmt28I1DT51xJKmp4Y7hBAdEGqQ2K7gfOn3mRBHoihuhKl2Xe8BMwFH7+v4mAEZEwAZBUOLAC7h+Tjig==
+"@sentry/node@8.20.0", "@sentry/node@^8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/node/-/node-8.20.0.tgz#dc20f03dfdec8797f2a0074ebe90044d305d1c59"
+ integrity sha512-i4ywT2m0Gw65U3uwI4NwiNcyqp9YF6/RsusfH1pg4YkiL/RYp7FS0MPVgMggfvoue9S3KjCgRVlzTLwFATyPXQ==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/context-async-hooks" "^1.25.1"
@@ -3177,44 +3177,45 @@
"@opentelemetry/resources" "^1.25.1"
"@opentelemetry/sdk-trace-base" "^1.25.1"
"@opentelemetry/semantic-conventions" "^1.25.1"
- "@prisma/instrumentation" "5.16.1"
- "@sentry/core" "8.18.0"
- "@sentry/opentelemetry" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@prisma/instrumentation" "5.17.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/opentelemetry" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
+ import-in-the-middle "^1.10.0"
optionalDependencies:
opentelemetry-instrumentation-fetch-node "1.2.3"
-"@sentry/opentelemetry@8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-8.18.0.tgz#dd8e00e096e0b0c10772792c24c967bfd8df1633"
- integrity sha512-P2OoXXJcU2RiRZmpBqOkK+NLGkwQrYizlOHl1zckHI1nYmQgOD1tcJj4c1xOYzH+eGPLp/IViXHO6vaBr8BGGg==
+"@sentry/opentelemetry@8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-8.20.0.tgz#5e62a361f43e6b53686037a62b82a7de51995578"
+ integrity sha512-NFcLK6+t9wUc4HlGKeuDn6W4KjZxZfZmWlrK2/tgC5KzG1cnVeOnWUrJzGHTa+YDDdIijpjiFUcpXGPkX3rmIg==
dependencies:
- "@sentry/core" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
-"@sentry/profiling-node@^8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/profiling-node/-/profiling-node-8.18.0.tgz#3235c5d355a778e3b769ef2c533e298020985b47"
- integrity sha512-bgX8aPRQe8o+KDS4CgWCayCRs3BC6t6oqto1vU1h7/Nzg2XuI8xPFlaalZ/ihFvpWO+qBJZvlMu4Z9zDBWeFfQ==
+"@sentry/profiling-node@^8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/profiling-node/-/profiling-node-8.20.0.tgz#eeac53c4926262b3bf19256c3364a34665ebaa6c"
+ integrity sha512-vQaMYjPM7o0qvmj4atxXZywIDhnxMwTlc6x24eKqT8zN0OFBuIc1nYIacT7pEmd7R6e/mXdiG04GH1Vg0bHfOQ==
dependencies:
- "@sentry/core" "8.18.0"
- "@sentry/node" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/node" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
detect-libc "^2.0.2"
node-abi "^3.61.0"
-"@sentry/react@^8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.18.0.tgz#0248daede8ccb99f25e5b31fdab7f417e88e56f3"
- integrity sha512-ckCKdxmeFdfR6moE/Aiq+cJyQuCUKoUqU/++xZwqVbgecuImsk4s7CzzpX9T6JoYK7jqru2SvuRSiwcdtLN6AQ==
+"@sentry/react@^8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.20.0.tgz#1145034199f7a03d10f8ddae59e45aebffb2de59"
+ integrity sha512-vqA0o9ysdfA24/ADhsJwsmCNdUWRu2ycmVN1Sr76v+ZggyOCFzE7XD13kbqk1G3jPb8nptNu/6Zwpcy5pP4mtw==
dependencies:
- "@sentry/browser" "8.18.0"
- "@sentry/core" "8.18.0"
- "@sentry/types" "8.18.0"
- "@sentry/utils" "8.18.0"
+ "@sentry/browser" "8.20.0"
+ "@sentry/core" "8.20.0"
+ "@sentry/types" "8.20.0"
+ "@sentry/utils" "8.20.0"
hoist-non-react-statics "^3.3.2"
"@sentry/release-parser@^1.3.1":
@@ -3227,17 +3228,17 @@
resolved "https://registry.yarnpkg.com/@sentry/status-page-list/-/status-page-list-0.3.0.tgz#d5520057007be1a021933aae26dfa6a4a3981c40"
integrity sha512-v/MkVOvs48QioXt7Ex8gmZEFGvjukWqx2DlIej+Ac4pVQJAfzF6/DFFVT3IK8/owIqv/IdEhY0XzHOcIB0yBIA==
-"@sentry/types@8.18.0", "@sentry/types@^8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.18.0.tgz#501e57e19567d0ff13de0957efd2af29a0956699"
- integrity sha512-5J+uOqptnmAnW3Rk31AHIqW36Wzvlo3UOM+p2wjSYGrC/PgcE47Klzr+w4UcOhN6AZqefalGd3vaUXz9NaFdRg==
+"@sentry/types@8.20.0", "@sentry/types@^8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.20.0.tgz#f0f50c84eb768df8b55ee7b41459fec2d39d0d5e"
+ integrity sha512-6IP278KojOpiAA7vrd1hjhUyn26cl0n0nGsShzic5ztCVs92sTeVRnh7MTB9irDVtAbOEyt/YH6go3h+Jia1pA==
-"@sentry/utils@8.18.0", "@sentry/utils@^8.18.0":
- version "8.18.0"
- resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.18.0.tgz#1c161a09470e0844bb41de04c7d2c798adcc8bce"
- integrity sha512-7wq7cgaeSIGJncl9/2VMu81ZN5ep4lp4H1/+O8+xUxOmnPb/05ZZcbn9/VxVQvIoqZSZdwCLPeBz6PEVukvokA==
+"@sentry/utils@8.20.0", "@sentry/utils@^8.20.0":
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.20.0.tgz#fcbf46c8e8c8eccbf1db532b087547eb4f6c449c"
+ integrity sha512-+1I5H8dojURiEUGPliDwheQk8dhjp8uV1sMccR/W/zjFrt4wZyPs+Ttp/V7gzm9LDJoNek9tmELert/jQqWTgg==
dependencies:
- "@sentry/types" "8.18.0"
+ "@sentry/types" "8.20.0"
"@sinclair/typebox@^0.27.8":
version "0.27.8"
@@ -7446,6 +7447,16 @@ import-in-the-middle@1.7.1:
cjs-module-lexer "^1.2.2"
module-details-from-path "^1.0.3"
+import-in-the-middle@^1.10.0:
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.0.tgz#a94c4925b8da18256cde3b3b7b38253e6ca5e708"
+ integrity sha512-5DimNQGoe0pLUHbR9qK84iWaWjjbsxiqXnw6Qz64+azRgleqv9k2kTt5fw7QsOpmaGYtuxxursnPPsnTKEx10Q==
+ dependencies:
+ acorn "^8.8.2"
+ acorn-import-attributes "^1.9.5"
+ cjs-module-lexer "^1.2.2"
+ module-details-from-path "^1.0.3"
+
import-in-the-middle@^1.8.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.9.1.tgz#83f68c0ca926709257562238e1993a1c31e01272"
From a324791069fb684dad40106b6c8f7b4478b99518 Mon Sep 17 00:00:00 2001
From: Andrew Liu <159852527+aliu39@users.noreply.github.com>
Date: Thu, 1 Aug 2024 15:58:21 -0700
Subject: [PATCH 03/26] Working start/stop links
---
.../components/replay/replayPanel.tsx | 237 ++++++++----------
1 file changed, 98 insertions(+), 139 deletions(-)
diff --git a/static/app/components/devtoolbar/components/replay/replayPanel.tsx b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
index 711f3e27e31f67..3bed8e70570de4 100644
--- a/static/app/components/devtoolbar/components/replay/replayPanel.tsx
+++ b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
@@ -1,16 +1,10 @@
-import {Fragment, useState} from 'react';
+import {Fragment, useEffect, useState} from 'react';
import {css} from '@emotion/react';
-import type {replayIntegration} from '@sentry/react';
import {Button} from 'sentry/components/button';
import SentryAppLink from 'sentry/components/devtoolbar/components/sentryAppLink';
-import {listItemPlaceholderWrapperCss} from 'sentry/components/devtoolbar/styles/listItem';
-import {
- resetFlexColumnCss,
- resetFlexRowCss,
-} from 'sentry/components/devtoolbar/styles/reset';
+import {resetFlexRowCss} from 'sentry/components/devtoolbar/styles/reset';
import ProjectBadge from 'sentry/components/idBadge/projectBadge';
-import Placeholder from 'sentry/components/placeholder';
import {IconPause, IconPlay} from 'sentry/icons';
import {t} from 'sentry/locale';
import type {PlatformKey} from 'sentry/types/project';
@@ -20,148 +14,113 @@ import {panelInsetContentCss, panelSectionCss} from '../../styles/panel';
import {smallCss} from '../../styles/typography';
import PanelLayout from '../panelLayout';
-export function StartReplayButton({
- replay,
- setReplayId,
-}: {
- replay: ReturnType | undefined | false;
- setReplayId: React.Dispatch>;
-}) {
- const [isStarted, setIsStarted] = useState(false);
- // isStarted is not always accurate, since we don't have an API fx to check if we're currently recording.
- // _replay.recordingMode == "session" is how we'd check w/ the internal API.
+const TRUNC_ID_LENGTH = 16;
+const POLL_INTERVAL_MS = 3000;
- return (
- : }
- disabled={!replay} // TODO: tooltip on why this could be disabled
- onClick={() => {
- if (replay) {
- try {
- if (isStarted) {
- replay.stop(); // stop should call flush
- } else {
- // If we're sampling errors, there's a chance the replay will be in buffering mode.
- // In this case start() will do nothing, while flush() will switch to session mode/start recording.
- // However if we're not buffering, flush() will not start a replay (needs more testing).
- // To improve this code we need an API fx to get the recording mode (see above)
- replay.flush();
- replay.start();
- }
- } catch (err) {
- console.error(err);
- } finally {
- setIsStarted(!isStarted); // TODO: improve
- }
+export default function ReplayPanel() {
+ const {projectSlug, projectId, projectPlatform, trackAnalytics, SentrySDK} =
+ useConfiguration();
+ const replay =
+ SentrySDK && 'getReplay' in SentrySDK ? SentrySDK.getReplay() : undefined;
- let replayId: string | undefined;
- try {
- replayId = replay.getReplayId();
- } catch (err) {
- console.error(err);
- }
- console.log('Replay ID=', replayId);
- setReplayId(replayId); // always set/refresh regardless of error
- }
- }}
- >
- {isStarted
- ? t('A replay recording is in progress.')
- : t('Start recording the current session')}
-
+ const [replayId, setReplayId] = useState(() =>
+ replay?.getReplayId()
);
-}
+ // Polls periodically since a replay could be started by sessionSampleRate
+ useEffect(() => {
+ const intervalId = setInterval(
+ () => setReplayId(replay?.getReplayId()),
+ POLL_INTERVAL_MS
+ );
+ return () => clearInterval(intervalId);
+ }, [replay]);
-const TRUNC_ID_LENGTH = 10; // TODO: import this from somewhere else? Make it more dynamic?
-
-export default function ReplayPanel() {
- // TODO: re-estimate. This is from releasesPanel
- const estimateSize = 515;
- const placeholderHeight = `${estimateSize - 8}px`; // The real height of the items, minus the padding-block value
+ const [isRecording, setIsRecording] = useState(
+ () => replay?.getReplayId() !== undefined
+ );
+ // Current replayId is only defined when there is an active recording session
+ useEffect(() => setIsRecording(replayId !== undefined), [replayId]);
- const {projectSlug, projectId, projectPlatform, trackAnalytics, SentrySDK} =
- useConfiguration();
- const replay = SentrySDK && 'getReplay' in SentrySDK && SentrySDK.getReplay();
- const [replayId, setReplayId] = useState(() => {
- try {
- if (replay) {
- return replay.getReplayId();
- }
- } catch {
- return undefined;
+ // Used to persist the link to the last replay even if it's stopped. //TODO: this is lost after leaving the panel
+ const [lastReplayId, setLastReplayId] = useState(() =>
+ replay?.getReplayId()
+ );
+ useEffect(() => {
+ if (replayId) {
+ setLastReplayId(replayId);
}
- return undefined;
- });
- console.log('Replay ID=', replayId);
-
- const [isLoading, isError] = [false, false]; // TODO: use if we query an endpoint for data like time started
+ }, [replayId]);
return (
- {isLoading || isError ? (
-
+ : }
+ disabled={!replay} // TODO: tooltip on why this is disabled,
+ onClick={() => {
+ if (replay) {
+ if (isRecording) {
+ replay.stop(); // stop should call flush
+ } else {
+ // If we're sampling errors, the we might be in buffering mode.
+ // In this case start() will do nothing. flush() will switch to session mode + start recording.
+ replay.flush(); // TODO: make sure this works in session mode too
+ }
+ setReplayId(replay.getReplayId()); // this will set isRecording
+ }
+ }}
>
-
-
- ) : (
-
-
-
- {replayId !== undefined ? (
-
- {'Replay of current session: '}
- {
- trackAnalytics?.({
- eventKey: `devtoolbar.current-replay-link.click`,
- eventName: `devtoolbar: Current replay link clicked`,
- });
- }}
+ {isRecording
+ ? t('In progress. Click to stop recording') // TODO: make sure this fits
+ : t('Start recording the current session')}
+
+
- {/* TODO: add DURATION and start time, similar to replay index page */}
- {/* {'1 min ago 01:12'} */}
-
- )}
+
+ {lastReplayId.slice(0, TRUNC_ID_LENGTH)}
+
+
+
+ ) : (
+ 'No replay'
+ )}
+
+
);
}
From c1e1ba75ecdba19b06c64b49009e3cdc12a84174 Mon Sep 17 00:00:00 2001
From: Andrew Liu <159852527+aliu39@users.noreply.github.com>
Date: Thu, 1 Aug 2024 16:00:02 -0700
Subject: [PATCH 04/26] Cleanup todos
---
.../components/devtoolbar/components/replay/replayPanel.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/static/app/components/devtoolbar/components/replay/replayPanel.tsx b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
index 3bed8e70570de4..4007b9e067eb51 100644
--- a/static/app/components/devtoolbar/components/replay/replayPanel.tsx
+++ b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
@@ -65,14 +65,14 @@ export default function ReplayPanel() {
} else {
// If we're sampling errors, the we might be in buffering mode.
// In this case start() will do nothing. flush() will switch to session mode + start recording.
- replay.flush(); // TODO: make sure this works in session mode too
+ replay.flush();
}
setReplayId(replay.getReplayId()); // this will set isRecording
}
}}
>
{isRecording
- ? t('In progress. Click to stop recording') // TODO: make sure this fits
+ ? t('In progress. Click to stop recording')
: t('Start recording the current session')}
From 1991afef9bf1f99ee1cb7b25a3f9222e2c8b8ae8 Mon Sep 17 00:00:00 2001
From: Andrew Liu <159852527+aliu39@users.noreply.github.com>
Date: Thu, 1 Aug 2024 21:11:12 -0700
Subject: [PATCH 05/26] Handle buffer mode
---
.../components/replay/replayPanel.tsx | 40 +++++++++++--------
1 file changed, 24 insertions(+), 16 deletions(-)
diff --git a/static/app/components/devtoolbar/components/replay/replayPanel.tsx b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
index 4007b9e067eb51..30991977a92a1c 100644
--- a/static/app/components/devtoolbar/components/replay/replayPanel.tsx
+++ b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
@@ -1,5 +1,6 @@
import {Fragment, useEffect, useState} from 'react';
import {css} from '@emotion/react';
+import type {ReplayRecordingMode} from '@sentry/types';
import {Button} from 'sentry/components/button';
import SentryAppLink from 'sentry/components/devtoolbar/components/sentryAppLink';
@@ -23,33 +24,40 @@ export default function ReplayPanel() {
const replay =
SentrySDK && 'getReplay' in SentrySDK ? SentrySDK.getReplay() : undefined;
- const [replayId, setReplayId] = useState(() =>
+ // sessionId is undefined iff we are recording in session OR buffer mode.
+ const [sessionId, setSessionId] = useState(() =>
replay?.getReplayId()
);
+ const [recordingMode, setRecordingMode] = useState(
+ () => replay?._replay.recordingMode
+ );
// Polls periodically since a replay could be started by sessionSampleRate
useEffect(() => {
- const intervalId = setInterval(
- () => setReplayId(replay?.getReplayId()),
- POLL_INTERVAL_MS
- );
+ const intervalId = setInterval(() => {
+ setSessionId(replay?.getReplayId());
+ setRecordingMode(replay?._replay.recordingMode);
+ }, POLL_INTERVAL_MS);
return () => clearInterval(intervalId);
}, [replay]);
const [isRecording, setIsRecording] = useState(
- () => replay?.getReplayId() !== undefined
+ () => replay?.getReplayId() && replay?._replay.recordingMode === 'session'
);
- // Current replayId is only defined when there is an active recording session
- useEffect(() => setIsRecording(replayId !== undefined), [replayId]);
-
- // Used to persist the link to the last replay even if it's stopped. //TODO: this is lost after leaving the panel
- const [lastReplayId, setLastReplayId] = useState(() =>
- replay?.getReplayId()
+ useEffect(
+ () => setIsRecording(sessionId && recordingMode === 'session'),
+ [sessionId, recordingMode]
);
+
+ // Used to persist the link to the last recorded replay, even if it's stopped.
+ // TODO: this is lost after leaving the panel. Could use a local storage?
+ const [lastReplayId, setLastReplayId] = useState(() => {
+ return recordingMode === 'session' ? replay?.getReplayId() : undefined;
+ });
useEffect(() => {
- if (replayId) {
- setLastReplayId(replayId);
+ if (sessionId && recordingMode === 'session') {
+ setLastReplayId(sessionId);
}
- }, [replayId]);
+ }, [sessionId, recordingMode]);
return (
@@ -67,7 +75,7 @@ export default function ReplayPanel() {
// In this case start() will do nothing. flush() will switch to session mode + start recording.
replay.flush();
}
- setReplayId(replay.getReplayId()); // this will set isRecording
+ setSessionId(replay.getReplayId()); // this will set isRecording
}
}}
>
From 9246bacbccf66defcc94acb93fb3bdd480a77527 Mon Sep 17 00:00:00 2001
From: Andrew Liu <159852527+aliu39@users.noreply.github.com>
Date: Thu, 1 Aug 2024 21:25:02 -0700
Subject: [PATCH 06/26] Add tooltip + some comments and cleanup
---
.../components/replay/replayPanel.tsx | 138 +++++++++---------
1 file changed, 70 insertions(+), 68 deletions(-)
diff --git a/static/app/components/devtoolbar/components/replay/replayPanel.tsx b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
index 30991977a92a1c..da681ebea8ae31 100644
--- a/static/app/components/devtoolbar/components/replay/replayPanel.tsx
+++ b/static/app/components/devtoolbar/components/replay/replayPanel.tsx
@@ -1,4 +1,4 @@
-import {Fragment, useEffect, useState} from 'react';
+import {useEffect, useState} from 'react';
import {css} from '@emotion/react';
import type {ReplayRecordingMode} from '@sentry/types';
@@ -7,7 +7,6 @@ import SentryAppLink from 'sentry/components/devtoolbar/components/sentryAppLink
import {resetFlexRowCss} from 'sentry/components/devtoolbar/styles/reset';
import ProjectBadge from 'sentry/components/idBadge/projectBadge';
import {IconPause, IconPlay} from 'sentry/icons';
-import {t} from 'sentry/locale';
import type {PlatformKey} from 'sentry/types/project';
import useConfiguration from '../../hooks/useConfiguration';
@@ -61,74 +60,77 @@ export default function ReplayPanel() {
return (
-
- : }
- disabled={!replay} // TODO: tooltip on why this is disabled,
- onClick={() => {
- if (replay) {
- if (isRecording) {
- replay.stop(); // stop should call flush
- } else {
- // If we're sampling errors, the we might be in buffering mode.
- // In this case start() will do nothing. flush() will switch to session mode + start recording.
- replay.flush();
- }
- setSessionId(replay.getReplayId()); // this will set isRecording
+ : }
+ disabled={!replay}
+ title={
+ replay ? undefined : 'Your app is missing the session replay integration.'
+ // TODO: should we also do FF checks?
+ }
+ onClick={() => {
+ if (replay) {
+ if (isRecording) {
+ replay.stop(); // stop should call flush
+ } else {
+ // If we're sampling errors, then we might be in buffer mode, and
+ // start() will do nothing. In either mode, flush() will set the
+ // mode to session and start recording.
+ replay.flush();
}
- }}
- >
- {isRecording
- ? t('In progress. Click to stop recording')
- : t('Start recording the current session')}
-
-
- {lastReplayId ? (
-
- {isRecording ? t('Current replay: ') : t('Last recorded replay: ')}
- {
- trackAnalytics?.({
- eventKey: `devtoolbar.current-replay-link.click`,
- eventName: `devtoolbar: Current replay link clicked`,
- });
- }}
+ setSessionId(replay.getReplayId()); // this will set isRecording
+ }
+ }}
+ >
+ {isRecording
+ ? 'In progress. Click to stop recording'
+ : 'Start recording the current session'}
+
+