Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,12 @@ export function EAPSpanSearchQueryBuilder({
SPANS_FILTER_KEY_SECTIONS.flatMap(section => section.children)
);
return [
...SPANS_FILTER_KEY_SECTIONS,
...SPANS_FILTER_KEY_SECTIONS.map(section => {
return {
...section,
children: section.children.filter(key => stringTags.hasOwnProperty(key)),
};
}),
{
value: 'custom_fields',
label: 'Custom Tags',
Expand Down
12 changes: 0 additions & 12 deletions static/app/utils/discover/fieldRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ type SpecialFields = {
replayId: SpecialField;
'span.description': SpecialField;
'span.status_code': SpecialField;
span_id: SpecialField;
team_key_transaction: SpecialField;
'timestamp.to_day': SpecialField;
'timestamp.to_hour': SpecialField;
Expand Down Expand Up @@ -482,17 +481,6 @@ const SPECIAL_FIELDS: SpecialFields = {
return <Container>{getShortEventId(id)}</Container>;
},
},
span_id: {
sortField: 'span_id',
renderFunc: data => {
const spanId: string | unknown = data?.span_id;
if (typeof spanId !== 'string') {
return null;
}

return <Container>{getShortEventId(spanId)}</Container>;
},
},
'span.description': {
sortField: 'span.description',
renderFunc: data => {
Expand Down
14 changes: 8 additions & 6 deletions static/app/utils/discover/fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1639,12 +1639,14 @@ export const COMBINED_DATASET_FILTER_KEY_SECTIONS: FilterKeySection[] = [
// will take in a project platform key, and output only the relevant filter key sections.
// This way, users will not be suggested mobile fields for a backend transaction, for example.

export const TYPED_TAG_KEY_RE = /tags\[(.*),(.*)\]/;
export const TYPED_TAG_KEY_RE = /tags\[([^\s]*),([^\s]*)\]/;

export function formatParsedFunction(func: ParsedFunction) {
const args = func.arguments.map(arg => {
const result = arg.match(TYPED_TAG_KEY_RE);
return result?.[1] ?? arg;
});
export function prettifyTagKey(key: string): string {
const result = key.match(TYPED_TAG_KEY_RE);
return result?.[1] ?? key;
}

export function prettifyParsedFunction(func: ParsedFunction) {
const args = func.arguments.map(prettifyTagKey);
return `${func.name}(${args.join(',')})`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2608,7 +2608,7 @@ describe('WidgetBuilder', function () {
body: [
{
key: 'plan',
name: 'Plan',
name: 'plan',
},
],
match: [
Expand All @@ -2621,12 +2621,12 @@ describe('WidgetBuilder', function () {
url: `/organizations/org-slug/spans/fields/`,
body: [
{
key: 'lcp.size',
name: 'Lcp.Size',
key: 'tags[lcp.size,number]',
name: 'lcp.size',
},
{
key: 'something.else',
name: 'Something.Else',
key: 'tags[something.else,number]',
name: 'something.else',
},
],
match: [
Expand Down
4 changes: 2 additions & 2 deletions static/app/views/explore/charts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {space} from 'sentry/styles/space';
import {dedupeArray} from 'sentry/utils/dedupeArray';
import {
aggregateOutputType,
formatParsedFunction,
parseFunction,
prettifyParsedFunction,
} from 'sentry/utils/discover/fields';
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
import useOrganization from 'sentry/utils/useOrganization';
Expand Down Expand Up @@ -172,7 +172,7 @@ export function ExploreCharts({query, setError}: ExploreChartsProps) {

const formattedYAxes = dedupedYAxes.map(yaxis => {
const func = parseFunction(yaxis);
return func ? formatParsedFunction(func) : undefined;
return func ? prettifyParsedFunction(func) : undefined;
});

const {chartType, label, yAxes: visualizeYAxes} = visualize;
Expand Down
131 changes: 84 additions & 47 deletions static/app/views/explore/contexts/spanTagsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ import {useApiQuery} from 'sentry/utils/queryClient';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import {SpanIndexedField} from 'sentry/views/insights/types';
import {
useSpanFieldStaticTags,
useSpanFieldSupportedTags,
} from 'sentry/views/performance/utils/useSpanFieldSupportedTags';
import {useSpanFieldCustomTags} from 'sentry/views/performance/utils/useSpanFieldSupportedTags';

type TypedSpanTags = {
number: TagCollection;
Expand All @@ -27,22 +24,9 @@ interface SpanTagsProviderProps {
}

export function SpanTagsProvider({children, dataset}: SpanTagsProviderProps) {
const numericSpanFields: Set<string> = useMemo(() => {
return new Set([
SpanIndexedField.SPAN_DURATION,
SpanIndexedField.SPAN_SELF_TIME,
SpanIndexedField.INP,
SpanIndexedField.INP_SCORE,
SpanIndexedField.INP_SCORE_WEIGHT,
SpanIndexedField.TOTAL_SCORE,
SpanIndexedField.CACHE_ITEM_SIZE,
SpanIndexedField.MESSAGING_MESSAGE_BODY_SIZE,
SpanIndexedField.MESSAGING_MESSAGE_RECEIVE_LATENCY,
SpanIndexedField.MESSAGING_MESSAGE_RETRY_COUNT,
]);
}, []);

const supportedTags = useSpanFieldSupportedTags();
const {data: indexedTags} = useSpanFieldCustomTags({
enabled: dataset === DiscoverDatasets.SPANS_INDEXED,
});

const numberTags: TagCollection = useTypedSpanTags({
enabled: dataset === DiscoverDatasets.SPANS_EAP,
Expand All @@ -54,42 +38,92 @@ export function SpanTagsProvider({children, dataset}: SpanTagsProviderProps) {
type: 'string',
});

const staticTags = useSpanFieldStaticTags();

const allNumberTags = useMemo(() => {
const measurements = [
SpanIndexedField.SPAN_DURATION,
SpanIndexedField.SPAN_SELF_TIME,
].map(measurement => [
measurement,
{
key: measurement,
name: measurement,
kind: FieldKind.MEASUREMENT,
},
]);

if (dataset === DiscoverDatasets.SPANS_INDEXED) {
return {};
return {
...Object.fromEntries(measurements),
};
}

return {
...numberTags,
...Object.fromEntries(
Object.entries(staticTags)
.filter(([key, _]) => numericSpanFields.has(key))
.map(([key, tag]) => [key, {...tag, kind: FieldKind.MEASUREMENT}])
),
...Object.fromEntries(measurements),
};
}, [dataset, numberTags, numericSpanFields, staticTags]);
}, [dataset, numberTags]);

const allStringTags = useMemo(() => {
const tags = [
// NOTE: intentionally choose to not expose transaction id
// as we're moving toward span ids

'id', // SpanIndexedField.SPAN_OP is actually `span_id`
SpanIndexedField.BROWSER_NAME,
SpanIndexedField.ENVIRONMENT,
SpanIndexedField.ORIGIN_TRANSACTION,
SpanIndexedField.PROJECT,
SpanIndexedField.RAW_DOMAIN,
SpanIndexedField.RELEASE,
SpanIndexedField.SDK_NAME,
SpanIndexedField.SDK_VERSION,
SpanIndexedField.SPAN_ACTION,
SpanIndexedField.SPAN_CATEGORY,
SpanIndexedField.SPAN_DESCRIPTION,
SpanIndexedField.SPAN_DOMAIN,
SpanIndexedField.SPAN_GROUP,
SpanIndexedField.SPAN_MODULE,
SpanIndexedField.SPAN_OP,
SpanIndexedField.SPAN_STATUS,
SpanIndexedField.TIMESTAMP,
SpanIndexedField.TRACE,
SpanIndexedField.TRANSACTION,
SpanIndexedField.TRANSACTION_METHOD,
SpanIndexedField.TRANSACTION_OP,
SpanIndexedField.USER,
SpanIndexedField.USER_EMAIL,
SpanIndexedField.USER_GEO_SUBREGION,
SpanIndexedField.USER_ID,
SpanIndexedField.USER_IP,
SpanIndexedField.USER_USERNAME,
].map(tag => [
tag,
{
key: tag,
name: tag,
kind: FieldKind.TAG,
},
]);

if (dataset === DiscoverDatasets.SPANS_INDEXED) {
return supportedTags.data;
return {
...indexedTags,
...Object.fromEntries(tags),
};
}

return {
...stringTags,
...Object.fromEntries(
Object.entries(staticTags)
.filter(([key, _]) => !numericSpanFields.has(key))
.map(([key, tag]) => [key, {...tag, kind: FieldKind.TAG}])
),
...Object.fromEntries(tags),
};
}, [dataset, supportedTags, stringTags, staticTags, numericSpanFields]);
}, [dataset, indexedTags, stringTags]);

const tags = {
number: allNumberTags,
string: allStringTags,
};
const tags = useMemo(() => {
return {
number: allNumberTags,
string: allStringTags,
};
}, [allNumberTags, allStringTags]);

return <SpanTagsContext.Provider value={tags}>{children}</SpanTagsContext.Provider>;
}
Expand Down Expand Up @@ -131,6 +165,7 @@ function useTypedSpanTags({
environment: selection.environments,
...normalizeDateTimeParams(selection.datetime),
dataset: 'spans',
process: 1,
type,
},
};
Expand All @@ -149,20 +184,22 @@ function useTypedSpanTags({
// For now, skip all the sentry. prefixed tags as they
// should be covered by the static tags that will be
// merged with these results.
if (tag.key.startsWith('sentry.')) {
if (tag.key.startsWith('sentry.') || tag.key.startsWith('tags[sentry.')) {
continue;
}

// EAP spans contain tags with illegal characters
if (!/^[a-zA-Z0-9_.:-]+$/.test(tag.key)) {
// SnQL forbids `-` but is allowed in RPC. So add it back later
if (
!/^[a-zA-Z0-9_.:]+$/.test(tag.key) &&
!/^tags\[[a-zA-Z0-9_.:]+,number\]$/.test(tag.key)
) {
continue;
}

const key = type === 'number' ? `tags[${tag.key},number]` : tag.key;

allTags[key] = {
key,
name: tag.key,
allTags[tag.key] = {
key: tag.key,
name: tag.name,
kind: type === 'number' ? FieldKind.MEASUREMENT : FieldKind.TAG,
};
}
Expand Down
4 changes: 2 additions & 2 deletions static/app/views/explore/hooks/useResultsMode.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('useResultMode', function () {

expect(resultMode).toEqual('samples'); // default
expect(sampleFields).toEqual([
'span_id',
'id',
'project',
'span.op',
'span.description',
Expand All @@ -56,7 +56,7 @@ describe('useResultMode', function () {
expect(resultMode).toEqual('samples');

expect(sampleFields).toEqual([
'span_id',
'id',
'project',
'span.op',
'span.description',
Expand Down
4 changes: 2 additions & 2 deletions static/app/views/explore/hooks/useSampleFields.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('useSampleFields', function () {
render(<TestPage />, {disableRouterMocks: true});

expect(sampleFields).toEqual([
'span_id',
'id',
'project',
'span.op',
'span.description',
Expand All @@ -27,7 +27,7 @@ describe('useSampleFields', function () {

act(() => setSampleFields([]));
expect(sampleFields).toEqual([
'span_id',
'id',
'project',
'span.op',
'span.description',
Expand Down
9 changes: 1 addition & 8 deletions static/app/views/explore/hooks/useSampleFields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,7 @@ function useSampleFieldsImpl({
return fields;
}

return [
'span_id',
'project',
'span.op',
'span.description',
'span.duration',
'timestamp',
];
return ['id', 'project', 'span.op', 'span.description', 'span.duration', 'timestamp'];
}, [location.query.field]);

const setSampleFields = useCallback(
Expand Down
4 changes: 2 additions & 2 deletions static/app/views/explore/tables/aggregatesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import EventView from 'sentry/utils/discover/eventView';
import type {Sort} from 'sentry/utils/discover/fields';
import {
fieldAlignment,
formatParsedFunction,
getAggregateAlias,
parseFunction,
prettifyParsedFunction,
} from 'sentry/utils/discover/fields';
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
import useOrganization from 'sentry/utils/useOrganization';
Expand Down Expand Up @@ -147,7 +147,7 @@ export function AggregatesTable({setError}: AggregatesTableProps) {

const func = parseFunction(field);
if (func) {
label = formatParsedFunction(func);
label = prettifyParsedFunction(func);
}

const direction = sorts.find(s => s.field === field)?.kind;
Expand Down
Loading
Loading