|
@@ -1,11 +1,14 @@
|
|
|
-import type {LineSeriesOption} from 'echarts';
|
|
|
+import React from 'react';
|
|
|
+import styled from '@emotion/styled';
|
|
|
|
|
|
+import {AreaChart, AreaChartSeries} from 'sentry/components/charts/areaChart';
|
|
|
import {BarChart, BarChartSeries} from 'sentry/components/charts/barChart';
|
|
|
import {getYAxisMaxFn} from 'sentry/components/charts/miniBarChart';
|
|
|
-import LineSeries from 'sentry/components/charts/series/lineSeries';
|
|
|
+import {HeaderTitle} from 'sentry/components/charts/styles';
|
|
|
import EmptyMessage from 'sentry/components/emptyMessage';
|
|
|
import {Panel, PanelBody} from 'sentry/components/panels';
|
|
|
import {t} from 'sentry/locale';
|
|
|
+import {space} from 'sentry/styles/space';
|
|
|
import {intervalToMilliseconds} from 'sentry/utils/dates';
|
|
|
import {axisLabelFormatter, tooltipFormatter} from 'sentry/utils/discover/charts';
|
|
|
import {AggregationOutputType} from 'sentry/utils/discover/fields';
|
|
@@ -59,25 +62,24 @@ const MonitorStats = ({monitor, monitorEnv, orgId}: Props) => {
|
|
|
let emptyStats = true;
|
|
|
const success: BarChartSeries = {
|
|
|
seriesName: t('Successful'),
|
|
|
- yAxisIndex: 0,
|
|
|
data: [],
|
|
|
};
|
|
|
const failed: BarChartSeries = {
|
|
|
seriesName: t('Failed'),
|
|
|
- yAxisIndex: 0,
|
|
|
data: [],
|
|
|
};
|
|
|
const missed: BarChartSeries = {
|
|
|
seriesName: t('Missed'),
|
|
|
- yAxisIndex: 0,
|
|
|
data: [],
|
|
|
};
|
|
|
const timeout: BarChartSeries = {
|
|
|
seriesName: t('Timeout'),
|
|
|
- yAxisIndex: 0,
|
|
|
data: [],
|
|
|
};
|
|
|
- const durationData = [] as [number, number][];
|
|
|
+ const duration: AreaChartSeries = {
|
|
|
+ seriesName: t('Average Duration'),
|
|
|
+ data: [],
|
|
|
+ };
|
|
|
|
|
|
data.stats?.forEach(p => {
|
|
|
if (p.ok || p.error || p.missed || p.timeout) {
|
|
@@ -88,22 +90,10 @@ const MonitorStats = ({monitor, monitorEnv, orgId}: Props) => {
|
|
|
failed.data.push({name: timestamp, value: p.error});
|
|
|
timeout.data.push({name: timestamp, value: p.timeout});
|
|
|
missed.data.push({name: timestamp, value: p.missed});
|
|
|
- durationData.push([timestamp, Math.trunc(p.duration)]);
|
|
|
+ duration.data.push({name: timestamp, value: Math.trunc(p.duration)});
|
|
|
});
|
|
|
const colors = [theme.green200, theme.red200, theme.red200, theme.yellow200];
|
|
|
|
|
|
- const durationTitle = t('Average Duration');
|
|
|
- const additionalSeries: LineSeriesOption[] = [
|
|
|
- LineSeries({
|
|
|
- name: durationTitle,
|
|
|
- data: durationData,
|
|
|
- lineStyle: {color: theme.purple300, width: 2},
|
|
|
- itemStyle: {color: theme.purple300},
|
|
|
- yAxisIndex: 1,
|
|
|
- animation: false,
|
|
|
- }),
|
|
|
- ];
|
|
|
-
|
|
|
const height = 150;
|
|
|
const getYAxisOptions = (aggregateType: AggregationOutputType) => ({
|
|
|
max: getYAxisMaxFn(height),
|
|
@@ -116,44 +106,74 @@ const MonitorStats = ({monitor, monitorEnv, orgId}: Props) => {
|
|
|
},
|
|
|
});
|
|
|
|
|
|
+ if (emptyStats) {
|
|
|
+ return renderComponent(
|
|
|
+ <Panel>
|
|
|
+ <PanelBody withPadding>
|
|
|
+ <EmptyMessage
|
|
|
+ title={t('No check-ins have been recorded for this time period.')}
|
|
|
+ />
|
|
|
+ </PanelBody>
|
|
|
+ </Panel>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
return renderComponent(
|
|
|
- <Panel>
|
|
|
- <PanelBody withPadding>
|
|
|
- {!emptyStats ? (
|
|
|
+ <React.Fragment>
|
|
|
+ <Panel>
|
|
|
+ <PanelBody withPadding>
|
|
|
+ <StyledHeaderTitle>{t('Recent Check-Ins')}</StyledHeaderTitle>
|
|
|
<BarChart
|
|
|
isGroupedByDate
|
|
|
showTimeInTooltip
|
|
|
useShortDate
|
|
|
series={[success, failed, timeout, missed]}
|
|
|
stacked
|
|
|
- additionalSeries={additionalSeries}
|
|
|
height={height}
|
|
|
colors={colors}
|
|
|
tooltip={{
|
|
|
trigger: 'axis',
|
|
|
- valueFormatter: (value: number, label?: string) => {
|
|
|
- return label === durationTitle
|
|
|
- ? tooltipFormatter(value, 'duration')
|
|
|
- : tooltipFormatter(value, 'number');
|
|
|
- },
|
|
|
}}
|
|
|
- yAxes={[{...getYAxisOptions('number')}, {...getYAxisOptions('duration')}]}
|
|
|
+ yAxis={getYAxisOptions('number')}
|
|
|
grid={{
|
|
|
top: 6,
|
|
|
bottom: 0,
|
|
|
- left: 4,
|
|
|
+ left: 0,
|
|
|
right: 0,
|
|
|
}}
|
|
|
animation={false}
|
|
|
/>
|
|
|
- ) : (
|
|
|
- <EmptyMessage
|
|
|
- title={t('No check-ins have been recorded for this time period.')}
|
|
|
+ </PanelBody>
|
|
|
+ </Panel>
|
|
|
+ <Panel>
|
|
|
+ <PanelBody withPadding>
|
|
|
+ <StyledHeaderTitle>{t('Average Duration')}</StyledHeaderTitle>
|
|
|
+ <AreaChart
|
|
|
+ isGroupedByDate
|
|
|
+ showTimeInTooltip
|
|
|
+ useShortDate
|
|
|
+ series={[duration]}
|
|
|
+ height={height}
|
|
|
+ colors={[theme.charts.colors[0]]}
|
|
|
+ yAxis={getYAxisOptions('duration')}
|
|
|
+ grid={{
|
|
|
+ top: 6,
|
|
|
+ bottom: 0,
|
|
|
+ left: 0,
|
|
|
+ right: 0,
|
|
|
+ }}
|
|
|
+ tooltip={{
|
|
|
+ valueFormatter: value => tooltipFormatter(value, 'duration'),
|
|
|
+ }}
|
|
|
/>
|
|
|
- )}
|
|
|
- </PanelBody>
|
|
|
- </Panel>
|
|
|
+ </PanelBody>
|
|
|
+ </Panel>
|
|
|
+ </React.Fragment>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
+const StyledHeaderTitle = styled(HeaderTitle)`
|
|
|
+ margin-bottom: ${space(1)};
|
|
|
+`;
|
|
|
+
|
|
|
export default MonitorStats;
|