Files
floci-ui/packages/api/src/cloud-spi/monitoringSchema.ts
T
2026-10-24 22:48:41 -04:00

133 lines
7.2 KiB
TypeScript

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
}