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 @@ -2,10 +2,10 @@ import {Fragment, useMemo} from 'react';

import {CompactSelect} from '@sentry/scraps/compactSelect';

import {useCaseInsensitivity} from 'sentry/components/searchQueryBuilder/hooks';
import {IconClock} from 'sentry/icons/iconClock';
import {IconGraph} from 'sentry/icons/iconGraph';
import {t} from 'sentry/locale';
import {useFetchSpanTimeSeries} from 'sentry/utils/timeSeries/useFetchEventsTimeSeries';
import type {TimeSeries} from 'sentry/views/dashboards/widgets/common/types';
import {Area} from 'sentry/views/dashboards/widgets/timeSeriesWidget/plottables/area';
import {Bars} from 'sentry/views/dashboards/widgets/timeSeriesWidget/plottables/bars';
Expand All @@ -14,18 +14,16 @@ import type {Plottable} from 'sentry/views/dashboards/widgets/timeSeriesWidget/p
import {TimeSeriesWidgetVisualization} from 'sentry/views/dashboards/widgets/timeSeriesWidget/timeSeriesWidgetVisualization';
import {Widget} from 'sentry/views/dashboards/widgets/widget/widget';
import {useChartInterval} from 'sentry/views/explore/hooks/useChartInterval';
import {useExploreTimeseries} from 'sentry/views/explore/hooks/useExploreTimeseries';
import {
useQueryParamsGroupBys,
useQueryParamsVisualizes,
useSetQueryParamsVisualizes,
} from 'sentry/views/explore/queryParams/context';
import type {Visualize} from 'sentry/views/explore/queryParams/visualize';
import {useCombinedQuery} from 'sentry/views/insights/agents/hooks/useCombinedQuery';
import {AI_GENERATIONS_PAGE_FILTER} from 'sentry/views/insights/aiGenerations/views/utils/constants';
import {Referrer} from 'sentry/views/insights/aiGenerations/views/utils/referrer';
import {ChartType} from 'sentry/views/insights/common/components/chart';
import {WidgetVisualizationStates} from 'sentry/views/insights/pages/platform/laravel/widgetVisualizationStates';
import type {SpanFields} from 'sentry/views/insights/types';

const CHART_TYPE_OPTIONS = [
{
Expand Down Expand Up @@ -67,6 +65,15 @@ function prettifyAggregation(aggregation: string): string {
export function GenerationsChart() {
const visualizes = useQueryParamsVisualizes();
const setVisualizes = useSetQueryParamsVisualizes();
const [caseInsensitive] = useCaseInsensitivity();

const {result: timeseriesResult} = useExploreTimeseries({
query: useCombinedQuery(AI_GENERATIONS_PAGE_FILTER),
enabled: true,
queryExtras: {
caseInsensitive,
},
});

function handleChartTypeChange(index: number, chartType: ChartType) {
const newVisualizes = visualizes.map((visualize, i) => {
Expand All @@ -86,6 +93,7 @@ export function GenerationsChart() {
key={index}
visualize={visualize}
onChartTypeChange={chartType => handleChartTypeChange(index, chartType)}
timeseriesResult={timeseriesResult}
/>
);
})}
Expand All @@ -96,40 +104,19 @@ export function GenerationsChart() {
function ChartWidget({
visualize,
onChartTypeChange,
timeseriesResult,
}: {
onChartTypeChange: (chartType: ChartType) => void;
timeseriesResult: ReturnType<typeof useExploreTimeseries>['result'];
visualize: Visualize;
}) {
const groupBys = useQueryParamsGroupBys().filter(Boolean);
const [interval, setInterval, intervalOptions] = useChartInterval();
const chartType = visualize.chartType;

const query = useCombinedQuery(AI_GENERATIONS_PAGE_FILTER);
const {data, isLoading, error} = useFetchSpanTimeSeries(
{
query,
yAxis: [visualize.yAxis] as any,
groupBy: groupBys as SpanFields[],
interval,
sort:
groupBys.length > 0 && groupBys[0]
? {
field: groupBys[0],
kind: 'desc' as const,
}
: undefined,
topEvents: groupBys.length > 0 ? 5 : undefined,
},
Referrer.GENERATIONS_CHART
);

const plottables = useMemo(() => {
return (
data?.timeSeries.map(
timeSeries => new plottableConstructors[chartType](timeSeries)
) ?? []
);
}, [chartType, data?.timeSeries]);
const timeSeries = timeseriesResult.data[visualize.yAxis] ?? [];
return timeSeries.map(series => new plottableConstructors[chartType](series)) ?? [];
}, [chartType, timeseriesResult.data, visualize.yAxis]);

const isEmpty = useMemo(
() => plottables.every(plottable => plottable.isEmpty),
Expand Down Expand Up @@ -170,8 +157,8 @@ function ChartWidget({
revealActions="always"
Visualization={
<WidgetVisualizationStates
isLoading={isLoading}
error={error}
isLoading={timeseriesResult.isLoading}
error={timeseriesResult.error}
isEmpty={isEmpty}
VisualizationType={TimeSeriesWidgetVisualization}
visualizationProps={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ import {Container, Grid} from '@sentry/scraps/layout';
import {Text} from '@sentry/scraps/text';
import {Tooltip} from '@sentry/scraps/tooltip';

import {useCaseInsensitivity} from 'sentry/components/searchQueryBuilder/hooks';
import {
COL_WIDTH_UNDEFINED,
type GridColumnOrder,
} from 'sentry/components/tables/gridEditable';
import TimeSince from 'sentry/components/timeSince';
import {t} from 'sentry/locale';
import type {NewQuery} from 'sentry/types/organization';
import {getTimeStampFromTableDateField} from 'sentry/utils/dates';
import EventView from 'sentry/utils/discover/eventView';
import {getFieldRenderer} from 'sentry/utils/discover/fieldRenderers';
import type {Sort} from 'sentry/utils/discover/fields';
import {DiscoverDatasets} from 'sentry/utils/discover/types';
import {getShortEventId} from 'sentry/utils/events';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import {useTraceViewDrawer} from 'sentry/views/insights/agents/components/drawer';
import {
HeadSortCell,
Expand All @@ -34,7 +39,7 @@ import {
import {Referrer} from 'sentry/views/insights/aiGenerations/views/utils/referrer';
import {useFieldsQueryParam} from 'sentry/views/insights/aiGenerations/views/utils/useFieldsQueryParam';
import {TextAlignRight} from 'sentry/views/insights/common/components/textAlign';
import {useSpans} from 'sentry/views/insights/common/queries/useDiscover';
import {useSpansQuery} from 'sentry/views/insights/common/queries/useSpansQuery';
import {PlatformInsightsTable} from 'sentry/views/insights/pages/platform/shared/table';
import {SpanFields} from 'sentry/views/insights/types';

Expand Down Expand Up @@ -87,6 +92,8 @@ export function GenerationsTable() {
const location = useLocation();
const organization = useOrganization();
const theme = useTheme();
const {selection} = usePageFilters();
const [caseInsensitive] = useCaseInsensitivity();

const fieldsToQuery = useMemo(() => {
return [
Expand All @@ -97,36 +104,58 @@ export function GenerationsTable() {
];
}, [fields]);

const {data, meta, isLoading, error, pageLinks, isPlaceholderData} = useSpans(
{
search: query,
fields: [...REQUIRED_FIELDS, ...fieldsToQuery] as any,
cursor,
sorts: [tableSort],
keepPreviousData: true,
limit: 20,
},
Referrer.GENERATIONS_TABLE
);
const eventView = useMemo(() => {
const queryFields = [...REQUIRED_FIELDS, ...fieldsToQuery];

const discoverQuery: NewQuery = {
id: undefined,
name: 'AI Generations',
fields: queryFields,
orderby: [`${tableSort.kind === 'desc' ? '-' : ''}${tableSort.field}`],
query,
version: 2,
dataset: DiscoverDatasets.SPANS,
};

return EventView.fromNewQueryWithPageFilters(discoverQuery, selection);
}, [fieldsToQuery, query, selection, tableSort.field, tableSort.kind]);

const {
data = [],
meta,
isLoading,
error,
pageLinks,
isPlaceholderData,
} = useSpansQuery<Array<Record<string, any>>>({
eventView,
cursor,
limit: 20,
referrer: Referrer.GENERATIONS_TABLE,
initialData: [],
allowAggregateConditions: false,
trackResponseAnalytics: false,
queryExtras: {caseInsensitive},
});

type TableData = (typeof data)[number];
type TableData = Record<string, any>;

const renderBodyCell = useCallback(
(column: GridColumnOrder<GenerationFields>, dataRow: TableData) => {
(column: GridColumnOrder<string>, dataRow: TableData) => {
if (column.key === SpanFields.ID) {
return (
<div>
<Button
priority="link"
onClick={() => {
openTraceViewDrawer(
dataRow.trace!,
dataRow.trace,
dataRow.id,
getTimeStampFromTableDateField(dataRow.timestamp)
);
}}
>
{getShortEventId(dataRow.id!)}
{getShortEventId(dataRow.id)}
</Button>
</div>
);
Expand Down Expand Up @@ -196,7 +225,7 @@ export function GenerationsTable() {
if (column.key === SpanFields.TIMESTAMP) {
return (
<TextAlignRight>
<TimeSince unitStyle="short" date={new Date(dataRow.timestamp!)} />
<TimeSince unitStyle="short" date={new Date(dataRow.timestamp)} />
</TextAlignRight>
);
}
Expand All @@ -212,7 +241,7 @@ export function GenerationsTable() {
);

const renderHeadCell = useCallback(
(column: GridColumnOrder<keyof TableData>) => {
(column: GridColumnOrder<string>) => {
return (
<HeadSortCell
align={column.key === SpanFields.TIMESTAMP ? 'right' : 'left'}
Expand All @@ -236,7 +265,7 @@ export function GenerationsTable() {
isLoading={isLoading}
error={error}
initialColumnOrder={fields.map(
(field): GridColumnOrder<GenerationFields> => ({
(field): GridColumnOrder<string> => ({
key: field,
name: prettyFieldNames[field] ?? field,
width: columnWidths[field] ?? COL_WIDTH_UNDEFINED,
Expand Down
6 changes: 6 additions & 0 deletions static/app/views/insights/aiGenerations/views/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
useEAPSpanSearchQueryBuilderProps,
} from 'sentry/components/performance/spanSearchQueryBuilder';
import {SearchQueryBuilderProvider} from 'sentry/components/searchQueryBuilder/context';
import {useCaseInsensitivity} from 'sentry/components/searchQueryBuilder/hooks';
import {IconChevron, IconEdit} from 'sentry/icons';
import {t} from 'sentry/locale';
import {getSelectedProjectList} from 'sentry/utils/project/useSelectedProjectsHaveField';
Expand Down Expand Up @@ -58,6 +59,7 @@ function AIGenerationsPage() {
const [sidebarOpen, setSidebarOpen] = useState(true);
const showOnboarding = useShowOnboarding();
const datePageFilterProps = limitMaxPickableDays(organization);
const [caseInsensitive, setCaseInsensitive] = useCaseInsensitivity();

const [searchQuery, setSearchQuery] = useQueryState(
'query',
Expand Down Expand Up @@ -93,12 +95,16 @@ function AIGenerationsPage() {
{key: 'trace', valuePattern: /^[0-9a-fA-F]{32}$/},
{key: 'id', valuePattern: /^[0-9a-fA-F]{16}$/},
],
caseInsensitive,
onCaseInsensitiveClick: setCaseInsensitive,
}),
[
caseInsensitive,
hasRawSearchReplacement,
numberSecondaryAliases,
numberTags,
searchQuery,
setCaseInsensitive,
setSearchQuery,
stringSecondaryAliases,
stringTags,
Expand Down
Loading