feat(api): add CloudWatch alarms and metric charts to the cloud explorer
CI / checks (pull_request) Successful in 27m29s
CI / checks (pull_request) Successful in 27m29s
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import type {CloudProvider, FieldSchema, ServiceSchema, TableColumnSchema} from './types'
|
||||
|
||||
export const ALARM_TYPES = ['metric', 'composite'] as const
|
||||
export const ALARM_STATISTICS = ['Average', 'Sum', 'Minimum', 'Maximum', 'SampleCount'] as const
|
||||
export const ALARM_COMPARISONS = [
|
||||
'GreaterThanThreshold',
|
||||
'GreaterThanOrEqualToThreshold',
|
||||
'LessThanThreshold',
|
||||
'LessThanOrEqualToThreshold',
|
||||
] as const
|
||||
export const ALARM_PERIODS = ['60', '300', '900', '3600'] as const
|
||||
export const ALARM_STATES = ['OK', 'ALARM', 'INSUFFICIENT_DATA'] as const
|
||||
/** CloudWatch's alarm name rule: 1-255 characters, no control characters. */
|
||||
export const ALARM_NAME_PATTERN = '^[^\\x00-\\x1f\\x7f]{1,255}$'
|
||||
|
||||
const alarmColumns: TableColumnSchema[] = [
|
||||
{name: 'name', label: 'Alarm'},
|
||||
{name: 'status', label: 'State', format: 'badge'},
|
||||
{name: 'alarmType', label: 'Type', path: 'metadata.alarmType'},
|
||||
{name: 'condition', label: 'Condition', path: 'metadata.condition', format: 'code', emptyText: '—'},
|
||||
{name: 'stateUpdatedAt', label: 'State changed', path: 'metadata.stateUpdatedAt', format: 'relative'},
|
||||
{name: 'actionsEnabled', label: 'Actions', path: 'metadata.actionsEnabled', format: 'boolean'},
|
||||
]
|
||||
|
||||
const alarmFilters: FieldSchema[] = [{name: 'search', label: 'Search', type: 'text', required: false}]
|
||||
|
||||
const metricOnly = {field: 'alarmType', values: ['metric']}
|
||||
|
||||
export function awsMonitoringSchema(): ServiceSchema {
|
||||
return {
|
||||
cloud: 'aws',
|
||||
service: 'monitoring',
|
||||
displayName: 'Amazon CloudWatch alarms',
|
||||
fields: [
|
||||
{
|
||||
name: 'alarmType',
|
||||
label: 'Alarm type',
|
||||
type: 'select',
|
||||
required: true,
|
||||
defaultValue: 'metric',
|
||||
options: [
|
||||
{label: 'Metric alarm (a threshold on one metric)', value: 'metric'},
|
||||
{label: 'Composite alarm (a rule over other alarms)', value: 'composite'},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Alarm name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
validation: {pattern: ALARM_NAME_PATTERN, message: 'Use up to 255 characters, without control characters'},
|
||||
},
|
||||
{name: 'description', label: 'Description', type: 'text', required: false},
|
||||
{name: 'namespace', label: 'Namespace', type: 'text', required: false, requiredWhen: {field: 'alarmType', equals: 'metric'}, visibleWhen: metricOnly, description: 'For example AWS/Lambda, AWS/SQS or your own, such as MyApp.'},
|
||||
{name: 'metricName', label: 'Metric name', type: 'text', required: false, requiredWhen: {field: 'alarmType', equals: 'metric'}, visibleWhen: metricOnly, description: 'For example Errors or Duration.'},
|
||||
{
|
||||
name: 'dimensions',
|
||||
label: 'Dimensions',
|
||||
type: 'textarea',
|
||||
required: false,
|
||||
visibleWhen: metricOnly,
|
||||
description: 'One Name=Value per line, for example FunctionName=checkout. Leave empty for the metric across all dimensions.',
|
||||
},
|
||||
{
|
||||
name: 'statistic',
|
||||
label: 'Statistic',
|
||||
type: 'select',
|
||||
required: false,
|
||||
defaultValue: 'Average',
|
||||
visibleWhen: metricOnly,
|
||||
options: ALARM_STATISTICS.map((value) => ({label: value, value})),
|
||||
},
|
||||
{
|
||||
name: 'period',
|
||||
label: 'Period',
|
||||
type: 'select',
|
||||
required: false,
|
||||
defaultValue: '300',
|
||||
visibleWhen: metricOnly,
|
||||
options: [{label: '1 minute', value: '60'}, {label: '5 minutes', value: '300'}, {label: '15 minutes', value: '900'}, {label: '1 hour', value: '3600'}],
|
||||
},
|
||||
{
|
||||
name: 'comparison',
|
||||
label: 'Condition',
|
||||
type: 'select',
|
||||
required: false,
|
||||
defaultValue: 'GreaterThanThreshold',
|
||||
visibleWhen: metricOnly,
|
||||
options: [
|
||||
{label: 'Greater than the threshold', value: 'GreaterThanThreshold'},
|
||||
{label: 'Greater than or equal to the threshold', value: 'GreaterThanOrEqualToThreshold'},
|
||||
{label: 'Less than the threshold', value: 'LessThanThreshold'},
|
||||
{label: 'Less than or equal to the threshold', value: 'LessThanOrEqualToThreshold'},
|
||||
],
|
||||
},
|
||||
{name: 'threshold', label: 'Threshold', type: 'text', required: false, requiredWhen: {field: 'alarmType', equals: 'metric'}, visibleWhen: metricOnly, validation: {pattern: '^-?\\d+(\\.\\d+)?$', message: 'Use a number'}},
|
||||
{name: 'evaluationPeriods', label: 'Periods to breach', type: 'text', required: false, defaultValue: '1', visibleWhen: metricOnly, description: 'How many periods in a row must breach before the alarm fires.', validation: {pattern: '^[1-9]\\d{0,2}$', message: 'Use a whole number from 1'}},
|
||||
{
|
||||
name: 'alarmRule',
|
||||
label: 'Rule',
|
||||
type: 'textarea',
|
||||
required: false,
|
||||
requiredWhen: {field: 'alarmType', equals: 'composite'},
|
||||
visibleWhen: {field: 'alarmType', values: ['composite']},
|
||||
description: 'For example ALARM("high-errors") OR ALARM("slow-checkout"). AND, OR, NOT and parentheses work; OK() and INSUFFICIENT_DATA() too.',
|
||||
},
|
||||
{name: 'topicArn', label: 'Notify SNS topic', type: 'text', required: false, description: 'Optional. An SNS topic ARN told when the alarm fires and when it recovers.'},
|
||||
],
|
||||
actions: ['list', 'create', 'delete', 'inspect'],
|
||||
capabilities: {
|
||||
resourceActions: [
|
||||
{name: 'list', label: 'List alarms', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'create', label: 'Create alarm', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete alarm', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'inspect', label: 'Inspect alarm', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
monitoringActions: [
|
||||
{name: 'listMetrics', label: 'Browse metrics', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'getMetricData', label: 'Chart a metric', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'alarmHistory', label: 'Show alarm history', enabled: false, status: 'blocked', reason: "TheCloud's runtime does not implement DescribeAlarmHistory yet.", runtimeRequired: true},
|
||||
{name: 'setAlarmState', label: 'Set an alarm state to test its actions', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'setAlarmActions', label: 'Turn alarm actions on or off', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
},
|
||||
filters: alarmFilters,
|
||||
columns: alarmColumns,
|
||||
}
|
||||
}
|
||||
|
||||
export function monitoringSchemaFor(cloud: CloudProvider): ServiceSchema | null {
|
||||
return cloud === 'aws' ? awsMonitoringSchema() : null
|
||||
}
|
||||
Reference in New Issue
Block a user