Skip to content

Commit d36fa24

Browse files
author
m.lindenberg
committed
multiple alerts with one file
1 parent 907d00d commit d36fa24

File tree

5 files changed

+137
-30
lines changed

5 files changed

+137
-30
lines changed

README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,29 @@ npm install serverless-plugin-alerting
3232
```
3333

3434
- place the alerting.json file next to your s-function.json in the directory of the function for which you want to configure alerting
35+
- *AND/OR* place a global-alerting.json file next to your s-project.json file in the projects root folder
3536
- feel free to modify it as required
3637

3738
### Run the Plugin
3839

3940
- the plugin uses a hook that is called after each deployment of a function
4041
- you only have to deploy your function as usual `sls function deploy`
41-
- it searches in the function folder for the alerting.json file and adds the configured alerts
4242

43-
### alerting.json
43+
#### Singe configuration for all functions
44+
45+
- copy the file global-alerting.json into your projects root folder
46+
- the provided alerts will be created for every deployed function automatically
47+
- same structure as alerting.json
48+
- these alerts were appended to the alerts defined in alerting.json
4449

45-
#### Structure
46-
- array of alerting definition objects (previous version: single alerting definition object still works)
50+
#### Special configuration for every function
51+
52+
- copy the file alerting.json into your functions folder
53+
- these alerts were appended to the alerts defined in global-alerting.json
54+
55+
### Structure
56+
57+
- array of alerting definition objects
4758
- you can add multiple alerts as an array of alerting-objects
4859
- you can add multiple mertic filters as in array of metricfilter-objects
4960
- you can add multiple subscription filters as in array of subscritionfilter-objects
@@ -83,11 +94,13 @@ npm install serverless-plugin-alerting
8394
- @see https://github.com/martinlindenberg/serverless-plugin-sns :)
8495

8596
#### Metric Filters
97+
8698
- key: name of the metric filter that needs to be created
8799
- the values were used to fill up a aws-cli command
88100
- http://docs.aws.amazon.com/cli/latest/reference/logs/put-metric-filter.html
89101

90102
#### Subscription Filters
103+
91104
- key: name of the subscription filter that needs to be created
92105
- the values were used to fill up a aws-cli command
93106
- http://docs.aws.amazon.com/cli/latest/reference/logs/put-subscription-filter.html

alerting.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ sed_memory_label1,used_memory_label2,used_memory_label3,used_memory,used_memory_
3030
"Duration": {
3131
"enabled": true,
3232
"alarmNamespace": "AWS/Lambda",
33-
"description": "Alarm if duration of the importer is above 500ms",
33+
"description": "Alarm if duration of the function is above 500ms",
3434
"alarmStatisticType": "Maximum",
3535
"alarmPeriod": "60",
3636
"alarmThreshold": "500",

global-alerting.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"notificationTopicStageMapping": {
4+
"dev": "your-dev-sns-topic",
5+
"testing": "your-testing-sns-topic",
6+
"staging": "your-staging-sns-topic",
7+
"live": "your-live-sns-topic"
8+
},
9+
"alerts": {
10+
"Throttles": {
11+
"enabled": true,
12+
"alarmNamespace": "AWS/Lambda",
13+
"description": "(Global) Alarm if function has more than 50 throttled requests",
14+
"alarmStatisticType": "Sum",
15+
"alarmPeriod": "60",
16+
"alarmThreshold": "50",
17+
"comparisonOperator": "GreaterThanOrEqualToThreshold",
18+
"evaluationPeriod": "1"
19+
}
20+
}
21+
}
22+
]

index.js

Lines changed: 96 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,48 +61,58 @@ module.exports = function(S) {
6161
_manageAlerts (evt, region) {
6262
let _this = this;
6363

64-
6564
_this.stage = evt.options.stage;
6665
_this._initAws(region);
6766

6867
if (S.cli.action != 'deploy' || (S.cli.context != 'function' && S.cli.context != 'dash'))
6968
return;
7069

71-
var functionAlertSettings = _this._getFunctionsAlertSettings(evt, region);
70+
// merges global and local alertsettings
71+
var alertSettings = _this._mergeAlertSettings([
72+
_this._getFunctionsAlertSettings(evt, region),
73+
_this._getProjectAlertSettings(evt, region),
74+
]);
7275

73-
// no alert.json found
74-
if (functionAlertSettings.length == 0) {
76+
// no settings found
77+
if (alertSettings.length == 0) {
7578
return;
7679
}
7780

78-
var requiredTopics = _this._getRequiredTopics(functionAlertSettings);
81+
var requiredTopics = _this._getRequiredTopics(alertSettings);
7982

8083
return _this._createTopics(requiredTopics)
8184
.then(function(){
8285
// topics exist now
8386
let _this = this;
8487

85-
var metricFilterPromises = _this._createMetricFilters(functionAlertSettings, _this)
86-
var subscriptionFilterPromises = _this._createSubscriptionFilters(functionAlertSettings, _this);
87-
var alertPromises = _this._createAlerts(functionAlertSettings, _this);
88-
89-
BbPromise.all(metricFilterPromises)
90-
.then(function(){
91-
console.log('metric filters created');
92-
});
93-
94-
BbPromise.all(subscriptionFilterPromises)
95-
.then(function(){
96-
console.log('subscription filters created');
97-
});
88+
var metricFilterPromises = _this._createMetricFilters(alertSettings, _this)
89+
var subscriptionFilterPromises = _this._createSubscriptionFilters(alertSettings, _this);
90+
var alertPromises = _this._createAlerts(alertSettings, _this);
9891

99-
BbPromise.all(alertPromises)
100-
.then(function(){
101-
console.log('alerts created');
102-
});
92+
if (metricFilterPromises.length > 0) {
93+
BbPromise.all(metricFilterPromises)
94+
.then(function(){
95+
console.log('metric filters created');
96+
});
97+
}
98+
99+
if (subscriptionFilterPromises.length > 0) {
100+
BbPromise.all(subscriptionFilterPromises)
101+
.then(function(){
102+
console.log('subscription filters created');
103+
});
104+
}
105+
106+
if(alertPromises.length > 0) {
107+
BbPromise.all(alertPromises)
108+
.then(function(){
109+
console.log('alerts created');
110+
});
111+
}
103112

104113
}.bind(_this))
105114
.catch(function(e){
115+
console.log('e', e)
106116
SCli.log('error in creating alerts', e)
107117
});
108118
}
@@ -336,6 +346,25 @@ module.exports = function(S) {
336346
return topics;
337347
}
338348

349+
/**
350+
* receives a list of settings and merges them (AND-Connected)
351+
*
352+
* @param array settingsList
353+
*
354+
* @return array
355+
*/
356+
_mergeAlertSettings(settingsList){
357+
var result = [];
358+
359+
for (var i in settingsList) {
360+
for (var j in settingsList[i]) {
361+
result.push(settingsList[i][j]);
362+
}
363+
}
364+
365+
return result;
366+
}
367+
339368
/**
340369
* parses the alert json file and returns the data
341370
*
@@ -347,8 +376,9 @@ module.exports = function(S) {
347376
_getFunctionsAlertSettings(evt, region){
348377
let _this = this;
349378
var settings = [];
379+
350380
for (var deployedIndex in evt.data.deployed[region]) {
351-
let deployed = evt.data.deployed[region][deployedIndex],
381+
var deployed = evt.data.deployed[region][deployedIndex],
352382
functionName = deployed['functionName'],
353383
alertPathFile = S.getProject().getFunction(functionName).getFilePath().replace('s-function.json', 'alerting.json');
354384

@@ -377,6 +407,46 @@ module.exports = function(S) {
377407
return settings;
378408
}
379409

410+
/**
411+
* parses the global alert josn file and returns data
412+
*
413+
* @param object evt
414+
* @param string region
415+
*
416+
* @return array
417+
*/
418+
_getProjectAlertSettings(evt, region){
419+
let _this = this;
420+
var settings = [];
421+
422+
var globalAlertFile = S.getProject().getRootPath('global-alerting.json');
423+
424+
if (!fs.existsSync(globalAlertFile)) {
425+
return settings;
426+
}
427+
try {
428+
// each deployed function receives its alert settings
429+
for (var deployedIndex in evt.data.deployed[region]) {
430+
var deployed = evt.data.deployed[region][deployedIndex];
431+
var alertContents = JSON.parse(fs.readFileSync(globalAlertFile));
432+
433+
if (!alertContents.length > 0) {
434+
alertContents = [alertContents];
435+
}
436+
437+
for (var i in alertContents) {
438+
alertContents[i].Arn = deployed.Arn;
439+
}
440+
441+
settings.push(alertContents);
442+
}
443+
} catch (e) {
444+
console.log('global-alerting.json not readable');
445+
}
446+
447+
return settings;
448+
}
449+
380450

381451
/**
382452
* @deprecated
@@ -415,7 +485,7 @@ module.exports = function(S) {
415485
_getAlarmConfig(functionName, metric, alertConfig, stage, topicName, notificationAction) {
416486
let resourceName = functionName + ":" + stage;
417487

418-
return {
488+
var config = {
419489
AlarmName: resourceName + ' ' + metric + ' -> ' + topicName,
420490
ComparisonOperator: alertConfig.comparisonOperator,
421491
EvaluationPeriods: alertConfig.evaluationPeriod,
@@ -433,6 +503,8 @@ module.exports = function(S) {
433503
OKActions: [notificationAction],
434504
AlarmActions: [notificationAction]
435505
};
506+
507+
return config;
436508
}
437509
}
438510

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "serverless-plugin-alerting",
3-
"version": "0.5.5",
3+
"version": "0.5.6",
44
"engines": {
55
"node": ">=4.0"
66
},

0 commit comments

Comments
 (0)