diff --git a/core/dashboards/dashboard.ts b/core/dashboards/dashboard.ts index 85a0a195..5ee93f52 100644 --- a/core/dashboards/dashboard.ts +++ b/core/dashboards/dashboard.ts @@ -533,7 +533,8 @@ export default function addDashboard (dashboardConfig: SlicWatchInputDashboardCo namespace: 'AWS/Events', metric, dimensions: { RuleName: `\${${logicalId}}` }, - stat + stat, + yAxis: metricConfig.yAxis }) } } diff --git a/core/dashboards/tests/dashboard-eventbridge.test.ts b/core/dashboards/tests/dashboard-eventbridge.test.ts new file mode 100644 index 00000000..f1e892b4 --- /dev/null +++ b/core/dashboards/tests/dashboard-eventbridge.test.ts @@ -0,0 +1,120 @@ +import { merge } from 'lodash' +import { test } from 'tap' +import { type MetricWidgetProperties } from 'cloudwatch-dashboard-types' + +import { type ResourceType } from '../../cf-template' +import addDashboard from '../dashboard' +import defaultConfig from '../../inputs/default-config' + +import { createTestCloudFormationTemplate, getDashboardFromTemplate, getDashboardWidgetsByTitle } from '../../tests/testing-utils' + +test('dashboard contains configured EventBridge resources', (t) => { + t.test('dashboards includes EventBridge metrics', (t) => { + const template = createTestCloudFormationTemplate() + addDashboard(defaultConfig.dashboard, template) + const { dashboard } = getDashboardFromTemplate(template) + + const widgets = getDashboardWidgetsByTitle(dashboard, /EventBridge Rule/) + const [ruleWidget] = widgets + + t.ok(ruleWidget) + + t.same((ruleWidget.properties as MetricWidgetProperties).metrics, [ + ['AWS/Events', 'FailedInvocations', 'RuleName', '${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}', { stat: 'Sum', yAxis: 'left' }], + ['AWS/Events', 'ThrottledRules', 'RuleName', '${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}', { stat: 'Sum', yAxis: 'left' }], + ['AWS/Events', 'Invocations', 'RuleName', '${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}', { stat: 'Sum', yAxis: 'left' }] + ]) + + const props: MetricWidgetProperties = ruleWidget.properties as MetricWidgetProperties + t.ok((props.metrics?.length ?? 0) > 0) + t.equal(props.period, 300) + t.equal(props.view, 'timeSeries') + t.end() + }) + + t.test('service config overrides take precedence', (t) => { + const template = createTestCloudFormationTemplate() + + const config = merge({}, defaultConfig.dashboard, { + widgets: { + Events: { + metricPeriod: 900, + width: 8, + height: 12, + FailedInvocations: { + Statistic: ['Count'] + }, + ThrottledRules: { + Statistic: ['Sum'], + enabled: false + }, + Invocations: { + Statistic: ['ts85'], + yAxis: 'right' + } + } + } + }) + + addDashboard(config, template) + const { dashboard } = getDashboardFromTemplate(template) + const widgets = getDashboardWidgetsByTitle(dashboard, /EventBridge Rule/) + + const [ruleWidget] = widgets + t.ok(ruleWidget) + t.same((ruleWidget.properties as MetricWidgetProperties).metrics, [ + ['AWS/Events', 'FailedInvocations', 'RuleName', '${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}', { stat: 'Count', yAxis: 'left' }], + ['AWS/Events', 'Invocations', 'RuleName', '${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}', { stat: 'ts85', yAxis: 'right' }] + ]) + + const props: MetricWidgetProperties = ruleWidget.properties as MetricWidgetProperties + t.ok((props.metrics?.length ?? 0) > 0) + t.equal(props.period, 900) + t.equal(props.view, 'timeSeries') + + t.end() + }) + + t.test('resource config overrides take precedence', (t) => { + const template = createTestCloudFormationTemplate(); + (template.Resources as ResourceType).ServerlesstestprojectdeveventsRulerule1EventBridgeRule.Metadata = { + slicWatch: { + dashboard: { + FailedInvocations: { + Statistic: ['ts85'], + yAxis: 'left', + enabled: true + }, + ThrottledRules: { + Statistic: ['Sum'], + enabled: false + }, + Invocations: { + Statistic: ['ts85'], + yAxis: 'right' + } + } + } + } + + addDashboard(defaultConfig.dashboard, template) + const { dashboard } = getDashboardFromTemplate(template) + const widgets = getDashboardWidgetsByTitle(dashboard, /EventBridge Rule/) + + const [ruleWidget] = widgets + t.ok(ruleWidget) + t.same((ruleWidget.properties as MetricWidgetProperties).metrics, [ + ['AWS/Events', 'FailedInvocations', 'RuleName', '${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}', { stat: 'ts85', yAxis: 'left' }], + ['AWS/Events', 'Invocations', 'RuleName', '${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}', { stat: 'ts85', yAxis: 'right' }] + ]) + + const props: MetricWidgetProperties = ruleWidget.properties as MetricWidgetProperties + t.ok((props.metrics?.length ?? 0) > 0) + t.equal(props.period, 300) + t.equal(props.view, 'timeSeries') + + t.end() + }) + + t.end() +}) diff --git a/core/dashboards/tests/dashboard.test.ts b/core/dashboards/tests/dashboard.test.ts index 28bfdacf..6a583ddd 100644 --- a/core/dashboards/tests/dashboard.test.ts +++ b/core/dashboards/tests/dashboard.test.ts @@ -53,27 +53,6 @@ test('A dashboard includes metrics', (t) => { t.end() }) - t.test('dashboard includes Events metrics', (t) => { - const widgets = dashboard.widgets.filter(({ properties }) => - ((properties as MetricWidgetProperties).title ?? '').startsWith('EventBridge') - ) - t.equal(widgets.length, 1) - const namespaces = new Set() - for (const widget of widgets) { - for (const metric of (widget.properties as MetricWidgetProperties).metrics ?? []) { - namespaces.add(metric[0]) - } - } - t.same(namespaces, new Set(['AWS/Events'])) - const expectedTitles = new Set(['EventBridge Rule ${ServerlesstestprojectdeveventsRulerule1EventBridgeRule}']) - - const actualTitles = new Set( - widgets.map((widget) => (widget.properties as MetricWidgetProperties).title) - ) - t.same(actualTitles, expectedTitles) - t.end() - }) - t.end() })