|
@@ -9,7 +9,7 @@ import momentTimezone from 'moment-timezone';
|
|
|
|
|
|
import {Client} from 'sentry/api';
|
|
|
import Feature from 'sentry/components/acl/feature';
|
|
|
-import GuideAnchor from 'sentry/components/assistant/guideAnchor';
|
|
|
+import {OnDemandMetricAlert} from 'sentry/components/alerts/onDemandMetricAlert';
|
|
|
import {Button} from 'sentry/components/button';
|
|
|
import {AreaChart, AreaChartSeries} from 'sentry/components/charts/areaChart';
|
|
|
import ChartZoom from 'sentry/components/charts/chartZoom';
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
SectionHeading,
|
|
|
SectionValue,
|
|
|
} from 'sentry/components/charts/styles';
|
|
|
+import {isEmptySeries} from 'sentry/components/charts/utils';
|
|
|
import CircleIndicator from 'sentry/components/circleIndicator';
|
|
|
import {
|
|
|
parseStatsPeriod,
|
|
@@ -87,7 +88,7 @@ type Props = WithRouterProps & {
|
|
|
rule: MetricRule;
|
|
|
timePeriod: TimePeriodType;
|
|
|
incidents?: Incident[];
|
|
|
- isOnDemandMetricAlert?: boolean;
|
|
|
+ isOnDemandAlert?: boolean;
|
|
|
selectedIncident?: Incident | null;
|
|
|
};
|
|
|
|
|
@@ -197,8 +198,7 @@ class MetricChart extends PureComponent<Props, State> {
|
|
|
totalDuration: number,
|
|
|
criticalDuration: number,
|
|
|
warningDuration: number,
|
|
|
- waitingForDataDuration: number,
|
|
|
- isOnDemandMetricAlert?: boolean
|
|
|
+ waitingForDataDuration: number
|
|
|
) {
|
|
|
const {rule, organization, project, timePeriod, query} = this.props;
|
|
|
|
|
@@ -226,59 +226,40 @@ class MetricChart extends PureComponent<Props, State> {
|
|
|
1
|
|
|
);
|
|
|
|
|
|
- const isOnDemandAlertWihtoutData =
|
|
|
- isOnDemandMetricAlert && waitingForDataDuration === totalDuration;
|
|
|
-
|
|
|
return (
|
|
|
<StyledChartControls>
|
|
|
<StyledInlineContainer>
|
|
|
- {isOnDemandAlertWihtoutData ? (
|
|
|
- <Fragment>
|
|
|
- <GuideAnchor
|
|
|
- disabled={false}
|
|
|
- target="empty_on_demand_chart"
|
|
|
- position="right"
|
|
|
- >
|
|
|
- <OnDemandNoDataWrapper>
|
|
|
- {t(
|
|
|
- 'This alert lacks historical data due to filters for which we don’t routinely extract metrics.'
|
|
|
+ <Fragment>
|
|
|
+ <SectionHeading>{t('Summary')}</SectionHeading>
|
|
|
+ <StyledSectionValue>
|
|
|
+ <ValueItem>
|
|
|
+ <IconCheckmark color="successText" isCircled />
|
|
|
+ {resolvedPercent ? resolvedPercent.toFixed(2) : 0}%
|
|
|
+ </ValueItem>
|
|
|
+ <ValueItem>
|
|
|
+ <IconWarning color="warningText" />
|
|
|
+ {warningPercent ? warningPercent.toFixed(2) : 0}%
|
|
|
+ </ValueItem>
|
|
|
+ <ValueItem>
|
|
|
+ <IconFire color="errorText" />
|
|
|
+ {criticalPercent ? criticalPercent.toFixed(2) : 0}%
|
|
|
+ </ValueItem>
|
|
|
+ {waitingForDataPercent > 0 && (
|
|
|
+ <StyledTooltip
|
|
|
+ underlineColor="gray200"
|
|
|
+ showUnderline
|
|
|
+ title={t(
|
|
|
+ 'The time spent waiting for metrics matching the filters used.'
|
|
|
)}
|
|
|
- </OnDemandNoDataWrapper>
|
|
|
- </GuideAnchor>
|
|
|
- </Fragment>
|
|
|
- ) : (
|
|
|
- <Fragment>
|
|
|
- <SectionHeading>{t('Summary')}</SectionHeading>
|
|
|
- <StyledSectionValue>
|
|
|
- <ValueItem>
|
|
|
- <IconCheckmark color="successText" isCircled />
|
|
|
- {resolvedPercent ? resolvedPercent.toFixed(2) : 0}%
|
|
|
- </ValueItem>
|
|
|
- <ValueItem>
|
|
|
- <IconWarning color="warningText" />
|
|
|
- {warningPercent ? warningPercent.toFixed(2) : 0}%
|
|
|
- </ValueItem>
|
|
|
- <ValueItem>
|
|
|
- <IconFire color="errorText" />
|
|
|
- {criticalPercent ? criticalPercent.toFixed(2) : 0}%
|
|
|
- </ValueItem>
|
|
|
- {waitingForDataPercent > 0 && (
|
|
|
- <StyledTooltip
|
|
|
- underlineColor="gray200"
|
|
|
- showUnderline
|
|
|
- title={t(
|
|
|
- 'The time spent waiting for metrics matching the filters used.'
|
|
|
- )}
|
|
|
- >
|
|
|
- <ValueItem>
|
|
|
- <IconClock />
|
|
|
- {waitingForDataPercent.toFixed(2)}%
|
|
|
- </ValueItem>
|
|
|
- </StyledTooltip>
|
|
|
- )}
|
|
|
- </StyledSectionValue>
|
|
|
- </Fragment>
|
|
|
- )}
|
|
|
+ >
|
|
|
+ <ValueItem>
|
|
|
+ <IconClock />
|
|
|
+ {waitingForDataPercent.toFixed(2)}%
|
|
|
+ </ValueItem>
|
|
|
+ </StyledTooltip>
|
|
|
+ )}
|
|
|
+ </StyledSectionValue>
|
|
|
+ </Fragment>
|
|
|
</StyledInlineContainer>
|
|
|
{!isSessionAggregate(rule.aggregate) && (
|
|
|
<Feature features={['discover-basic']}>
|
|
@@ -334,7 +315,7 @@ class MetricChart extends PureComponent<Props, State> {
|
|
|
rule,
|
|
|
incidents,
|
|
|
selectedIncident,
|
|
|
- isOnDemandMetricAlert: this.props.isOnDemandMetricAlert,
|
|
|
+ isOnDemandMetricAlert: this.props.isOnDemandAlert,
|
|
|
handleIncidentClick,
|
|
|
});
|
|
|
|
|
@@ -509,13 +490,27 @@ class MetricChart extends PureComponent<Props, State> {
|
|
|
totalDuration,
|
|
|
criticalDuration,
|
|
|
warningDuration,
|
|
|
- waitingForDataDuration,
|
|
|
- this.props.isOnDemandMetricAlert
|
|
|
+ waitingForDataDuration
|
|
|
)}
|
|
|
</ChartPanel>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ renderEmptyOnDemandAlert(timeseriesData: Series[] = [], loading?: boolean) {
|
|
|
+ if (loading || !this.props.isOnDemandAlert || !isEmptySeries(timeseriesData[0])) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <OnDemandMetricAlert
|
|
|
+ dismissable
|
|
|
+ message={t(
|
|
|
+ 'This alert lacks historical data due to filters for which we don’t routinely extract metrics.'
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
renderEmpty(placeholderText = '') {
|
|
|
return (
|
|
|
<ChartPanel>
|
|
@@ -536,7 +531,7 @@ class MetricChart extends PureComponent<Props, State> {
|
|
|
interval,
|
|
|
query,
|
|
|
location,
|
|
|
- isOnDemandMetricAlert,
|
|
|
+ isOnDemandAlert,
|
|
|
} = this.props;
|
|
|
const {aggregate, timeWindow, environment, dataset} = rule;
|
|
|
|
|
@@ -611,11 +606,19 @@ class MetricChart extends PureComponent<Props, State> {
|
|
|
partial={false}
|
|
|
queryExtras={queryExtras}
|
|
|
referrer="api.alerts.alert-rule-chart"
|
|
|
- useOnDemandMetrics={isOnDemandMetricAlert}
|
|
|
+ useOnDemandMetrics={isOnDemandAlert}
|
|
|
>
|
|
|
- {({loading, timeseriesData, comparisonTimeseriesData}) =>
|
|
|
- this.renderChart(loading, timeseriesData, undefined, comparisonTimeseriesData)
|
|
|
- }
|
|
|
+ {({loading, timeseriesData, comparisonTimeseriesData}) => (
|
|
|
+ <Fragment>
|
|
|
+ {this.renderEmptyOnDemandAlert(timeseriesData, loading)}
|
|
|
+ {this.renderChart(
|
|
|
+ loading,
|
|
|
+ timeseriesData,
|
|
|
+ undefined,
|
|
|
+ comparisonTimeseriesData
|
|
|
+ )}
|
|
|
+ </Fragment>
|
|
|
+ )}
|
|
|
</EventsRequest>
|
|
|
);
|
|
|
}
|
|
@@ -668,10 +671,6 @@ const StyledSectionValue = styled(SectionValue)`
|
|
|
margin: 0 0 0 ${space(1.5)};
|
|
|
`;
|
|
|
|
|
|
-const OnDemandNoDataWrapper = styled(SectionValue)`
|
|
|
- margin: 0;
|
|
|
-`;
|
|
|
-
|
|
|
const ValueItem = styled('div')`
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(2, auto);
|