|
|
|
@ -1,10 +1,11 @@
|
|
|
|
|
import { sendNotification, InfoMeta, AnalyticMeta, WebhookType, Notification } from './notification_service'; |
|
|
|
|
|
|
|
|
|
import * as _ from 'lodash'; |
|
|
|
|
import * as AnalyticUnit from '../models/analytic_units'; |
|
|
|
|
import { Segment } from '../models/segment_model'; |
|
|
|
|
import { availableReporter } from '../utils/reporter'; |
|
|
|
|
import { ORG_ID } from '../config'; |
|
|
|
|
import { ORG_ID, HASTIC_API_KEY, HASTIC_WEBHOOK_IMAGE_ENABLED } from '../config'; |
|
|
|
|
|
|
|
|
|
import axios from 'axios'; |
|
|
|
|
import * as _ from 'lodash'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class Alert { |
|
|
|
@ -12,21 +13,52 @@ export class Alert {
|
|
|
|
|
constructor(protected analyticUnit: AnalyticUnit.AnalyticUnit) {}; |
|
|
|
|
public receive(segment: Segment) { |
|
|
|
|
if(this.enabled) { |
|
|
|
|
sendNotification(this.makeNotification(segment)); |
|
|
|
|
this.send(segment); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
protected makeNotification(segment: Segment): Notification { |
|
|
|
|
protected async send(segment) { |
|
|
|
|
const notification = await this.makeNotification(segment); |
|
|
|
|
sendNotification(notification); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected async makeNotification(segment: Segment): Promise<Notification> { |
|
|
|
|
const meta = this.makeMeta(segment); |
|
|
|
|
const message = this.makeMessage(meta); |
|
|
|
|
return { meta, message }; |
|
|
|
|
let result: Notification = { meta, message }; |
|
|
|
|
if(HASTIC_WEBHOOK_IMAGE_ENABLED) { |
|
|
|
|
try { |
|
|
|
|
const image = await this.loadImage(); |
|
|
|
|
result.image = image; |
|
|
|
|
} catch(err) { |
|
|
|
|
console.error(`Can't load alert image: ${err}. Check that API key has admin permissions`); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected async loadImage() { |
|
|
|
|
const headers = { Authorization: `Bearer ${HASTIC_API_KEY}` }; |
|
|
|
|
const dashdoardId = this.analyticUnit.panelId.split('/')[0]; |
|
|
|
|
const panelId = this.analyticUnit.panelId.split('/')[1]; |
|
|
|
|
const dashboardApiURL = `${this.analyticUnit.grafanaUrl}/api/dashboards/uid/${dashdoardId}`; |
|
|
|
|
const dashboardInfo: any = await axios.get(dashboardApiURL, { headers }); |
|
|
|
|
const dashboardName = _.last(dashboardInfo.data.meta.url.split('/')); |
|
|
|
|
const renderUrl = `${this.analyticUnit.grafanaUrl}/render/d-solo/${dashdoardId}/${dashboardName}?panelId=${panelId}&ordId=${ORG_ID}&api-rendering`; |
|
|
|
|
const response = await axios.get(renderUrl, { |
|
|
|
|
headers, |
|
|
|
|
responseType: 'arraybuffer' |
|
|
|
|
}); |
|
|
|
|
return new Buffer(response.data, 'binary').toString('base64'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected makeMeta(segment: Segment): AnalyticMeta { |
|
|
|
|
const datshdoardId = this.analyticUnit.panelId.split('/')[0]; |
|
|
|
|
const dashdoardId = this.analyticUnit.panelId.split('/')[0]; |
|
|
|
|
const panelId = this.analyticUnit.panelId.split('/')[1]; |
|
|
|
|
const grafanaUrl = `${this.analyticUnit.grafanaUrl}/d/${datshdoardId}?panelId=${panelId}&edit=true&fullscreen=true?orgId=${ORG_ID}`; |
|
|
|
|
const alert: AnalyticMeta = { |
|
|
|
|
const grafanaUrl = `${this.analyticUnit.grafanaUrl}/d/${dashdoardId}?panelId=${panelId}&edit=true&fullscreen=true?orgId=${ORG_ID}`; |
|
|
|
|
|
|
|
|
|
let alert: AnalyticMeta = { |
|
|
|
|
type: WebhookType.DETECT, |
|
|
|
|
analyticUnitType: this.analyticUnit.type, |
|
|
|
|
analyticUnitName: this.analyticUnit.name, |
|
|
|
@ -61,7 +93,7 @@ class PatternAlert extends Alert {
|
|
|
|
|
if(this.lastSentSegment === undefined || !segment.equals(this.lastSentSegment) ) { |
|
|
|
|
this.lastSentSegment = segment; |
|
|
|
|
if(this.enabled) { |
|
|
|
|
sendNotification(this.makeNotification(segment)); |
|
|
|
|
this.send(segment); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -89,14 +121,14 @@ class ThresholdAlert extends Alert {
|
|
|
|
|
if(this.lastOccurence === 0) { |
|
|
|
|
this.lastOccurence = segment.from; |
|
|
|
|
if(this.enabled) { |
|
|
|
|
sendNotification(this.makeNotification(segment)); |
|
|
|
|
this.send(segment); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
if(segment.from - this.lastOccurence > this.EXPIRE_PERIOD_MS) { |
|
|
|
|
if(this.enabled) { |
|
|
|
|
console.log(`time between threshold occurences ${segment.from - this.lastOccurence}ms, send alert`); |
|
|
|
|
sendNotification(this.makeNotification(segment)); |
|
|
|
|
this.send(segment); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -169,7 +201,7 @@ export class AlertService {
|
|
|
|
|
public sendGrafanaAvailableWebhook() { |
|
|
|
|
this._grafanaAvailableReporter(true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public sendGrafanaUnavailableWebhook() { |
|
|
|
|
this._grafanaAvailableReporter(false); |
|
|
|
|
} |
|
|
|
|