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
 | 
			
		||||
alertdata/
 | 
			
		||||
.npmrc
 | 
			
		||||
.cache/
 | 
			
		||||
 
 | 
			
		||||
@@ -9,3 +9,4 @@ logs/
 | 
			
		||||
bgpalerter.pid
 | 
			
		||||
alertdata/
 | 
			
		||||
.npmrc
 | 
			
		||||
.cache/
 | 
			
		||||
 
 | 
			
		||||
@@ -201,10 +201,12 @@ reports:
 | 
			
		||||
# - notificationIntervalSeconds
 | 
			
		||||
#       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.
 | 
			
		||||
#
 | 
			
		||||
# - 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
 | 
			
		||||
 | 
			
		||||
persistStatus: true
 | 
			
		||||
 | 
			
		||||
logging:
 | 
			
		||||
  directory: logs
 | 
			
		||||
@@ -216,7 +218,6 @@ logging:
 | 
			
		||||
  
 | 
			
		||||
checkForUpdatesAtBoot: true
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
############################
 | 
			
		||||
# Process monitoring settings:
 | 
			
		||||
# 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:
 | 
			
		||||
  - prefixes.yml
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
############################
 | 
			
		||||
# HTTP proxy setting:
 | 
			
		||||
# 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,
 | 
			
		||||
    alarmOnlyOnce: false,
 | 
			
		||||
    monitoredPrefixesFiles: ["prefixes.yml"],
 | 
			
		||||
    persistStatus: true,
 | 
			
		||||
    logging: {
 | 
			
		||||
        directory: "logs",
 | 
			
		||||
        logRotatePattern: "YYYY-MM-DD",
 | 
			
		||||
@@ -266,7 +267,15 @@ config.connectors = config.connectors
 | 
			
		||||
if (config.httpProxy) {
 | 
			
		||||
    const HttpsProxyAgent = require("https-proxy-agent");
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ export default class Monitor {
 | 
			
		||||
        this.pubSub = env.pubSub;
 | 
			
		||||
        this.logger = env.logger;
 | 
			
		||||
        this.input = env.input;
 | 
			
		||||
        this.storage = env.storage;
 | 
			
		||||
        this.params = params || {};
 | 
			
		||||
        this.maxDataSamples = this.params.maxDataSamples || 1000;
 | 
			
		||||
        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.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 = {
 | 
			
		||||
            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
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -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) => {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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",
 | 
			
		||||
                    "fadeOffSeconds",
 | 
			
		||||
                    "checkFadeOffGroupsSeconds",
 | 
			
		||||
                    "volume"
 | 
			
		||||
                    "volume",
 | 
			
		||||
                    "persistStatus"
 | 
			
		||||
                ]);
 | 
			
		||||
            expect(config.connectors[0]).to.have
 | 
			
		||||
                .property('class')
 | 
			
		||||
 
 | 
			
		||||
@@ -76,6 +76,7 @@ logging:
 | 
			
		||||
  compressOnRotation: true
 | 
			
		||||
 | 
			
		||||
checkForUpdatesAtBoot: true
 | 
			
		||||
persistStatus: true
 | 
			
		||||
 | 
			
		||||
processMonitors:
 | 
			
		||||
  - file: uptimeApi
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user