Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event filtering #22

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 60 additions & 13 deletions App.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Pmx = require("pmx");
const Health_1 = require("./Health");
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
exports.__esModule = true;
var Pmx = require("pmx");
var Health_1 = require("./Health");
Pmx.initModule({
type: "generic",
el: {
Expand All @@ -13,13 +49,24 @@ Pmx.initModule({
cpu: true,
mem: true
}
}, async (ex, config) => {
Health_1.stopIfEx(ex);
try {
await (new Health_1.Health(config)).go();
}
catch (ex) {
Health_1.stopIfEx(ex);
}
});
//# sourceMappingURL=App.js.map
}, function (ex, config) { return __awaiter(_this, void 0, void 0, function () {
var ex_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
Health_1.stopIfEx(ex);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, (new Health_1.Health(config)).go()];
case 2:
_a.sent();
return [3 /*break*/, 4];
case 3:
ex_1 = _a.sent();
Health_1.stopIfEx(ex_1);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); });
515 changes: 303 additions & 212 deletions Health.js

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions Health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const
"!=": (a, b, t) => a !== b,
"!~": (a, b, t) => Math.abs(a - b) > t
},
CONFIG_KEYS = ["events", "metric", "exceptions", "messages", "messageExcludeExps", "appsExcluded", "metricIntervalS", "addLogs", "aliveTimeoutS"];
CONFIG_KEYS = ["events", "metric", "exceptions", "messages", "messageExcludeExps", "eventExcludeExps", "appsExcluded", "metricIntervalS", "addLogs", "aliveTimeoutS"];

interface IMonitConfig {
events: string[];
Expand All @@ -42,6 +42,7 @@ interface IMonitConfig {
exceptions: boolean;
messages: boolean;
messageExcludeExps: string;
eventExcludeExps: string;
appsIncluded: string[];
appsExcluded: string[];
metricIntervalS: number;
Expand Down Expand Up @@ -101,11 +102,15 @@ export class Health {
}

_messageExcludeExps: RegExp[];
_eventExcludeExps: RegExp[];

configChanged() {
this._messageExcludeExps = [];
if (Array.isArray(this._config.messageExcludeExps))
this._messageExcludeExps = this._config.messageExcludeExps.map(e => new RegExp(e));
this._eventExcludeExps = [];
if (Array.isArray(this._config.eventExcludeExps))
this._eventExcludeExps = this._config.eventExcludeExps.map(e => new RegExp(e));
}

isAppIncluded(app: string) {
Expand Down Expand Up @@ -150,6 +155,11 @@ export class Health {

if (Array.isArray(this._config.events) && this._config.events.indexOf(data.event) === -1)
return;

const json = JSON.stringify(data, undefined, 4);

if (this._eventExcludeExps.some(e => e.test(json)))
return; // exclude

this.mail(
`${data.process.name}:${data.process.pm_id} - ${data.event}`,
Expand Down Expand Up @@ -376,4 +386,4 @@ export function stopIfEx(ex: Error) {
PM2.disconnect();
process.exit(1);
}
}
}
7 changes: 3 additions & 4 deletions Log.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.__esModule = true;
function info(text) {
console.log(`${new Date().toISOString()}: ${text}`);
console.log(new Date().toISOString() + ": " + text);
}
exports.info = info;
function error(text) {
console.error(`${new Date().toISOString()}: ${text}`);
console.error(new Date().toISOString() + ": " + text);
}
exports.error = error;
//# sourceMappingURL=Log.js.map
133 changes: 90 additions & 43 deletions Mail.js
Original file line number Diff line number Diff line change
@@ -1,62 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Mailer = require("nodemailer");
const Fs = require("fs");
const os_1 = require("os");
const Log_1 = require("./Log");
class Mail {
constructor(_config) {
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var Mailer = require("nodemailer");
var Fs = require("fs");
var os_1 = require("os");
var Log_1 = require("./Log");
var Mail = /** @class */ (function () {
function Mail(_config) {
this._config = _config;
this._template = "<p><!-- body --></p><p><!-- timeStamp --></p>";
if (!this._config.smtp)
this._config.smtp = { disabled: true };
if (this._config.smtp.disabled === true)
return; // don't analyze config if disabled
if (!this._config.smtp)
throw new Error(`[smtp] not set`);
throw new Error("[smtp] not set");
if (!this._config.smtp.host)
throw new Error(`[smtp.host] not set`);
throw new Error("[smtp.host] not set");
if (!this._config.smtp)
throw new Error(`[smtp.port] not set`);
throw new Error("[smtp.port] not set");
if (!this._config.mailTo)
throw new Error(`[mailTo] not set`);
throw new Error("[mailTo] not set");
try {
this._template = Fs.readFileSync("Template.html", "utf8");
}
catch (_a) {
Log_1.info(`Template.html not found`);
Log_1.info("Template.html not found");
}
}
async send(subject, body, priority, attachements = []) {
if (this._config.smtp.disabled === true)
return;
const temp = {
host: this._config.smtp.host,
port: this._config.smtp.port,
tls: { rejectUnauthorized: false },
secure: this._config.smtp.secure === true,
auth: null
};
if (this._config.smtp.user)
temp.auth = {
user: this._config.smtp.user,
pass: this._config.smtp.password
};
const transport = Mailer.createTransport(temp), headers = {};
if (priority)
headers["importance"] = priority;
await transport.sendMail({
to: this._config.mailTo,
from: this._config.smtp.from || this._config.smtp.user,
replyTo: this._config.replyTo,
subject: `pm2-health: ${os_1.hostname()}, ${subject}`,
html: this._template
.replace(/<!--\s*body\s*-->/, body)
.replace(/<!--\s*timeStamp\s*-->/, new Date().toISOString()),
attachments: attachements,
headers
Mail.prototype.send = function (subject, body, priority, attachements) {
if (attachements === void 0) { attachements = []; }
return __awaiter(this, void 0, void 0, function () {
var temp, transport, headers;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this._config.smtp.disabled === true)
return [2 /*return*/];
temp = {
host: this._config.smtp.host,
port: this._config.smtp.port,
tls: { rejectUnauthorized: false },
secure: this._config.smtp.secure === true,
auth: null
};
if (this._config.smtp.user)
temp.auth = {
user: this._config.smtp.user,
pass: this._config.smtp.password
};
transport = Mailer.createTransport(temp), headers = {};
if (priority)
headers["importance"] = priority;
return [4 /*yield*/, transport.sendMail({
to: this._config.mailTo,
from: this._config.smtp.from || this._config.smtp.user,
replyTo: this._config.replyTo,
subject: "pm2-health: " + os_1.hostname() + ", " + subject,
html: this._template
.replace(/<!--\s*body\s*-->/, body)
.replace(/<!--\s*timeStamp\s*-->/, new Date().toISOString()),
attachments: attachements,
headers: headers
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
}
}
};
return Mail;
}());
exports.Mail = Mail;
//# sourceMappingURL=Mail.js.map
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ After installation run `pm2 conf` to configure module. Alternatively edit `modul

* `events` - list of events to monitor (optional). If not set, all events will be monitored.

* `eventExcludeExps` - array of regular expressions used to exclude events (optional).

> Manually triggered events will not send notification.

* `exceptions` - if `true` apps exceptions will be monitored (optional)
Expand Down Expand Up @@ -221,4 +223,4 @@ To send test mail: `pm2 trigger pm2-health mail`

`es2017` is supported by Node 8+. If you need to use ealier version, build solution using `es5` or `es6` target.

> Solution includes VS Code settings for build and debug.
> Solution includes VS Code settings for build and debug.
Loading