|
@@ -10,14 +10,22 @@ import {dedupeArray} from 'sentry/utils/dedupeArray';
|
|
|
import {aggregateOutputType} from 'sentry/utils/discover/fields';
|
|
|
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
|
|
|
import usePageFilters from 'sentry/utils/usePageFilters';
|
|
|
+import {formatVersion} from 'sentry/utils/versions/formatVersion';
|
|
|
import {useChartInterval} from 'sentry/views/explore/hooks/useChartInterval';
|
|
|
import {useDataset} from 'sentry/views/explore/hooks/useDataset';
|
|
|
import {useVisualizes} from 'sentry/views/explore/hooks/useVisualizes';
|
|
|
import Chart, {ChartType} from 'sentry/views/insights/common/components/chart';
|
|
|
import ChartPanel from 'sentry/views/insights/common/components/chartPanel';
|
|
|
import {useSpanIndexedSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
|
|
|
+import {useSortedTopNSeries} from 'sentry/views/insights/common/queries/useSortedTopNSeries';
|
|
|
import {CHART_HEIGHT} from 'sentry/views/insights/database/settings';
|
|
|
|
|
|
+import {useGroupBys} from '../hooks/useGroupBys';
|
|
|
+import {useResultMode} from '../hooks/useResultsMode';
|
|
|
+import {useSorts} from '../hooks/useSorts';
|
|
|
+import {TOP_EVENTS_LIMIT, useTopEvents} from '../hooks/useTopEvents';
|
|
|
+import {formatSort} from '../tables/aggregatesTable';
|
|
|
+
|
|
|
interface ExploreChartsProps {
|
|
|
query: string;
|
|
|
}
|
|
@@ -44,6 +52,28 @@ export function ExploreCharts({query}: ExploreChartsProps) {
|
|
|
const [dataset] = useDataset();
|
|
|
const [visualizes, setVisualizes] = useVisualizes();
|
|
|
const [interval, setInterval, intervalOptions] = useChartInterval();
|
|
|
+ const [groupBys] = useGroupBys();
|
|
|
+ const [resultMode] = useResultMode();
|
|
|
+ const topEvents = useTopEvents();
|
|
|
+
|
|
|
+ const fields: string[] = useMemo(() => {
|
|
|
+ if (resultMode === 'samples') {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [...groupBys, ...visualizes.flatMap(visualize => visualize.yAxes)].filter(
|
|
|
+ Boolean
|
|
|
+ );
|
|
|
+ }, [resultMode, groupBys, visualizes]);
|
|
|
+ const [sorts] = useSorts({fields});
|
|
|
+
|
|
|
+ const orderby: string | string[] | undefined = useMemo(() => {
|
|
|
+ if (!sorts.length) {
|
|
|
+ return undefined;
|
|
|
+ }
|
|
|
+
|
|
|
+ return sorts.map(formatSort);
|
|
|
+ }, [sorts]);
|
|
|
|
|
|
const yAxes = useMemo(() => {
|
|
|
const deduped = dedupeArray(visualizes.flatMap(visualize => visualize.yAxes));
|
|
@@ -51,17 +81,42 @@ export function ExploreCharts({query}: ExploreChartsProps) {
|
|
|
return deduped;
|
|
|
}, [visualizes]);
|
|
|
|
|
|
- const series = useSpanIndexedSeries(
|
|
|
+ const singleSeriesResult = useSpanIndexedSeries(
|
|
|
{
|
|
|
search: new MutableSearch(query ?? ''),
|
|
|
yAxis: yAxes,
|
|
|
interval: interval ?? getInterval(pageFilters.selection.datetime, 'metrics'),
|
|
|
- enabled: true,
|
|
|
+ enabled: topEvents === undefined,
|
|
|
},
|
|
|
'api.explorer.stats',
|
|
|
dataset
|
|
|
);
|
|
|
|
|
|
+ const topNSeriesResult = useSortedTopNSeries(
|
|
|
+ {
|
|
|
+ search: new MutableSearch(query ?? ''),
|
|
|
+ yAxis: yAxes,
|
|
|
+ interval: interval ?? getInterval(pageFilters.selection.datetime, 'metrics'),
|
|
|
+ enabled: topEvents !== undefined,
|
|
|
+ fields,
|
|
|
+ orderby,
|
|
|
+ topEvents,
|
|
|
+ },
|
|
|
+ 'api.explorer.stats',
|
|
|
+ dataset
|
|
|
+ );
|
|
|
+
|
|
|
+ const getSeries = useCallback(
|
|
|
+ (dedupedYAxes: string[]) => {
|
|
|
+ if (topEvents !== undefined) {
|
|
|
+ return topNSeriesResult.data;
|
|
|
+ }
|
|
|
+
|
|
|
+ return dedupedYAxes.map(yAxis => singleSeriesResult.data[yAxis]);
|
|
|
+ },
|
|
|
+ [singleSeriesResult, topNSeriesResult, topEvents]
|
|
|
+ );
|
|
|
+
|
|
|
const handleChartTypeChange = useCallback(
|
|
|
(chartType: ChartType, index: number) => {
|
|
|
const newVisualizes = visualizes.slice();
|
|
@@ -71,6 +126,11 @@ export function ExploreCharts({query}: ExploreChartsProps) {
|
|
|
[visualizes, setVisualizes]
|
|
|
);
|
|
|
|
|
|
+ const error =
|
|
|
+ topEvents === undefined ? singleSeriesResult.error : topNSeriesResult.error;
|
|
|
+ const loading =
|
|
|
+ topEvents === undefined ? singleSeriesResult.isPending : topNSeriesResult.isPending;
|
|
|
+
|
|
|
return (
|
|
|
<Fragment>
|
|
|
{visualizes.map((visualize, index) => {
|
|
@@ -108,10 +168,12 @@ export function ExploreCharts({query}: ExploreChartsProps) {
|
|
|
top: '8px',
|
|
|
bottom: '0',
|
|
|
}}
|
|
|
- data={dedupedYAxes.map(yAxis => series.data[yAxis])}
|
|
|
- error={series.error}
|
|
|
- loading={series.isPending}
|
|
|
- chartColors={CHART_PALETTE[2]}
|
|
|
+ legendFormatter={value => formatVersion(value)}
|
|
|
+ data={getSeries(dedupedYAxes)}
|
|
|
+ error={error}
|
|
|
+ loading={loading}
|
|
|
+ // TODO Abdullah: Make chart colors dynamic, with changing topN events count and overlay count.
|
|
|
+ chartColors={CHART_PALETTE[TOP_EVENTS_LIMIT - 1]}
|
|
|
type={chartType}
|
|
|
// for now, use the first y axis unit
|
|
|
aggregateOutputFormat={aggregateOutputType(dedupedYAxes[0])}
|