mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Updates to APM alert annotations (#101106)
Make alert annotations on the latency chart show a line annotation at the beginning and have a tooltip.
This commit is contained in:
parent
b740640a2a
commit
fc8ca1da63
7 changed files with 1070 additions and 36 deletions
|
@ -50,7 +50,6 @@ describe('renderApp', () => {
|
|||
const plugins = {
|
||||
licensing: { license$: new Observable() },
|
||||
triggersActionsUi: { actionTypeRegistry: {}, alertTypeRegistry: {} },
|
||||
usageCollection: { reportUiCounter: () => {} },
|
||||
data: {
|
||||
query: {
|
||||
timefilter: {
|
||||
|
@ -69,6 +68,8 @@ describe('renderApp', () => {
|
|||
const embeddable = embeddablePluginMock.createStartContract();
|
||||
|
||||
const pluginsStart = ({
|
||||
data,
|
||||
embeddable,
|
||||
observability: {
|
||||
navigation: {
|
||||
registerSections: () => jest.fn(),
|
||||
|
@ -83,8 +84,7 @@ describe('renderApp', () => {
|
|||
getAddAlertFlyout: jest.fn(),
|
||||
getEditAlertFlyout: jest.fn(),
|
||||
},
|
||||
data,
|
||||
embeddable,
|
||||
usageCollection: { reportUiCounter: () => {} },
|
||||
} as unknown) as ApmPluginStartDeps;
|
||||
|
||||
jest.spyOn(window, 'scrollTo').mockReturnValueOnce(undefined);
|
||||
|
|
|
@ -26,6 +26,7 @@ import { asRelativeDateTimeRange } from '../../../../../common/utils/formatters'
|
|||
import { useTheme } from '../../../../hooks/use_theme';
|
||||
import { AlertType } from '../../../../../common/alert_types';
|
||||
import { getAlertAnnotations } from '../../../shared/charts/helper/get_alert_annotations';
|
||||
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
|
||||
|
||||
type ErrorDistributionAPIResponse = APIReturnType<'GET /api/apm/services/{serviceName}/errors/distribution'>;
|
||||
|
||||
|
@ -64,8 +65,9 @@ export function ErrorDistribution({ distribution, title }: Props) {
|
|||
const xMax = d3.max(buckets, (d) => d.x0);
|
||||
|
||||
const xFormatter = niceTimeFormatter([xMin, xMax]);
|
||||
|
||||
const { observabilityRuleTypeRegistry } = useApmPluginContext();
|
||||
const { alerts } = useApmServiceContext();
|
||||
const { getFormatter } = observabilityRuleTypeRegistry;
|
||||
|
||||
const tooltipProps: SettingsSpec['tooltip'] = {
|
||||
headerFormatter: (tooltip: TooltipValue) => {
|
||||
|
@ -118,6 +120,8 @@ export function ErrorDistribution({ distribution, title }: Props) {
|
|||
alerts: alerts?.filter(
|
||||
(alert) => alert[RULE_ID]?.[0] === AlertType.ErrorCount
|
||||
),
|
||||
chartStartTime: buckets[0].x0,
|
||||
getFormatter,
|
||||
theme,
|
||||
})}
|
||||
</Chart>
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ALERT_SEVERITY_LEVEL } from '@kbn/rule-data-utils/target/technical_field_names';
|
||||
import { ValuesType } from 'utility-types';
|
||||
import { EuiTheme } from '../../../../../../../../src/plugins/kibana_react/common';
|
||||
import { ObservabilityRuleTypeRegistry } from '../../../../../../observability/public';
|
||||
import { APIReturnType } from '../../../../services/rest/createCallApmApi';
|
||||
import { getAlertAnnotations } from './get_alert_annotations';
|
||||
|
||||
type Alert = ValuesType<
|
||||
APIReturnType<'GET /api/apm/services/{serviceName}/alerts'>['alerts']
|
||||
>;
|
||||
|
||||
const euiColorDanger = 'red';
|
||||
const euiColorWarning = 'yellow';
|
||||
const theme = ({
|
||||
eui: { euiColorDanger, euiColorWarning },
|
||||
} as unknown) as EuiTheme;
|
||||
const alert: Alert = {
|
||||
'rule.id': ['apm.transaction_duration'],
|
||||
'kibana.rac.alert.evaluation.value': [2057657.39],
|
||||
'service.name': ['frontend-rum'],
|
||||
'rule.name': ['Latency threshold | frontend-rum'],
|
||||
'kibana.rac.alert.duration.us': [62879000],
|
||||
'kibana.rac.alert.status': ['open'],
|
||||
tags: ['apm', 'service.name:frontend-rum'],
|
||||
'transaction.type': ['page-load'],
|
||||
'kibana.rac.alert.producer': ['apm'],
|
||||
'kibana.rac.alert.uuid': ['af2ae371-df79-4fca-b0eb-a2dbd9478180'],
|
||||
'rule.uuid': ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'],
|
||||
'event.action': ['active'],
|
||||
'@timestamp': ['2021-06-01T16:16:05.183Z'],
|
||||
'kibana.rac.alert.id': ['apm.transaction_duration_All'],
|
||||
'processor.event': ['transaction'],
|
||||
'kibana.rac.alert.evaluation.threshold': [500000],
|
||||
'kibana.rac.alert.start': ['2021-06-01T16:15:02.304Z'],
|
||||
'event.kind': ['state'],
|
||||
'rule.category': ['Latency threshold'],
|
||||
};
|
||||
const chartStartTime = new Date(
|
||||
alert['kibana.rac.alert.start']![0] as string
|
||||
).getTime();
|
||||
const getFormatter: ObservabilityRuleTypeRegistry['getFormatter'] = () => () => ({
|
||||
link: '/',
|
||||
reason: 'a good reason',
|
||||
});
|
||||
|
||||
describe('getAlertAnnotations', () => {
|
||||
describe('with no alerts', () => {
|
||||
it('returns an empty array', () => {
|
||||
expect(
|
||||
getAlertAnnotations({ alerts: [], chartStartTime, getFormatter, theme })
|
||||
).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an alert with an undefined severity', () => {
|
||||
it('uses the danger color', () => {
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [alert],
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.style.line.stroke
|
||||
).toEqual(euiColorDanger);
|
||||
});
|
||||
|
||||
it('says "Alert" in the header', () => {
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [alert],
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.dataValues[0].header
|
||||
).toEqual('Alert');
|
||||
});
|
||||
|
||||
it('uses the reason in the annotation details', () => {
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [alert],
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.dataValues[0].details
|
||||
).toEqual('a good reason');
|
||||
});
|
||||
|
||||
describe('with no formatter', () => {
|
||||
it('uses the rule type', () => {
|
||||
const getNoFormatter: ObservabilityRuleTypeRegistry['getFormatter'] = () =>
|
||||
undefined;
|
||||
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [alert],
|
||||
chartStartTime,
|
||||
getFormatter: getNoFormatter,
|
||||
theme,
|
||||
})![0].props.dataValues[0].details
|
||||
).toEqual(alert['rule.name']![0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the alert start time is before the chart start time', () => {
|
||||
it('uses the chart start time', () => {
|
||||
const beforeChartStartTime = 1622565000000;
|
||||
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [alert],
|
||||
chartStartTime: beforeChartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.dataValues[0].dataValue
|
||||
).toEqual(beforeChartStartTime);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an alert with a warning severity', () => {
|
||||
const warningAlert: Alert = {
|
||||
...alert,
|
||||
[ALERT_SEVERITY_LEVEL]: ['warning'],
|
||||
};
|
||||
|
||||
it('uses the warning color', () => {
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [warningAlert],
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.style.line.stroke
|
||||
).toEqual(euiColorWarning);
|
||||
});
|
||||
|
||||
it('says "Warning Alert" in the header', () => {
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [warningAlert],
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.dataValues[0].header
|
||||
).toEqual('Warning Alert');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an alert with a critical severity', () => {
|
||||
const criticalAlert: Alert = {
|
||||
...alert,
|
||||
[ALERT_SEVERITY_LEVEL]: ['critical'],
|
||||
};
|
||||
|
||||
it('uses the critical color', () => {
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [criticalAlert],
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.style.line.stroke
|
||||
).toEqual(euiColorDanger);
|
||||
});
|
||||
|
||||
it('says "Critical Alert" in the header', () => {
|
||||
expect(
|
||||
getAlertAnnotations({
|
||||
alerts: [criticalAlert],
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
})![0].props.dataValues[0].header
|
||||
).toEqual('Critical Alert');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,46 +4,119 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { ValuesType } from 'utility-types';
|
||||
import { RectAnnotation } from '@elastic/charts';
|
||||
import { EuiTheme } from 'src/plugins/kibana_react/common';
|
||||
import { rgba } from 'polished';
|
||||
import {
|
||||
AnnotationDomainType,
|
||||
LineAnnotation,
|
||||
Position,
|
||||
RectAnnotation,
|
||||
} from '@elastic/charts';
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
ALERT_DURATION,
|
||||
RULE_ID,
|
||||
ALERT_SEVERITY_LEVEL,
|
||||
ALERT_START,
|
||||
ALERT_UUID,
|
||||
RULE_ID,
|
||||
RULE_NAME,
|
||||
} from '@kbn/rule-data-utils/target/technical_field_names';
|
||||
import React from 'react';
|
||||
import { EuiTheme } from 'src/plugins/kibana_react/common';
|
||||
import { ValuesType } from 'utility-types';
|
||||
import type { ObservabilityRuleTypeRegistry } from '../../../../../../observability/public';
|
||||
import { parseTechnicalFields } from '../../../../../../rule_registry/common';
|
||||
import { asDuration, asPercent } from '../../../../../common/utils/formatters';
|
||||
import { APIReturnType } from '../../../../services/rest/createCallApmApi';
|
||||
|
||||
type Alert = ValuesType<
|
||||
APIReturnType<'GET /api/apm/services/{serviceName}/alerts'>['alerts']
|
||||
>;
|
||||
|
||||
function getAlertColor({ theme, ruleId }: { ruleId: string; theme: EuiTheme }) {
|
||||
switch (ruleId) {
|
||||
function getAlertColor({
|
||||
severityLevel,
|
||||
theme,
|
||||
}: {
|
||||
severityLevel: string | undefined;
|
||||
theme: EuiTheme;
|
||||
}) {
|
||||
switch (severityLevel) {
|
||||
case 'warning':
|
||||
return theme.eui.euiColorWarning;
|
||||
default:
|
||||
return theme.eui.euiColorVis2;
|
||||
return theme.eui.euiColorDanger;
|
||||
}
|
||||
}
|
||||
|
||||
function getAlertHeader({
|
||||
severityLevel,
|
||||
}: {
|
||||
severityLevel: string | undefined;
|
||||
}) {
|
||||
switch (severityLevel) {
|
||||
case 'critical':
|
||||
return i18n.translate('xpack.apm.alertAnnotationCriticalTitle', {
|
||||
defaultMessage: 'Critical Alert',
|
||||
});
|
||||
case 'warning':
|
||||
return i18n.translate('xpack.apm.alertAnnotationWarningTitle', {
|
||||
defaultMessage: 'Warning Alert',
|
||||
});
|
||||
default:
|
||||
return i18n.translate('xpack.apm.alertAnnotationNoSeverityTitle', {
|
||||
defaultMessage: 'Alert',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getAlertAnnotations({
|
||||
alerts,
|
||||
chartStartTime,
|
||||
getFormatter,
|
||||
theme,
|
||||
}: {
|
||||
alerts?: Alert[];
|
||||
chartStartTime: number;
|
||||
getFormatter: ObservabilityRuleTypeRegistry['getFormatter'];
|
||||
theme: EuiTheme;
|
||||
}) {
|
||||
return alerts?.flatMap((alert) => {
|
||||
const parsed = parseTechnicalFields(alert);
|
||||
const uuid = parsed[ALERT_UUID]!;
|
||||
const start = new Date(parsed[ALERT_START]!).getTime();
|
||||
// Don't start the annotation before the beginning of the chart time range
|
||||
const start = Math.max(
|
||||
chartStartTime,
|
||||
new Date(parsed[ALERT_START]!).getTime()
|
||||
);
|
||||
const end = start + parsed[ALERT_DURATION]! / 1000;
|
||||
const color = getAlertColor({ ruleId: parsed[RULE_ID]!, theme });
|
||||
const severityLevel = parsed[ALERT_SEVERITY_LEVEL];
|
||||
const color = getAlertColor({ severityLevel, theme });
|
||||
const header = getAlertHeader({ severityLevel });
|
||||
const formatter = getFormatter(parsed[RULE_ID]!);
|
||||
const formatted = {
|
||||
link: undefined,
|
||||
reason: parsed[RULE_NAME],
|
||||
...(formatter?.({
|
||||
fields: parsed,
|
||||
formatters: { asDuration, asPercent },
|
||||
}) ?? {}),
|
||||
};
|
||||
|
||||
return [
|
||||
<LineAnnotation
|
||||
dataValues={[
|
||||
{
|
||||
dataValue: start,
|
||||
details: formatted.reason,
|
||||
header,
|
||||
},
|
||||
]}
|
||||
domainType={AnnotationDomainType.XDomain}
|
||||
id={`alert_${uuid}_line`}
|
||||
key={`alert_${uuid}_line`}
|
||||
marker={<EuiIcon type="alert" />}
|
||||
markerPosition={Position.Top}
|
||||
style={{ line: { opacity: 1, strokeWidth: 2, stroke: color } }}
|
||||
/>,
|
||||
<RectAnnotation
|
||||
key={`alert_${uuid}_area`}
|
||||
id={`alert_${uuid}_area`}
|
||||
|
@ -57,26 +130,6 @@ export function getAlertAnnotations({
|
|||
]}
|
||||
style={{ fill: color }}
|
||||
/>,
|
||||
<RectAnnotation
|
||||
key={`alert_${uuid}_border`}
|
||||
id={`alert_${uuid}_border`}
|
||||
dataValues={[
|
||||
{
|
||||
coordinates: {
|
||||
x0: start,
|
||||
x1: end,
|
||||
y0: 0,
|
||||
y1: 0,
|
||||
},
|
||||
},
|
||||
]}
|
||||
style={{
|
||||
fill: rgba(0, 0, 0, 0),
|
||||
strokeWidth: 2,
|
||||
stroke: color,
|
||||
opacity: 1,
|
||||
}}
|
||||
/>,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,787 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { StoryContext } from '@storybook/react';
|
||||
import React, { ComponentType } from 'react';
|
||||
import { MemoryRouter, Route } from 'react-router-dom';
|
||||
import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_react/common';
|
||||
import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types';
|
||||
import {
|
||||
ApmPluginContext,
|
||||
ApmPluginContextValue,
|
||||
} from '../../../../context/apm_plugin/apm_plugin_context';
|
||||
import { ApmServiceContextProvider } from '../../../../context/apm_service/apm_service_context';
|
||||
import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context';
|
||||
import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider';
|
||||
import {
|
||||
APIReturnType,
|
||||
createCallApmApi,
|
||||
} from '../../../../services/rest/createCallApmApi';
|
||||
import { LatencyChart } from './';
|
||||
|
||||
interface Args {
|
||||
alertsResponse: APIReturnType<'GET /api/apm/services/{serviceName}/alerts'>;
|
||||
latencyChartResponse: APIReturnType<'GET /api/apm/services/{serviceName}/transactions/charts/latency'>;
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'shared/charts/LatencyChart',
|
||||
component: LatencyChart,
|
||||
argTypes: {
|
||||
latencyChartResponse: {
|
||||
control: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
(Story: ComponentType, { args }: StoryContext) => {
|
||||
const { alertsResponse, latencyChartResponse } = args as Args;
|
||||
|
||||
const apmPluginContextMock = ({
|
||||
core: {
|
||||
notifications: {
|
||||
toasts: { addWarning: () => {}, addDanger: () => {} },
|
||||
},
|
||||
http: {
|
||||
get: (endpoint: string) => {
|
||||
switch (endpoint) {
|
||||
case '/api/apm/services/test-service/transactions/charts/latency':
|
||||
return latencyChartResponse;
|
||||
case '/api/apm/services/test-service/alerts':
|
||||
return alertsResponse;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
uiSettings: { get: () => true },
|
||||
},
|
||||
plugins: { observability: { isAlertingExperienceEnabled: () => true } },
|
||||
observabilityRuleTypeRegistry: { getFormatter: () => undefined },
|
||||
} as unknown) as ApmPluginContextValue;
|
||||
|
||||
createCallApmApi(apmPluginContextMock.core);
|
||||
|
||||
return (
|
||||
<ApmPluginContext.Provider value={apmPluginContextMock}>
|
||||
<MemoryRouter initialEntries={[`/app/apm/services/test-service`]}>
|
||||
<Route path="/app/apm/services/:serviceName">
|
||||
<EuiThemeProvider>
|
||||
<MockUrlParamsContextProvider
|
||||
params={{
|
||||
latencyAggregationType: LatencyAggregationType.avg,
|
||||
transactionType: `${Math.random()}`, // So we don't memoize
|
||||
}}
|
||||
>
|
||||
<ApmServiceContextProvider>
|
||||
<ChartPointerEventContextProvider>
|
||||
<Story />
|
||||
</ChartPointerEventContextProvider>
|
||||
</ApmServiceContextProvider>
|
||||
</MockUrlParamsContextProvider>
|
||||
</EuiThemeProvider>
|
||||
</Route>
|
||||
</MemoryRouter>
|
||||
</ApmPluginContext.Provider>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function Example(_args: Args) {
|
||||
return <LatencyChart height={300} />;
|
||||
}
|
||||
Example.args = {
|
||||
alertsResponse: {
|
||||
alerts: [
|
||||
{
|
||||
'rule.id': ['apm.transaction_duration'],
|
||||
'kibana.rac.alert.evaluation.value': [2001708.19],
|
||||
'service.name': ['frontend-rum'],
|
||||
'rule.name': ['Latency threshold | frontend-rum'],
|
||||
'kibana.rac.alert.duration.us': [10000000000],
|
||||
'kibana.rac.alert.status': ['open'],
|
||||
tags: ['apm', 'service.name:frontend-rum'],
|
||||
'transaction.type': ['page-load'],
|
||||
'kibana.rac.alert.producer': ['apm'],
|
||||
'kibana.rac.alert.uuid': ['af2ae371-df79-4fca-b0eb-a2dbd9478180'],
|
||||
'rule.uuid': ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'],
|
||||
'event.action': ['active'],
|
||||
'@timestamp': ['2021-06-01T20:27:48.833Z'],
|
||||
'kibana.rac.alert.id': ['apm.transaction_duration_All'],
|
||||
'processor.event': ['transaction'],
|
||||
'kibana.rac.alert.evaluation.threshold': [500000],
|
||||
'kibana.rac.alert.start': ['2021-06-02T04:00:00.000Z'],
|
||||
'event.kind': ['state'],
|
||||
'rule.category': ['Latency threshold'],
|
||||
},
|
||||
{
|
||||
'rule.id': ['apm.transaction_duration'],
|
||||
'kibana.rac.alert.evaluation.value': [2001708.19],
|
||||
'service.name': ['frontend-rum'],
|
||||
'rule.name': ['Latency threshold | frontend-rum'],
|
||||
'kibana.rac.alert.duration.us': [10000000000],
|
||||
'kibana.rac.alert.status': ['open'],
|
||||
tags: ['apm', 'service.name:frontend-rum'],
|
||||
'transaction.type': ['page-load'],
|
||||
'kibana.rac.alert.producer': ['apm'],
|
||||
'kibana.rac.alert.severity.level': ['warning'],
|
||||
'kibana.rac.alert.uuid': ['af2ae371-df79-4fca-b0eb-a2dbd9478181'],
|
||||
'rule.uuid': ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'],
|
||||
'event.action': ['active'],
|
||||
'@timestamp': ['2021-06-01T20:27:48.833Z'],
|
||||
'kibana.rac.alert.id': ['apm.transaction_duration_All'],
|
||||
'processor.event': ['transaction'],
|
||||
'kibana.rac.alert.evaluation.threshold': [500000],
|
||||
'kibana.rac.alert.start': ['2021-06-02T10:45:00.000Z'],
|
||||
'event.kind': ['state'],
|
||||
'rule.category': ['Latency threshold'],
|
||||
},
|
||||
{
|
||||
'rule.id': ['apm.transaction_duration'],
|
||||
'kibana.rac.alert.evaluation.value': [2001708.19],
|
||||
'service.name': ['frontend-rum'],
|
||||
'rule.name': ['Latency threshold | frontend-rum'],
|
||||
'kibana.rac.alert.duration.us': [1000000000],
|
||||
'kibana.rac.alert.status': ['open'],
|
||||
tags: ['apm', 'service.name:frontend-rum'],
|
||||
'transaction.type': ['page-load'],
|
||||
'kibana.rac.alert.producer': ['apm'],
|
||||
'kibana.rac.alert.severity.level': ['critical'],
|
||||
'kibana.rac.alert.uuid': ['af2ae371-df79-4fca-b0eb-a2dbd9478182'],
|
||||
'rule.uuid': ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'],
|
||||
'event.action': ['active'],
|
||||
'@timestamp': ['2021-06-01T20:27:48.833Z'],
|
||||
'kibana.rac.alert.id': ['apm.transaction_duration_All'],
|
||||
'processor.event': ['transaction'],
|
||||
'kibana.rac.alert.evaluation.threshold': [500000],
|
||||
'kibana.rac.alert.start': ['2021-06-02T16:50:00.000Z'],
|
||||
'event.kind': ['state'],
|
||||
'rule.category': ['Latency threshold'],
|
||||
},
|
||||
],
|
||||
},
|
||||
latencyChartResponse: {
|
||||
anomalyTimeseries: {
|
||||
jobId: 'apm-production-00aa-high_mean_transaction_duration',
|
||||
anomalyScore: [
|
||||
{
|
||||
x0: 1622613600000,
|
||||
x: 1622616000000,
|
||||
y: 90.7449171687341,
|
||||
},
|
||||
],
|
||||
anomalyBoundaries: [],
|
||||
},
|
||||
currentPeriod: {
|
||||
overallAvgDuration: 3912.628446632232,
|
||||
latencyTimeseries: [
|
||||
{
|
||||
x: 1622610000000,
|
||||
y: 4208.681982447083,
|
||||
},
|
||||
{
|
||||
x: 1622610300000,
|
||||
y: 4279.664790174002,
|
||||
},
|
||||
{
|
||||
x: 1622610600000,
|
||||
y: 4137.2139896373055,
|
||||
},
|
||||
{
|
||||
x: 1622610900000,
|
||||
y: 3982.6822523881347,
|
||||
},
|
||||
{
|
||||
x: 1622611200000,
|
||||
y: 4536.218125960061,
|
||||
},
|
||||
{
|
||||
x: 1622611500000,
|
||||
y: 3732.4789422135163,
|
||||
},
|
||||
{
|
||||
x: 1622611800000,
|
||||
y: 4350.351269035533,
|
||||
},
|
||||
{
|
||||
x: 1622612100000,
|
||||
y: 3793.9078812691914,
|
||||
},
|
||||
{
|
||||
x: 1622612400000,
|
||||
y: 4274.450577019568,
|
||||
},
|
||||
{
|
||||
x: 1622612700000,
|
||||
y: 3860.8989280245023,
|
||||
},
|
||||
{
|
||||
x: 1622613000000,
|
||||
y: 4391.058464667006,
|
||||
},
|
||||
{
|
||||
x: 1622613300000,
|
||||
y: 3404.659691081216,
|
||||
},
|
||||
{
|
||||
x: 1622613600000,
|
||||
y: 4743.44957537155,
|
||||
},
|
||||
{
|
||||
x: 1622613900000,
|
||||
y: 4214.091001525166,
|
||||
},
|
||||
{
|
||||
x: 1622614200000,
|
||||
y: 4250.700154559506,
|
||||
},
|
||||
{
|
||||
x: 1622614500000,
|
||||
y: 3814.481089258699,
|
||||
},
|
||||
{
|
||||
x: 1622614800000,
|
||||
y: 10653.246323529413,
|
||||
},
|
||||
{
|
||||
x: 1622615100000,
|
||||
y: 4068.8035160289555,
|
||||
},
|
||||
{
|
||||
x: 1622615400000,
|
||||
y: 4333.230019493178,
|
||||
},
|
||||
{
|
||||
x: 1622615700000,
|
||||
y: 4333.82428115016,
|
||||
},
|
||||
{
|
||||
x: 1622616000000,
|
||||
y: 4532.12358974359,
|
||||
},
|
||||
{
|
||||
x: 1622616300000,
|
||||
y: 3908.336274001038,
|
||||
},
|
||||
{
|
||||
x: 1622616600000,
|
||||
y: 3960.448223350254,
|
||||
},
|
||||
{
|
||||
x: 1622616900000,
|
||||
y: 3823.611138491868,
|
||||
},
|
||||
{
|
||||
x: 1622617200000,
|
||||
y: 4057.287344913151,
|
||||
},
|
||||
{
|
||||
x: 1622617500000,
|
||||
y: 4235.4057539682535,
|
||||
},
|
||||
{
|
||||
x: 1622617800000,
|
||||
y: 4038.2624040920714,
|
||||
},
|
||||
{
|
||||
x: 1622618100000,
|
||||
y: 3672.8091328886608,
|
||||
},
|
||||
{
|
||||
x: 1622618400000,
|
||||
y: 3791.836018957346,
|
||||
},
|
||||
{
|
||||
x: 1622618700000,
|
||||
y: 3744.2,
|
||||
},
|
||||
{
|
||||
x: 1622619000000,
|
||||
y: 3850.6309760956174,
|
||||
},
|
||||
{
|
||||
x: 1622619300000,
|
||||
y: 3644.7181141439205,
|
||||
},
|
||||
{
|
||||
x: 1622619600000,
|
||||
y: 3524.808994441637,
|
||||
},
|
||||
{
|
||||
x: 1622619900000,
|
||||
y: 3292.7054108216435,
|
||||
},
|
||||
{
|
||||
x: 1622620200000,
|
||||
y: 2737.1506919528447,
|
||||
},
|
||||
{
|
||||
x: 1622620500000,
|
||||
y: 3606.829304390725,
|
||||
},
|
||||
{
|
||||
x: 1622620800000,
|
||||
y: 3564.9021739130435,
|
||||
},
|
||||
{
|
||||
x: 1622621100000,
|
||||
y: 3460.8380952380953,
|
||||
},
|
||||
{
|
||||
x: 1622621400000,
|
||||
y: 3667.977192093259,
|
||||
},
|
||||
{
|
||||
x: 1622621700000,
|
||||
y: 3216.88613625536,
|
||||
},
|
||||
{
|
||||
x: 1622622000000,
|
||||
y: 3803.754601226994,
|
||||
},
|
||||
{
|
||||
x: 1622622300000,
|
||||
y: 3412.371867007673,
|
||||
},
|
||||
{
|
||||
x: 1622622600000,
|
||||
y: 3052.968344577063,
|
||||
},
|
||||
{
|
||||
x: 1622622900000,
|
||||
y: 3729.7686965811968,
|
||||
},
|
||||
{
|
||||
x: 1622623200000,
|
||||
y: 4686.836363636364,
|
||||
},
|
||||
{
|
||||
x: 1622623500000,
|
||||
y: 2971.9769189479334,
|
||||
},
|
||||
{
|
||||
x: 1622623800000,
|
||||
y: 2778.008875739645,
|
||||
},
|
||||
{
|
||||
x: 1622624100000,
|
||||
y: 3562.3027475375843,
|
||||
},
|
||||
{
|
||||
x: 1622624400000,
|
||||
y: 4080.326075949367,
|
||||
},
|
||||
{
|
||||
x: 1622624700000,
|
||||
y: 3467.0493765586034,
|
||||
},
|
||||
{
|
||||
x: 1622625000000,
|
||||
y: 3492.6954887218044,
|
||||
},
|
||||
{
|
||||
x: 1622625300000,
|
||||
y: 3761.7813765182186,
|
||||
},
|
||||
{
|
||||
x: 1622625600000,
|
||||
y: 3287.3570332480817,
|
||||
},
|
||||
{
|
||||
x: 1622625900000,
|
||||
y: 3450.071392910634,
|
||||
},
|
||||
{
|
||||
x: 1622626200000,
|
||||
y: 4051.925287356322,
|
||||
},
|
||||
{
|
||||
x: 1622626500000,
|
||||
y: 3557.3268442622953,
|
||||
},
|
||||
{
|
||||
x: 1622626800000,
|
||||
y: 3541.3430837878036,
|
||||
},
|
||||
{
|
||||
x: 1622627100000,
|
||||
y: 3259.4907546226887,
|
||||
},
|
||||
{
|
||||
x: 1622627400000,
|
||||
y: 4360.087576374745,
|
||||
},
|
||||
{
|
||||
x: 1622627700000,
|
||||
y: 2857.941555225359,
|
||||
},
|
||||
{
|
||||
x: 1622628000000,
|
||||
y: 3200.8869168356996,
|
||||
},
|
||||
{
|
||||
x: 1622628300000,
|
||||
y: 4180.898125901009,
|
||||
},
|
||||
{
|
||||
x: 1622628600000,
|
||||
y: 3802.3408973697783,
|
||||
},
|
||||
{
|
||||
x: 1622628900000,
|
||||
y: 4238.939425051335,
|
||||
},
|
||||
{
|
||||
x: 1622629200000,
|
||||
y: 3179.4705021940517,
|
||||
},
|
||||
{
|
||||
x: 1622629500000,
|
||||
y: 3201.2916006339146,
|
||||
},
|
||||
{
|
||||
x: 1622629800000,
|
||||
y: 3275.699311023622,
|
||||
},
|
||||
{
|
||||
x: 1622630100000,
|
||||
y: 3257.324406265791,
|
||||
},
|
||||
{
|
||||
x: 1622630400000,
|
||||
y: 3034.4371781668383,
|
||||
},
|
||||
{
|
||||
x: 1622630700000,
|
||||
y: 5369.278318810866,
|
||||
},
|
||||
{
|
||||
x: 1622631000000,
|
||||
y: 4041.9754016064257,
|
||||
},
|
||||
{
|
||||
x: 1622631300000,
|
||||
y: 3714.3182773109243,
|
||||
},
|
||||
{
|
||||
x: 1622631600000,
|
||||
y: 3433.1565173628587,
|
||||
},
|
||||
{
|
||||
x: 1622631900000,
|
||||
y: 3911.4570990806947,
|
||||
},
|
||||
{
|
||||
x: 1622632200000,
|
||||
y: 3399.647921760391,
|
||||
},
|
||||
{
|
||||
x: 1622632500000,
|
||||
y: 3406.6709171162333,
|
||||
},
|
||||
{
|
||||
x: 1622632800000,
|
||||
y: 3796.1313494099536,
|
||||
},
|
||||
{
|
||||
x: 1622633100000,
|
||||
y: 4641.3845376452755,
|
||||
},
|
||||
{
|
||||
x: 1622633400000,
|
||||
y: 4476.154203197524,
|
||||
},
|
||||
{
|
||||
x: 1622633700000,
|
||||
y: 3615.25256147541,
|
||||
},
|
||||
{
|
||||
x: 1622634000000,
|
||||
y: 4720.787442099846,
|
||||
},
|
||||
{
|
||||
x: 1622634300000,
|
||||
y: 3572.421187308086,
|
||||
},
|
||||
{
|
||||
x: 1622634600000,
|
||||
y: 3945.6472690148034,
|
||||
},
|
||||
{
|
||||
x: 1622634900000,
|
||||
y: 3737.5801910507794,
|
||||
},
|
||||
{
|
||||
x: 1622635200000,
|
||||
y: 4170.001972386588,
|
||||
},
|
||||
{
|
||||
x: 1622635500000,
|
||||
y: 3420.740480961924,
|
||||
},
|
||||
{
|
||||
x: 1622635800000,
|
||||
y: 4206.541751527495,
|
||||
},
|
||||
{
|
||||
x: 1622636100000,
|
||||
y: 5315.030436917034,
|
||||
},
|
||||
{
|
||||
x: 1622636400000,
|
||||
y: 3784.5201995012467,
|
||||
},
|
||||
{
|
||||
x: 1622636700000,
|
||||
y: 3948.166,
|
||||
},
|
||||
{
|
||||
x: 1622637000000,
|
||||
y: 3856.821,
|
||||
},
|
||||
{
|
||||
x: 1622637300000,
|
||||
y: 3463.410723581468,
|
||||
},
|
||||
{
|
||||
x: 1622637600000,
|
||||
y: 3747.9292260692464,
|
||||
},
|
||||
{
|
||||
x: 1622637900000,
|
||||
y: 3454.205677290837,
|
||||
},
|
||||
{
|
||||
x: 1622638200000,
|
||||
y: 4110.846038114343,
|
||||
},
|
||||
{
|
||||
x: 1622638500000,
|
||||
y: 3336.22131147541,
|
||||
},
|
||||
{
|
||||
x: 1622638800000,
|
||||
y: 4649.731621349446,
|
||||
},
|
||||
{
|
||||
x: 1622639100000,
|
||||
y: 3165.643870314083,
|
||||
},
|
||||
{
|
||||
x: 1622639400000,
|
||||
y: 4956.4894625922025,
|
||||
},
|
||||
{
|
||||
x: 1622639700000,
|
||||
y: 3683.55785750379,
|
||||
},
|
||||
{
|
||||
x: 1622640000000,
|
||||
y: 3352.1956841589013,
|
||||
},
|
||||
{
|
||||
x: 1622640300000,
|
||||
y: 4620.592957017089,
|
||||
},
|
||||
{
|
||||
x: 1622640600000,
|
||||
y: 3428.9030303030304,
|
||||
},
|
||||
{
|
||||
x: 1622640900000,
|
||||
y: 3698.219571567673,
|
||||
},
|
||||
{
|
||||
x: 1622641200000,
|
||||
y: 4377.621443089431,
|
||||
},
|
||||
{
|
||||
x: 1622641500000,
|
||||
y: 5961.083591331269,
|
||||
},
|
||||
{
|
||||
x: 1622641800000,
|
||||
y: 3669.294088425236,
|
||||
},
|
||||
{
|
||||
x: 1622642100000,
|
||||
y: 3259.020638820639,
|
||||
},
|
||||
{
|
||||
x: 1622642400000,
|
||||
y: 3819.455216535433,
|
||||
},
|
||||
{
|
||||
x: 1622642700000,
|
||||
y: 3371.4274809160306,
|
||||
},
|
||||
{
|
||||
x: 1622643000000,
|
||||
y: 3743.922564102564,
|
||||
},
|
||||
{
|
||||
x: 1622643300000,
|
||||
y: 3834.112612612613,
|
||||
},
|
||||
{
|
||||
x: 1622643600000,
|
||||
y: 5444.119339371337,
|
||||
},
|
||||
{
|
||||
x: 1622643900000,
|
||||
y: 3574.8830908178625,
|
||||
},
|
||||
{
|
||||
x: 1622644200000,
|
||||
y: 3768.3267119707266,
|
||||
},
|
||||
{
|
||||
x: 1622644500000,
|
||||
y: 4140.902912621359,
|
||||
},
|
||||
{
|
||||
x: 1622644800000,
|
||||
y: 3342.3307086614172,
|
||||
},
|
||||
{
|
||||
x: 1622645100000,
|
||||
y: 3236.124428643982,
|
||||
},
|
||||
{
|
||||
x: 1622645400000,
|
||||
y: 3657.412544620092,
|
||||
},
|
||||
{
|
||||
x: 1622645700000,
|
||||
y: 3674.141194331984,
|
||||
},
|
||||
{
|
||||
x: 1622646000000,
|
||||
y: 3898.6586586586586,
|
||||
},
|
||||
{
|
||||
x: 1622646300000,
|
||||
y: 3124.4311287916457,
|
||||
},
|
||||
{
|
||||
x: 1622646600000,
|
||||
y: 3272.2118126272912,
|
||||
},
|
||||
{
|
||||
x: 1622646900000,
|
||||
y: 3800.5066872427983,
|
||||
},
|
||||
{
|
||||
x: 1622647200000,
|
||||
y: 3578.5175751400916,
|
||||
},
|
||||
{
|
||||
x: 1622647500000,
|
||||
y: 3542.9040895813046,
|
||||
},
|
||||
{
|
||||
x: 1622647800000,
|
||||
y: 3732.763408521303,
|
||||
},
|
||||
{
|
||||
x: 1622648100000,
|
||||
y: 3434.2902750491157,
|
||||
},
|
||||
{
|
||||
x: 1622648400000,
|
||||
y: 4330.74908328968,
|
||||
},
|
||||
{
|
||||
x: 1622648700000,
|
||||
y: 4577.840615690169,
|
||||
},
|
||||
{
|
||||
x: 1622649000000,
|
||||
y: 4781.996879875195,
|
||||
},
|
||||
{
|
||||
x: 1622649300000,
|
||||
y: 4025.662721893491,
|
||||
},
|
||||
{
|
||||
x: 1622649600000,
|
||||
y: 3477.1844410097888,
|
||||
},
|
||||
{
|
||||
x: 1622649900000,
|
||||
y: 3391.0057291666667,
|
||||
},
|
||||
{
|
||||
x: 1622650200000,
|
||||
y: 4029.693094629156,
|
||||
},
|
||||
{
|
||||
x: 1622650500000,
|
||||
y: 3592.2772633744858,
|
||||
},
|
||||
{
|
||||
x: 1622650800000,
|
||||
y: 4179.225288509784,
|
||||
},
|
||||
{
|
||||
x: 1622651100000,
|
||||
y: 4873.780174627632,
|
||||
},
|
||||
{
|
||||
x: 1622651400000,
|
||||
y: 3727.96688409433,
|
||||
},
|
||||
{
|
||||
x: 1622651700000,
|
||||
y: 4258.164556962025,
|
||||
},
|
||||
{
|
||||
x: 1622652000000,
|
||||
y: 5636.077639751553,
|
||||
},
|
||||
{
|
||||
x: 1622652300000,
|
||||
y: 4770.074738415546,
|
||||
},
|
||||
{
|
||||
x: 1622652600000,
|
||||
y: 4078.271392405063,
|
||||
},
|
||||
{
|
||||
x: 1622652900000,
|
||||
y: 3408.997037037037,
|
||||
},
|
||||
{
|
||||
x: 1622653200000,
|
||||
y: 5453.50645994832,
|
||||
},
|
||||
{
|
||||
x: 1622653500000,
|
||||
y: 3975.198969072165,
|
||||
},
|
||||
{
|
||||
x: 1622653800000,
|
||||
y: 2694.520754716981,
|
||||
},
|
||||
],
|
||||
},
|
||||
previousPeriod: { latencyTimeseries: [] },
|
||||
},
|
||||
};
|
||||
|
||||
export function NoData(_args: Args) {
|
||||
return <LatencyChart height={300} />;
|
||||
}
|
||||
NoData.args = {
|
||||
alertsResponse: { alerts: [] },
|
||||
latencyChartResponse: {
|
||||
currentPeriod: { latencyTimeseries: [] },
|
||||
previousPeriod: { latencyTimeseries: [] },
|
||||
},
|
||||
};
|
|
@ -43,6 +43,7 @@ import { onBrushEnd, isTimeseriesEmpty } from './helper/helper';
|
|||
import { getLatencyChartSelector } from '../../../selectors/latency_chart_selectors';
|
||||
import { APMServiceAlert } from '../../../context/apm_service/apm_service_context';
|
||||
import { getAlertAnnotations } from './helper/get_alert_annotations';
|
||||
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
|
@ -81,6 +82,8 @@ export function TimeseriesChart({
|
|||
alerts,
|
||||
}: Props) {
|
||||
const history = useHistory();
|
||||
const { observabilityRuleTypeRegistry } = useApmPluginContext();
|
||||
const { getFormatter } = observabilityRuleTypeRegistry;
|
||||
const { annotations } = useAnnotationsContext();
|
||||
const { setPointerEvent, chartRef } = useChartPointerEventContext();
|
||||
const theme = useTheme();
|
||||
|
@ -203,6 +206,8 @@ export function TimeseriesChart({
|
|||
)}
|
||||
{getAlertAnnotations({
|
||||
alerts,
|
||||
chartStartTime: xValues[0],
|
||||
getFormatter,
|
||||
theme,
|
||||
})}
|
||||
</Chart>
|
||||
|
|
|
@ -9,7 +9,7 @@ import { AlertTypeModel, AlertTypeRegistryContract } from '../../../triggers_act
|
|||
import { ParsedTechnicalFields } from '../../../rule_registry/common/parse_technical_fields';
|
||||
import { AsDuration, AsPercent } from '../../common/utils/formatters';
|
||||
|
||||
type Formatter = (options: {
|
||||
export type Formatter = (options: {
|
||||
fields: ParsedTechnicalFields & Record<string, any>;
|
||||
formatters: { asDuration: AsDuration; asPercent: AsPercent };
|
||||
}) => { reason: string; link: string };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue