llmMonitoringCharts.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import {CHART_PALETTE} from 'sentry/constants/chartPalette';
  2. import {t} from 'sentry/locale';
  3. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  4. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  5. import Chart, {ChartType} from 'sentry/views/insights/common/components/chart';
  6. import ChartPanel from 'sentry/views/insights/common/components/chartPanel';
  7. import {
  8. useSpanIndexedSeries,
  9. useSpanMetricsSeries,
  10. } from 'sentry/views/insights/common/queries/useDiscoverSeries';
  11. import {ALERTS} from 'sentry/views/insights/llmMonitoring/alerts';
  12. interface TotalTokensUsedChartProps {
  13. groupId?: string;
  14. }
  15. export function EAPTotalTokensUsedChart({groupId}: TotalTokensUsedChartProps) {
  16. const aggregate = 'sum(ai.total_tokens.used)';
  17. let query = 'span.category:"ai"';
  18. if (groupId) {
  19. query = `${query} span.ai.pipeline.group:"${groupId}"`;
  20. }
  21. const {data, isPending, error} = useSpanIndexedSeries(
  22. {
  23. yAxis: [aggregate],
  24. search: new MutableSearch(query),
  25. },
  26. 'api.ai-pipelines.view',
  27. DiscoverDatasets.SPANS_EAP
  28. );
  29. return (
  30. <ChartPanel
  31. title={t('Total tokens used')}
  32. alertConfigs={[{...ALERTS.tokensUsed, query}]}
  33. >
  34. <Chart
  35. height={200}
  36. grid={{
  37. left: '4px',
  38. right: '0',
  39. top: '8px',
  40. bottom: '0',
  41. }}
  42. data={[data[aggregate]]}
  43. loading={isPending}
  44. error={error}
  45. type={ChartType.LINE}
  46. chartColors={[CHART_PALETTE[2][0]]}
  47. />
  48. </ChartPanel>
  49. );
  50. }
  51. export function TotalTokensUsedChart({groupId}: TotalTokensUsedChartProps) {
  52. const aggregate = 'sum(ai.total_tokens.used)';
  53. let query = 'span.category:"ai"';
  54. if (groupId) {
  55. query = `${query} span.ai.pipeline.group:"${groupId}"`;
  56. }
  57. const {data, isPending, error} = useSpanMetricsSeries(
  58. {
  59. yAxis: [aggregate],
  60. search: new MutableSearch(query),
  61. },
  62. 'api.ai-pipelines.view'
  63. );
  64. return (
  65. <ChartPanel
  66. title={t('Total tokens used')}
  67. alertConfigs={[{...ALERTS.tokensUsed, query}]}
  68. >
  69. <Chart
  70. height={200}
  71. grid={{
  72. left: '4px',
  73. right: '0',
  74. top: '8px',
  75. bottom: '0',
  76. }}
  77. data={[data[aggregate]]}
  78. loading={isPending}
  79. error={error}
  80. type={ChartType.LINE}
  81. chartColors={[CHART_PALETTE[2][0]]}
  82. />
  83. </ChartPanel>
  84. );
  85. }
  86. interface NumberOfPipelinesChartProps {
  87. groupId?: string;
  88. }
  89. export function EAPNumberOfPipelinesChart({groupId}: NumberOfPipelinesChartProps) {
  90. const aggregate = 'count()';
  91. let query = 'span.category:"ai.pipeline"';
  92. if (groupId) {
  93. query = `${query} span.group:"${groupId}"`;
  94. }
  95. const {data, isPending, error} = useSpanIndexedSeries(
  96. {
  97. yAxis: [aggregate],
  98. search: new MutableSearch(query),
  99. },
  100. 'api.ai-pipelines-eap.view',
  101. DiscoverDatasets.SPANS_EAP
  102. );
  103. return (
  104. <ChartPanel title={t('Number of AI pipelines')}>
  105. <Chart
  106. height={200}
  107. grid={{
  108. left: '4px',
  109. right: '0',
  110. top: '8px',
  111. bottom: '0',
  112. }}
  113. data={[data[aggregate]]}
  114. loading={isPending}
  115. error={error}
  116. type={ChartType.LINE}
  117. chartColors={[CHART_PALETTE[2][1]]}
  118. />
  119. </ChartPanel>
  120. );
  121. }
  122. export function NumberOfPipelinesChart({groupId}: NumberOfPipelinesChartProps) {
  123. const aggregate = 'count()';
  124. let query = 'span.category:"ai.pipeline"';
  125. if (groupId) {
  126. query = `${query} span.group:"${groupId}"`;
  127. }
  128. const {data, isPending, error} = useSpanMetricsSeries(
  129. {
  130. yAxis: [aggregate],
  131. search: new MutableSearch(query),
  132. },
  133. 'api.ai-pipelines.view'
  134. );
  135. return (
  136. <ChartPanel title={t('Number of AI pipelines')}>
  137. <Chart
  138. height={200}
  139. grid={{
  140. left: '4px',
  141. right: '0',
  142. top: '8px',
  143. bottom: '0',
  144. }}
  145. data={[data[aggregate]]}
  146. loading={isPending}
  147. error={error}
  148. type={ChartType.LINE}
  149. chartColors={[CHART_PALETTE[2][1]]}
  150. />
  151. </ChartPanel>
  152. );
  153. }
  154. interface PipelineDurationChartProps {
  155. groupId?: string;
  156. }
  157. export function EAPPipelineDurationChart({groupId}: PipelineDurationChartProps) {
  158. const aggregate = 'avg(span.duration)';
  159. let query = 'span.category:"ai.pipeline"';
  160. if (groupId) {
  161. query = `${query} span.group:"${groupId}"`;
  162. }
  163. const {data, isPending, error} = useSpanIndexedSeries(
  164. {
  165. yAxis: [aggregate],
  166. search: new MutableSearch(query),
  167. },
  168. 'api.ai-pipelines-eap.view',
  169. DiscoverDatasets.SPANS_EAP
  170. );
  171. return (
  172. <ChartPanel
  173. title={t('Pipeline Duration')}
  174. alertConfigs={[{...ALERTS.duration, query}]}
  175. >
  176. <Chart
  177. height={200}
  178. grid={{
  179. left: '4px',
  180. right: '0',
  181. top: '8px',
  182. bottom: '0',
  183. }}
  184. data={[data[aggregate]]}
  185. loading={isPending}
  186. error={error}
  187. type={ChartType.LINE}
  188. chartColors={[CHART_PALETTE[2][2]]}
  189. />
  190. </ChartPanel>
  191. );
  192. }
  193. export function PipelineDurationChart({groupId}: PipelineDurationChartProps) {
  194. const aggregate = 'avg(span.duration)';
  195. let query = 'span.category:"ai.pipeline"';
  196. if (groupId) {
  197. query = `${query} span.group:"${groupId}"`;
  198. }
  199. const {data, isPending, error} = useSpanMetricsSeries(
  200. {
  201. yAxis: [aggregate],
  202. search: new MutableSearch(query),
  203. },
  204. 'api.ai-pipelines.view'
  205. );
  206. return (
  207. <ChartPanel
  208. title={t('Pipeline Duration')}
  209. alertConfigs={[{...ALERTS.duration, query}]}
  210. >
  211. <Chart
  212. height={200}
  213. grid={{
  214. left: '4px',
  215. right: '0',
  216. top: '8px',
  217. bottom: '0',
  218. }}
  219. data={[data[aggregate]]}
  220. loading={isPending}
  221. error={error}
  222. type={ChartType.LINE}
  223. chartColors={[CHART_PALETTE[2][2]]}
  224. />
  225. </ChartPanel>
  226. );
  227. }