Files
2024-02-15 17:01:50 +00:00

97 lines
2.6 KiB
TypeScript

import type {EventsStatsData, Organization} from 'sentry/types';
import type {
DiscoverQueryProps,
GenericChildrenProps,
} from 'sentry/utils/discover/genericDiscoverQuery';
import GenericDiscoverQuery from 'sentry/utils/discover/genericDiscoverQuery';
import {ANOMALY_FLAG} from 'sentry/views/performance/transactionSummary/transactionAnomalies/utils';
type AnomaliesProps = {};
type RequestProps = DiscoverQueryProps & AnomaliesProps;
export type ChildrenProps = Omit<GenericChildrenProps<AnomaliesProps>, 'tableData'> & {
data: AnomalyPayload | null;
};
type Props = Omit<RequestProps, 'orgSlug'> & {
children: (props: ChildrenProps) => React.ReactNode;
organization: Organization;
};
export type AnomalyConfidence = 'high' | 'low';
// Should match events stats data in format.
type AnomalyStatsData = {
data: EventsStatsData;
end?: number;
start?: number;
};
// Anomaly info describes what the anomaly service determines is an 'anomaly area'.
export type AnomalyInfo = {
confidence: AnomalyConfidence;
end: number;
expected: number;
id: string;
received: number;
start: number;
};
export type AnomalyPayload = {
anomalies: AnomalyInfo[];
y: AnomalyStatsData;
yhat_lower: AnomalyStatsData;
yhat_upper: AnomalyStatsData;
};
function transformStatsTimes(stats: AnomalyStatsData) {
stats.data.forEach(d => (d[0] = d[0] * 1000));
return stats;
}
function transformAnomaliesTimes(anoms: AnomalyInfo[]) {
anoms.forEach(a => {
a.start = a.start * 1000;
a.end = a.end * 1000;
});
return anoms;
}
function transformPayload(payload: AnomalyPayload): AnomalyPayload {
const newPayload = {...payload};
if (!payload.y || !payload.yhat_lower || !payload.yhat_upper || !payload.anomalies) {
return newPayload;
}
newPayload.y = transformStatsTimes(payload.y);
newPayload.yhat_upper = transformStatsTimes(payload.yhat_upper);
newPayload.yhat_lower = transformStatsTimes(payload.yhat_lower);
newPayload.anomalies = transformAnomaliesTimes(payload.anomalies);
return newPayload;
}
function AnomaliesSeriesQuery(props: Props) {
if (!props.organization.features.includes(ANOMALY_FLAG)) {
return (
<div>
{props.children({data: null, isLoading: false, error: null, pageLinks: null})}
</div>
);
}
return (
<GenericDiscoverQuery<AnomalyPayload, {}>
route="transaction-anomaly-detection"
{...props}
>
{({tableData, ...rest}) => {
return props.children({
data: tableData?.y ? transformPayload(tableData) : null,
...rest,
});
}}
</GenericDiscoverQuery>
);
}
export default AnomaliesSeriesQuery;