Skip to content

Commit 1613388

Browse files
authored
Merge branch 'master' into tkdodo/ref/workflows-endpoint-to-apiOptions
2 parents 15c790c + 7c7bdcb commit 1613388

File tree

32 files changed

+633
-195
lines changed

32 files changed

+633
-195
lines changed

src/sentry/data_export/models.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,19 @@ def email_failure(self, message: str) -> None:
169169
error_payload=self.payload,
170170
creation_date=self.date_added,
171171
)
172-
if NotificationService.has_access(self.organization, data.source):
172+
has_access = NotificationService.has_access(self.organization, data.source)
173+
logger.info(
174+
"notification.platform.data-export-failure.has_access",
175+
extra={
176+
"organization_id": self.organization.id,
177+
"data_export_id": self.id,
178+
"data_source": data.source,
179+
"has_access": has_access,
180+
"user_email": user.email,
181+
},
182+
)
183+
184+
if has_access:
173185
NotificationService(data=data).notify_async(
174186
targets=[
175187
GenericNotificationTarget(

src/sentry/profiles/task.py

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from datetime import datetime, timezone
1010
from operator import itemgetter
1111
from time import time
12-
from typing import Any, TypedDict
12+
from typing import Any
1313
from uuid import UUID
1414

1515
import msgpack
@@ -58,7 +58,6 @@
5858
from sentry.profiles.utils import (
5959
Profile,
6060
apply_stack_trace_rules_to_profile,
61-
get_from_profiling_service,
6261
)
6362
from sentry.search.utils import DEVICE_CLASS
6463
from sentry.signals import first_profile_received
@@ -1075,62 +1074,6 @@ def _track_failed_outcome(profile: Profile, project: Project, reason: str) -> No
10751074
)
10761075

10771076

1078-
@metrics.wraps("process_profile.insert_vroom_profile")
1079-
def _insert_vroom_profile(profile: Profile) -> bool:
1080-
with sentry_sdk.start_span(op="task.profiling.insert_vroom"):
1081-
try:
1082-
path = "/chunk" if "profiler_id" in profile else "/profile"
1083-
response = get_from_profiling_service(
1084-
method="POST",
1085-
path=path,
1086-
json_data=profile,
1087-
metric=(
1088-
"profiling.profile.payload.size",
1089-
{
1090-
"type": "chunk" if "profiler_id" in profile else "profile",
1091-
"platform": profile["platform"],
1092-
},
1093-
),
1094-
)
1095-
1096-
sentry_sdk.set_tag("vroom.response.status_code", str(response.status))
1097-
1098-
reason = "bad status"
1099-
1100-
if response.status == 204:
1101-
return True
1102-
elif response.status == 429:
1103-
reason = "gcs timeout"
1104-
elif response.status == 412:
1105-
reason = "duplicate profile"
1106-
1107-
metrics.incr(
1108-
"process_profile.insert_vroom_profile.error",
1109-
tags={
1110-
"platform": profile["platform"],
1111-
"reason": reason,
1112-
"status_code": response.status,
1113-
},
1114-
sample_rate=1.0,
1115-
)
1116-
return False
1117-
except Exception as e:
1118-
sentry_sdk.capture_exception(e)
1119-
metrics.incr(
1120-
"process_profile.insert_vroom_profile.error",
1121-
tags={"platform": profile["platform"], "reason": "encountered error"},
1122-
sample_rate=1.0,
1123-
)
1124-
return False
1125-
1126-
1127-
def _push_profile_to_vroom(profile: Profile, project: Project) -> bool:
1128-
if _insert_vroom_profile(profile=profile):
1129-
return True
1130-
_track_failed_outcome(profile, project, "profiling_failed_vroom_insertion")
1131-
return False
1132-
1133-
11341077
def prepare_android_js_profile(profile: Profile) -> None:
11351078
profile["js_profile"] = {"profile": profile["js_profile"]}
11361079
p = profile["js_profile"]
@@ -1152,11 +1095,6 @@ def clean_android_js_profile(profile: Profile) -> None:
11521095
del p["dist"]
11531096

11541097

1155-
class _ProjectKeyKwargs(TypedDict):
1156-
project_id: int
1157-
use_case: str
1158-
1159-
11601098
@metrics.wraps("process_profile.track_outcome")
11611099
def _track_duration_outcome(
11621100
profile: Profile,

src/sentry/search/eap/preprod_size/attributes.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Literal
2+
13
from sentry.search.eap import constants
24
from sentry.search.eap.columns import ResolvedAttribute, datetime_processor
35
from sentry.search.eap.common_columns import COMMON_COLUMNS
@@ -56,6 +58,11 @@
5658
internal_name="git_head_ref",
5759
search_type="string",
5860
),
61+
ResolvedAttribute(
62+
public_alias="installable",
63+
internal_name="has_installable_file",
64+
search_type="boolean",
65+
),
5966
ResolvedAttribute(
6067
public_alias="timestamp",
6168
internal_name="sentry.timestamp",
@@ -65,3 +72,23 @@
6572
),
6673
]
6774
}
75+
76+
PREPROD_SIZE_INTERNAL_TO_PUBLIC_ALIAS_MAPPINGS: dict[
77+
Literal["string", "number", "boolean"], dict[str, str]
78+
] = {
79+
"string": {
80+
definition.internal_name: definition.public_alias
81+
for definition in PREPROD_SIZE_ATTRIBUTE_DEFINITIONS.values()
82+
if not definition.secondary_alias and definition.search_type == "string"
83+
},
84+
"boolean": {
85+
definition.internal_name: definition.public_alias
86+
for definition in PREPROD_SIZE_ATTRIBUTE_DEFINITIONS.values()
87+
if not definition.secondary_alias and definition.search_type == "boolean"
88+
},
89+
"number": {
90+
definition.internal_name: definition.public_alias
91+
for definition in PREPROD_SIZE_ATTRIBUTE_DEFINITIONS.values()
92+
if not definition.secondary_alias and definition.search_type != "string"
93+
},
94+
}

src/sentry/search/eap/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
OURLOG_ATTRIBUTE_DEFINITIONS,
1717
)
1818
from sentry.search.eap.ourlogs.definitions import OURLOG_DEFINITIONS
19+
from sentry.search.eap.preprod_size.attributes import (
20+
PREPROD_SIZE_INTERNAL_TO_PUBLIC_ALIAS_MAPPINGS,
21+
)
1922
from sentry.search.eap.profile_functions.attributes import (
2023
PROFILE_FUNCTIONS_ATTRIBUTE_DEFINITIONS,
2124
PROFILE_FUNCTIONS_INTERNAL_TO_PUBLIC_ALIAS_MAPPINGS,
@@ -69,6 +72,7 @@ def add_start_end_conditions(
6972
SupportedTraceItemType.LOGS: LOGS_INTERNAL_TO_PUBLIC_ALIAS_MAPPINGS,
7073
SupportedTraceItemType.TRACEMETRICS: TRACE_METRICS_INTERNAL_TO_PUBLIC_ALIAS_MAPPINGS,
7174
SupportedTraceItemType.PROFILE_FUNCTIONS: PROFILE_FUNCTIONS_INTERNAL_TO_PUBLIC_ALIAS_MAPPINGS,
75+
SupportedTraceItemType.PREPROD: PREPROD_SIZE_INTERNAL_TO_PUBLIC_ALIAS_MAPPINGS,
7276
}
7377

7478
PUBLIC_ALIAS_TO_INTERNAL_MAPPING: dict[SupportedTraceItemType, dict[str, ResolvedAttribute]] = {

static/app/components/emptyStateWarning.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,33 @@ import styled from '@emotion/styled';
22

33
import {EmptyMessage} from 'sentry/components/emptyMessage';
44
import {IconSearch} from 'sentry/icons';
5+
import type {IconVariant} from 'sentry/icons/svgIcon';
56

67
type Props = {
78
children?: React.ReactNode;
89
className?: string;
910
small?: boolean;
11+
variant?: IconVariant;
1012
withIcon?: boolean;
1113
};
1214

1315
export function EmptyStateWarning({
1416
small = false,
17+
variant = 'muted',
1518
withIcon = true,
1619
children,
1720
className,
1821
}: Props) {
1922
return small ? (
2023
<EmptyMessage className={className}>
2124
<SmallMessage>
22-
{withIcon && <StyledIconSearch variant="muted" size="lg" />}
25+
{withIcon && <StyledIconSearch variant={variant} size="lg" />}
2326
{children}
2427
</SmallMessage>
2528
</EmptyMessage>
2629
) : (
2730
<EmptyStreamWrapper data-test-id="empty-state" className={className}>
28-
{withIcon && <IconSearch variant="muted" legacySize="54px" />}
31+
{withIcon && <IconSearch variant={variant} legacySize="54px" />}
2932
{children}
3033
</EmptyStreamWrapper>
3134
);

static/app/components/events/autofix/preferences/hooks/useBulkAutofixAutomationSettings.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,14 @@ export function useUpdateBulkAutofixAutomationSettings(
124124
},
125125
...options,
126126
onSettled: (...args) => {
127+
const bulkAutofixAutomationSettingsQueryOptions =
128+
bulkAutofixAutomationSettingsInfiniteOptions({
129+
organization,
130+
});
127131
queryClient.invalidateQueries({
128-
queryKey: [
129-
getApiUrl(`/organizations/$organizationIdOrSlug/autofix/automation-settings/`, {
130-
path: {organizationIdOrSlug: organization.slug},
131-
}),
132-
],
132+
queryKey: bulkAutofixAutomationSettingsQueryOptions.queryKey,
133133
});
134+
134135
const [, , data] = args;
135136
data.projectIds.forEach(projectId => {
136137
const project = projectsById.get(projectId);

static/app/components/events/autofix/preferences/hooks/useUpdateProjectSeerPreferences.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
} from 'sentry/utils/queryClient';
1717
import {useOrganization} from 'sentry/utils/useOrganization';
1818

19+
import {bulkAutofixAutomationSettingsInfiniteOptions} from './useBulkAutofixAutomationSettings';
20+
1921
type Context =
2022
| {
2123
previousPrefs: SeerPreferencesResponse;
@@ -86,8 +88,13 @@ export function useUpdateProjectSeerPreferences(project: Project) {
8688
},
8789
onSettled: () => {
8890
queryClient.invalidateQueries({queryKey});
91+
92+
const bulkAutofixAutomationSettingsQueryOptions =
93+
bulkAutofixAutomationSettingsInfiniteOptions({
94+
organization,
95+
});
8996
queryClient.invalidateQueries({
90-
queryKey: [`/organizations/${organization.slug}/autofix/automation-settings/`],
97+
queryKey: bulkAutofixAutomationSettingsQueryOptions.queryKey,
9198
});
9299
},
93100
});

static/app/icons/svgIcon.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import type {ContentVariant, IconSize} from 'sentry/utils/theme';
44

55
import {useIconDefaults} from './useIconDefaults';
66

7+
export type IconVariant = ContentVariant | 'muted';
8+
79
export interface SVGIconProps extends Omit<
810
React.SVGAttributes<SVGSVGElement>,
911
'color' | 'type'
@@ -16,7 +18,7 @@ export interface SVGIconProps extends Omit<
1618
legacySize?: string;
1719
ref?: React.Ref<SVGSVGElement>;
1820
size?: IconSize;
19-
variant?: ContentVariant | 'muted';
21+
variant?: IconVariant;
2022
}
2123

2224
export function SvgIcon(props: SVGIconProps) {

static/app/utils/discover/fieldRenderers.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import {getShortEventId} from 'sentry/utils/events';
5151
import {formatRate} from 'sentry/utils/formatters';
5252
import {getDynamicText} from 'sentry/utils/getDynamicText';
5353
import {formatApdex} from 'sentry/utils/number/formatApdex';
54-
import {formatFloat} from 'sentry/utils/number/formatFloat';
54+
import {formatNumber} from 'sentry/utils/number/formatNumber';
5555
import {formatPercentage} from 'sentry/utils/number/formatPercentage';
5656
import {toPercent} from 'sentry/utils/number/toPercent';
5757
import {generateProfileFlamechartRouteWithQuery} from 'sentry/utils/profiling/routes';
@@ -63,10 +63,7 @@ import {
6363
findLinkedDashboardForField,
6464
getLinkedDashboardUrl,
6565
} from 'sentry/views/dashboards/utils/getLinkedDashboardUrl';
66-
import {
67-
NUMBER_MAX_FRACTION_DIGITS,
68-
NUMBER_MIN_VALUE,
69-
} from 'sentry/views/dashboards/widgets/common/settings';
66+
import {NUMBER_MIN_VALUE} from 'sentry/views/dashboards/widgets/common/settings';
7067
import {formatTooltipValue} from 'sentry/views/dashboards/widgets/timeSeriesWidget/formatters/formatTooltipValue';
7168
import {QuickContextHoverWrapper} from 'sentry/views/discover/table/quickContext/quickContextWrapper';
7269
import {ContextType} from 'sentry/views/discover/table/quickContext/utils';
@@ -319,16 +316,7 @@ export const FIELD_FORMATTERS: FieldFormatters = {
319316
</NumberContainer>
320317
);
321318
}
322-
return (
323-
<NumberContainer>
324-
{formatFloat(data[field], NUMBER_MAX_FRACTION_DIGITS).toLocaleString(
325-
undefined,
326-
{
327-
maximumFractionDigits: NUMBER_MAX_FRACTION_DIGITS,
328-
}
329-
)}
330-
</NumberContainer>
331-
);
319+
return <NumberContainer>{formatNumber(data[field])}</NumberContainer>;
332320
},
333321
},
334322
percentage: {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {formatNumber} from 'sentry/utils/number/formatNumber';
2+
3+
describe('formatNumber()', () => {
4+
it('returns the value with commas when the value has 12 digits', () => {
5+
expect(formatNumber(123_456_789_012)).toBe('123,456,789,012');
6+
});
7+
8+
it('returns the value with commas when the value has 13 digits', () => {
9+
expect(formatNumber(1_234_567_890_123)).toBe('1,234,567,890,123');
10+
});
11+
12+
it('returns the value when the value has 14 digits', () => {
13+
expect(formatNumber(12_345_678_901_234)).toBe(12345678901234);
14+
});
15+
16+
it('returns the value when the value has 15 digits', () => {
17+
expect(formatNumber(123_456_789_012_345)).toBe(123456789012345);
18+
});
19+
20+
it('returns the value when the value does not have digits', () => {
21+
expect(formatNumber(1)).toBe('1');
22+
});
23+
24+
it('returns the value when the value has fewer digits than NUMBER_MAX_FRACTION_DIGITS', () => {
25+
expect(formatNumber(1.2345)).toBe('1.2345');
26+
});
27+
28+
it('returns a truncated value when the value has more digits than NUMBER_MAX_FRACTION_DIGITS', () => {
29+
expect(formatNumber(1.23456)).toBe('1.2345');
30+
});
31+
});

0 commit comments

Comments
 (0)