review: Update alert template and add tests

This commit is contained in:
Drew Davis 2026-04-16 11:15:49 -04:00
parent 5ee40f64c6
commit f4459e4e60
5 changed files with 692 additions and 25 deletions

View file

@ -0,0 +1,284 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`buildAlertMessageTemplateTitle saved search alerts ALERT state above threshold=5 alertValue=10 1`] = `"🚨 Alert for "My Search" - 10 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts ALERT state above_exclusive threshold=5 alertValue=10 1`] = `"🚨 Alert for "My Search" - 10 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts ALERT state below threshold=5 alertValue=2 1`] = `"🚨 Alert for "My Search" - 2 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts ALERT state below_or_equal threshold=5 alertValue=3 1`] = `"🚨 Alert for "My Search" - 3 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts ALERT state equal threshold=5 alertValue=5 1`] = `"🚨 Alert for "My Search" - 5 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts ALERT state not_equal threshold=5 alertValue=10 1`] = `"🚨 Alert for "My Search" - 10 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts OK state (resolved) above threshold=5 okValue=3 1`] = `"✅ Alert for "My Search" - 3 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts OK state (resolved) above_exclusive threshold=5 okValue=3 1`] = `"✅ Alert for "My Search" - 3 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts OK state (resolved) below threshold=5 okValue=10 1`] = `"✅ Alert for "My Search" - 10 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts OK state (resolved) below_or_equal threshold=5 okValue=10 1`] = `"✅ Alert for "My Search" - 10 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts OK state (resolved) equal threshold=5 okValue=10 1`] = `"✅ Alert for "My Search" - 10 lines found"`;
exports[`buildAlertMessageTemplateTitle saved search alerts OK state (resolved) not_equal threshold=5 okValue=5 1`] = `"✅ Alert for "My Search" - 5 lines found"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state above threshold=5 alertValue=10 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 10 meets or exceeds 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state above_exclusive threshold=5 alertValue=10 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 10 exceeds 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state below threshold=5 alertValue=2 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 2 falls below 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state below_or_equal threshold=5 alertValue=3 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 3 falls to or below 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state decimal threshold 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 10.1 meets or exceeds 1.5"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state equal threshold=5 alertValue=5 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 5 equals 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state integer threshold rounds value 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 11 meets or exceeds 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts ALERT state not_equal threshold=5 alertValue=10 1`] = `"🚨 Alert for "Test Chart" in "My Dashboard" - 10 does not equal 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts OK state (resolved) above threshold=5 okValue=3 1`] = `"✅ Alert for "Test Chart" in "My Dashboard" - 3 falls below 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts OK state (resolved) above_exclusive threshold=5 okValue=3 1`] = `"✅ Alert for "Test Chart" in "My Dashboard" - 3 falls to or below 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts OK state (resolved) below threshold=5 okValue=10 1`] = `"✅ Alert for "Test Chart" in "My Dashboard" - 10 meets or exceeds 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts OK state (resolved) below_or_equal threshold=5 okValue=10 1`] = `"✅ Alert for "Test Chart" in "My Dashboard" - 10 exceeds 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts OK state (resolved) equal threshold=5 okValue=10 1`] = `"✅ Alert for "Test Chart" in "My Dashboard" - 10 does not equal 5"`;
exports[`buildAlertMessageTemplateTitle tile alerts OK state (resolved) not_equal threshold=5 okValue=5 1`] = `"✅ Alert for "Test Chart" in "My Dashboard" - 5 equals 5"`;
exports[`renderAlertTemplate saved search alerts ALERT state above threshold=5 alertValue=10 1`] = `
"
10 lines found, which meets or exceeds the threshold of 5 lines
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
\`\`\`
"2023-03-17 22:14:01","error","Failed to connect to database"
"2023-03-17 22:13:45","error","Connection timeout after 30s"
"2023-03-17 22:12:30","error","Retry limit exceeded"
\`\`\`"
`;
exports[`renderAlertTemplate saved search alerts ALERT state above_exclusive threshold=5 alertValue=10 1`] = `
"
10 lines found, which exceeds the threshold of 5 lines
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
\`\`\`
"2023-03-17 22:14:01","error","Failed to connect to database"
"2023-03-17 22:13:45","error","Connection timeout after 30s"
"2023-03-17 22:12:30","error","Retry limit exceeded"
\`\`\`"
`;
exports[`renderAlertTemplate saved search alerts ALERT state below threshold=5 alertValue=2 1`] = `
"
2 lines found, which falls below the threshold of 5 lines
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
\`\`\`
"2023-03-17 22:14:01","error","Failed to connect to database"
"2023-03-17 22:13:45","error","Connection timeout after 30s"
"2023-03-17 22:12:30","error","Retry limit exceeded"
\`\`\`"
`;
exports[`renderAlertTemplate saved search alerts ALERT state below_or_equal threshold=5 alertValue=3 1`] = `
"
3 lines found, which falls to or below the threshold of 5 lines
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
\`\`\`
"2023-03-17 22:14:01","error","Failed to connect to database"
"2023-03-17 22:13:45","error","Connection timeout after 30s"
"2023-03-17 22:12:30","error","Retry limit exceeded"
\`\`\`"
`;
exports[`renderAlertTemplate saved search alerts ALERT state equal threshold=5 alertValue=5 1`] = `
"
5 lines found, which equals the threshold of 5 lines
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
\`\`\`
"2023-03-17 22:14:01","error","Failed to connect to database"
"2023-03-17 22:13:45","error","Connection timeout after 30s"
"2023-03-17 22:12:30","error","Retry limit exceeded"
\`\`\`"
`;
exports[`renderAlertTemplate saved search alerts ALERT state not_equal threshold=5 alertValue=10 1`] = `
"
10 lines found, which does not equal the threshold of 5 lines
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
\`\`\`
"2023-03-17 22:14:01","error","Failed to connect to database"
"2023-03-17 22:13:45","error","Connection timeout after 30s"
"2023-03-17 22:12:30","error","Retry limit exceeded"
\`\`\`"
`;
exports[`renderAlertTemplate saved search alerts ALERT state with group 1`] = `
"Group: "http"
10 lines found, which meets or exceeds the threshold of 5 lines
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
\`\`\`
"2023-03-17 22:14:01","error","Failed to connect to database"
"2023-03-17 22:13:45","error","Connection timeout after 30s"
"2023-03-17 22:12:30","error","Retry limit exceeded"
\`\`\`"
`;
exports[`renderAlertTemplate saved search alerts OK state (resolved) above threshold=5 okValue=3 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate saved search alerts OK state (resolved) above_exclusive threshold=5 okValue=3 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate saved search alerts OK state (resolved) below threshold=5 okValue=10 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate saved search alerts OK state (resolved) below_or_equal threshold=5 okValue=10 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate saved search alerts OK state (resolved) equal threshold=5 okValue=10 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate saved search alerts OK state (resolved) not_equal threshold=5 okValue=5 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate saved search alerts OK state (resolved) with group 1`] = `
"Group: "http" - The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state above threshold=5 alertValue=10 1`] = `
"
10 meets or exceeds 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state above_exclusive threshold=5 alertValue=10 1`] = `
"
10 exceeds 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state below threshold=5 alertValue=2 1`] = `
"
2 falls below 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state below_or_equal threshold=5 alertValue=3 1`] = `
"
3 falls to or below 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state decimal threshold 1`] = `
"
10.1 meets or exceeds 1.5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state equal threshold=5 alertValue=5 1`] = `
"
5 equals 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state integer threshold rounds value 1`] = `
"
11 meets or exceeds 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state not_equal threshold=5 alertValue=10 1`] = `
"
10 does not equal 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts ALERT state with group 1`] = `
"Group: "us-east-1"
10 meets or exceeds 5
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts OK state (resolved) above threshold=5 okValue=3 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts OK state (resolved) above_exclusive threshold=5 okValue=3 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts OK state (resolved) below threshold=5 okValue=10 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts OK state (resolved) below_or_equal threshold=5 okValue=10 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts OK state (resolved) equal threshold=5 okValue=10 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts OK state (resolved) not_equal threshold=5 okValue=5 1`] = `
"The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;
exports[`renderAlertTemplate tile alerts OK state (resolved) with group 1`] = `
"Group: "us-east-1" - The alert has been resolved.
Time Range (UTC): [Mar 17 10:10:00 PM - Mar 17 10:15:00 PM)
"
`;

View file

@ -952,7 +952,7 @@ describe('checkAlerts', () => {
text: [
'*<http://app:8080/search/fake-saved-search-id?from=1679091183103&to=1679091239103&isLive=false | 🚨 Alert for "My Search" - 10 lines found>*',
'Group: "http"',
'10 lines found, expected less than 1 lines',
'10 lines found, which meets or exceeds the threshold of 1 lines',
'Time Range (UTC): [Mar 17 10:13:03 PM - Mar 17 10:13:59 PM)',
'Custom body ',
'```',
@ -1012,7 +1012,7 @@ describe('checkAlerts', () => {
text: [
'*<http://app:8080/search/fake-saved-search-id?from=1679091183103&to=1679091239103&isLive=false | 🚨 Alert for "My Search" - 10 lines found>*',
'Group: "http"',
'10 lines found, expected less than 1 lines',
'10 lines found, which meets or exceeds the threshold of 1 lines',
'Time Range (UTC): [Mar 17 10:13:03 PM - Mar 17 10:13:59 PM)',
'Custom body ',
'```',
@ -1119,7 +1119,7 @@ describe('checkAlerts', () => {
text: [
'*<http://app:8080/search/fake-saved-search-id?from=1679091183103&to=1679091239103&isLive=false | 🚨 Alert for "My Search" - 10 lines found>*',
'Group: "http"',
'10 lines found, expected less than 1 lines',
'10 lines found, which meets or exceeds the threshold of 1 lines',
'Time Range (UTC): [Mar 17 10:13:03 PM - Mar 17 10:13:59 PM)',
'',
' Runbook URL: https://example.com',
@ -1148,7 +1148,7 @@ describe('checkAlerts', () => {
text: [
'*<http://app:8080/search/fake-saved-search-id?from=1679091183103&to=1679091239103&isLive=false | 🚨 Alert for "My Search" - 10 lines found>*',
'Group: "http"',
'10 lines found, expected less than 1 lines',
'10 lines found, which meets or exceeds the threshold of 1 lines',
'Time Range (UTC): [Mar 17 10:13:03 PM - Mar 17 10:13:59 PM)',
'',
' Runbook URL: https://example.com',

View file

@ -0,0 +1,402 @@
import {
AlertState,
AlertThresholdType,
SourceKind,
} from '@hyperdx/common-utils/dist/types';
import mongoose from 'mongoose';
import { makeTile } from '@/fixtures';
import { AlertSource } from '@/models/alert';
import { loadProvider } from '@/tasks/checkAlerts/providers';
import {
AlertMessageTemplateDefaultView,
buildAlertMessageTemplateTitle,
renderAlertTemplate,
} from '@/tasks/checkAlerts/template';
let alertProvider: any;
beforeAll(async () => {
alertProvider = await loadProvider();
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const mockMetadata = {
getColumn: jest.fn().mockImplementation(({ column }) => {
const columnMap = {
Timestamp: { name: 'Timestamp', type: 'DateTime' },
Body: { name: 'Body', type: 'String' },
SeverityText: { name: 'SeverityText', type: 'String' },
ServiceName: { name: 'ServiceName', type: 'String' },
};
return Promise.resolve(columnMap[column]);
}),
getColumns: jest.fn().mockResolvedValue([]),
getMapKeys: jest.fn().mockResolvedValue([]),
getMapValues: jest.fn().mockResolvedValue([]),
getAllFields: jest.fn().mockResolvedValue([]),
getTableMetadata: jest.fn().mockResolvedValue({}),
getClickHouseSettings: jest.fn().mockReturnValue({}),
setClickHouseSettings: jest.fn(),
getSkipIndices: jest.fn().mockResolvedValue([]),
getSetting: jest.fn().mockResolvedValue(undefined),
} as any;
const sampleLogsCsv = [
'"2023-03-17 22:14:01","error","Failed to connect to database"',
'"2023-03-17 22:13:45","error","Connection timeout after 30s"',
'"2023-03-17 22:12:30","error","Retry limit exceeded"',
].join('\n');
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const mockClickhouseClient = {
query: jest.fn().mockResolvedValue({
json: jest.fn().mockResolvedValue({ data: [] }),
text: jest.fn().mockResolvedValue(sampleLogsCsv),
}),
} as any;
const startTime = new Date('2023-03-17T22:10:00.000Z');
const endTime = new Date('2023-03-17T22:15:00.000Z');
const makeSearchView = (
overrides: Partial<AlertMessageTemplateDefaultView> & {
thresholdType?: AlertThresholdType;
threshold?: number;
value?: number;
group?: string;
} = {},
): AlertMessageTemplateDefaultView => ({
alert: {
thresholdType: overrides.thresholdType ?? AlertThresholdType.ABOVE,
threshold: overrides.threshold ?? 5,
source: AlertSource.SAVED_SEARCH,
channel: { type: null },
interval: '1m',
},
source: {
id: 'fake-source-id',
kind: SourceKind.Log,
team: 'team-123',
from: { databaseName: 'default', tableName: 'otel_logs' },
timestampValueExpression: 'Timestamp',
connection: 'connection-123',
name: 'Logs',
defaultTableSelectExpression: 'Timestamp, Body',
},
savedSearch: {
_id: 'fake-saved-search-id' as any,
team: 'team-123' as any,
id: 'fake-saved-search-id',
name: 'My Search',
select: 'Body',
where: 'Body: "error"',
whereLanguage: 'lucene',
orderBy: 'timestamp',
source: 'fake-source-id' as any,
tags: ['test'],
createdAt: new Date(),
updatedAt: new Date(),
},
attributes: {},
granularity: '1m',
group: overrides.group,
isGroupedAlert: false,
startTime,
endTime,
value: overrides.value ?? 10,
});
const testTile = makeTile({ id: 'test-tile-id' });
const makeTileView = (
overrides: Partial<AlertMessageTemplateDefaultView> & {
thresholdType?: AlertThresholdType;
threshold?: number;
value?: number;
group?: string;
} = {},
): AlertMessageTemplateDefaultView => ({
alert: {
thresholdType: overrides.thresholdType ?? AlertThresholdType.ABOVE,
threshold: overrides.threshold ?? 5,
source: AlertSource.TILE,
channel: { type: null },
interval: '1m',
tileId: 'test-tile-id',
},
dashboard: {
_id: new mongoose.Types.ObjectId(),
id: 'id-123',
name: 'My Dashboard',
tiles: [testTile],
team: 'team-123' as any,
tags: ['test'],
createdAt: new Date(),
updatedAt: new Date(),
},
attributes: {},
granularity: '5 minute',
group: overrides.group,
isGroupedAlert: false,
startTime,
endTime,
value: overrides.value ?? 10,
});
const render = (view: AlertMessageTemplateDefaultView, state: AlertState) =>
renderAlertTemplate({
alertProvider,
clickhouseClient: mockClickhouseClient,
metadata: mockMetadata,
state,
template: null,
title: 'Test Alert Title',
view,
teamWebhooksById: new Map(),
});
interface AlertCase {
thresholdType: AlertThresholdType;
threshold: number;
alertValue: number; // value that would trigger the alert
okValue: number; // value that would resolve the alert
}
const alertCases: AlertCase[] = [
{
thresholdType: AlertThresholdType.ABOVE,
threshold: 5,
alertValue: 10,
okValue: 3,
},
{
thresholdType: AlertThresholdType.ABOVE_EXCLUSIVE,
threshold: 5,
alertValue: 10,
okValue: 3,
},
{
thresholdType: AlertThresholdType.BELOW,
threshold: 5,
alertValue: 2,
okValue: 10,
},
{
thresholdType: AlertThresholdType.BELOW_OR_EQUAL,
threshold: 5,
alertValue: 3,
okValue: 10,
},
{
thresholdType: AlertThresholdType.EQUAL,
threshold: 5,
alertValue: 5,
okValue: 10,
},
{
thresholdType: AlertThresholdType.NOT_EQUAL,
threshold: 5,
alertValue: 10,
okValue: 5,
},
];
describe('renderAlertTemplate', () => {
describe('saved search alerts', () => {
describe('ALERT state', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold alertValue=$alertValue',
async ({ thresholdType, threshold, alertValue }) => {
const result = await render(
makeSearchView({ thresholdType, threshold, value: alertValue }),
AlertState.ALERT,
);
expect(result).toMatchSnapshot();
},
);
it('with group', async () => {
const result = await render(
makeSearchView({ group: 'http' }),
AlertState.ALERT,
);
expect(result).toMatchSnapshot();
});
});
describe('OK state (resolved)', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold okValue=$okValue',
async ({ thresholdType, threshold, okValue }) => {
const result = await render(
makeSearchView({ thresholdType, threshold, value: okValue }),
AlertState.OK,
);
expect(result).toMatchSnapshot();
},
);
it('with group', async () => {
const result = await render(
makeSearchView({ group: 'http' }),
AlertState.OK,
);
expect(result).toMatchSnapshot();
});
});
});
describe('tile alerts', () => {
describe('ALERT state', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold alertValue=$alertValue',
async ({ thresholdType, threshold, alertValue }) => {
const result = await render(
makeTileView({ thresholdType, threshold, value: alertValue }),
AlertState.ALERT,
);
expect(result).toMatchSnapshot();
},
);
it('with group', async () => {
const result = await render(
makeTileView({ group: 'us-east-1' }),
AlertState.ALERT,
);
expect(result).toMatchSnapshot();
});
it('decimal threshold', async () => {
const result = await render(
makeTileView({
thresholdType: AlertThresholdType.ABOVE,
threshold: 1.5,
value: 10.123,
}),
AlertState.ALERT,
);
expect(result).toMatchSnapshot();
});
it('integer threshold rounds value', async () => {
const result = await render(
makeTileView({
thresholdType: AlertThresholdType.ABOVE,
threshold: 5,
value: 10.789,
}),
AlertState.ALERT,
);
expect(result).toMatchSnapshot();
});
});
describe('OK state (resolved)', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold okValue=$okValue',
async ({ thresholdType, threshold, okValue }) => {
const result = await render(
makeTileView({ thresholdType, threshold, value: okValue }),
AlertState.OK,
);
expect(result).toMatchSnapshot();
},
);
it('with group', async () => {
const result = await render(
makeTileView({ group: 'us-east-1' }),
AlertState.OK,
);
expect(result).toMatchSnapshot();
});
});
});
});
describe('buildAlertMessageTemplateTitle', () => {
describe('saved search alerts', () => {
describe('ALERT state', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold alertValue=$alertValue',
({ thresholdType, threshold, alertValue }) => {
const result = buildAlertMessageTemplateTitle({
view: makeSearchView({
thresholdType,
threshold,
value: alertValue,
}),
state: AlertState.ALERT,
});
expect(result).toMatchSnapshot();
},
);
});
describe('OK state (resolved)', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold okValue=$okValue',
({ thresholdType, threshold, okValue }) => {
const result = buildAlertMessageTemplateTitle({
view: makeSearchView({ thresholdType, threshold, value: okValue }),
state: AlertState.OK,
});
expect(result).toMatchSnapshot();
},
);
});
});
describe('tile alerts', () => {
describe('ALERT state', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold alertValue=$alertValue',
({ thresholdType, threshold, alertValue }) => {
const result = buildAlertMessageTemplateTitle({
view: makeTileView({ thresholdType, threshold, value: alertValue }),
state: AlertState.ALERT,
});
expect(result).toMatchSnapshot();
},
);
it('decimal threshold', () => {
const result = buildAlertMessageTemplateTitle({
view: makeTileView({
thresholdType: AlertThresholdType.ABOVE,
threshold: 1.5,
value: 10.123,
}),
state: AlertState.ALERT,
});
expect(result).toMatchSnapshot();
});
it('integer threshold rounds value', () => {
const result = buildAlertMessageTemplateTitle({
view: makeTileView({
thresholdType: AlertThresholdType.ABOVE,
threshold: 5,
value: 10.789,
}),
state: AlertState.ALERT,
});
expect(result).toMatchSnapshot();
});
});
describe('OK state (resolved)', () => {
it.each(alertCases)(
'$thresholdType threshold=$threshold okValue=$okValue',
({ thresholdType, threshold, okValue }) => {
const result = buildAlertMessageTemplateTitle({
view: makeTileView({ thresholdType, threshold, value: okValue }),
state: AlertState.OK,
});
expect(result).toMatchSnapshot();
},
);
});
});
});

View file

@ -248,7 +248,7 @@ describe('Single Invocation Alert Test', () => {
// Verify the message body contains the search link
const messageBody = webhookPayload.blocks[0].text.text;
expect(messageBody).toContain('lines found');
expect(messageBody).toContain('expected less than 1 lines');
expect(messageBody).toContain('meets or exceeds the threshold of 1 lines');
expect(messageBody).toContain('http://app:8080/search/');
expect(messageBody).toContain('from=');
expect(messageBody).toContain('to=');

View file

@ -81,25 +81,6 @@ const describeThresholdResolution = (
}
};
const describeThresholdExpectation = (
thresholdType: AlertThresholdType,
): string => {
switch (thresholdType) {
case AlertThresholdType.ABOVE:
return 'less than';
case AlertThresholdType.BELOW:
return 'at least';
case AlertThresholdType.ABOVE_EXCLUSIVE:
return 'at most';
case AlertThresholdType.BELOW_OR_EQUAL:
return 'greater than';
case AlertThresholdType.EQUAL:
return 'not equal to';
case AlertThresholdType.NOT_EQUAL:
return 'equal to';
}
};
const MAX_MESSAGE_LENGTH = 500;
const NOTIFY_FN_NAME = '__hdx_notify_channel__';
const IS_MATCH_FN_NAME = 'is_match';
@ -703,7 +684,7 @@ ${targetTemplate}`;
}
rawTemplateBody = `${group ? `Group: "${group}"` : ''}
${value} lines found, expected ${describeThresholdExpectation(alert.thresholdType)} ${alert.threshold} lines\n${timeRangeMessage}
${value} lines found, which ${describeThresholdViolation(alert.thresholdType)} the threshold of ${alert.threshold} lines\n${timeRangeMessage}
${targetTemplate}
\`\`\`
${truncatedResults}