123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import type {MetricsExtractionRule} from 'sentry/types/metrics';
- import {
- type ApiQueryKey,
- getApiQueryData,
- type QueryClient,
- setApiQueryData,
- useApiQuery,
- useMutation,
- useQueryClient,
- } from 'sentry/utils/queryClient';
- import type RequestError from 'sentry/utils/requestError/requestError';
- import useApi from 'sentry/utils/useApi';
- /**
- * Remove temporary ids from conditions before sending to the server
- */
- function filterTempIds(rules: MetricsExtractionRule[]) {
- return rules.map(rule => ({
- ...rule,
- conditions: rule.conditions.map(condition => ({
- ...condition,
- id: condition.id < 0 ? undefined : condition.id,
- })),
- }));
- }
- export const getMetricsExtractionRulesApiKey = (orgSlug: string, projectSlug: string) =>
- [`/projects/${orgSlug}/${projectSlug}/metrics/extraction-rules/`] as const;
- export function useMetricsExtractionRules(orgSlug: string, projectSlug: string) {
- return useApiQuery<MetricsExtractionRule[]>(
- getMetricsExtractionRulesApiKey(orgSlug, projectSlug),
- {
- staleTime: 0,
- retry: false,
- }
- );
- }
- // Rules are identified by the combination of span_attribute, type and unit
- function getRuleIdentifier(rule: MetricsExtractionRule) {
- return rule.spanAttribute + rule.unit;
- }
- function createOptimisticUpdate(
- queryClient: QueryClient,
- queryKey: ApiQueryKey,
- updater: (
- variables: {metricsExtractionRules: MetricsExtractionRule[]},
- old: MetricsExtractionRule[] | undefined
- ) => MetricsExtractionRule[] | undefined
- ) {
- return function (variables: {metricsExtractionRules: MetricsExtractionRule[]}) {
- queryClient.cancelQueries(queryKey);
- const previous = getApiQueryData<MetricsExtractionRule[]>(queryClient, queryKey);
- setApiQueryData<MetricsExtractionRule[] | undefined>(
- queryClient,
- queryKey,
- oldRules => {
- return updater(variables, oldRules);
- }
- );
- return {previous};
- };
- }
- function createRollback(queryClient: QueryClient, queryKey: ApiQueryKey) {
- return function (
- _error: RequestError,
- _variables: {metricsExtractionRules: MetricsExtractionRule[]},
- context?: {previous?: MetricsExtractionRule[]}
- ) {
- if (context?.previous) {
- setApiQueryData<MetricsExtractionRule[]>(queryClient, queryKey, context.previous);
- }
- };
- }
- export function useDeleteMetricsExtractionRules(orgSlug: string, projectSlug: string) {
- const api = useApi();
- const queryClient = useQueryClient();
- const queryKey = getMetricsExtractionRulesApiKey(orgSlug, projectSlug);
- return useMutation<
- MetricsExtractionRule[],
- RequestError,
- {metricsExtractionRules: MetricsExtractionRule[]},
- {previous?: MetricsExtractionRule[]}
- >(
- data => {
- return api.requestPromise(queryKey[0], {
- method: 'DELETE',
- data,
- });
- },
- {
- onMutate: createOptimisticUpdate(queryClient, queryKey, (variables, old) => {
- const deletedRules = variables.metricsExtractionRules;
- const deletedKeys = new Set(deletedRules.map(getRuleIdentifier));
- return old?.filter(rule => !deletedKeys.has(getRuleIdentifier(rule)));
- }),
- onError: createRollback(queryClient, queryKey),
- onSettled: () => {
- queryClient.invalidateQueries(queryKey);
- },
- }
- );
- }
- export function useCreateMetricsExtractionRules(orgSlug: string, projectSlug: string) {
- const api = useApi();
- const queryClient = useQueryClient();
- const queryKey = getMetricsExtractionRulesApiKey(orgSlug, projectSlug);
- return useMutation<
- MetricsExtractionRule[],
- RequestError,
- {metricsExtractionRules: MetricsExtractionRule[]},
- {previous?: MetricsExtractionRule[]}
- >(
- data => {
- return api.requestPromise(queryKey[0], {
- method: 'POST',
- data: {
- metricsExtractionRules: filterTempIds(data.metricsExtractionRules),
- },
- });
- },
- {
- onMutate: createOptimisticUpdate(queryClient, queryKey, (variables, old) => {
- const newRules = variables.metricsExtractionRules;
- const existingKeys = new Set((old ?? []).map(getRuleIdentifier));
- const copy = old ? [...old] : [];
- newRules.forEach(rule => {
- if (!existingKeys.has(getRuleIdentifier(rule))) {
- copy.push(rule);
- }
- });
- return copy;
- }),
- onError: createRollback(queryClient, queryKey),
- onSettled: () => {
- queryClient.invalidateQueries(queryKey);
- },
- }
- );
- }
- export function useUpdateMetricsExtractionRules(orgSlug: string, projectSlug: string) {
- const api = useApi();
- const queryClient = useQueryClient();
- const queryKey = getMetricsExtractionRulesApiKey(orgSlug, projectSlug);
- return useMutation<
- MetricsExtractionRule[],
- RequestError,
- {metricsExtractionRules: MetricsExtractionRule[]},
- {previous?: MetricsExtractionRule[]}
- >(
- data => {
- return api.requestPromise(queryKey[0], {
- method: 'PUT',
- data: {
- metricsExtractionRules: filterTempIds(data.metricsExtractionRules),
- },
- });
- },
- {
- onMutate: createOptimisticUpdate(queryClient, queryKey, (variables, old) => {
- const updatedRules = variables.metricsExtractionRules;
- const updatedRulesMap = new Map(
- updatedRules.map(rule => [getRuleIdentifier(rule), rule])
- );
- return old?.map(rule => {
- const updatedRule = updatedRulesMap.get(getRuleIdentifier(rule));
- return updatedRule ?? rule;
- });
- }),
- onError: createRollback(queryClient, queryKey),
- onSettled: () => {
- queryClient.invalidateQueries(queryKey);
- },
- }
- );
- }
|