Browse Source

ref(metrics-extraction): Fetch extraction rules in one request (#73827)

ArthurKnaus 8 months ago
parent
commit
ba90407411

+ 1 - 0
static/app/types/metrics.tsx

@@ -135,6 +135,7 @@ export interface MetricsExtractionCondition {
 export interface MetricsExtractionRule {
   aggregates: MetricAggregation[];
   conditions: MetricsExtractionCondition[];
+  projectId: number;
   spanAttribute: string;
   tags: string[];
   unit: string;

+ 20 - 38
static/app/utils/metrics/virtualMetricsContext.tsx

@@ -10,14 +10,9 @@ import type {
 } from 'sentry/types/metrics';
 import {DEFAULT_MRI, parseMRI} from 'sentry/utils/metrics/mri';
 import type {MetricTag} from 'sentry/utils/metrics/types';
-import {useApiQueries} from 'sentry/utils/queryClient';
+import {useApiQuery} from 'sentry/utils/queryClient';
 import useOrganization from 'sentry/utils/useOrganization';
-import {useSelectedProjects} from 'sentry/views/metrics/utils/useSelectedProjects';
-import {getMetricsExtractionRulesApiKey} from 'sentry/views/settings/projectMetrics/utils/api';
-
-interface MetricsExtractionRuleWithProject extends MetricsExtractionRule {
-  projectId: number;
-}
+import usePageFilters from 'sentry/utils/usePageFilters';
 
 const Context = createContext<{
   getConditions: (mri: MRI) => MetricsExtractionCondition[];
@@ -60,13 +55,11 @@ interface Props {
   children: React.ReactNode;
 }
 
-function createVirtualMRI(rule: MetricsExtractionRuleWithProject): MRI {
+function createVirtualMRI(rule: MetricsExtractionRule): MRI {
   return `v:custom/${rule.spanAttribute}|${rule.projectId}@${rule.unit}`;
 }
 
-export function createMRIToVirtualMap(
-  rules: MetricsExtractionRuleWithProject[]
-): Map<MRI, MRI> {
+export function createMRIToVirtualMap(rules: MetricsExtractionRule[]): Map<MRI, MRI> {
   const mriMap = new Map<MRI, MRI>();
   for (const rule of rules) {
     for (const condition of rule.conditions) {
@@ -91,44 +84,33 @@ const aggregationToMetricType: Record<MetricAggregation, MetricType> = {
   p99: 'd',
 };
 
+const getMetricsExtractionRulesApiKey = (orgSlug: string, projects: number[]) =>
+  [
+    `/organizations/${orgSlug}/metrics/extraction-rules/`,
+    {
+      query: {
+        project: projects,
+      },
+    },
+  ] as const;
+
+const EMPTY_ARRAY: never[] = [];
+
 export function VirtualMetricsContextProvider({children}: Props) {
   const organization = useOrganization();
-  const projects = useSelectedProjects();
+  const {selection} = usePageFilters();
 
   // TODO: support querying multiple projects in the API
-  const requests = useApiQueries<MetricsExtractionRule[]>(
-    projects.map(project =>
-      getMetricsExtractionRulesApiKey(organization.slug, project.slug)
-    ),
+  const {isLoading, data = EMPTY_ARRAY} = useApiQuery<MetricsExtractionRule[]>(
+    getMetricsExtractionRulesApiKey(organization.slug, selection.projects),
     {staleTime: 0}
   );
 
-  const {isLoading, data} = useMemo(
-    () =>
-      requests.reduce(
-        (acc, request, index) => {
-          acc.isLoading ||= request.isLoading;
-          const rules = (request.data ?? []).map(rule => ({
-            ...rule,
-            projectId: Number(projects[index].id),
-          }));
-          acc.data = acc.data.concat(rules);
-
-          return acc;
-        },
-        {
-          isLoading: false,
-          data: [] as MetricsExtractionRuleWithProject[],
-        }
-      ),
-    [projects, requests]
-  );
-
   const mriToVirtualMap = useMemo(() => createMRIToVirtualMap(data), [data]);
 
   const virtualMRIToRuleMap = useMemo(
     () =>
-      new Map<MRI, MetricsExtractionRuleWithProject>(
+      new Map<MRI, MetricsExtractionRule>(
         data.map(rule => [createVirtualMRI(rule), rule])
       ),
     [data]

+ 2 - 1
static/app/views/settings/projectMetrics/extractMetric.tsx

@@ -53,6 +53,7 @@ function ExtractMetric({project}: {project: Project}) {
         aggregates: data.aggregates.flatMap(explodeAggregateGroup),
         unit: 'none',
         conditions: data.conditions,
+        projectId: parseInt(project.id, 10),
       };
 
       createExtractionRuleMutation.mutate(
@@ -76,7 +77,7 @@ function ExtractMetric({project}: {project: Project}) {
       );
       onSubmitSuccess(data);
     },
-    [createExtractionRuleMutation, navigate]
+    [createExtractionRuleMutation, navigate, project.id]
   );
 
   if (!hasCustomMetricsExtractionRules(organization)) {

+ 2 - 1
static/app/views/settings/projectMetrics/metricsExtractionRuleEditModal.tsx

@@ -58,6 +58,7 @@ export function MetricsExtractionRuleEditModal({
         aggregates: data.aggregates.flatMap(explodeAggregateGroup),
         unit: 'none',
         conditions: data.conditions,
+        projectId: parseInt(project.id, 10),
       };
 
       updateExtractionRuleMutation.mutate(
@@ -81,7 +82,7 @@ export function MetricsExtractionRuleEditModal({
       );
       onSubmitSuccess(data);
     },
-    [closeModal, updateExtractionRuleMutation]
+    [closeModal, project.id, updateExtractionRuleMutation]
   );
 
   return (