From 353a3d829f71b4fad3a5e8420e1e6ddf1e581208 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Tue, 22 Apr 2025 15:44:26 -0400 Subject: [PATCH 1/8] ref(insights): Refactor Insights -> LLM charts Refactors the Insights -> LLM charts to better support deep linking in a future PR. Notable in this PR is the introduction of a `chartProperties` prop for `LoadableChartWidgetProps`. These are to be used as URL query params when linking to the Releases Drawer, but also used to render the chart as well. They are chart-specific, which is the reason for the additional level of object nesting. Part of https://github.com/getsentry/sentry/issues/88560 --- .../llm-monitoring/llmMonitoringSection.tsx | 12 +-- .../components/insightsTimeSeriesWidget.tsx | 3 +- .../llmNumberOfPipelinesChartWidget.tsx | 39 +++++++ .../llmPipelineDurationChartWidget.tsx | 39 +++++++ .../widgets/llmTotalTokensUsedChartWidget.tsx | 39 +++++++ .../common/components/widgets/types.tsx | 14 ++- .../components/charts/llmMonitoringCharts.tsx | 102 ------------------ .../views/llmMonitoringDetailsPage.tsx | 14 ++- .../views/llmMonitoringLandingPage.tsx | 14 ++- 9 files changed, 149 insertions(+), 127 deletions(-) create mode 100644 static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx create mode 100644 static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx create mode 100644 static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx delete mode 100644 static/app/views/insights/llmMonitoring/components/charts/llmMonitoringCharts.tsx diff --git a/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx b/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx index 69463f104a83b0..f7b2517bf26147 100644 --- a/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx +++ b/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx @@ -5,12 +5,10 @@ import {t} from 'sentry/locale'; import type {Event} from 'sentry/types/event'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout'; +import LlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget'; +import LlmTotalTokensUsedChart from 'sentry/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget'; import {useSpansIndexed} from 'sentry/views/insights/common/queries/useDiscover'; import {useModuleURL} from 'sentry/views/insights/common/utils/useModuleURL'; -import { - NumberOfPipelinesChart, - TotalTokensUsedChart, -} from 'sentry/views/insights/llmMonitoring/components/charts/llmMonitoringCharts'; import {SpanIndexedField} from 'sentry/views/insights/types'; import {SectionKey} from 'sentry/views/issueDetails/streamline/context'; import {InterimSection} from 'sentry/views/issueDetails/streamline/interimSection'; @@ -53,10 +51,12 @@ export default function LLMMonitoringSection({event}: Props) { {aiPipelineGroup ? ( - + - + ) : ( diff --git a/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx b/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx index 4c36bd06e83791..dfc68493a5f0d2 100644 --- a/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx +++ b/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx @@ -36,7 +36,8 @@ import {INGESTION_DELAY} from 'sentry/views/insights/settings'; export interface InsightsTimeSeriesWidgetProps extends WidgetTitleProps, - LoadableChartWidgetProps { + Omit, + Partial> { error: Error | null; isLoading: boolean; series: DiscoverSeries[]; diff --git a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx new file mode 100644 index 00000000000000..96bc1bf571c9d6 --- /dev/null +++ b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx @@ -0,0 +1,39 @@ +import {useTheme} from '@emotion/react'; + +import {t} from 'sentry/locale'; +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; + +export default function LlmNumberOfPipelinesChartWidget( + props: LoadableChartWidgetProps<{groupId?: string}> +) { + const theme = useTheme(); + const aggregate = 'count()'; + + let query = 'span.category:"ai.pipeline"'; + if (props.chartProperties?.groupId) { + query = `${query} span.group:"${props.chartProperties?.groupId}"`; + } + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view' + ); + + const colors = theme.chart.getColorPalette(2); + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx new file mode 100644 index 00000000000000..ce753daba90834 --- /dev/null +++ b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx @@ -0,0 +1,39 @@ +import {useTheme} from '@emotion/react'; + +import {t} from 'sentry/locale'; +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; + +export default function LlmPipelineDurationChartWidget( + props: LoadableChartWidgetProps<{groupId?: string}> +) { + const theme = useTheme(); + const aggregate = 'avg(span.duration)'; + + let query = 'span.category:"ai.pipeline"'; + if (props.chartProperties?.groupId) { + query = `${query} span.group:"${props.chartProperties?.groupId}"`; + } + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view' + ); + + const colors = theme.chart.getColorPalette(2); + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx new file mode 100644 index 00000000000000..d5c8cf25ac083d --- /dev/null +++ b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx @@ -0,0 +1,39 @@ +import {useTheme} from '@emotion/react'; + +import {t} from 'sentry/locale'; +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; + +export default function LlmTotalTokensUsedChartWidget( + props: LoadableChartWidgetProps<{groupId?: string}> +) { + const theme = useTheme(); + const aggregate = 'sum(ai.total_tokens.used)'; + + let query = 'span.category:"ai"'; + if (props.chartProperties?.groupId) { + query = `${query} span.ai.pipeline.group:"${props.chartProperties.groupId}"`; + } + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view' + ); + + const colors = theme.chart.getColorPalette(2); + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/types.tsx b/static/app/views/insights/common/components/widgets/types.tsx index 5f9ec743a372f3..828658e092c986 100644 --- a/static/app/views/insights/common/components/widgets/types.tsx +++ b/static/app/views/insights/common/components/widgets/types.tsx @@ -4,10 +4,20 @@ import type {PageFilters} from 'sentry/types/core'; * These props are common across components that are required to dynamically * render an Insight Chart Widget */ -export interface LoadableChartWidgetProps { - // TODO(billy): This should be required when all chart widgets are converted +export interface LoadableChartWidgetProps | undefined> { + /** + * Additional chart-specific properties that are required to render the + * chart. `chartProperties` should be of type Record as it + * will be appended to the URL as query parameters so that the chart can be + * linked. + */ + + chartProperties?: T; + /** * Unique ID for the widget + * + * TODO(billy): This should be required when all chart widgets are converted */ id?: string; diff --git a/static/app/views/insights/llmMonitoring/components/charts/llmMonitoringCharts.tsx b/static/app/views/insights/llmMonitoring/components/charts/llmMonitoringCharts.tsx deleted file mode 100644 index 76c111e09cc8a0..00000000000000 --- a/static/app/views/insights/llmMonitoring/components/charts/llmMonitoringCharts.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import {useTheme} from '@emotion/react'; - -import {t} from 'sentry/locale'; -import {MutableSearch} from 'sentry/utils/tokenizeSearch'; -import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; -import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; - -interface TotalTokensUsedChartProps { - groupId?: string; -} - -export function TotalTokensUsedChart({groupId}: TotalTokensUsedChartProps) { - const theme = useTheme(); - const aggregate = 'sum(ai.total_tokens.used)'; - - let query = 'span.category:"ai"'; - if (groupId) { - query = `${query} span.ai.pipeline.group:"${groupId}"`; - } - const {data, isPending, error} = useSpanMetricsSeries( - { - yAxis: [aggregate], - search: new MutableSearch(query), - transformAliasToInputFormat: true, - }, - 'api.ai-pipelines.view' - ); - - const colors = theme.chart.getColorPalette(2); - return ( - - ); -} - -interface NumberOfPipelinesChartProps { - groupId?: string; -} - -export function NumberOfPipelinesChart({groupId}: NumberOfPipelinesChartProps) { - const theme = useTheme(); - const aggregate = 'count()'; - - let query = 'span.category:"ai.pipeline"'; - if (groupId) { - query = `${query} span.group:"${groupId}"`; - } - const {data, isPending, error} = useSpanMetricsSeries( - { - yAxis: [aggregate], - search: new MutableSearch(query), - transformAliasToInputFormat: true, - }, - 'api.ai-pipelines.view' - ); - - const colors = theme.chart.getColorPalette(2); - return ( - - ); -} - -interface PipelineDurationChartProps { - groupId?: string; -} - -export function PipelineDurationChart({groupId}: PipelineDurationChartProps) { - const theme = useTheme(); - - const aggregate = 'avg(span.duration)'; - let query = 'span.category:"ai.pipeline"'; - if (groupId) { - query = `${query} span.group:"${groupId}"`; - } - const {data, isPending, error} = useSpanMetricsSeries( - { - yAxis: [aggregate], - search: new MutableSearch(query), - transformAliasToInputFormat: true, - }, - 'api.ai-pipelines.view' - ); - - const colors = theme.chart.getColorPalette(2); - return ( - - ); -} diff --git a/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx b/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx index d0cc41081ccc98..bc7f9e36be1ae2 100644 --- a/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx +++ b/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx @@ -16,12 +16,10 @@ import {ModulePageFilterBar} from 'sentry/views/insights/common/components/modul import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders'; import {ModuleBodyUpsellHook} from 'sentry/views/insights/common/components/moduleUpsellHookWrapper'; import {ReadoutRibbon, ToolRibbon} from 'sentry/views/insights/common/components/ribbon'; +import LlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget'; +import LlmPipelineDurationChartWidget from 'sentry/views/insights/common/components/widgets/llmPipelineDurationChartWidget'; +import LlmTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget'; import {useSpanMetrics} from 'sentry/views/insights/common/queries/useDiscover'; -import { - NumberOfPipelinesChart, - PipelineDurationChart, - TotalTokensUsedChart, -} from 'sentry/views/insights/llmMonitoring/components/charts/llmMonitoringCharts'; import {PipelineSpansTable} from 'sentry/views/insights/llmMonitoring/components/tables/pipelineSpansTable'; import {RELEASE_LEVEL} from 'sentry/views/insights/llmMonitoring/settings'; import {AiHeader} from 'sentry/views/insights/pages/ai/aiPageHeader'; @@ -148,13 +146,13 @@ function LLMMonitoringPage({params}: Props) { - + - + - + diff --git a/static/app/views/insights/llmMonitoring/views/llmMonitoringLandingPage.tsx b/static/app/views/insights/llmMonitoring/views/llmMonitoringLandingPage.tsx index 6585e71bd543ad..1980a5b66da305 100644 --- a/static/app/views/insights/llmMonitoring/views/llmMonitoringLandingPage.tsx +++ b/static/app/views/insights/llmMonitoring/views/llmMonitoringLandingPage.tsx @@ -4,11 +4,9 @@ import {ModulePageFilterBar} from 'sentry/views/insights/common/components/modul import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders'; import {ModulesOnboarding} from 'sentry/views/insights/common/components/modulesOnboarding'; import {ModuleBodyUpsellHook} from 'sentry/views/insights/common/components/moduleUpsellHookWrapper'; -import { - NumberOfPipelinesChart, - PipelineDurationChart, - TotalTokensUsedChart, -} from 'sentry/views/insights/llmMonitoring/components/charts/llmMonitoringCharts'; +import LlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget'; +import LlmPipelineDurationChartWidget from 'sentry/views/insights/common/components/widgets/llmPipelineDurationChartWidget'; +import LlmTotalTokensUsedChart from 'sentry/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget'; import {PipelinesTable} from 'sentry/views/insights/llmMonitoring/components/tables/pipelinesTable'; import {AiHeader} from 'sentry/views/insights/pages/ai/aiPageHeader'; import {ModuleName} from 'sentry/views/insights/types'; @@ -26,13 +24,13 @@ function LLMMonitoringPage() { - + - + - + From 9cc14a4b60b0577278d86b3c2be5839d868454c9 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Tue, 22 Apr 2025 17:28:16 -0400 Subject: [PATCH 2/8] pass pageFilters --- .../insights/common/components/insightsTimeSeriesWidget.tsx | 2 ++ .../components/widgets/llmNumberOfPipelinesChartWidget.tsx | 3 ++- .../components/widgets/llmPipelineDurationChartWidget.tsx | 3 ++- .../components/widgets/llmTotalTokensUsedChartWidget.tsx | 5 +++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx b/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx index dfc68493a5f0d2..377ac99b567b1b 100644 --- a/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx +++ b/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx @@ -144,6 +144,7 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) { {...enableReleaseBubblesProps} legendSelection={props.legendSelection} onLegendSelectionChange={props.onLegendSelectionChange} + chartProperties={props.chartProperties} {...visualizationProps} /> } @@ -170,6 +171,7 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) { legendSelection={props.legendSelection} onLegendSelectionChange={props.onLegendSelectionChange} releases={releases ?? []} + chartProperties={props.chartProperties} /> ), diff --git a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx index 96bc1bf571c9d6..816193580ffc3f 100644 --- a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx @@ -22,7 +22,8 @@ export default function LlmNumberOfPipelinesChartWidget( search: new MutableSearch(query), transformAliasToInputFormat: true, }, - 'api.ai-pipelines.view' + 'api.ai-pipelines.view', + props.pageFilters ); const colors = theme.chart.getColorPalette(2); diff --git a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx index ce753daba90834..28fb420913d069 100644 --- a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx @@ -22,7 +22,8 @@ export default function LlmPipelineDurationChartWidget( search: new MutableSearch(query), transformAliasToInputFormat: true, }, - 'api.ai-pipelines.view' + 'api.ai-pipelines.view', + props.pageFilters ); const colors = theme.chart.getColorPalette(2); diff --git a/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx index d5c8cf25ac083d..aa8753c538503b 100644 --- a/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx @@ -22,14 +22,15 @@ export default function LlmTotalTokensUsedChartWidget( search: new MutableSearch(query), transformAliasToInputFormat: true, }, - 'api.ai-pipelines.view' + 'api.ai-pipelines.view', + props.pageFilters ); const colors = theme.chart.getColorPalette(2); return ( Date: Wed, 23 Apr 2025 18:10:16 -0400 Subject: [PATCH 3/8] refactor to remove chartProperties --- .../llm-monitoring/llmMonitoringSection.tsx | 49 +++++-------------- .../baseLlmNumberOfPipelinesChartWidget.tsx | 44 +++++++++++++++++ .../baseLlmPipelineDurationChartWidget.tsx | 44 +++++++++++++++++ .../baseLlmTotalTokensUsedChartWidget.tsx | 44 +++++++++++++++++ .../widgets/hooks/useAiPipelineGroup.tsx | 43 ++++++++++++++++ .../llmEventNumberOfPipelinesChartWidget.tsx | 21 ++++++++ .../llmEventTotalTokensUsedChartWidget.tsx | 21 ++++++++ .../llmNumberOfPipelinesChartWidget.tsx | 37 +++----------- .../llmPipelineDurationChartWidget.tsx | 37 +++----------- .../widgets/llmTotalTokensUsedChartWidget.tsx | 37 +++----------- .../common/components/widgets/types.tsx | 11 +---- .../views/llmMonitoringDetailsPage.tsx | 6 +-- .../groupEventDetailsContent.tsx | 2 +- 13 files changed, 251 insertions(+), 145 deletions(-) create mode 100644 static/app/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget.tsx create mode 100644 static/app/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget.tsx create mode 100644 static/app/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget.tsx create mode 100644 static/app/views/insights/common/components/widgets/hooks/useAiPipelineGroup.tsx create mode 100644 static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx create mode 100644 static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx diff --git a/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx b/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx index f7b2517bf26147..78c4f9e49d9f77 100644 --- a/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx +++ b/static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx @@ -2,36 +2,15 @@ import {LinkButton} from 'sentry/components/core/button'; import {ButtonBar} from 'sentry/components/core/button/buttonBar'; import {IconOpen} from 'sentry/icons'; import {t} from 'sentry/locale'; -import type {Event} from 'sentry/types/event'; -import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout'; -import LlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget'; -import LlmTotalTokensUsedChart from 'sentry/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget'; -import {useSpansIndexed} from 'sentry/views/insights/common/queries/useDiscover'; +import LlmEventNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget'; +import LlmEventTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget'; import {useModuleURL} from 'sentry/views/insights/common/utils/useModuleURL'; -import {SpanIndexedField} from 'sentry/views/insights/types'; import {SectionKey} from 'sentry/views/issueDetails/streamline/context'; import {InterimSection} from 'sentry/views/issueDetails/streamline/interimSection'; -interface Props { - event: Event; -} - -export default function LLMMonitoringSection({event}: Props) { +export default function LLMMonitoringSection() { const moduleUrl = useModuleURL('ai'); - const trace = event.contexts.trace; - - const {data} = useSpansIndexed( - { - limit: 1, - fields: [SpanIndexedField.SPAN_AI_PIPELINE_GROUP], - search: new MutableSearch(`trace:${trace?.trace_id} id:"${trace?.span_id}"`), - enabled: Boolean(trace?.span_id) && Boolean(trace?.trace_id), - }, - 'api.ai-pipelines.view' - ); - - const aiPipelineGroup = data[0]?.[SpanIndexedField.SPAN_AI_PIPELINE_GROUP]; const actions = ( @@ -48,20 +27,14 @@ export default function LLMMonitoringSection({event}: Props) { help={t('Charts showing how many tokens are being used')} actions={actions} > - {aiPipelineGroup ? ( - - - - - - - - - ) : ( - 'loading' - )} + + + + + + + + ); } diff --git a/static/app/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget.tsx new file mode 100644 index 00000000000000..4f0561deaf91ea --- /dev/null +++ b/static/app/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget.tsx @@ -0,0 +1,44 @@ +import {useTheme} from '@emotion/react'; + +import {t} from 'sentry/locale'; +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; + +export default function BaseLlmNumberOfPipelinesChartWidget({ + groupId, + ...props +}: { + error?: Error | null; + groupId?: string; + isLoading?: boolean; +} & LoadableChartWidgetProps) { + const theme = useTheme(); + const aggregate = 'count()'; + + let query = 'span.category:"ai.pipeline"'; + if (groupId) { + query = `${query} span.group:"${groupId}"`; + } + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + + const colors = theme.chart.getColorPalette(2); + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget.tsx new file mode 100644 index 00000000000000..d04adaba90f6cb --- /dev/null +++ b/static/app/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget.tsx @@ -0,0 +1,44 @@ +import {useTheme} from '@emotion/react'; + +import {t} from 'sentry/locale'; +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; + +export default function BaseLlmPipelineDurationChartWidget({ + groupId, + ...props +}: { + error?: Error | null; + groupId?: string; + isLoading?: boolean; +} & LoadableChartWidgetProps) { + const theme = useTheme(); + const aggregate = 'avg(span.duration)'; + + let query = 'span.category:"ai.pipeline"'; + if (groupId) { + query = `${query} span.group:"${groupId}"`; + } + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + + const colors = theme.chart.getColorPalette(2); + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget.tsx new file mode 100644 index 00000000000000..98aeaf165c73b0 --- /dev/null +++ b/static/app/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget.tsx @@ -0,0 +1,44 @@ +import {useTheme} from '@emotion/react'; + +import {t} from 'sentry/locale'; +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; + +export default function BaseLlmTotalTokensUsedChartWidget({ + groupId, + ...props +}: { + error?: Error | null; + groupId?: string; + isLoading?: boolean; +} & LoadableChartWidgetProps) { + const theme = useTheme(); + const aggregate = 'sum(ai.total_tokens.used)'; + + let query = 'span.category:"ai"'; + if (groupId) { + query = `${query} span.ai.pipeline.group:"${groupId}"`; + } + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + + const colors = theme.chart.getColorPalette(2); + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/hooks/useAiPipelineGroup.tsx b/static/app/views/insights/common/components/widgets/hooks/useAiPipelineGroup.tsx new file mode 100644 index 00000000000000..ef0e892c6c2985 --- /dev/null +++ b/static/app/views/insights/common/components/widgets/hooks/useAiPipelineGroup.tsx @@ -0,0 +1,43 @@ +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {useSpansIndexed} from 'sentry/views/insights/common/queries/useDiscover'; +import {SpanIndexedField} from 'sentry/views/insights/types'; +import {useGroupEvent} from 'sentry/views/issueDetails/useGroupEvent'; + +/** + * Given an issue's groupId + eventId, fetch the AI + * Pipeline's group ID via event's trace + */ +export function useAiPipelineGroup({ + groupId, + eventId, +}: { + groupId: string; + eventId?: string; +}) { + const { + data: event, + isPending: isGroupPending, + error: groupError, + } = useGroupEvent({groupId, eventId}); + + const trace = event?.contexts.trace; + const { + data, + isPending: isSpanPending, + error: spanError, + } = useSpansIndexed( + { + limit: 1, + fields: [SpanIndexedField.SPAN_AI_PIPELINE_GROUP], + search: new MutableSearch(`trace:${trace?.trace_id} id:"${trace?.span_id}"`), + enabled: Boolean(trace?.span_id) && Boolean(trace?.trace_id), + }, + 'api.ai-pipelines.view' + ); + + return { + groupId: data[0]?.[SpanIndexedField.SPAN_AI_PIPELINE_GROUP], + isPending: isGroupPending || isSpanPending, + error: groupError || spanError, + }; +} diff --git a/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx new file mode 100644 index 00000000000000..ed1e76542f19e7 --- /dev/null +++ b/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx @@ -0,0 +1,21 @@ +import {useParams} from 'sentry/utils/useParams'; +import BaseLlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget'; +import {useAiPipelineGroup} from 'sentry/views/insights/common/components/widgets/hooks/useAiPipelineGroup'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; + +export default function LlmEventNumberOfPipelinesChartWidget( + props: LoadableChartWidgetProps +) { + const params = useParams<{groupId: string; eventId?: string}>(); + const {groupId, isPending, error} = useAiPipelineGroup(params); + + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx new file mode 100644 index 00000000000000..ee38fd28c92422 --- /dev/null +++ b/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx @@ -0,0 +1,21 @@ +import {useParams} from 'sentry/utils/useParams'; +import BaseLlmTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget'; +import {useAiPipelineGroup} from 'sentry/views/insights/common/components/widgets/hooks/useAiPipelineGroup'; +import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; + +export default function LlmEventTotalTokensUsedChartWidget( + props: LoadableChartWidgetProps +) { + const params = useParams<{groupId: string; eventId?: string}>(); + const {groupId, isPending, error} = useAiPipelineGroup(params); + + return ( + + ); +} diff --git a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx index 816193580ffc3f..ee48b33744af22 100644 --- a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx @@ -1,40 +1,15 @@ -import {useTheme} from '@emotion/react'; - -import {t} from 'sentry/locale'; -import {MutableSearch} from 'sentry/utils/tokenizeSearch'; -import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import {useParams} from 'sentry/utils/useParams'; +import BaseLlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; -import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; - -export default function LlmNumberOfPipelinesChartWidget( - props: LoadableChartWidgetProps<{groupId?: string}> -) { - const theme = useTheme(); - const aggregate = 'count()'; - let query = 'span.category:"ai.pipeline"'; - if (props.chartProperties?.groupId) { - query = `${query} span.group:"${props.chartProperties?.groupId}"`; - } - const {data, isPending, error} = useSpanMetricsSeries( - { - yAxis: [aggregate], - search: new MutableSearch(query), - transformAliasToInputFormat: true, - }, - 'api.ai-pipelines.view', - props.pageFilters - ); +export default function LlmNumberOfPipelinesChartWidget(props: LoadableChartWidgetProps) { + const {groupId} = useParams(); - const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx index 28fb420913d069..0e20c204a145af 100644 --- a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx @@ -1,40 +1,15 @@ -import {useTheme} from '@emotion/react'; - -import {t} from 'sentry/locale'; -import {MutableSearch} from 'sentry/utils/tokenizeSearch'; -import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import {useParams} from 'sentry/utils/useParams'; +import BaseLlmPipelineDurationChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; -import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; - -export default function LlmPipelineDurationChartWidget( - props: LoadableChartWidgetProps<{groupId?: string}> -) { - const theme = useTheme(); - const aggregate = 'avg(span.duration)'; - let query = 'span.category:"ai.pipeline"'; - if (props.chartProperties?.groupId) { - query = `${query} span.group:"${props.chartProperties?.groupId}"`; - } - const {data, isPending, error} = useSpanMetricsSeries( - { - yAxis: [aggregate], - search: new MutableSearch(query), - transformAliasToInputFormat: true, - }, - 'api.ai-pipelines.view', - props.pageFilters - ); +export default function LlmPipelineDurationChartWidget(props: LoadableChartWidgetProps) { + const {groupId} = useParams(); - const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx index aa8753c538503b..24eca798a2c390 100644 --- a/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx @@ -1,40 +1,15 @@ -import {useTheme} from '@emotion/react'; - -import {t} from 'sentry/locale'; -import {MutableSearch} from 'sentry/utils/tokenizeSearch'; -import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; +import {useParams} from 'sentry/utils/useParams'; +import BaseLlmTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; -import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; - -export default function LlmTotalTokensUsedChartWidget( - props: LoadableChartWidgetProps<{groupId?: string}> -) { - const theme = useTheme(); - const aggregate = 'sum(ai.total_tokens.used)'; - let query = 'span.category:"ai"'; - if (props.chartProperties?.groupId) { - query = `${query} span.ai.pipeline.group:"${props.chartProperties.groupId}"`; - } - const {data, isPending, error} = useSpanMetricsSeries( - { - yAxis: [aggregate], - search: new MutableSearch(query), - transformAliasToInputFormat: true, - }, - 'api.ai-pipelines.view', - props.pageFilters - ); +export default function LlmTotalTokensUsedChartWidget(props: LoadableChartWidgetProps) { + const {groupId} = useParams(); - const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/common/components/widgets/types.tsx b/static/app/views/insights/common/components/widgets/types.tsx index 828658e092c986..6f38ce4a8bf399 100644 --- a/static/app/views/insights/common/components/widgets/types.tsx +++ b/static/app/views/insights/common/components/widgets/types.tsx @@ -4,16 +4,7 @@ import type {PageFilters} from 'sentry/types/core'; * These props are common across components that are required to dynamically * render an Insight Chart Widget */ -export interface LoadableChartWidgetProps | undefined> { - /** - * Additional chart-specific properties that are required to render the - * chart. `chartProperties` should be of type Record as it - * will be appended to the URL as query parameters so that the chart can be - * linked. - */ - - chartProperties?: T; - +export interface LoadableChartWidgetProps { /** * Unique ID for the widget * diff --git a/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx b/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx index bc7f9e36be1ae2..e8aff9492aeb5f 100644 --- a/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx +++ b/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx @@ -146,13 +146,13 @@ function LLMMonitoringPage({params}: Props) { - + - + - + diff --git a/static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsx b/static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsx index c8614d58aebad9..bd396308a74106 100644 --- a/static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsx +++ b/static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsx @@ -213,7 +213,7 @@ export function EventDetailsContent({ lowerText.includes('langchain')) ); }) ? ( - + ) : null} {!hasStreamlinedUI && group.issueType === IssueType.UPTIME_DOMAIN_FAILURE && ( From 4a10f67ae92572942aec23431b7d24b63a225290 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Wed, 23 Apr 2025 18:16:50 -0400 Subject: [PATCH 4/8] revert changes --- .../insights/common/components/insightsTimeSeriesWidget.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx b/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx index 377ac99b567b1b..4c36bd06e83791 100644 --- a/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx +++ b/static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx @@ -36,8 +36,7 @@ import {INGESTION_DELAY} from 'sentry/views/insights/settings'; export interface InsightsTimeSeriesWidgetProps extends WidgetTitleProps, - Omit, - Partial> { + LoadableChartWidgetProps { error: Error | null; isLoading: boolean; series: DiscoverSeries[]; @@ -144,7 +143,6 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) { {...enableReleaseBubblesProps} legendSelection={props.legendSelection} onLegendSelectionChange={props.onLegendSelectionChange} - chartProperties={props.chartProperties} {...visualizationProps} /> } @@ -171,7 +169,6 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) { legendSelection={props.legendSelection} onLegendSelectionChange={props.onLegendSelectionChange} releases={releases ?? []} - chartProperties={props.chartProperties} /> ), From 2ffb132aac1a42e24f93fa610f8d38541248c02a Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 24 Apr 2025 13:51:44 -0400 Subject: [PATCH 5/8] remove base* widgets --- .../llmEventNumberOfPipelinesChartWidget.tsx | 37 ++++++++++++++++--- .../llmEventTotalTokensUsedChartWidget.tsx | 37 ++++++++++++++++--- ... llmGroupNumberOfPipelinesChartWidget.tsx} | 23 +++++------- ...> llmGroupPipelineDurationChartWidget.tsx} | 25 +++++-------- ...=> llmGroupTotalTokensUsedChartWidget.tsx} | 25 +++++-------- .../llmNumberOfPipelinesChartWidget.tsx | 29 ++++++++++++--- .../llmPipelineDurationChartWidget.tsx | 29 ++++++++++++--- .../widgets/llmTotalTokensUsedChartWidget.tsx | 30 ++++++++++++--- .../views/llmMonitoringDetailsPage.tsx | 12 +++--- 9 files changed, 172 insertions(+), 75 deletions(-) rename static/app/views/insights/common/components/widgets/{base/baseLlmNumberOfPipelinesChartWidget.tsx => llmGroupNumberOfPipelinesChartWidget.tsx} (75%) rename static/app/views/insights/common/components/widgets/{base/baseLlmPipelineDurationChartWidget.tsx => llmGroupPipelineDurationChartWidget.tsx} (68%) rename static/app/views/insights/common/components/widgets/{base/baseLlmTotalTokensUsedChartWidget.tsx => llmGroupTotalTokensUsedChartWidget.tsx} (72%) diff --git a/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx index ed1e76542f19e7..1d8b61961ddfe9 100644 --- a/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx @@ -1,7 +1,11 @@ +import {useTheme} from '@emotion/react'; + +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {useParams} from 'sentry/utils/useParams'; -import BaseLlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import {useAiPipelineGroup} from 'sentry/views/insights/common/components/widgets/hooks/useAiPipelineGroup'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; export default function LlmEventNumberOfPipelinesChartWidget( props: LoadableChartWidgetProps @@ -9,13 +13,36 @@ export default function LlmEventNumberOfPipelinesChartWidget( const params = useParams<{groupId: string; eventId?: string}>(); const {groupId, isPending, error} = useAiPipelineGroup(params); + const theme = useTheme(); + const aggregate = 'count()'; + + let query = 'span.category:"ai.pipeline"'; + if (groupId) { + query = `${query} span.group:"${groupId}"`; + } + const { + data, + isPending: spanMetricsSeriesIsPending, + error: spanMetricsSeriesError, + } = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + + const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx index ee38fd28c92422..35ca93349fbaa4 100644 --- a/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx @@ -1,7 +1,11 @@ +import {useTheme} from '@emotion/react'; + +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {useParams} from 'sentry/utils/useParams'; -import BaseLlmTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import {useAiPipelineGroup} from 'sentry/views/insights/common/components/widgets/hooks/useAiPipelineGroup'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; export default function LlmEventTotalTokensUsedChartWidget( props: LoadableChartWidgetProps @@ -9,13 +13,36 @@ export default function LlmEventTotalTokensUsedChartWidget( const params = useParams<{groupId: string; eventId?: string}>(); const {groupId, isPending, error} = useAiPipelineGroup(params); + const theme = useTheme(); + const aggregate = 'sum(ai.total_tokens.used)'; + + let query = 'span.category:"ai"'; + if (groupId) { + query = `${query} span.ai.pipeline.group:"${groupId}"`; + } + const { + data, + isPending: spanMetricsSeriesIsPending, + error: spanMetricsSeriesError, + } = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + + const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmGroupNumberOfPipelinesChartWidget.tsx similarity index 75% rename from static/app/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget.tsx rename to static/app/views/insights/common/components/widgets/llmGroupNumberOfPipelinesChartWidget.tsx index 4f0561deaf91ea..67e8eb15db17dd 100644 --- a/static/app/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmGroupNumberOfPipelinesChartWidget.tsx @@ -2,25 +2,19 @@ import {useTheme} from '@emotion/react'; import {t} from 'sentry/locale'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {useParams} from 'sentry/utils/useParams'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; -export default function BaseLlmNumberOfPipelinesChartWidget({ - groupId, - ...props -}: { - error?: Error | null; - groupId?: string; - isLoading?: boolean; -} & LoadableChartWidgetProps) { +export default function LlmGroupNumberOfPipelinesChartWidget( + props: LoadableChartWidgetProps +) { + const {groupId} = useParams<{groupId: string}>(); const theme = useTheme(); const aggregate = 'count()'; - let query = 'span.category:"ai.pipeline"'; - if (groupId) { - query = `${query} span.group:"${groupId}"`; - } + const query = `span.category:"ai.pipeline" span.group:"${groupId}"`; const {data, isPending, error} = useSpanMetricsSeries( { yAxis: [aggregate], @@ -34,11 +28,12 @@ export default function BaseLlmNumberOfPipelinesChartWidget({ const colors = theme.chart.getColorPalette(2); return ( ); } diff --git a/static/app/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget.tsx similarity index 68% rename from static/app/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget.tsx rename to static/app/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget.tsx index d04adaba90f6cb..8bc43b8ed6a8e1 100644 --- a/static/app/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget.tsx @@ -2,25 +2,19 @@ import {useTheme} from '@emotion/react'; import {t} from 'sentry/locale'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {useParams} from 'sentry/utils/useParams'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; -export default function BaseLlmPipelineDurationChartWidget({ - groupId, - ...props -}: { - error?: Error | null; - groupId?: string; - isLoading?: boolean; -} & LoadableChartWidgetProps) { +export default function LlmGroupPipelineDurationChartWidget( + props: LoadableChartWidgetProps +) { + const {groupId} = useParams<{groupId: string}>(); const theme = useTheme(); const aggregate = 'avg(span.duration)'; - let query = 'span.category:"ai.pipeline"'; - if (groupId) { - query = `${query} span.group:"${groupId}"`; - } + const query = `span.category:"ai.pipeline" span.group:"${groupId}"`; const {data, isPending, error} = useSpanMetricsSeries( { yAxis: [aggregate], @@ -34,11 +28,12 @@ export default function BaseLlmPipelineDurationChartWidget({ const colors = theme.chart.getColorPalette(2); return ( ); } diff --git a/static/app/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget.tsx similarity index 72% rename from static/app/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget.tsx rename to static/app/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget.tsx index 98aeaf165c73b0..38231634845f04 100644 --- a/static/app/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget.tsx @@ -2,25 +2,19 @@ import {useTheme} from '@emotion/react'; import {t} from 'sentry/locale'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {useParams} from 'sentry/utils/useParams'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; -export default function BaseLlmTotalTokensUsedChartWidget({ - groupId, - ...props -}: { - error?: Error | null; - groupId?: string; - isLoading?: boolean; -} & LoadableChartWidgetProps) { +export default function LlmGroupTotalTokensUsedChartWidget( + props: LoadableChartWidgetProps +) { + const {groupId} = useParams<{groupId: string}>(); const theme = useTheme(); const aggregate = 'sum(ai.total_tokens.used)'; - let query = 'span.category:"ai"'; - if (groupId) { - query = `${query} span.ai.pipeline.group:"${groupId}"`; - } + const query = `span.category:"ai" span.group:"${groupId}"`; const {data, isPending, error} = useSpanMetricsSeries( { yAxis: [aggregate], @@ -34,11 +28,12 @@ export default function BaseLlmTotalTokensUsedChartWidget({ const colors = theme.chart.getColorPalette(2); return ( ); } diff --git a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx index ee48b33744af22..a175194e01db80 100644 --- a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx @@ -1,15 +1,34 @@ -import {useParams} from 'sentry/utils/useParams'; -import BaseLlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmNumberOfPipelinesChartWidget'; +import {useTheme} from '@emotion/react'; + +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; export default function LlmNumberOfPipelinesChartWidget(props: LoadableChartWidgetProps) { - const {groupId} = useParams(); + const theme = useTheme(); + const aggregate = 'count()'; + + const query = 'span.category:"ai.pipeline"'; + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx index 0e20c204a145af..567edf409776ad 100644 --- a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx @@ -1,15 +1,34 @@ -import {useParams} from 'sentry/utils/useParams'; -import BaseLlmPipelineDurationChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmPipelineDurationChartWidget'; +import {useTheme} from '@emotion/react'; + +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; export default function LlmPipelineDurationChartWidget(props: LoadableChartWidgetProps) { - const {groupId} = useParams(); + const theme = useTheme(); + const aggregate = 'avg(span.duration)'; + + const query = 'span.category:"ai.pipeline"'; + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx index 24eca798a2c390..814d0ed260ee6d 100644 --- a/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget.tsx @@ -1,15 +1,35 @@ -import {useParams} from 'sentry/utils/useParams'; -import BaseLlmTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/base/baseLlmTotalTokensUsedChartWidget'; +import {useTheme} from '@emotion/react'; + +import {t} from 'sentry/locale'; +import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; export default function LlmTotalTokensUsedChartWidget(props: LoadableChartWidgetProps) { - const {groupId} = useParams(); + const theme = useTheme(); + const aggregate = 'sum(ai.total_tokens.used)'; + + const query = 'span.category:"ai"'; + const {data, isPending, error} = useSpanMetricsSeries( + { + yAxis: [aggregate], + search: new MutableSearch(query), + transformAliasToInputFormat: true, + }, + 'api.ai-pipelines.view', + props.pageFilters + ); + const colors = theme.chart.getColorPalette(2); return ( - ); } diff --git a/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx b/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx index e8aff9492aeb5f..de15f9bc40a00b 100644 --- a/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx +++ b/static/app/views/insights/llmMonitoring/views/llmMonitoringDetailsPage.tsx @@ -16,9 +16,9 @@ import {ModulePageFilterBar} from 'sentry/views/insights/common/components/modul import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders'; import {ModuleBodyUpsellHook} from 'sentry/views/insights/common/components/moduleUpsellHookWrapper'; import {ReadoutRibbon, ToolRibbon} from 'sentry/views/insights/common/components/ribbon'; -import LlmNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget'; -import LlmPipelineDurationChartWidget from 'sentry/views/insights/common/components/widgets/llmPipelineDurationChartWidget'; -import LlmTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/llmTotalTokensUsedChartWidget'; +import LlmGroupNumberOfPipelinesChartWidget from 'sentry/views/insights/common/components/widgets/llmGroupNumberOfPipelinesChartWidget'; +import LlmGroupPipelineDurationChartWidget from 'sentry/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget'; +import LlmGroupTotalTokensUsedChartWidget from 'sentry/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget'; import {useSpanMetrics} from 'sentry/views/insights/common/queries/useDiscover'; import {PipelineSpansTable} from 'sentry/views/insights/llmMonitoring/components/tables/pipelineSpansTable'; import {RELEASE_LEVEL} from 'sentry/views/insights/llmMonitoring/settings'; @@ -146,13 +146,13 @@ function LLMMonitoringPage({params}: Props) { - + - + - + From fbb0c2049217ded68e972ed3bf01bb28c6f57c45 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 24 Apr 2025 14:00:35 -0400 Subject: [PATCH 6/8] imports --- .../components/widgets/llmEventNumberOfPipelinesChartWidget.tsx | 2 ++ .../components/widgets/llmEventTotalTokensUsedChartWidget.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx index 1d8b61961ddfe9..19c15d8a1c1d7a 100644 --- a/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmEventNumberOfPipelinesChartWidget.tsx @@ -1,5 +1,6 @@ import {useTheme} from '@emotion/react'; +import {t} from 'sentry/locale'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {useParams} from 'sentry/utils/useParams'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; @@ -29,6 +30,7 @@ export default function LlmEventNumberOfPipelinesChartWidget( yAxis: [aggregate], search: new MutableSearch(query), transformAliasToInputFormat: true, + enabled: !!groupId, }, 'api.ai-pipelines.view', props.pageFilters diff --git a/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx index 35ca93349fbaa4..3c93ec439ad35b 100644 --- a/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmEventTotalTokensUsedChartWidget.tsx @@ -1,5 +1,6 @@ import {useTheme} from '@emotion/react'; +import {t} from 'sentry/locale'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {useParams} from 'sentry/utils/useParams'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; @@ -29,6 +30,7 @@ export default function LlmEventTotalTokensUsedChartWidget( yAxis: [aggregate], search: new MutableSearch(query), transformAliasToInputFormat: true, + enabled: !!groupId, }, 'api.ai-pipelines.view', props.pageFilters From d9cce3372cefdc4f17e3d1b772f3d656ac18b189 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 24 Apr 2025 14:06:39 -0400 Subject: [PATCH 7/8] imports --- .../components/widgets/llmNumberOfPipelinesChartWidget.tsx | 1 + .../common/components/widgets/llmPipelineDurationChartWidget.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx index a175194e01db80..08447d11600890 100644 --- a/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmNumberOfPipelinesChartWidget.tsx @@ -1,5 +1,6 @@ import {useTheme} from '@emotion/react'; +import {t} from 'sentry/locale'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; diff --git a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx index 567edf409776ad..baea49d8b62101 100644 --- a/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmPipelineDurationChartWidget.tsx @@ -1,5 +1,6 @@ import {useTheme} from '@emotion/react'; +import {t} from 'sentry/locale'; import {MutableSearch} from 'sentry/utils/tokenizeSearch'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; From ee7f0b9841e82484b177ee520146ea9b92d43d34 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 24 Apr 2025 14:37:07 -0400 Subject: [PATCH 8/8] copy and paste bugs --- .../widgets/llmGroupPipelineDurationChartWidget.tsx | 2 +- .../components/widgets/llmGroupTotalTokensUsedChartWidget.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/static/app/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget.tsx index 8bc43b8ed6a8e1..0fe7933ad226cf 100644 --- a/static/app/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmGroupPipelineDurationChartWidget.tsx @@ -31,7 +31,7 @@ export default function LlmGroupPipelineDurationChartWidget( {...props} id="llmGroupPipelineDurationChartWidget" title={t('Pipeline duration')} - series={[{...data[aggregate], color: colors[1]}]} + series={[{...data[aggregate], color: colors[2]}]} isLoading={isPending} error={error} /> diff --git a/static/app/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget.tsx b/static/app/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget.tsx index 38231634845f04..5ee76882c85909 100644 --- a/static/app/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/llmGroupTotalTokensUsedChartWidget.tsx @@ -14,7 +14,7 @@ export default function LlmGroupTotalTokensUsedChartWidget( const theme = useTheme(); const aggregate = 'sum(ai.total_tokens.used)'; - const query = `span.category:"ai" span.group:"${groupId}"`; + const query = `span.category:"ai" span.ai.pipeline.group:"${groupId}"`; const {data, isPending, error} = useSpanMetricsSeries( { yAxis: [aggregate], @@ -31,7 +31,7 @@ export default function LlmGroupTotalTokensUsedChartWidget( {...props} id="llmGroupTotalTokensUsedChartWidget" title={t('Total tokens used')} - series={[{...data[aggregate], color: colors[1]}]} + series={[{...data[aggregate], color: colors[0]}]} isLoading={isPending} error={error} />