Browse Source

Detection in selected time range #235 (#259)

master
rozetko 6 years ago committed by GitHub
parent
commit
b86b28f703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 65
      src/panel/graph_panel/controllers/analytic_controller.ts
  2. 13
      src/panel/graph_panel/graph_ctrl.ts
  3. 7
      src/panel/graph_panel/graph_renderer.ts
  4. 10
      src/panel/graph_panel/models/analytic_unit.ts
  5. 14
      src/panel/graph_panel/models/detection_status.ts
  6. 18
      src/panel/graph_panel/partials/tab_analytics.html
  7. 13
      src/panel/graph_panel/services/analytic_service.ts

65
src/panel/graph_panel/controllers/analytic_controller.ts

@ -14,6 +14,7 @@ import { SegmentsSet } from '../models/segment_set';
import { SegmentArray } from '../models/segment_array';
import { HasticServerInfo, HasticServerInfoUnknown } from '../models/hastic_server_info';
import { Threshold, Condition } from '../models/threshold';
import { DetectionState } from '../models/detection_status';
import text from '../partials/help_section.html';
import {
@ -223,6 +224,28 @@ export class AnalyticController {
this.analyticUnits.forEach(a => this._runStatusWaiter(a));
}
async fetchAnalyticUnitsDetectionStatuses(from: number, to: number): Promise<void[]> {
if(!_.isNumber(+from)) {
throw new Error('from isn`t number');
}
if(!_.isNumber(+to)) {
throw new Error('to isn`t number');
}
const tasks = this.analyticUnits
.map(analyticUnit => this.fetchDetectionStatus(analyticUnit, from, to));
return Promise.all(tasks);
}
async fetchDetectionStatus(analyticUnit: AnalyticUnit, from: number, to: number): Promise<void> {
if(!_.isNumber(+from)) {
throw new Error('from isn`t number');
}
if(!_.isNumber(+to)) {
throw new Error('to isn`t number');
}
analyticUnit.detectionStatuses = await this._analyticService.getDetectionStatus(analyticUnit.id, from, to);
}
async fetchAnalyticUnitsSegments(from: number, to: number): Promise<void[]> {
if(!_.isNumber(+from)) {
throw new Error('from isn`t number');
@ -285,7 +308,9 @@ export class AnalyticController {
}
// TODO: move to renderer
updateFlotEvents(isEditMode: boolean, options: any): void {
updateFlotEvents(isEditMode: boolean, plot: any): void {
// We get a reference to flot options so we can change it and it'll be rendered
let options = plot.getOptions();
if(options.grid.markings === undefined) {
options.markings = [];
}
@ -343,6 +368,36 @@ export class AnalyticController {
color: segmentBorderColor
});
});
if(!analyticUnit.inspect) {
return;
}
const detectionStatuses = analyticUnit.detectionStatuses;
if(detectionStatuses === undefined) {
return;
}
const minValue = _.min(_.map(plot.getYAxes(), axis => axis.min));
detectionStatuses.forEach(detectionStatus => {
let underlineColor;
switch(detectionStatus.state) {
case DetectionState.READY:
underlineColor = 'green'
break;
case DetectionState.RUNNING:
underlineColor = 'yellow'
break;
case DetectionState.FAILED:
underlineColor = 'red'
break;
default:
break;
}
options.grid.markings.push({
xaxis: { from: detectionStatus.from, to: detectionStatus.to },
color: underlineColor,
yaxis: { from: minValue, to: minValue }
});
});
}
}
@ -504,6 +559,14 @@ export class AnalyticController {
await this.saveAnalyticUnit(analyticUnit);
}
public async toggleInspect(id: AnalyticUnitId) {
const analyticUnit = this._analyticUnitsSet.byId(id);
if(!analyticUnit.inspect) {
this.analyticUnits.forEach(analyticUnit => analyticUnit.inspect = false);
}
analyticUnit.inspect = !analyticUnit.inspect;
}
public onAnalyticUnitDetectorChange(analyticUnitTypes: any) {
this.newAnalyticUnit.type = analyticUnitTypes[this.newAnalyticUnit.detectorType][0].value;
}

13
src/panel/graph_panel/graph_ctrl.ts

@ -393,9 +393,13 @@ class GraphCtrl extends MetricsPanelCtrl {
}
if(this.analyticsController !== undefined) {
var loadTasks = [
const from = +this.range.from;
const to = +this.range.to;
const loadTasks = [
// this.annotationsPromise,
this.analyticsController.fetchAnalyticUnitsSegments(+this.range.from, +this.range.to)
this.analyticsController.fetchAnalyticUnitsSegments(from, to),
// TODO: run detection status waiter if detection state !== 'READY'
this.analyticsController.fetchAnalyticUnitsDetectionStatuses(from, to)
];
await Promise.all(loadTasks);
@ -665,6 +669,11 @@ class GraphCtrl extends MetricsPanelCtrl {
this.refresh();
}
onToggleInspect(id: AnalyticUnitId) {
this.analyticsController.toggleInspect(id);
this.refresh();
}
private async _updatePanelInfo() {
let datasource = undefined;
if(this.panel.datasource) {

7
src/panel/graph_panel/graph_renderer.ts

@ -338,7 +338,6 @@ export class GraphRenderer {
this._prepareXAxis(this.panel);
this._configureYAxisOptions(this.data);
// this.eventManager.addFlotEvents(this.annotations, this.flotOptions);
this._analyticController.updateFlotEvents(this.contextSrv.isEditor, this.flotOptions);
this.sortedSeries = this._sortSeries(this.data, this.panel);
this._callPlot(true);
@ -442,11 +441,17 @@ export class GraphRenderer {
}
}
private _drawAnalyticHook(plot: any) {
// We call updateFlotEvents from hook cause we need access to min Y axis value
this._analyticController.updateFlotEvents(this.contextSrv.isEditor, plot)
}
private _buildFlotOptions(panel) {
const stack = panel.stack ? true : null;
this.flotOptions = {
hooks: {
draw: [this._drawHook.bind(this)],
drawBackground: [this._drawAnalyticHook.bind(this)],
processOffset: [this._processOffsetHook.bind(this)],
},
legend: { show: false },

10
src/panel/graph_panel/models/analytic_unit.ts

@ -1,6 +1,7 @@
import { SegmentsSet } from './segment_set';
import { SegmentArray } from './segment_array';
import { Segment, SegmentId } from './segment';
import { DetectionStatus } from './detection_status';
import { ANALYTIC_UNIT_COLORS, DEFAULT_DELETED_SEGMENT_COLOR } from '../colors';
@ -39,6 +40,8 @@ export class AnalyticUnit {
private _selected: boolean = false;
private _saving: boolean = false;
private _segmentSet = new SegmentArray<AnalyticSegment>();
private _detectionStatuses: DetectionStatus[];
private _inspect = false;
private _status: string;
private _error: string;
@ -90,6 +93,9 @@ export class AnalyticUnit {
get saving(): boolean { return this._saving; }
set saving(value: boolean) { this._saving = value; }
get inspect(): boolean { return this._inspect; }
set inspect(value: boolean) { this._inspect = value; }
get visible(): boolean {
return (this._serverObject.visible === undefined) ? true : this._serverObject.visible
}
@ -113,8 +119,12 @@ export class AnalyticUnit {
this._segmentSet.setSegments(value.getSegments());
}
get detectionStatuses(): DetectionStatus[] { return this._detectionStatuses; }
set detectionStatuses(value: DetectionStatus[]) { this._detectionStatuses = value; }
get status() { return this._status; }
set status(value) {
// TODO: use enum
if(
value !== '404' &&
value !== 'READY' &&

14
src/panel/graph_panel/models/detection_status.ts

@ -0,0 +1,14 @@
import { AnalyticUnitId } from './analytic_unit';
export enum DetectionState {
READY = 'READY',
RUNNING = 'RUNNING',
FAILED = 'FAILED'
};
export type DetectionStatus = {
id: AnalyticUnitId,
state: DetectionState,
from: number,
to: number
};

18
src/panel/graph_panel/partials/tab_analytics.html

@ -140,6 +140,23 @@
</a>
</label>
<label class="gf-form-label" ng-if="analyticUnit.status === 'READY' && analyticUnit.visible">
<a
class="pointer"
ng-click="ctrl.onToggleInspect(analyticUnit.id)"
ng-if="!analyticUnit.inspect"
>
Inspect
</a>
<a
class="pointer"
ng-click="ctrl.onToggleInspect(analyticUnit.id)"
ng-if="analyticUnit.inspect"
>
Disable Inspect
</a>
</label>
<label class="gf-form-label">
<a
ng-if="!analyticUnit.selected"
@ -164,7 +181,6 @@
<i ng-if="analyticUnit.status === 'PENDING'" class="grafana-tip fa fa-list-ul ng-scope" bs-tooltip="'Pending'"></i>
<i ng-if="analyticUnit.status === 'FAILED'" class="grafana-tip fa fa-exclamation-circle ng-scope" bs-tooltip="'Error: ' + analyticUnit.error"></i>
</label>
</div>
</div>

13
src/panel/graph_panel/services/analytic_service.ts

@ -5,6 +5,7 @@ import { SegmentsSet } from '../models/segment_set';
import { AnalyticUnitId, AnalyticUnit, AnalyticSegment } from '../models/analytic_unit';
import { HasticServerInfo, HasticServerInfoUnknown } from '../models/hastic_server_info';
import { Threshold } from '../models/threshold';
import { DetectionStatus } from '../models/detection_status';
import { isHasticServerResponse, isSupportedServerVersion, SUPPORTED_SERVER_VERSION } from '../../../utlis';
@ -135,6 +136,18 @@ export class AnalyticService {
return data.addedIds as SegmentId[];
}
async getDetectionStatus(id: AnalyticUnitId, from: number, to: number): Promise<DetectionStatus[]> {
if(id === undefined) {
throw new Error('id is undefined');
}
let payload: any = { id, from, to };
const data = await this.get('/detectionStatus', payload);
if(data.timeranges === undefined) {
throw new Error('Server didn`t return timeranges array');
}
return data.timeranges;
}
async getSegments(id: AnalyticUnitId, from?: number, to?: number): Promise<AnalyticSegment[]> {
if(id === undefined) {
throw new Error('id is undefined');

Loading…
Cancel
Save