Browse Source

Not sent request to hastic server on deletion #96 (#97)

* delete request to hastic-server
* sync plugin with hastic-server state
master
Alexey Velikiy 6 years ago committed by GitHub
parent
commit
613775c882
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 53
      src/controllers/analytic_controller.ts
  2. 2
      src/graph_renderer.ts
  3. 9
      src/models/analytic_unit.ts
  4. 40
      src/module.ts
  5. 92
      src/services/analytic_service.ts

53
src/controllers/analytic_controller.ts

@ -45,12 +45,12 @@ export class AnalyticController {
private _serverInfo: ServerInfo; private _serverInfo: ServerInfo;
constructor(private _panelObject: any, private _analyticService: AnalyticService, private _emitter: Emitter) { constructor(private _panelObject: any, private _analyticService: AnalyticService, private _emitter: Emitter) {
if(_panelObject.anomalyTypes === undefined) { if(_panelObject.analyticUnits === undefined) {
_panelObject.anomalyTypes = []; _panelObject.analyticUnits = _panelObject.anomalyTypes || [];
} }
this._labelingDataAddedSegments = new SegmentArray<AnalyticSegment>(); this._labelingDataAddedSegments = new SegmentArray<AnalyticSegment>();
this._labelingDataDeletedSegments = new SegmentArray<AnalyticSegment>(); this._labelingDataDeletedSegments = new SegmentArray<AnalyticSegment>();
this._analyticUnitsSet = new AnalyticUnitsSet(this._panelObject.anomalyTypes); this._analyticUnitsSet = new AnalyticUnitsSet(this._panelObject.analyticUnits);
// this.analyticUnits.forEach(a => this.runEnabledWaiter(a)); // this.analyticUnits.forEach(a => this.runEnabledWaiter(a));
} }
@ -101,15 +101,15 @@ export class AnalyticController {
get graphLocked() { return this._graphLocked; } get graphLocked() { return this._graphLocked; }
set graphLocked(value) { this._graphLocked = value; } set graphLocked(value) { this._graphLocked = value; }
get labelingAnomaly(): AnalyticUnit { get labelingUnit(): AnalyticUnit {
if(this._selectedAnalyticUnitId === null) { if(this._selectedAnalyticUnitId === null) {
return null; return null;
} }
return this._analyticUnitsSet.byId(this._selectedAnalyticUnitId); return this._analyticUnitsSet.byId(this._selectedAnalyticUnitId);
} }
async toggleAnomalyTypeLabelingMode(id: AnalyticUnitId) { async toggleUnitTypeLabelingMode(id: AnalyticUnitId) {
if(this.labelingAnomaly && this.labelingAnomaly.saving) { if(this.labelingUnit && this.labelingUnit.saving) {
throw new Error('Can`t toggle during saving'); throw new Error('Can`t toggle during saving');
} }
if(this._selectedAnalyticUnitId === id) { if(this._selectedAnalyticUnitId === id) {
@ -117,7 +117,7 @@ export class AnalyticController {
} }
await this.disableLabeling(); await this.disableLabeling();
this._selectedAnalyticUnitId = id; this._selectedAnalyticUnitId = id;
this.labelingAnomaly.selected = true; this.labelingUnit.selected = true;
this.toggleVisibility(id, true); this.toggleVisibility(id, true);
} }
@ -125,22 +125,22 @@ export class AnalyticController {
if(this._selectedAnalyticUnitId === null) { if(this._selectedAnalyticUnitId === null) {
return; return;
} }
this.labelingAnomaly.saving = true; this.labelingUnit.saving = true;
var newIds = await this._saveLabelingData(); var newIds = await this._saveLabelingData();
this._labelingDataAddedSegments.getSegments().forEach((s, i) => { this._labelingDataAddedSegments.getSegments().forEach((s, i) => {
this.labelingAnomaly.segments.updateId(s.id, newIds[i]); this.labelingUnit.segments.updateId(s.id, newIds[i]);
}); });
this.labelingAnomaly.saving = false; this.labelingUnit.saving = false;
var anomaly = this.labelingAnomaly; var anomaly = this.labelingUnit;
this.dropLabeling(); this.dropLabeling();
this._runStatusWaiter(anomaly); this._runStatusWaiter(anomaly);
} }
undoLabeling() { undoLabeling() {
this._labelingDataAddedSegments.getSegments().forEach(s => { this._labelingDataAddedSegments.getSegments().forEach(s => {
this.labelingAnomaly.segments.remove(s.id); this.labelingUnit.segments.remove(s.id);
}); });
this._labelingDataDeletedSegments.getSegments().forEach(s => { this._labelingDataDeletedSegments.getSegments().forEach(s => {
s.deleted = false; s.deleted = false;
@ -151,7 +151,7 @@ export class AnalyticController {
dropLabeling() { dropLabeling() {
this._labelingDataAddedSegments.clear(); this._labelingDataAddedSegments.clear();
this._labelingDataDeletedSegments.clear(); this._labelingDataDeletedSegments.clear();
this.labelingAnomaly.selected = false; this.labelingUnit.selected = false;
this._selectedAnalyticUnitId = null; this._selectedAnalyticUnitId = null;
this._tempIdCounted = -1; this._tempIdCounted = -1;
} }
@ -164,11 +164,11 @@ export class AnalyticController {
if(!this.labelingMode) { if(!this.labelingMode) {
return false; return false;
} }
return this.labelingAnomaly.deleteMode; return this.labelingUnit.deleteMode;
} }
addLabelSegment(segment: Segment) { addLabelSegment(segment: Segment) {
var asegment = this.labelingAnomaly.addLabeledSegment(segment); var asegment = this.labelingUnit.addLabeledSegment(segment);
this._labelingDataAddedSegments.addSegment(asegment); this._labelingDataAddedSegments.addSegment(asegment);
} }
@ -183,11 +183,11 @@ export class AnalyticController {
this._analyticUnitsSet.byId(id).color = value; this._analyticUnitsSet.byId(id).color = value;
} }
fetchAnomalyTypesStatuses() { fetchAnalyticUnitsStatuses() {
this.analyticUnits.forEach(a => this._runStatusWaiter(a)); this.analyticUnits.forEach(a => this._runStatusWaiter(a));
} }
async fetchAnomalyTypesSegments(from: number, to: number) { async fetchAnalyticUnitsSegments(from: number, to: number) {
if(!_.isNumber(+from)) { if(!_.isNumber(+from)) {
throw new Error('from isn`t number'); throw new Error('from isn`t number');
} }
@ -215,9 +215,9 @@ export class AnalyticController {
} }
private async _saveLabelingData(): Promise<SegmentId[]> { private async _saveLabelingData(): Promise<SegmentId[]> {
var anomaly = this.labelingAnomaly; var unit = this.labelingUnit;
if(anomaly === null) { if(unit === null) {
throw new Error('anomaly is not selected'); throw new Error('analytic unit is not selected');
} }
if( if(
@ -228,7 +228,7 @@ export class AnalyticController {
} }
return this._analyticService.updateSegments( return this._analyticService.updateSegments(
anomaly.id, this._labelingDataAddedSegments, this._labelingDataDeletedSegments unit.id, this._labelingDataAddedSegments, this._labelingDataDeletedSegments
); );
} }
@ -304,7 +304,7 @@ export class AnalyticController {
} }
deleteLabelingAnomalySegmentsInRange(from: number, to: number) { deleteLabelingAnomalySegmentsInRange(from: number, to: number) {
var allRemovedSegs = this.labelingAnomaly.removeSegmentsInRange(from, to); var allRemovedSegs = this.labelingUnit.removeSegmentsInRange(from, to);
allRemovedSegs.forEach(s => { allRemovedSegs.forEach(s => {
if(!this._labelingDataAddedSegments.has(s.id)) { if(!this._labelingDataAddedSegments.has(s.id)) {
this._labelingDataDeletedSegments.addSegment(s); this._labelingDataDeletedSegments.addSegment(s);
@ -317,14 +317,17 @@ export class AnalyticController {
if(!this.labelingMode) { if(!this.labelingMode) {
throw new Error('Cant enter delete mode is labeling mode disabled'); throw new Error('Cant enter delete mode is labeling mode disabled');
} }
this.labelingAnomaly.deleteMode = !this.labelingAnomaly.deleteMode; this.labelingUnit.deleteMode = !this.labelingUnit.deleteMode;
} }
removeAnalyticUnit(id: AnalyticUnitId) { async removeAnalyticUnit(id: AnalyticUnitId, silent: boolean = false) {
if(id === this._selectedAnalyticUnitId) { if(id === this._selectedAnalyticUnitId) {
this.dropLabeling(); this.dropLabeling();
} }
this._analyticUnitsSet.removeItem(id); this._analyticUnitsSet.removeItem(id);
if(!silent) {
await this._analyticService.removeAnalyticUnit(id);
}
} }
private async _runStatusWaiter(analyticUnit: AnalyticUnit) { private async _runStatusWaiter(analyticUnit: AnalyticUnit) {
@ -354,7 +357,7 @@ export class AnalyticController {
if(error !== undefined) { if(error !== undefined) {
analyticUnit.error = error; analyticUnit.error = error;
} }
this._emitter.emit('anomaly-type-status-change', analyticUnit); this._emitter.emit('analytic-unit-status-change', analyticUnit);
} }
if(!analyticUnit.isActiveStatus) { if(!analyticUnit.isActiveStatus) {
break; break;

2
src/graph_renderer.ts

@ -352,7 +352,7 @@ export class GraphRenderer {
ANOMALY_REGION_DELETE_COLOR_LIGHT : ANOMALY_REGION_DELETE_COLOR_LIGHT :
ANOMALY_REGION_DELETE_COLOR_DARK; ANOMALY_REGION_DELETE_COLOR_DARK;
} else { } else {
color = this._analyticController.labelingAnomaly.color; color = this._analyticController.labelingUnit.color;
} }
fillAlpha = ANOMALY_REGION_FILL_ALPHA; fillAlpha = ANOMALY_REGION_FILL_ALPHA;
strokeAlpha = ANOMALY_REGION_STROKE_ALPHA; strokeAlpha = ANOMALY_REGION_STROKE_ALPHA;

9
src/models/analytic_unit.ts

@ -100,6 +100,7 @@ export class AnalyticUnit {
get status() { return this._status; } get status() { return this._status; }
set status(value) { set status(value) {
if( if(
value !== '404' &&
value !== 'READY' && value !== 'READY' &&
value !== 'LEARNING' && value !== 'LEARNING' &&
value !== 'PENDING' && value !== 'PENDING' &&
@ -114,7 +115,13 @@ export class AnalyticUnit {
set error(value) { this._error = value; } set error(value) { this._error = value; }
get isActiveStatus() { get isActiveStatus() {
return this.status !== 'READY' && this.status !== 'FAILED'; switch(this.status) {
case '404':
case 'READY':
case 'FAILED':
return false;
}
return true;
} }
get panelObject() { return this._panelObject; } get panelObject() { return this._panelObject; }

40
src/module.ts

@ -17,6 +17,9 @@ import { axesEditorComponent } from './axes_editor';
import { MetricsPanelCtrl, alertTab } from 'grafana/app/plugins/sdk'; import { MetricsPanelCtrl, alertTab } from 'grafana/app/plugins/sdk';
import { appEvents } from 'grafana/app/core/core' import { appEvents } from 'grafana/app/core/core'
import { BackendSrv } from 'grafana/app/core/services/backend_srv';
import { AlertSrv } from 'grafana/app/core/services/alert_srv';
import config from 'grafana/app/core/config'; import config from 'grafana/app/core/config';
import _ from 'lodash'; import _ from 'lodash';
@ -148,10 +151,13 @@ class GraphCtrl extends MetricsPanelCtrl {
/** @ngInject */ /** @ngInject */
constructor( constructor(
$scope, $injector, $http, private annotationsSrv, $scope, $injector, $http,
private keybindingSrv, private backendSrv, private annotationsSrv,
private popoverSrv, private contextSrv, private keybindingSrv,
private alertSrv private backendSrv: BackendSrv,
private popoverSrv,
private contextSrv,
private alertSrv: AlertSrv
) { ) {
super($scope, $injector); super($scope, $injector);
@ -162,8 +168,7 @@ class GraphCtrl extends MetricsPanelCtrl {
this.processor = new DataProcessor(this.panel); this.processor = new DataProcessor(this.panel);
this.analyticService = new AnalyticService(this.backendURL, $http, this.backendSrv, this.alertSrv);
this.analyticService = new AnalyticService(this.backendURL, $http, this.alertSrv);
this.runBackendConnectivityCheck(); this.runBackendConnectivityCheck();
@ -180,12 +185,15 @@ class GraphCtrl extends MetricsPanelCtrl {
this.events.on('anomaly-type-alert-change', () => { this.events.on('anomaly-type-alert-change', () => {
this.$scope.$digest() this.$scope.$digest()
}); });
this.events.on('anomaly-type-status-change', async (anomalyType: AnalyticUnit) => { this.events.on('analytic-unit-status-change', async (analyticUnit: AnalyticUnit) => {
if(anomalyType === undefined) { if(analyticUnit === undefined) {
throw new Error('anomalyType is undefined'); throw new Error('analyticUnit is undefined');
}
if(analyticUnit.status === '404') {
await this.analyticsController.removeAnalyticUnit(analyticUnit.id, true);
} }
if(anomalyType.status === 'READY') { if(analyticUnit.status === 'READY') {
await this.analyticsController.fetchSegments(anomalyType, +this.range.from, +this.range.to); await this.analyticsController.fetchSegments(analyticUnit, +this.range.from, +this.range.to);
} }
this.render(this.seriesList); this.render(this.seriesList);
this.$scope.$digest(); this.$scope.$digest();
@ -203,7 +211,7 @@ class GraphCtrl extends MetricsPanelCtrl {
}; };
}); });
this.analyticsController.fetchAnomalyTypesStatuses(); this.analyticsController.fetchAnalyticUnitsStatuses();
} }
@ -326,7 +334,7 @@ class GraphCtrl extends MetricsPanelCtrl {
var loadTasks = [ var loadTasks = [
// this.annotationsPromise, // this.annotationsPromise,
this.analyticsController.fetchAnomalyTypesSegments(+this.range.from, +this.range.to) this.analyticsController.fetchAnalyticUnitsSegments(+this.range.from, +this.range.to)
]; ];
var results = await Promise.all(loadTasks); var results = await Promise.all(loadTasks);
@ -558,11 +566,11 @@ class GraphCtrl extends MetricsPanelCtrl {
this.render(); this.render();
} }
onRemove(id: AnalyticUnitId) { async onRemove(id: AnalyticUnitId) {
if(id === undefined) { if(id === undefined) {
throw new Error('id is undefined'); throw new Error('id is undefined');
} }
this.analyticsController.removeAnalyticUnit(id); await this.analyticsController.removeAnalyticUnit(id);
this.render(); this.render();
} }
@ -584,7 +592,7 @@ class GraphCtrl extends MetricsPanelCtrl {
} }
async onToggleLabelingMode(key) { async onToggleLabelingMode(key) {
await this.analyticsController.toggleAnomalyTypeLabelingMode(key as AnalyticUnitId); await this.analyticsController.toggleUnitTypeLabelingMode(key as AnalyticUnitId);
this.$scope.$digest(); this.$scope.$digest();
this.render(); this.render();
} }

92
src/services/analytic_service.ts

@ -4,12 +4,18 @@ import { DatasourceRequest } from '../models/datasource';
import { SegmentsSet } from '../models/segment_set'; import { SegmentsSet } from '../models/segment_set';
import { AnalyticUnitId, AnalyticUnit, AnalyticSegment } from '../models/analytic_unit'; import { AnalyticUnitId, AnalyticUnit, AnalyticSegment } from '../models/analytic_unit';
import { ServerInfo } from '../models/info'; import { ServerInfo } from '../models/info';
import { BackendSrv } from 'grafana/app/core/services/backend_srv';
import { AlertSrv } from 'grafana/app/core/services/alert_srv';
export class AnalyticService { export class AnalyticService {
private _isUp = false; private _isUp = false;
constructor(private _backendURL: string, private $http, private alertSrv) { constructor(
private _backendURL: string, private $http,
private _backendSrv: BackendSrv,
private _alertSrv: AlertSrv
) {
this.isBackendOk(); this.isBackendOk();
} }
@ -17,10 +23,10 @@ export class AnalyticService {
metric: MetricExpanded, datasourceRequest: DatasourceRequest, metric: MetricExpanded, datasourceRequest: DatasourceRequest,
newItem: AnalyticUnit, panelId: number newItem: AnalyticUnit, panelId: number
): Promise<AnalyticUnitId> { ): Promise<AnalyticUnitId> {
let datasource = await this.get(`/api/datasources/name/${metric.datasource}`); let datasource = await this._backendSrv.get(`/api/datasources/name/${metric.datasource}`);
datasourceRequest.type = datasource.type; datasourceRequest.type = datasource.type;
const response = await this.post(this._backendURL + '/analyticUnits', { const response = await this.post('/analyticUnits', {
panelUrl: window.location.origin + window.location.pathname + `?panelId=${panelId}&fullscreen`, panelUrl: window.location.origin + window.location.pathname + `?panelId=${panelId}&fullscreen`,
type: newItem.type, type: newItem.type,
name: newItem.name, name: newItem.name,
@ -31,9 +37,12 @@ export class AnalyticService {
return response.id as AnalyticUnitId; return response.id as AnalyticUnitId;
} }
async isBackendOk(): Promise<boolean> { async removeAnalyticUnit(id: AnalyticUnitId) {
await this.get(this._backendURL); return this.delete('/analyticUnits', { id });
}
async isBackendOk(): Promise<boolean> {
await this.get('/');
return this._isUp; return this._isUp;
} }
@ -51,7 +60,7 @@ export class AnalyticService {
removedSegments: removedSegments.getSegments().map(s => s.id) removedSegments: removedSegments.getSegments().map(s => s.id)
}; };
var data = await this.patch(this._backendURL + '/segments', payload); var data = await this.patch('/segments', payload);
if(data.addedIds === undefined) { if(data.addedIds === undefined) {
throw new Error('Server didn`t send addedIds'); throw new Error('Server didn`t send addedIds');
} }
@ -69,7 +78,7 @@ export class AnalyticService {
if(to !== undefined) { if(to !== undefined) {
payload['to'] = to; payload['to'] = to;
} }
var data = await this.get(this._backendURL + '/segments', payload); var data = await this.get('/segments', payload);
if(data.segments === undefined) { if(data.segments === undefined) {
throw new Error('Server didn`t return segments array'); throw new Error('Server didn`t return segments array');
} }
@ -77,13 +86,21 @@ export class AnalyticService {
return segments.map(s => new AnalyticSegment(s.labeled, s.id, s.from, s.to, s.deleted)); return segments.map(s => new AnalyticSegment(s.labeled, s.id, s.from, s.to, s.deleted));
} }
async * getStatusGenerator(id: AnalyticUnitId, duration: number) { async * getStatusGenerator(id: AnalyticUnitId, duration: number):
AsyncIterableIterator<{ status: string, errorMessage?: string }> {
if(id === undefined) { if(id === undefined) {
throw new Error('id is undefined'); throw new Error('id is undefined');
} }
let statusCheck = async () => { let statusCheck = async () => {
var data = await this.get(this._backendURL + '/analyticUnits/status', { id }); try {
return data; return await this.get('/analyticUnits/status', { id });
} catch(error) {
if(error.status === 404) {
return { status: '404' };
}
throw error;
}
} }
let timeout = async () => new Promise( let timeout = async () => new Promise(
@ -100,7 +117,7 @@ export class AnalyticService {
if(id === undefined) { if(id === undefined) {
throw new Error('id is undefined'); throw new Error('id is undefined');
} }
var data = await this.get(this._backendURL + '/alerts', { id }); var data = await this.get('/alerts', { id });
if(data.enabled === undefined) { if(data.enabled === undefined) {
throw new Error('Server didn`t return "enabled"'); throw new Error('Server didn`t return "enabled"');
} }
@ -111,12 +128,11 @@ export class AnalyticService {
if(id === undefined) { if(id === undefined) {
throw new Error('id is undefined'); throw new Error('id is undefined');
} }
return await this.post(this._backendURL + '/alerts', { id, enabled }); return await this.post('/alerts', { id, enabled });
} }
async getServerInfo(): Promise<ServerInfo> { async getServerInfo(): Promise<ServerInfo> {
let data = await this.get(this._backendURL); let data = await this.get('/');
console.log(data);
return { return {
nodeVersion: data.nodeVersion, nodeVersion: data.nodeVersion,
packageVersion: data.packageVersion, packageVersion: data.packageVersion,
@ -129,44 +145,48 @@ export class AnalyticService {
}; };
} }
private async get(url, params?) { private async _analyticRequest(method: string, url: string, data?) {
try { try {
let response = await this.$http({ method: 'GET', url, params }); method = method.toUpperCase();
url = this._backendURL + url;
let requestObject: any = { method, url };
if(method === 'GET' || method === 'DELETE') {
requestObject.params = data;
} else {
requestObject.data = data;
}
let response = await this.$http(requestObject);
this._isUp = true; this._isUp = true;
return response.data; return response.data;
} catch(error) { } catch(error) {
if(error.xhrStatus === 'error') {
this.displayConnectionAlert(); this.displayConnectionAlert();
console.error(error);
this._isUp = false; this._isUp = false;
} else {
this._isUp = true;
}
throw error;
} }
} }
private async post(url, data) { private async get(url, params?) {
try { return this._analyticRequest('GET', url, params);
let response = await this.$http({ method: 'POST', url, data });
this._isUp = true;
return response.data;
} catch(error) {
this.displayConnectionAlert();
console.error(error);
this._isUp = false;
} }
private async post(url, data?) {
return this._analyticRequest('POST', url, data);
} }
private async patch(url, data) { private async patch(url, data?) {
try { return this._analyticRequest('PATCH', url, data);
let response = await this.$http({ method: 'PATCH', url, data });
this._isUp = true;
return response.data;
} catch(error) {
this.displayConnectionAlert();
console.error(error);
this._isUp = false;
} }
private async delete(url, data?) {
return this._analyticRequest('DELETE', url, data);
} }
private displayConnectionAlert() { private displayConnectionAlert() {
this.alertSrv.set( this._alertSrv.set(
'No connection to Hastic server', 'No connection to Hastic server',
`Hastic server: "${this._backendURL}"`, `Hastic server: "${this._backendURL}"`,
'warning', 4000 'warning', 4000

Loading…
Cancel
Save