import {Fragment, useCallback} from 'react'; import styled from '@emotion/styled'; import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator'; import {Button} from 'sentry/components/button'; import {openConfirmModal} from 'sentry/components/confirm'; import {DateTime} from 'sentry/components/dateTime'; import UserBadge from 'sentry/components/idBadge/userBadge'; import {PanelTable} from 'sentry/components/panels/panelTable'; import SearchBar from 'sentry/components/searchBar'; import {Tooltip} from 'sentry/components/tooltip'; import {IconWarning} from 'sentry/icons'; import {IconArrow} from 'sentry/icons/iconArrow'; import {IconDelete} from 'sentry/icons/iconDelete'; import {IconEdit} from 'sentry/icons/iconEdit'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {MetricsExtractionRule} from 'sentry/types/metrics'; import type {Project} from 'sentry/types/project'; import {DEFAULT_METRICS_CARDINALITY_LIMIT} from 'sentry/utils/metrics/constants'; import {useMetricsCardinality} from 'sentry/utils/metrics/useMetricsCardinality'; import {useMembers} from 'sentry/utils/useMembers'; import useOrganization from 'sentry/utils/useOrganization'; import {openExtractionRuleCreateModal} from 'sentry/views/settings/projectMetrics/metricsExtractionRuleCreateModal'; import {openExtractionRuleEditModal} from 'sentry/views/settings/projectMetrics/metricsExtractionRuleEditModal'; import { useDeleteMetricsExtractionRules, useMetricsExtractionRules, } from 'sentry/views/settings/projectMetrics/utils/useMetricsExtractionRules'; import {useSearchQueryParam} from 'sentry/views/settings/projectMetrics/utils/useSearchQueryParam'; type Props = { project: Project; }; export function MetricsExtractionRulesTable({project}: Props) { const organization = useOrganization(); const [query, setQuery] = useSearchQueryParam('query'); const {data: extractionRules, isLoading: isLoadingExtractionRules} = useMetricsExtractionRules(organization.slug, project.id, {query}); const {mutate: deleteMetricsExtractionRules} = useDeleteMetricsExtractionRules( organization.slug, project.id ); const {data: cardinality, isLoading: isLoadingCardinality} = useMetricsCardinality({ projects: [project.id], }); const handleDelete = useCallback( (rule: MetricsExtractionRule) => { openConfirmModal({ onConfirm: () => deleteMetricsExtractionRules( {metricsExtractionRules: [rule]}, { onSuccess: () => { addSuccessMessage(t('Metric extraction rule deleted')); }, onError: () => { addErrorMessage(t('Failed to delete metric extraction rule')); }, } ), message: t('Are you sure you want to delete this extraction rule?'), confirmText: t('Delete Extraction Rule'), }); }, [deleteMetricsExtractionRules] ); const handleEdit = useCallback((rule: MetricsExtractionRule) => { openExtractionRuleEditModal({ metricExtractionRule: rule, }); }, []); const handleCreate = useCallback(() => { openExtractionRuleCreateModal({projectId: project.id}); }, [project]); return (
{t('Span Metrics')}
); } interface RulesTableProps { cardinality: Record; extractionRules: MetricsExtractionRule[]; hasSearch: boolean; isLoading: boolean; onDelete: (rule: MetricsExtractionRule) => void; onEdit: (rule: MetricsExtractionRule) => void; } function RulesTable({ extractionRules, cardinality, isLoading, onDelete, onEdit, hasSearch, }: RulesTableProps) { const {members} = useMembers(); const getMaxCardinality = (rule: MetricsExtractionRule) => { const mris = rule.conditions.flatMap(condition => condition.mris); return mris.reduce((acc, mri) => Math.max(acc, cardinality[mri] || 0), 0); }; return ( {t('Span attribute')} , {t('Created by')}, {t('Created at')} , {t('Actions')} , ]} emptyMessage={ hasSearch ? t('No metrics match the query.') : t('You have not created any span metrics yet.') } isEmpty={extractionRules.length === 0} isLoading={isLoading} > {extractionRules .toSorted((a, b) => a?.spanAttribute?.localeCompare(b?.spanAttribute)) .map(rule => { const createdByUser = members.find( member => member.id === String(rule.createdById) ); return ( {getMaxCardinality(rule) >= DEFAULT_METRICS_CARDINALITY_LIMIT ? ( ) : null} {rule.spanAttribute}