Browse Source

Image for webhook #705 (#706)

pull/1/head
Evgeny Smyshlyaev 5 years ago committed by rozetko
parent
commit
15e2cbccb6
  1. 1
      docker-compose.yml
  2. 4
      server/src/config.ts
  3. 58
      server/src/services/alert_service.ts
  4. 6
      server/src/services/notification_service.ts

1
docker-compose.yml

@ -12,6 +12,7 @@ services:
HASTIC_WEBHOOK_TYPE: ${HASTIC_WEBHOOK_TYPE}
GRAFANA_URL: ${GRAFANA_URL}
HASTIC_INSTANCE_NAME: ${HASTIC_INSTANCE_NAME}
HASTIC_WEBHOOK_IMAGE_ENABLED: ${HASTIC_WEBHOOK_IMAGE_ENABLED}
ports:
- ${HASTIC_PORT:-8000}:8000
volumes:

4
server/src/config.ts

@ -29,8 +29,10 @@ export const GRAFANA_URL = normalizeUrl(getConfigField('GRAFANA_URL', null));
// TODO: save orgId in analytic_units.db
export const ORG_ID = getConfigField('ORG_ID', 1);
export const HASTIC_WEBHOOK_URL = getConfigField('HASTIC_WEBHOOK_URL', null);
export const HASTIC_WEBHOOK_TYPE = getConfigField('HASTIC_WEBHOOK_TYPE', 'application/x-www-form-urlencoded');
export const HASTIC_WEBHOOK_TYPE = getConfigField('HASTIC_WEBHOOK_TYPE', 'application/json');
export const HASTIC_WEBHOOK_SECRET = getConfigField('HASTIC_WEBHOOK_SECRET', null);
export const HASTIC_WEBHOOK_IMAGE_ENABLED = getConfigField('HASTIC_WEBHOOK_IMAGE', false);
export const ANLYTICS_PING_INTERVAL = 500; // ms
export const PACKAGE_VERSION = getPackageVersion();
export const GIT_INFO = getGitInfo();

58
server/src/services/alert_service.ts

@ -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);
}

6
server/src/services/notification_service.ts

@ -25,8 +25,7 @@ export declare type AnalyticMeta = {
grafanaUrl: string,
from: number,
to: number
message?: any,
regionImage?: any
message?: any
}
export declare type InfoMeta = {
@ -38,7 +37,8 @@ export declare type InfoMeta = {
export declare type Notification = {
message: string,
meta: InfoMeta | AnalyticMeta
meta: InfoMeta | AnalyticMeta,
image?: any
}
export async function sendNotification(notification: Notification) {

Loading…
Cancel
Save