|
@@ -1,4 +1,10 @@
|
|
|
-import {AnchorHTMLAttributes, cloneElement, createContext, useState} from 'react';
|
|
|
+import {
|
|
|
+ AnchorHTMLAttributes,
|
|
|
+ cloneElement,
|
|
|
+ createContext,
|
|
|
+ useCallback,
|
|
|
+ useState,
|
|
|
+} from 'react';
|
|
|
import styled from '@emotion/styled';
|
|
|
|
|
|
import {Button} from 'sentry/components/button';
|
|
@@ -12,7 +18,8 @@ import {space} from 'sentry/styles/space';
|
|
|
import {PlatformType, Project} from 'sentry/types';
|
|
|
import {Event} from 'sentry/types/event';
|
|
|
import {STACK_TYPE} from 'sentry/types/stacktrace';
|
|
|
-import {isNativePlatform} from 'sentry/utils/platform';
|
|
|
+import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
|
|
|
+import {isMobilePlatform, isNativePlatform} from 'sentry/utils/platform';
|
|
|
import useApi from 'sentry/utils/useApi';
|
|
|
import useOrganization from 'sentry/utils/useOrganization';
|
|
|
|
|
@@ -91,6 +98,181 @@ export function TraceEventDataSection({
|
|
|
display: [],
|
|
|
});
|
|
|
|
|
|
+ const isMobile = isMobilePlatform(platform);
|
|
|
+
|
|
|
+ const handleFilterFramesChange = useCallback(
|
|
|
+ (val: 'full' | 'relevant') => {
|
|
|
+ const isFullOptionClicked = val === 'full';
|
|
|
+
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ isFullOptionClicked
|
|
|
+ ? 'stack-trace.full_stack_trace_clicked'
|
|
|
+ : 'stack-trace.most_relevant_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ setState(currentState => ({...currentState, fullStackTrace: isFullOptionClicked}));
|
|
|
+ },
|
|
|
+ [organization, platform, projectSlug, isMobile]
|
|
|
+ );
|
|
|
+
|
|
|
+ const handleSortByChange = useCallback(
|
|
|
+ (val: keyof typeof sortByOptions) => {
|
|
|
+ const isRecentFirst = val === 'recent-first';
|
|
|
+
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ isRecentFirst
|
|
|
+ ? 'stack-trace.sort_option_recent_first_clicked'
|
|
|
+ : 'stack-trace.sort_option_recent_last_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ setState(currentState => ({...currentState, sortBy: val}));
|
|
|
+ },
|
|
|
+ [organization, platform, projectSlug, isMobile]
|
|
|
+ );
|
|
|
+
|
|
|
+ const handleDisplayChange = useCallback(
|
|
|
+ (vals: (keyof typeof displayOptions)[]) => {
|
|
|
+ if (vals.includes('raw-stack-trace')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_raw_stack_trace_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: true,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } else if (state.display.includes('raw-stack-trace')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_raw_stack_trace_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vals.includes('absolute-addresses')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_absolute_addresses_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: true,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } else if (state.display.includes('absolute-addresses')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_absolute_addresses_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vals.includes('absolute-file-paths')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_absolute_file_paths_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: true,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } else if (state.display.includes('absolute-file-paths')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_absolute_file_paths_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vals.includes('minified')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ platform.startsWith('javascript')
|
|
|
+ ? 'stack-trace.display_option_minified_clicked'
|
|
|
+ : 'stack-trace.display_option_unsymbolicated_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: true,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } else if (state.display.includes('minified')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ platform.startsWith('javascript')
|
|
|
+ ? 'stack-trace.display_option_minified_clicked'
|
|
|
+ : 'stack-trace.display_option_unsymbolicated_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vals.includes('verbose-function-names')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_verbose_function_names_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: true,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ } else if (state.display.includes('verbose-function-names')) {
|
|
|
+ trackAdvancedAnalyticsEvent(
|
|
|
+ 'stack-trace.display_option_verbose_function_names_clicked',
|
|
|
+ {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ checked: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ setState(currentState => ({...currentState, display: vals}));
|
|
|
+ },
|
|
|
+ [organization, platform, projectSlug, isMobile, state]
|
|
|
+ );
|
|
|
+
|
|
|
function getDisplayOptions(): {
|
|
|
label: string;
|
|
|
value: keyof typeof displayOptions;
|
|
@@ -216,7 +398,7 @@ export function TraceEventDataSection({
|
|
|
size="xs"
|
|
|
aria-label={t('Filter frames')}
|
|
|
value={state.fullStackTrace ? 'full' : 'relevant'}
|
|
|
- onChange={val => setState({...state, fullStackTrace: val === 'full'})}
|
|
|
+ onChange={handleFilterFramesChange}
|
|
|
>
|
|
|
<SegmentedControl.Item key="relevant" disabled={!hasAppOnlyFrames}>
|
|
|
{t('Most Relevant')}
|
|
@@ -232,6 +414,14 @@ export function TraceEventDataSection({
|
|
|
size="xs"
|
|
|
href={rawStackTraceDownloadLink}
|
|
|
title={t('Download raw stack trace file')}
|
|
|
+ onClick={() => {
|
|
|
+ trackAdvancedAnalyticsEvent('stack-trace.download_clicked', {
|
|
|
+ organization,
|
|
|
+ project_slug: projectSlug,
|
|
|
+ platform,
|
|
|
+ is_mobile: isMobile,
|
|
|
+ });
|
|
|
+ }}
|
|
|
>
|
|
|
{t('Download')}
|
|
|
</Button>
|
|
@@ -245,7 +435,7 @@ export function TraceEventDataSection({
|
|
|
disabled={!!sortByTooltip}
|
|
|
position="bottom-end"
|
|
|
onChange={selectedOption => {
|
|
|
- setState({...state, sortBy: selectedOption.value});
|
|
|
+ handleSortByChange(selectedOption.value);
|
|
|
}}
|
|
|
value={state.sortBy}
|
|
|
options={Object.entries(sortByOptions).map(([value, label]) => ({
|
|
@@ -264,7 +454,7 @@ export function TraceEventDataSection({
|
|
|
triggerLabel=""
|
|
|
position="bottom-end"
|
|
|
value={state.display}
|
|
|
- onChange={opts => setState({...state, display: opts.map(opt => opt.value)})}
|
|
|
+ onChange={opts => handleDisplayChange(opts.map(opt => opt.value))}
|
|
|
options={[{label: t('Display'), options: getDisplayOptions()}]}
|
|
|
/>
|
|
|
</ButtonBar>
|