Browse Source
* Add webhook settings to config * Update notification service * Remove alerts controller * Remove alerts router * Add alert field to analytic unit * Add endpoints: - GET analyticUnits/units - PATCH analyticUnits/alert * Rename sendNotification -> sendWebhook * Change webhook payload * Send webhook on detectionpull/1/head
8 changed files with 136 additions and 151 deletions
@ -1,4 +1,7 @@ |
|||||||
{ |
{ |
||||||
"HASTIC_PORT": 8000, |
"HASTIC_PORT": 8000, |
||||||
"HASTIC_API_KEY": "eyJrIjoiVjZqMHY0dHk4UEE3eEN4MzgzRnd2aURlMWlIdXdHNW4iLCJuIjoiaGFzdGljIiwiaWQiOjF9" |
"HASTIC_API_KEY": "eyJrIjoiVjZqMHY0dHk4UEE3eEN4MzgzRnd2aURlMWlIdXdHNW4iLCJuIjoiaGFzdGljIiwiaWQiOjF9", |
||||||
|
"HASTIC_WEBHOOK_URL": "http://localhost:8080", |
||||||
|
"HASTIC_WEBHOOK_TYPE": "application/x-www-form-urlencoded", |
||||||
|
"HASTIC_WEBHOOK_SECRET": "mysecret" |
||||||
} |
} |
||||||
|
@ -1,72 +0,0 @@ |
|||||||
/** |
|
||||||
* Alarting is not supported yet |
|
||||||
*/ |
|
||||||
|
|
||||||
throw new Error('not supported'); |
|
||||||
|
|
||||||
|
|
||||||
// import { runDetect } from './analytics_controller';
|
|
||||||
// import { getLabeledSegments } from './segments_controller';
|
|
||||||
// import { AnalyticUnitId } from '../models/analytic_unit';
|
|
||||||
// import { sendNotification } from '../services/notification_service';
|
|
||||||
// import { getJsonDataSync, writeJsonDataSync } from '../services/json_service';
|
|
||||||
// import { ANALYTIC_UNITS_PATH } from '../config';
|
|
||||||
|
|
||||||
// import * as path from 'path';
|
|
||||||
// import * as fs from 'fs';
|
|
||||||
|
|
||||||
|
|
||||||
// const ALERT_TIMEOUT = 60000; // ms
|
|
||||||
// const ALERTS_DB_PATH = path.join(ANALYTIC_UNITS_PATH, `alerts_anomalies.json`);
|
|
||||||
|
|
||||||
|
|
||||||
// export function getAlertsAnomalies(): AnalyticUnitId[] {
|
|
||||||
// if(!fs.existsSync(ALERTS_DB_PATH)) {
|
|
||||||
// saveAlertsAnomalies([]);
|
|
||||||
// }
|
|
||||||
// return getJsonDataSync(ALERTS_DB_PATH);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function saveAlertsAnomalies(units: AnalyticUnitId[]) {
|
|
||||||
// return writeJsonDataSync(ALERTS_DB_PATH, units);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function processAlerts(id: AnalyticUnitId) {
|
|
||||||
// let segments = getLabeledSegments(id);
|
|
||||||
|
|
||||||
// const currentTime = new Date().getTime();
|
|
||||||
// const activeAlert = activeAlerts.has(id);
|
|
||||||
// let newActiveAlert = false;
|
|
||||||
|
|
||||||
// if(segments.length > 0) {
|
|
||||||
// let lastSegment = segments[segments.length - 1];
|
|
||||||
// if(lastSegment.finish >= currentTime - ALERT_TIMEOUT) {
|
|
||||||
// newActiveAlert = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if(!activeAlert && newActiveAlert) {
|
|
||||||
// activeAlerts.add(id);
|
|
||||||
// sendNotification(id, true);
|
|
||||||
// } else if(activeAlert && !newActiveAlert) {
|
|
||||||
// activeAlerts.delete(id);
|
|
||||||
// sendNotification(id, false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async function alertsTick() {
|
|
||||||
// let alertsAnomalies = getAlertsAnomalies();
|
|
||||||
// for (let detectorId of alertsAnomalies) {
|
|
||||||
// try {
|
|
||||||
// await runDetect(detectorId);
|
|
||||||
// processAlerts(detectorId);
|
|
||||||
// } catch (e) {
|
|
||||||
// console.error(e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// setTimeout(alertsTick, 5000);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// const activeAlerts = new Set<string>();
|
|
||||||
// setTimeout(alertsTick, 5000);
|
|
@ -1,43 +0,0 @@ |
|||||||
// /**
|
|
||||||
// * Alarting is not supported yet
|
|
||||||
// */
|
|
||||||
|
|
||||||
// throw new console.error("Not supported");
|
|
||||||
|
|
||||||
|
|
||||||
// import * as AnalyticUnit from '../models/analytic_unit';
|
|
||||||
// import { getAlertsAnomalies, saveAlertsAnomalies } from '../controllers/alerts_controller';
|
|
||||||
|
|
||||||
// import * as Router from 'koa-router';
|
|
||||||
|
|
||||||
|
|
||||||
// function getAlert(ctx: Router.IRouterContext) {
|
|
||||||
// let id: AnalyticUnit.AnalyticUnitId = ctx.request.query.id;
|
|
||||||
|
|
||||||
// let alertsAnomalies = getAlertsAnomalies();
|
|
||||||
// let pos = alertsAnomalies.indexOf(id);
|
|
||||||
|
|
||||||
// let enabled: boolean = (pos !== -1);
|
|
||||||
// ctx.response.body = { enabled };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function setAlertEnabled(ctx: Router.IRouterContext) {
|
|
||||||
// let id: AnalyticUnit.AnalyticUnitId = ctx.request.body.id;
|
|
||||||
// let enabled: boolean = ctx.request.body.enabled;
|
|
||||||
|
|
||||||
// let alertsAnomalies = getAlertsAnomalies();
|
|
||||||
// let pos: number = alertsAnomalies.indexOf(id);
|
|
||||||
// if(enabled && pos == -1) {
|
|
||||||
// alertsAnomalies.push(id);
|
|
||||||
// saveAlertsAnomalies(alertsAnomalies);
|
|
||||||
// } else if(!enabled && pos > -1) {
|
|
||||||
// alertsAnomalies.splice(pos, 1);
|
|
||||||
// saveAlertsAnomalies(alertsAnomalies);
|
|
||||||
// }
|
|
||||||
// ctx.response.body = { status: 'OK' };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export const router = new Router();
|
|
||||||
|
|
||||||
// router.get('/', getAlert);
|
|
||||||
// router.post('/', setAlertEnabled);
|
|
@ -1,39 +1,47 @@ |
|||||||
import { findById, AnalyticUnitId } from '../models/analytic_unit_model'; |
import { Segment } from '../models/segment_model'; |
||||||
|
import { HASTIC_WEBHOOK_URL, HASTIC_WEBHOOK_TYPE, HASTIC_WEBHOOK_SECRET } from '../config'; |
||||||
|
|
||||||
import axios from 'axios'; |
import axios from 'axios'; |
||||||
|
import * as querystring from 'querystring'; |
||||||
|
|
||||||
|
|
||||||
// TODO: send notification with payload without dep to AnalyticUnit
|
// TODO: send webhook with payload without dep to AnalyticUnit
|
||||||
export async function sendNotification(id: AnalyticUnitId, active: boolean) { |
export async function sendWebhook(analyticUnitName: string, segment: Segment) { |
||||||
let anomalyName = (await findById(id)).name |
if(HASTIC_WEBHOOK_URL === null) { |
||||||
console.log('Notification ' + anomalyName); |
throw new Error(`Can't send alert, HASTIC_WEBHOOK_URL is undefined`); |
||||||
|
} |
||||||
|
|
||||||
let notification = { |
const alert = { |
||||||
anomaly: anomalyName, |
analyticUnitName, |
||||||
status: '' |
from: segment.from, |
||||||
|
to: segment.to
|
||||||
}; |
}; |
||||||
if(active) { |
|
||||||
notification.status = 'alert'; |
console.log(`Sending alert: ${JSON.stringify(alert)}`); |
||||||
|
|
||||||
|
let payload; |
||||||
|
if(HASTIC_WEBHOOK_TYPE === 'application/json') { |
||||||
|
payload = JSON.stringify(alert); |
||||||
|
} else if(HASTIC_WEBHOOK_TYPE === 'application/x-www-form-urlencoded') { |
||||||
|
payload = querystring.stringify(alert); |
||||||
} else { |
} else { |
||||||
notification.status = 'OK'; |
throw new Error(`Unknown webhook type: ${HASTIC_WEBHOOK_TYPE}`); |
||||||
} |
} |
||||||
|
|
||||||
// TODO: more to config
|
// TODO: use HASTIC_WEBHOOK_SECRET
|
||||||
let endpoint = process.env.HASTIC_ALERT_ENDPOINT; |
const options = { |
||||||
if(endpoint === undefined) { |
method: 'POST', |
||||||
console.error(`Can't send alert, env HASTIC_ALERT_ENDPOINT is undefined`); |
url: HASTIC_WEBHOOK_URL, |
||||||
return; |
data: payload, |
||||||
} |
headers: { 'Content-Type': HASTIC_WEBHOOK_TYPE } |
||||||
|
}; |
||||||
|
|
||||||
try { |
try { |
||||||
var data = await axios.post(endpoint, { |
const response = await axios(options); |
||||||
method: 'POST', |
console.log(response); |
||||||
body: JSON.stringify(notification) |
|
||||||
}) |
|
||||||
console.log(data); |
|
||||||
} catch(err) { |
} catch(err) { |
||||||
console.error(`Can't send alert to ${endpoint}. Error: ${err}`); |
console.error(`Can't send alert to ${HASTIC_WEBHOOK_URL}. Error: ${err.message}`); |
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
|
Loading…
Reference in new issue