|
@@ -1,8 +1,14 @@
|
|
|
import {Moment, unix} from 'moment';
|
|
|
|
|
|
-import {EventTransaction} from 'sentry/types';
|
|
|
-import {useDiscoverQuery} from 'sentry/utils/discover/discoverQuery';
|
|
|
+import {EventTransaction, NewQuery} from 'sentry/types';
|
|
|
+import {
|
|
|
+ DiscoverQueryComponentProps,
|
|
|
+ DiscoverQueryPropsWithThresholds,
|
|
|
+ useDiscoverQuery,
|
|
|
+} from 'sentry/utils/discover/discoverQuery';
|
|
|
import EventView from 'sentry/utils/discover/eventView';
|
|
|
+import {useGenericDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery';
|
|
|
+import {DiscoverDatasets} from 'sentry/utils/discover/types';
|
|
|
import {DefinedUseQueryResult, useQuery} from 'sentry/utils/queryClient';
|
|
|
import {useLocation} from 'sentry/utils/useLocation';
|
|
|
import useOrganization from 'sentry/utils/useOrganization';
|
|
@@ -156,40 +162,88 @@ export const useQueryTopDbOperationsChart = (
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-export const useGetTransactionsForTables = (tableNames: string[], interval: number) => {
|
|
|
+type TopTransactionData = {
|
|
|
+ interval: string;
|
|
|
+ transaction: string;
|
|
|
+ epm?: number;
|
|
|
+ p75?: number;
|
|
|
+};
|
|
|
+
|
|
|
+export const useGetTransactionsForTables = (
|
|
|
+ tableNames: string[],
|
|
|
+ interval: number
|
|
|
+): DefinedUseQueryResult<TopTransactionData[]> => {
|
|
|
const pageFilter = usePageFilters();
|
|
|
+ const location = useLocation();
|
|
|
const {startTime, endTime} = getDateFilters(pageFilter);
|
|
|
const dateFilters = getDateQueryFilter(startTime, endTime);
|
|
|
- const transactionFilter = `transaction IN (${getTransactionsFromTableSubquery(
|
|
|
- tableNames,
|
|
|
- dateFilters
|
|
|
- )})`;
|
|
|
-
|
|
|
- const filters = [transactionFilter];
|
|
|
|
|
|
- const query = `
|
|
|
- SELECT
|
|
|
- transaction,
|
|
|
- floor(quantile(0.75)(exclusive_time), 5) as p75,
|
|
|
- count() as count,
|
|
|
- toStartOfInterval(start_timestamp, INTERVAL ${interval} hour) as interval
|
|
|
- FROM default.spans_experimental_starfish
|
|
|
- WHERE
|
|
|
- ${filters.join(' AND ')}
|
|
|
- ${dateFilters}
|
|
|
- GROUP BY interval, transaction
|
|
|
- ORDER BY interval
|
|
|
- `;
|
|
|
+ const transactionNameQuery = getTransactionsFromTableSubquery(tableNames, dateFilters);
|
|
|
|
|
|
- const {start, end} = pageFilter.selection.datetime;
|
|
|
+ const {start, end, period} = pageFilter.selection.datetime;
|
|
|
|
|
|
- return useQuery({
|
|
|
+ const result1 = useQuery<{transaction: string}[]>({
|
|
|
enabled: !!tableNames?.length,
|
|
|
- queryKey: ['topTable', tableNames.join(','), start, end],
|
|
|
- queryFn: () => fetch(`${HOST}/?query=${query}`).then(res => res.json()),
|
|
|
+ queryKey: ['topTransactionNames', tableNames.join(','), start, end],
|
|
|
+ queryFn: () =>
|
|
|
+ fetch(`${HOST}/?query=${transactionNameQuery}`).then(res => res.json()),
|
|
|
retry: false,
|
|
|
initialData: [],
|
|
|
});
|
|
|
+
|
|
|
+ const query: NewQuery = {
|
|
|
+ id: undefined,
|
|
|
+ name: 'Db module - epm/p75 for top transactions',
|
|
|
+ query: `transaction:[${result1.data?.map(d => d.transaction).join(',')}]`,
|
|
|
+ projects: [1],
|
|
|
+ fields: ['transaction', 'epm()', 'p75(transaction.duration)'],
|
|
|
+ version: 1,
|
|
|
+ topEvents: '5',
|
|
|
+ start: start?.toString(),
|
|
|
+ end: end?.toString(),
|
|
|
+ dataset: DiscoverDatasets.METRICS_ENHANCED,
|
|
|
+ interval: `${interval}h`,
|
|
|
+ yAxis: ['epm()', 'p75(transaction.duration)'],
|
|
|
+ };
|
|
|
+
|
|
|
+ const eventView = EventView.fromNewQueryWithLocation(query, location);
|
|
|
+ eventView.statsPeriod = period ?? undefined;
|
|
|
+
|
|
|
+ const result2 = useDiscoverEventsStatsQuery({
|
|
|
+ eventView,
|
|
|
+ referrer: 'api.starfish.database.charts',
|
|
|
+ location,
|
|
|
+ orgSlug: 'sentry',
|
|
|
+ queryExtras: {
|
|
|
+ interval: `${interval}h`, // This interval isn't being propogated from eventView
|
|
|
+ yAxis: ['epm()', 'p75(transaction.duration)'], // workaround - eventView actually doesn't support multiple yAxis
|
|
|
+ excludeOther: '1',
|
|
|
+ topEvents: '5',
|
|
|
+ per_page: undefined,
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const data: TopTransactionData[] = [];
|
|
|
+ if (!result2.isLoading && result2.data) {
|
|
|
+ Object.entries(result2.data).forEach(([transactionName, result]: [string, any]) => {
|
|
|
+ result['epm()'].data.forEach(entry => {
|
|
|
+ data.push({
|
|
|
+ transaction: transactionName,
|
|
|
+ interval: unix(entry[0]).format('YYYY-MM-DDTHH:mm:ss'),
|
|
|
+ epm: entry[1][0].count,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ result['p75(transaction.duration)'].data.forEach(entry => {
|
|
|
+ data.push({
|
|
|
+ transaction: transactionName,
|
|
|
+ interval: unix(entry[0]).format('YYYY-MM-DDTHH:mm:ss'),
|
|
|
+ p75: entry[1][0].count,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return {...result2, data} as DefinedUseQueryResult<TopTransactionData[]>;
|
|
|
};
|
|
|
|
|
|
type TopTableQuery = {
|
|
@@ -558,3 +612,34 @@ export const getDateQueryFilter = (startTime: Moment, endTime: Moment) => {
|
|
|
${end_timestamp ? `AND lessOrEquals(start_timestamp, '${end_timestamp}')` : ''}
|
|
|
`;
|
|
|
};
|
|
|
+
|
|
|
+const shouldRefetchData = (
|
|
|
+ prevProps: DiscoverQueryPropsWithThresholds,
|
|
|
+ nextProps: DiscoverQueryPropsWithThresholds
|
|
|
+) => {
|
|
|
+ return (
|
|
|
+ prevProps.transactionName !== nextProps.transactionName ||
|
|
|
+ prevProps.transactionThreshold !== nextProps.transactionThreshold ||
|
|
|
+ prevProps.transactionThresholdMetric !== nextProps.transactionThresholdMetric
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+// We should find a way to use this in discover
|
|
|
+export function useDiscoverEventsStatsQuery(
|
|
|
+ props: Omit<DiscoverQueryComponentProps, 'children'>
|
|
|
+) {
|
|
|
+ const afterFetch = (data, _) => {
|
|
|
+ const {fields, ...otherMeta} = data.meta ?? {};
|
|
|
+ return {
|
|
|
+ ...data,
|
|
|
+ meta: {...fields, ...otherMeta},
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ return useGenericDiscoverQuery({
|
|
|
+ route: 'events-stats',
|
|
|
+ shouldRefetchData,
|
|
|
+ afterFetch,
|
|
|
+ ...props,
|
|
|
+ });
|
|
|
+}
|