diff --git a/src/panel/graph_panel/controllers/analytic_controller.ts b/src/panel/graph_panel/controllers/analytic_controller.ts index 57d3a8d..4abb753 100644 --- a/src/panel/graph_panel/controllers/analytic_controller.ts +++ b/src/panel/graph_panel/controllers/analytic_controller.ts @@ -12,7 +12,7 @@ import { DatasourceRequest } from '../models/datasource'; import { Segment, SegmentId } from '../models/segment'; import { SegmentsSet } from '../models/segment_set'; import { SegmentArray } from '../models/segment_array'; -import { ServerInfo } from '../models/info'; +import { ServerInfo, ServerInfoUnknown } from '../models/info'; import { Threshold, Condition } from '../models/threshold'; import text from '../partials/help_section.html'; @@ -48,7 +48,11 @@ export class AnalyticController { private _currentDatasource: DatasourceRequest; private _thresholds: Threshold[]; - constructor(private _panelObject: any, private _analyticService: AnalyticService, private _emitter: Emitter) { + constructor( + private _panelObject: any, + private _emitter: Emitter, + private _analyticService?: AnalyticService, + ) { if(_panelObject.analyticUnits === undefined) { _panelObject.analyticUnits = _panelObject.anomalyTypes || []; } @@ -57,8 +61,6 @@ export class AnalyticController { this._analyticUnitsSet = new AnalyticUnitsSet(this._panelObject.analyticUnits); this._thresholds = []; this.updateThresholds(); - - // this.analyticUnits.forEach(a => this.runEnabledWaiter(a)); } get helpSectionText() { return text; } @@ -376,6 +378,9 @@ export class AnalyticController { } async updateThresholds(): Promise { + if(this._analyticService === undefined) { + return; + } const ids = _.map(this._panelObject.analyticUnits, (analyticUnit: any) => analyticUnit.id); const thresholds = await this._analyticService.getThresholds(ids); this._thresholds = thresholds; @@ -410,6 +415,9 @@ export class AnalyticController { } private async _runStatusWaiter(analyticUnit: AnalyticUnit) { + if(this._analyticService === undefined) { + return; + } if(analyticUnit === undefined || analyticUnit === null) { throw new Error('analyticUnit not defined'); } @@ -468,6 +476,10 @@ export class AnalyticController { } public async updateServerInfo() { + if(!this._analyticService) { + this._serverInfo = ServerInfoUnknown; + return; + } this._serverInfo = await this._analyticService.getServerInfo(); } @@ -475,7 +487,10 @@ export class AnalyticController { return this._serverInfo; } - public get serverStatus() { + public get serverStatus(): boolean { + if(this._analyticService === undefined) { + return false; + } return this._analyticService.isUp; } } diff --git a/src/panel/graph_panel/graph_ctrl.ts b/src/panel/graph_panel/graph_ctrl.ts index 8b179d1..e6e5332 100644 --- a/src/panel/graph_panel/graph_ctrl.ts +++ b/src/panel/graph_panel/graph_ctrl.ts @@ -183,7 +183,7 @@ class GraphCtrl extends MetricsPanelCtrl { this.rebindKeys(); } - getHasticDatasourceURL(): string { + getHasticDatasourceURL(): string | undefined { const hasticDatasourceId = this.panel.hasticDatasource; if(hasticDatasourceId !== undefined && hasticDatasourceId !== null) { const hasticDatasource = _.find(this._hasticDatasources, { id: hasticDatasourceId }); @@ -297,20 +297,24 @@ class GraphCtrl extends MetricsPanelCtrl { await this._fetchHasticDatasources(); const hasticDatasourceURL = this.getHasticDatasourceURL(); + if(hasticDatasourceURL === undefined) { + delete this.analyticService; + } else { + this.analyticService = new AnalyticService(hasticDatasourceURL, this.$http); + this.runDatasourceConnectivityCheck(); + } - this.analyticService = new AnalyticService(hasticDatasourceURL, this.$http); - this.runDatasourceConnectivityCheck(); - - this.analyticsController = new AnalyticController(this.panel, this.analyticService, this.events); + this.analyticsController = new AnalyticController(this.panel, this.events, this.analyticService); this.analyticsController.fetchAnalyticUnitsStatuses(); + this._updatePanelInfo(); + this.analyticsController.updateServerInfo(); + this._graphRenderer = new GraphRenderer( - this.$graphElem, this.timeSrv, this.contextSrv, this.$scope + this.$graphElem, this.timeSrv, this.contextSrv, this.$scope, this.analyticsController ); this._graphLegend = new GraphLegend(this.$legendElem, this.popoverSrv, this.$scope); - this._updatePanelInfo(); - this.analyticsController.updateServerInfo(); } issueQueries(datasource) { diff --git a/src/panel/graph_panel/graph_renderer.ts b/src/panel/graph_panel/graph_renderer.ts index 9537249..56c901e 100644 --- a/src/panel/graph_panel/graph_renderer.ts +++ b/src/panel/graph_panel/graph_renderer.ts @@ -40,7 +40,7 @@ const COLOR_SELECTION = '#666'; export class GraphRenderer { - private _analyticController: AnalyticController; + ; private data: any; private tooltip: GraphTooltip; private panelWidth: number; @@ -58,7 +58,13 @@ export class GraphRenderer { private timeSrv: any; private _graphMousePosition: any; - constructor($elem: JQuery, timeSrv, contextSrv, scope) { + constructor( + $elem: JQuery, timeSrv, contextSrv, scope, + private _analyticController: AnalyticController + ) { + if(this._analyticController === undefined) { + throw new TypeError('_analyticController is undefined'); + } var self = this; this.$elem = $elem; this.ctrl = scope.ctrl; @@ -69,11 +75,6 @@ export class GraphRenderer { this.contextSrv = contextSrv; this.scope = scope; - this._analyticController = this.ctrl.analyticsController; - if(this._analyticController === undefined) { - throw new Error('analyticController is undefined'); - } - // this.annotations = []; this.panelWidth = 0; @@ -153,7 +154,7 @@ export class GraphRenderer { segment.from, segment.to ); this._analyticController.addLabelSegment(segment, true); - } + } if(this._analyticController.labelingMode === LabelingMode.LABELING) { this._analyticController.addLabelSegment(segment, false); } @@ -161,7 +162,7 @@ export class GraphRenderer { this._analyticController.deleteLabelingAnalyticUnitSegmentsInRange( segment.from, segment.to ); - } + } this.renderPanel(); return; diff --git a/src/panel/graph_panel/graph_tooltip.ts b/src/panel/graph_panel/graph_tooltip.ts index 97c5f31..a7a95f9 100644 --- a/src/panel/graph_panel/graph_tooltip.ts +++ b/src/panel/graph_panel/graph_tooltip.ts @@ -12,7 +12,7 @@ export class GraphTooltip { constructor( private $elem: JQuery, private dashboard, private scope, private getSeriesFn, - private _analyticSegmentsSearcher: AnalyticSegmentsSearcher + private _analyticSegmentsSearcher?: AnalyticSegmentsSearcher ) { this.ctrl = scope.ctrl; this.panel = this.ctrl.panel; @@ -115,7 +115,9 @@ export class GraphTooltip { plot.highlight(hoverInfo.index, hoverInfo.hoverIndex); } + seriesHtml += this._appendAnomaliesHTML(pos.x, rangeDist); + this._renderAndShow(absoluteTime, seriesHtml, pos, xMode); } @@ -191,6 +193,9 @@ export class GraphTooltip { }; private _appendAnomaliesHTML(pos: number, rangeDist: number): string { + if(this._analyticSegmentsSearcher === undefined) { + return ''; + } var result = ''; var segments = this._analyticSegmentsSearcher(pos, rangeDist); if(segments.length === 0) { diff --git a/src/panel/graph_panel/models/info.ts b/src/panel/graph_panel/models/info.ts index 474b94b..dcb70c2 100644 --- a/src/panel/graph_panel/models/info.ts +++ b/src/panel/graph_panel/models/info.ts @@ -9,6 +9,17 @@ export type ServerInfo = { gitCommitHash: string } +export const ServerInfoUnknown: ServerInfo = { + nodeVersion: 'unknown', + packageVersion: 'unknown', + npmUserAgent: 'unknown', + docker: 'unknown', + zmqConectionString: 'unknown', + serverPort: 'unknown', + gitBranch: 'unknown', + gitCommitHash: 'unknown' +}; + export type PanelInfo = { grafanaVersion: string, grafanaUrl: string, diff --git a/src/panel/graph_panel/services/analytic_service.ts b/src/panel/graph_panel/services/analytic_service.ts index bd4a33e..f7ee951 100644 --- a/src/panel/graph_panel/services/analytic_service.ts +++ b/src/panel/graph_panel/services/analytic_service.ts @@ -3,19 +3,23 @@ import { MetricExpanded } from '../models/metric'; import { DatasourceRequest } from '../models/datasource'; import { SegmentsSet } from '../models/segment_set'; import { AnalyticUnitId, AnalyticUnit, AnalyticSegment } from '../models/analytic_unit'; -import { ServerInfo } from '../models/info'; +import { ServerInfo, ServerInfoUnknown } from '../models/info'; import { Threshold } from '../models/threshold'; import { appEvents } from 'grafana/app/core/core'; export class AnalyticService { - private _isUp = false; + private _isUp: boolean = false; constructor( private _hasticDatasourceURL: string, private $http - ) { } + ) { + if(this._hasticDatasourceURL === undefined) { + throw new TypeError('_hasticDatasourceURL is undefined'); + } + } async getAnalyticUnitTypes() { return this.get('/analyticUnits/types'); @@ -149,16 +153,7 @@ export class AnalyticService { async getServerInfo(): Promise { const data = await this.get('/'); if(data === undefined) { - return { - nodeVersion: 'unknown', - packageVersion: 'unknown', - npmUserAgent: 'unknown', - docker: 'unknown', - zmqConectionString: 'unknown', - serverPort: 'unknown', - gitBranch: 'unknown', - gitCommitHash: 'unknown' - }; + return ServerInfoUnknown; } return { nodeVersion: data.nodeVersion, @@ -256,7 +251,7 @@ export class AnalyticService { ); } - public get isUp() { + public get isUp(): boolean { return this._isUp; } } diff --git a/tests/setup_tests.ts b/tests/setup_tests.ts index 46dfac2..ba85c9b 100644 --- a/tests/setup_tests.ts +++ b/tests/setup_tests.ts @@ -17,13 +17,15 @@ function $http() { } const analyticService = new AnalyticService('', $http); -analyticService.postNewItem = async function (newItem: AnalyticUnit, metric: MetricExpanded, datasource: DatasourceRequest, panelUrl: string +analyticService.postNewItem = async function ( + newItem: AnalyticUnit, metric: MetricExpanded, + datasource: DatasourceRequest, panelUrl: string ): Promise { id++; return Promise.resolve(id.toString()); } -export const analyticController = new AnalyticController({}, analyticService, new Emitter()); +export const analyticController = new AnalyticController({}, new Emitter(), analyticService); jest.mock('../src/panel/graph_panel/partials/help_section.html', () => '');