mirror of
https://github.com/nttgin/BGPalerter.git
synced 2024-05-19 06:50:08 +00:00
introduced persistence module
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,3 +9,4 @@ logs/
|
|||||||
bgpalerter.pid
|
bgpalerter.pid
|
||||||
alertdata/
|
alertdata/
|
||||||
.npmrc
|
.npmrc
|
||||||
|
.cache/
|
||||||
|
|||||||
@@ -9,3 +9,4 @@ logs/
|
|||||||
bgpalerter.pid
|
bgpalerter.pid
|
||||||
alertdata/
|
alertdata/
|
||||||
.npmrc
|
.npmrc
|
||||||
|
.cache/
|
||||||
|
|||||||
@@ -201,10 +201,12 @@ reports:
|
|||||||
# - notificationIntervalSeconds
|
# - notificationIntervalSeconds
|
||||||
# Defines the amount of seconds after which an alert can be repeated. An alert is repeated only if the event that
|
# Defines the amount of seconds after which an alert can be repeated. An alert is repeated only if the event that
|
||||||
# triggered it is not yet solved.
|
# triggered it is not yet solved.
|
||||||
#
|
# - persistStatus
|
||||||
|
# Persist the status of BGPalerter. If the process is restarted, the list of alerts already sent is recovered
|
||||||
|
# and they are not repeated. The process must be able to write on disc, this option will create a file inside .cache/
|
||||||
|
|
||||||
notificationIntervalSeconds: 14400
|
notificationIntervalSeconds: 14400
|
||||||
|
persistStatus: true
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
directory: logs
|
directory: logs
|
||||||
@@ -216,7 +218,6 @@ logging:
|
|||||||
|
|
||||||
checkForUpdatesAtBoot: true
|
checkForUpdatesAtBoot: true
|
||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# Process monitoring settings:
|
# Process monitoring settings:
|
||||||
# Uncomment or add classes under processMonitors if you want to monitor or send logs about the status of the BGPalerter process
|
# Uncomment or add classes under processMonitors if you want to monitor or send logs about the status of the BGPalerter process
|
||||||
@@ -246,6 +247,7 @@ checkForUpdatesAtBoot: true
|
|||||||
monitoredPrefixesFiles:
|
monitoredPrefixesFiles:
|
||||||
- prefixes.yml
|
- prefixes.yml
|
||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# HTTP proxy setting:
|
# HTTP proxy setting:
|
||||||
# Allow to run BGPalerter behind an HTTP/HTTPS proxy.
|
# Allow to run BGPalerter behind an HTTP/HTTPS proxy.
|
||||||
|
|||||||
11
src/env.js
11
src/env.js
@@ -130,6 +130,7 @@ let config = {
|
|||||||
notificationIntervalSeconds: 14400,
|
notificationIntervalSeconds: 14400,
|
||||||
alarmOnlyOnce: false,
|
alarmOnlyOnce: false,
|
||||||
monitoredPrefixesFiles: ["prefixes.yml"],
|
monitoredPrefixesFiles: ["prefixes.yml"],
|
||||||
|
persistStatus: true,
|
||||||
logging: {
|
logging: {
|
||||||
directory: "logs",
|
directory: "logs",
|
||||||
logRotatePattern: "YYYY-MM-DD",
|
logRotatePattern: "YYYY-MM-DD",
|
||||||
@@ -266,7 +267,15 @@ config.connectors = config.connectors
|
|||||||
if (config.httpProxy) {
|
if (config.httpProxy) {
|
||||||
const HttpsProxyAgent = require("https-proxy-agent");
|
const HttpsProxyAgent = require("https-proxy-agent");
|
||||||
vector.agent = new HttpsProxyAgent(url.parse(config.httpProxy));
|
vector.agent = new HttpsProxyAgent(url.parse(config.httpProxy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!!config.persistStatus) {
|
||||||
|
const Storage = require("./utils/storages/storageFile").default;
|
||||||
|
vector.storage = new Storage({
|
||||||
|
validity: 3600 * 4,
|
||||||
|
}, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const input = new Input(config);
|
const input = new Input(config);
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export default class Monitor {
|
|||||||
this.pubSub = env.pubSub;
|
this.pubSub = env.pubSub;
|
||||||
this.logger = env.logger;
|
this.logger = env.logger;
|
||||||
this.input = env.input;
|
this.input = env.input;
|
||||||
|
this.storage = env.storage;
|
||||||
this.params = params || {};
|
this.params = params || {};
|
||||||
this.maxDataSamples = this.params.maxDataSamples || 1000;
|
this.maxDataSamples = this.params.maxDataSamples || 1000;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -56,9 +57,10 @@ export default class Monitor {
|
|||||||
this.truncated = {}; // Dictionary containing <id, boolean> if the alerts Array for "id" is truncated according to maxDataSamples
|
this.truncated = {}; // Dictionary containing <id, boolean> if the alerts Array for "id" is truncated according to maxDataSamples
|
||||||
this.fadeOff = {}; // Dictionary containing the last alert unix timestamp of each group <id, int> which contains alerts that have been triggered but are not ready yet to be sent (e.g. thresholdMinPeers not yet reached)
|
this.fadeOff = {}; // Dictionary containing the last alert unix timestamp of each group <id, int> which contains alerts that have been triggered but are not ready yet to be sent (e.g. thresholdMinPeers not yet reached)
|
||||||
|
|
||||||
|
this._retrieveStatus();
|
||||||
this.internalConfig = {
|
this.internalConfig = {
|
||||||
notificationInterval: (this.config.notificationIntervalSeconds || 14400) * 1000,
|
notificationInterval: (this.config.notificationIntervalSeconds || 14400) * 1000,
|
||||||
checkFadeOffGroups: this.config.checkFadeOffGroupsSeconds || 30 * 1000,
|
checkFadeOffGroups: (this.config.checkFadeOffGroupsSeconds || 30) * 1000,
|
||||||
fadeOff: this.config.fadeOffSeconds * 1000 || 60 * 6 * 1000
|
fadeOff: this.config.fadeOffSeconds * 1000 || 60 * 6 * 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -158,6 +160,47 @@ export default class Monitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._persistStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
_retrieveStatus = () => {
|
||||||
|
if (this.storage) {
|
||||||
|
this.storage.get("status")
|
||||||
|
.then(({ alerts={}, sent={}, truncated={}, fadeOff={} }) => {
|
||||||
|
this.alerts = alerts;
|
||||||
|
this.sent = sent;
|
||||||
|
this.truncated = truncated;
|
||||||
|
this.fadeOff = fadeOff;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.logger.log({
|
||||||
|
level: 'error',
|
||||||
|
message: error
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_persistStatus = () => {
|
||||||
|
if (this.storage) {
|
||||||
|
const status = {
|
||||||
|
alerts: this.alerts,
|
||||||
|
sent: this.sent,
|
||||||
|
truncated: this.truncated,
|
||||||
|
fadeOff: this.fadeOff
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Object.values(status).some(i => Object.keys(i).length > 0)) { // If there is anything in the cache
|
||||||
|
this.storage.set("status", status)
|
||||||
|
.catch(error => {
|
||||||
|
this.logger.log({
|
||||||
|
level: 'error',
|
||||||
|
message: error
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_publishGroupId = (id, now) => {
|
_publishGroupId = (id, now) => {
|
||||||
|
|||||||
49
src/utils/storage.js
Normal file
49
src/utils/storage.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
export default class Storage {
|
||||||
|
|
||||||
|
constructor(params, config){
|
||||||
|
this.config = config;
|
||||||
|
this.params = params;
|
||||||
|
this.validity = this.params.validity || 3600 * 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
set = (key, value) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
if (/^[a-z\-]+$/i.test(key)) {
|
||||||
|
|
||||||
|
const envelop = {
|
||||||
|
date: new Date().getTime(),
|
||||||
|
value
|
||||||
|
};
|
||||||
|
this._set(key, envelop)
|
||||||
|
.then(resolve);
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject("Not a valid key. Use only chars and dashes.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
get = (key) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
if (/^[a-z\-]+$/i.test(key)) {
|
||||||
|
this._get(key)
|
||||||
|
.then(({ date, value }) => {
|
||||||
|
const now = new Date().getTime();
|
||||||
|
if (date + this.validity >= now) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(resolve);
|
||||||
|
} else {
|
||||||
|
reject("Not a valid key. Use only chars and dashes.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_set = (key, value) => {
|
||||||
|
throw new Error("The set method must be implemented");
|
||||||
|
};
|
||||||
|
|
||||||
|
_get = (key) => {
|
||||||
|
throw new Error("The get method must be implemented");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
44
src/utils/storages/storageFile.js
Normal file
44
src/utils/storages/storageFile.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import Storage from "../storage";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
export default class StorageFile extends Storage{
|
||||||
|
constructor(params, config){
|
||||||
|
super(params, config);
|
||||||
|
this.directory = this.config.volume + (this.params.directory || ".cache/");
|
||||||
|
if (!fs.existsSync(this.directory)) {
|
||||||
|
fs.mkdirSync(this.directory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_set = (key, value) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const file = this.directory + key + ".json";
|
||||||
|
fs.writeFile(file, JSON.stringify(value), error => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
_get = (key) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const file = this.directory + key + ".json";
|
||||||
|
if (fs.existsSync(file)) {
|
||||||
|
fs.readFile(file, (error, content) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
resolve(JSON.parse(content));
|
||||||
|
} catch (e) {
|
||||||
|
resolve({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve({});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -78,7 +78,8 @@ describe("Composition", function() {
|
|||||||
"maxMessagesPerSecond",
|
"maxMessagesPerSecond",
|
||||||
"fadeOffSeconds",
|
"fadeOffSeconds",
|
||||||
"checkFadeOffGroupsSeconds",
|
"checkFadeOffGroupsSeconds",
|
||||||
"volume"
|
"volume",
|
||||||
|
"persistStatus"
|
||||||
]);
|
]);
|
||||||
expect(config.connectors[0]).to.have
|
expect(config.connectors[0]).to.have
|
||||||
.property('class')
|
.property('class')
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ logging:
|
|||||||
compressOnRotation: true
|
compressOnRotation: true
|
||||||
|
|
||||||
checkForUpdatesAtBoot: true
|
checkForUpdatesAtBoot: true
|
||||||
|
persistStatus: true
|
||||||
|
|
||||||
processMonitors:
|
processMonitors:
|
||||||
- file: uptimeApi
|
- file: uptimeApi
|
||||||
|
|||||||
Reference in New Issue
Block a user