Skip to content

Commit 5f49eed

Browse files
authored
feat(trace-view): Add UI fallback to old view for STs (#73684)
### Summary Singletenant (and on-prem etc.) may not be fully rolled out for span extraction. This means the new trace-view which is entirely span based won't work. This causes links to fallback to the old trace view if the organization is one without span-extraction rolled out, then proceeds to check the rollout date so we can offer the new experience where possible right away. #### Aside - `OrganizationSummary` didn't need to be narrowed, so switched it out for the full `Organization` provided at the top level by `useOrganization`, can't see a reason why we wouldn't.
1 parent 9ee245d commit 5f49eed

File tree

6 files changed

+63
-36
lines changed

6 files changed

+63
-36
lines changed

static/app/components/quickTrace/index.tsx

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {backend, frontend, mobile, serverless} from 'sentry/data/platformCategor
1818
import {IconFire} from 'sentry/icons';
1919
import {t, tct, tn} from 'sentry/locale';
2020
import type {Event} from 'sentry/types/event';
21-
import type {OrganizationSummary} from 'sentry/types/organization';
2221
import {trackAnalytics} from 'sentry/utils/analytics';
2322
import {getDocsPlatform} from 'sentry/utils/docs';
2423
import getDuration from 'sentry/utils/duration/getDuration';
@@ -35,6 +34,7 @@ import Projects from 'sentry/utils/projects';
3534
const FRONTEND_PLATFORMS: string[] = [...frontend, ...mobile];
3635
const BACKEND_PLATFORMS: string[] = [...backend, ...serverless];
3736

37+
import type {Organization} from 'sentry/types/organization';
3838
import {generateLinkToEventInTraceView} from 'sentry/utils/discover/urls';
3939

4040
import {
@@ -67,7 +67,7 @@ type QuickTraceProps = Pick<
6767
> & {
6868
event: Event;
6969
location: Location;
70-
organization: OrganizationSummary;
70+
organization: Organization;
7171
quickTrace: QuickTraceType;
7272
};
7373

@@ -288,18 +288,14 @@ export default function QuickTrace({
288288
return <QuickTraceContainer>{nodes}</QuickTraceContainer>;
289289
}
290290

291-
function handleNode(key: string, organization: OrganizationSummary) {
291+
function handleNode(key: string, organization: Organization) {
292292
trackAnalytics('quick_trace.node.clicked', {
293293
organization: organization.id,
294294
node_key: key,
295295
});
296296
}
297297

298-
function handleDropdownItem(
299-
key: string,
300-
organization: OrganizationSummary,
301-
extra: boolean
302-
) {
298+
function handleDropdownItem(key: string, organization: Organization, extra: boolean) {
303299
const eventKey = extra
304300
? 'quick_trace.dropdown.clicked_extra'
305301
: 'quick_trace.dropdown.clicked';
@@ -316,7 +312,7 @@ type EventNodeSelectorProps = {
316312
events: QuickTraceEvent[];
317313
location: Location;
318314
nodeKey: keyof typeof TOOLTIP_PREFIX;
319-
organization: OrganizationSummary;
315+
organization: Organization;
320316
text: React.ReactNode;
321317
traceSlug: string;
322318
transactionDest: TransactionDestination;
@@ -410,10 +406,7 @@ function EventNodeSelector({
410406
projectSlug: events[0].project_slug,
411407
timestamp: events[0].timestamp,
412408
location,
413-
organization: {
414-
slug: organization.slug,
415-
features: organization.features,
416-
},
409+
organization,
417410
transactionName: events[0].transaction,
418411
type: transactionDest,
419412
});
@@ -484,10 +477,7 @@ function EventNodeSelector({
484477
projectSlug: event.project_slug,
485478
eventId: event.event_id,
486479
location,
487-
organization: {
488-
slug: organization.slug,
489-
features: organization.features,
490-
},
480+
organization,
491481
type: transactionDest,
492482
transactionName: event.transaction,
493483
});
@@ -525,7 +515,7 @@ function EventNodeSelector({
525515
type DropdownNodeProps = {
526516
anchor: 'left' | 'right';
527517
event: TraceError | QuickTraceEvent | TracePerformanceIssue;
528-
organization: OrganizationSummary;
518+
organization: Organization;
529519
allowDefaultEvent?: boolean;
530520
onSelect?: (eventKey: any) => void;
531521
subtext?: string;

static/app/components/quickTrace/utils.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type {Location, LocationDescriptor} from 'history';
33
import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
44
import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters';
55
import type {Event} from 'sentry/types/event';
6-
import type {OrganizationSummary} from 'sentry/types/organization';
6+
import type {Organization} from 'sentry/types/organization';
77
import {defined} from 'sentry/utils';
88
import EventView from 'sentry/utils/discover/eventView';
99
import {
@@ -32,7 +32,7 @@ export type TransactionDestination = 'discover' | 'performance';
3232

3333
export function generateIssueEventTarget(
3434
event: TraceError | TracePerformanceIssue,
35-
organization: OrganizationSummary,
35+
organization: Organization,
3636
referrer?: string
3737
): LocationDescriptor {
3838
const queryParams = referrer ? '?referrer=' + referrer : '';
@@ -41,7 +41,7 @@ export function generateIssueEventTarget(
4141

4242
function generateDiscoverEventTarget(
4343
event: EventLite | TraceError | TracePerformanceIssue,
44-
organization: OrganizationSummary,
44+
organization: Organization,
4545
location: Location,
4646
referrer?: string
4747
): LocationDescriptor {
@@ -67,7 +67,7 @@ function generateDiscoverEventTarget(
6767

6868
export function generateSingleErrorTarget(
6969
event: TraceError | TracePerformanceIssue,
70-
organization: OrganizationSummary,
70+
organization: Organization,
7171
location: Location,
7272
destination: ErrorDestination,
7373
referrer?: string
@@ -84,7 +84,7 @@ export function generateSingleErrorTarget(
8484
export function generateMultiTransactionsTarget(
8585
currentEvent: Event,
8686
events: EventLite[],
87-
organization: OrganizationSummary,
87+
organization: Organization,
8888
groupType: 'Ancestor' | 'Children' | 'Descendant'
8989
): LocationDescriptor {
9090
const queryResults = new MutableSearch([]);
@@ -134,7 +134,7 @@ export function getEventTimestamp(event: Event): string | number | undefined {
134134

135135
export function generateTraceTarget(
136136
event: Event,
137-
organization: OrganizationSummary,
137+
organization: Organization,
138138
location: Location,
139139
source?: string
140140
): LocationDescriptor {

static/app/types/organization.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ export interface Organization extends OrganizationSummary {
4848
allowJoinRequests: boolean;
4949
allowSharedIssues: boolean;
5050
attachmentsRole: string;
51-
availableRoles: {id: string; name: string}[]; // Deprecated, use orgRoleList
51+
/** @deprecated use orgRoleList instead. */
52+
availableRoles: {id: string; name: string}[];
5253
dataScrubber: boolean;
5354
dataScrubberDefaults: boolean;
5455
debugFilesRole: string;
@@ -79,6 +80,12 @@ export interface Organization extends OrganizationSummary {
7980
trustedRelays: Relay[];
8081
desiredSampleRate?: number | null;
8182
effectiveSampleRate?: number | null;
83+
extraOptions?: {
84+
traces: {
85+
checkSpanExtractionDate: boolean;
86+
spansExtractionDate: number;
87+
};
88+
};
8289
orgRole?: string;
8390
planSampleRate?: number | null;
8491
}

static/app/utils/discover/urls.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function generateLinkToEventInTraceView({
5757
}: {
5858
eventId: string;
5959
location: Location;
60-
organization: Pick<Organization, 'slug' | 'features'>;
60+
organization: Organization;
6161
projectSlug: string;
6262
timestamp: string | number;
6363
traceSlug: string;

static/app/views/performance/traceDetails/TraceDetailsRouting.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {browserHistory} from 'sentry/utils/browserHistory';
77
import {useLocation} from 'sentry/utils/useLocation';
88
import useOrganization from 'sentry/utils/useOrganization';
99

10-
import {getTraceDetailsUrl} from './utils';
10+
import {getTraceDetailsUrl, shouldForceRouteToOldView} from './utils';
1111

1212
type Props = {
1313
children: JSX.Element;
@@ -25,7 +25,10 @@ function TraceDetailsRouting(props: Props) {
2525
return children;
2626
}
2727

28-
if (organization.features.includes('trace-view-v1')) {
28+
if (
29+
organization.features.includes('trace-view-v1') &&
30+
!shouldForceRouteToOldView(organization, getEventTimestamp(event))
31+
) {
2932
if (event?.groupID && event?.eventID) {
3033
const issuesLocation = `/organizations/${organization.slug}/issues/${event.groupID}/events/${event.eventID}`;
3134
browserHistory.replace({

static/app/views/performance/traceDetails/utils.tsx

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type {Location, LocationDescriptorObject} from 'history';
22

33
import {PAGE_URL_PARAM} from 'sentry/constants/pageFilters';
4-
import type {Organization, OrganizationSummary} from 'sentry/types';
4+
import type {Organization} from 'sentry/types';
55
import {getTimeStampFromTableDateField} from 'sentry/utils/dates';
66
import type {
77
EventLite,
@@ -29,7 +29,7 @@ export function getTraceDetailsUrl({
2929
}: {
3030
dateSelection;
3131
location: Location;
32-
organization: Pick<OrganizationSummary, 'slug' | 'features'>;
32+
organization: Organization;
3333
traceSlug: string;
3434
demo?: string;
3535
eventId?: string;
@@ -46,6 +46,17 @@ export function getTraceDetailsUrl({
4646
[PAGE_URL_PARAM.PAGE_END]: end,
4747
};
4848

49+
const oldTraceUrl = {
50+
pathname: normalizeUrl(
51+
`/organizations/${organization.slug}/performance/trace/${traceSlug}/`
52+
),
53+
query: queryParams,
54+
};
55+
56+
if (shouldForceRouteToOldView(organization, timestamp)) {
57+
return oldTraceUrl;
58+
}
59+
4960
if (organization.features.includes('trace-view-v1')) {
5061
if (spanId) {
5162
queryParams.node = [`span-${spanId}`, `txn-${eventId}`];
@@ -68,12 +79,28 @@ export function getTraceDetailsUrl({
6879
queryParams.limit = DEFAULT_TRACE_ROWS_LIMIT;
6980
}
7081

71-
return {
72-
pathname: normalizeUrl(
73-
`/organizations/${organization.slug}/performance/trace/${traceSlug}/`
74-
),
75-
query: queryParams,
76-
};
82+
return oldTraceUrl;
83+
}
84+
85+
/**
86+
* Single tenant, on-premise etc. users may not have span extraction enabled.
87+
*
88+
* This code can be removed at the time we're sure all STs have rolled out span extraction.
89+
*/
90+
export function shouldForceRouteToOldView(
91+
organization: Organization,
92+
timestamp: string | number | undefined
93+
) {
94+
const usableTimestamp = getTimeStampFromTableDateField(timestamp);
95+
if (!usableTimestamp) {
96+
// Timestamps must always be provided for the new view, if it doesn't exist, fall back to the old view.
97+
return true;
98+
}
99+
100+
return (
101+
organization.extraOptions?.traces.checkSpanExtractionDate &&
102+
organization.extraOptions?.traces.spansExtractionDate <= usableTimestamp
103+
);
77104
}
78105

79106
function transactionVisitor() {

0 commit comments

Comments
 (0)