Skip to content
This repository has been archived by the owner on Oct 25, 2023. It is now read-only.

Commit

Permalink
Merge d0f5f69 into 2efe499
Browse files Browse the repository at this point in the history
  • Loading branch information
mrthehud committed May 22, 2020
2 parents 2efe499 + d0f5f69 commit f1488a8
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ custom:
dashboards: true

nameTemplate: $[functionName]-$[metricName]-Alarm # Optionally - naming template for alarms, can be overwritten in definitions
prefixTemplate: $[stackName] # Optionally - override the alarm name prefix

topics:
ok: ${self:service}-${opt:stage}-alerts-ok
Expand All @@ -38,6 +39,7 @@ custom:
description: 'My custom alarm'
namespace: 'AWS/Lambda'
nameTemplate: $[functionName]-Duration-IMPORTANT-Alarm # Optionally - naming template for the alarms, overwrites globally defined one
prefixTemplate: $[stackName] # Optionally - override the alarm name prefix, overwrites globally defined one
metric: duration
threshold: 200
statistic: Average
Expand Down
3 changes: 2 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class AlertsPlugin {
if (definition.nameTemplate) {
alarm.Properties.AlarmName = this.naming.getAlarmName({
template: definition.nameTemplate,
prefixTemplate: definition.prefixTemplate,
functionLogicalId: functionRef,
metricName: definition.metric,
metricId,
Expand Down Expand Up @@ -274,7 +275,7 @@ class AlertsPlugin {
const normalizedFunctionName = this.providerNaming.getLambdaLogicalId(functionName);

const functionAlarms = this.getFunctionAlarms(functionObj, config, definitions);
const alarms = globalAlarms.concat(functionAlarms).map(alarm => _.assign({ nameTemplate: config.nameTemplate }, alarm));
const alarms = globalAlarms.concat(functionAlarms).map(alarm => _.assign({ nameTemplate: config.nameTemplate, prefixTemplate: config.prefixTemplate }, alarm));

const alarmStatements = alarms.reduce((statements, alarm) => {
const key = this.naming.getAlarmCloudFormationRef(alarm.name, functionName);
Expand Down
90 changes: 90 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,48 @@ describe('#index', function () {
});
});

it('should use globally defined prefixTemplate when it`s not provided in definitions', function() {
let config = {
nameTemplate: '$[functionName]-global',
prefixTemplate: 'notTheStackName',
function: ['functionErrors']
};

const plugin = pluginFactory(config);

config = plugin.getConfig();
const definitions = plugin.getDefinitions(config);
const alertTopics = plugin.compileAlertTopics(config);

plugin.compileAlarms(config, definitions, alertTopics);
expect(plugin.serverless.service.provider.compiledCloudFormationTemplate.Resources).toEqual({
FooFunctionErrorsAlarm: {
Type: 'AWS::CloudWatch::Alarm',
Properties: {
AlarmName: 'notTheStackName-foo-global',
Namespace: 'AWS/Lambda',
MetricName: 'Errors',
Threshold: 1,
Statistic: 'Sum',
Period: 60,
EvaluationPeriods: 1,
DatapointsToAlarm: 1,
ComparisonOperator: 'GreaterThanOrEqualToThreshold',
AlarmActions: [],
OKActions: [],
InsufficientDataActions: [],
Dimensions: [{
Name: 'FunctionName',
Value: {
Ref: 'FooLambdaFunction'
},
}],
TreatMissingData: 'missing',
}
}
});
});

it('should overwrite globally defined nameTemplate using definitions', function() {
let config = {
nameTemplate: '$[functionName]-global',
Expand Down Expand Up @@ -716,6 +758,54 @@ describe('#index', function () {
}
});
});

it('should overwrite globally defined prefixTemplate using definitions', function() {
let config = {
nameTemplate: '$[functionName]-global',
prefixTemplate: 'notTheStackName',
definitions: {
functionErrors: {
nameTemplate: '$[functionName]-local',
prefixTemplate: 'somethingCompletelyCustom'
}
},
function: ['functionErrors']
};

const plugin = pluginFactory(config);

config = plugin.getConfig();
const definitions = plugin.getDefinitions(config);
const alertTopics = plugin.compileAlertTopics(config);

plugin.compileAlarms(config, definitions, alertTopics);
expect(plugin.serverless.service.provider.compiledCloudFormationTemplate.Resources).toEqual({
FooFunctionErrorsAlarm: {
Type: 'AWS::CloudWatch::Alarm',
Properties: {
AlarmName: 'somethingCompletelyCustom-foo-local',
Namespace: 'AWS/Lambda',
MetricName: 'Errors',
Threshold: 1,
Statistic: 'Sum',
Period: 60,
EvaluationPeriods: 1,
DatapointsToAlarm: 1,
ComparisonOperator: 'GreaterThanOrEqualToThreshold',
AlarmActions: [],
OKActions: [],
InsufficientDataActions: [],
Dimensions: [{
Name: 'FunctionName',
Value: {
Ref: 'FooLambdaFunction'
},
}],
TreatMissingData: 'missing',
}
}
});
});
});

describe('#compileCloudWatchAlarms', () => {
Expand Down
10 changes: 9 additions & 1 deletion src/naming.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ class Naming {
.replace('$[metricName]', options.metricName)
.replace('$[metricId]', options.metricId);

return `${options.stackName}-${interpolatedTemplate}`;
const prefixTemplate = typeof options.prefixTemplate !== 'undefined'
? options.prefixTemplate
: '$[stackName]';
const interpolatedPrefix = prefixTemplate
.replace('$[stackName]', options.stackName);

return interpolatedPrefix
? `${interpolatedPrefix}-${interpolatedTemplate}`
: interpolatedTemplate;
}
}

Expand Down
30 changes: 30 additions & 0 deletions src/naming.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,35 @@ describe('#naming', function () {

expect(actual).toEqual(expected);
});

it('should interpolate alarm prefix', () => {
const template = '$[functionName]-$[functionId]-$[metricName]-$[metricId]';
const prefixTemplate = 'notTheStackName';
const functionName = 'function';
const functionLogicalId = 'functionId';
const metricName = 'metric';
const metricId = 'metricId';
const stackName = 'fooservice-dev';

const expected = `notTheStackName-${functionName}-${functionLogicalId}-${metricName}-${metricId}`;
const actual = naming.getAlarmName({ template, prefixTemplate, functionName, functionLogicalId, metricName, metricId, stackName });

expect(actual).toEqual(expected);
});

it('should interpolate an empty alarm prefix', () => {
const template = '$[functionName]-$[functionId]-$[metricName]-$[metricId]';
const prefixTemplate = '';
const functionName = 'function';
const functionLogicalId = 'functionId';
const metricName = 'metric';
const metricId = 'metricId';
const stackName = 'fooservice-dev';

const expected = `${functionName}-${functionLogicalId}-${metricName}-${metricId}`;
const actual = naming.getAlarmName({ template, prefixTemplate, functionName, functionLogicalId, metricName, metricId, stackName });

expect(actual).toEqual(expected);
});
});
});

0 comments on commit f1488a8

Please sign in to comment.