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 }