anomaliesQuery.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import {EventsStatsData, Organization} from 'sentry/types';
  2. import GenericDiscoverQuery, {
  3. DiscoverQueryProps,
  4. GenericChildrenProps,
  5. } from 'sentry/utils/discover/genericDiscoverQuery';
  6. import {ANOMALY_FLAG} from 'sentry/views/performance/transactionSummary/transactionAnomalies/utils';
  7. type AnomaliesProps = {};
  8. type RequestProps = DiscoverQueryProps & AnomaliesProps;
  9. export type ChildrenProps = Omit<GenericChildrenProps<AnomaliesProps>, 'tableData'> & {
  10. data: AnomalyPayload | null;
  11. };
  12. type Props = Omit<RequestProps, 'orgSlug'> & {
  13. children: (props: ChildrenProps) => React.ReactNode;
  14. organization: Organization;
  15. };
  16. export type AnomalyConfidence = 'high' | 'low';
  17. // Should match events stats data in format.
  18. type AnomalyStatsData = {
  19. data: EventsStatsData;
  20. end?: number;
  21. start?: number;
  22. };
  23. // Anomaly info describes what the anomaly service determines is an 'anomaly area'.
  24. export type AnomalyInfo = {
  25. confidence: AnomalyConfidence;
  26. end: number;
  27. expected: number;
  28. id: string;
  29. received: number;
  30. start: number;
  31. };
  32. export type AnomalyPayload = {
  33. anomalies: AnomalyInfo[];
  34. y: AnomalyStatsData;
  35. yhat_lower: AnomalyStatsData;
  36. yhat_upper: AnomalyStatsData;
  37. };
  38. function transformStatsTimes(stats: AnomalyStatsData) {
  39. stats.data.forEach(d => (d[0] = d[0] * 1000));
  40. return stats;
  41. }
  42. function transformAnomaliesTimes(anoms: AnomalyInfo[]) {
  43. anoms.forEach(a => {
  44. a.start = a.start * 1000;
  45. a.end = a.end * 1000;
  46. });
  47. return anoms;
  48. }
  49. function transformPayload(payload: AnomalyPayload): AnomalyPayload {
  50. const newPayload = {...payload};
  51. if (!payload.y || !payload.yhat_lower || !payload.yhat_upper || !payload.anomalies) {
  52. return newPayload;
  53. }
  54. newPayload.y = transformStatsTimes(payload.y);
  55. newPayload.yhat_upper = transformStatsTimes(payload.yhat_upper);
  56. newPayload.yhat_lower = transformStatsTimes(payload.yhat_lower);
  57. newPayload.anomalies = transformAnomaliesTimes(payload.anomalies);
  58. return newPayload;
  59. }
  60. function AnomaliesSeriesQuery(props: Props) {
  61. if (!props.organization.features.includes(ANOMALY_FLAG)) {
  62. return (
  63. <div>
  64. {props.children({data: null, isLoading: false, error: null, pageLinks: null})}
  65. </div>
  66. );
  67. }
  68. return (
  69. <GenericDiscoverQuery<AnomalyPayload, {}>
  70. route="transaction-anomaly-detection"
  71. {...props}
  72. >
  73. {({tableData, ...rest}) => {
  74. return props.children({
  75. data: tableData && tableData.y ? transformPayload(tableData) : null,
  76. ...rest,
  77. });
  78. }}
  79. </GenericDiscoverQuery>
  80. );
  81. }
  82. export default AnomaliesSeriesQuery;