diff --git a/public/app/plugins/datasource/graphite/query_ctrl.ts b/public/app/plugins/datasource/graphite/query_ctrl.ts index 3a6a24f5cee0..31582f487a51 100644 --- a/public/app/plugins/datasource/graphite/query_ctrl.ts +++ b/public/app/plugins/datasource/graphite/query_ctrl.ts @@ -24,8 +24,9 @@ export class GraphiteQueryCtrl extends QueryCtrl { supportsTags: boolean; paused: boolean; - // to avoid error flooding, it's shown only once per session + // to avoid error flooding, these errors are shown only once per session private _tagsAutoCompleteErrorShown = false; + private _metricAutoCompleteErrorShown = false; /** @ngInject */ constructor( @@ -110,7 +111,7 @@ export class GraphiteQueryCtrl extends QueryCtrl { } }) .catch((err: any) => { - dispatch(notifyApp(createErrorNotification('Error', err))); + this.handleMetricsAutoCompleteError(err); }); } @@ -183,6 +184,7 @@ export class GraphiteQueryCtrl extends QueryCtrl { } }) .catch((err: any): any[] => { + this.handleMetricsAutoCompleteError(err); return []; }); } @@ -431,12 +433,20 @@ export class GraphiteQueryCtrl extends QueryCtrl { } private handleTagsAutoCompleteError(error: Error): void { - console.log(error); + console.error(error); if (!this._tagsAutoCompleteErrorShown) { this._tagsAutoCompleteErrorShown = true; dispatch(notifyApp(createErrorNotification(`Fetching tags failed: ${error.message}.`))); } } + + private handleMetricsAutoCompleteError(error: Error): void { + console.error(error); + if (!this._metricAutoCompleteErrorShown) { + this._metricAutoCompleteErrorShown = true; + dispatch(notifyApp(createErrorNotification(`Fetching metrics failed: ${error.message}.`))); + } + } } function mapToDropdownOptions(results: any[]) { diff --git a/public/app/plugins/datasource/graphite/specs/query_ctrl.test.ts b/public/app/plugins/datasource/graphite/specs/query_ctrl.test.ts index dedf20e18c0b..322f078d780c 100644 --- a/public/app/plugins/datasource/graphite/specs/query_ctrl.test.ts +++ b/public/app/plugins/datasource/graphite/specs/query_ctrl.test.ts @@ -193,10 +193,61 @@ describe('GraphiteQueryCtrl', () => { }); }); + describe('when autocomplete for metric names is not available', () => { + silenceConsoleOutput(); + beforeEach(() => { + ctx.ctrl.datasource.getTagsAutoComplete = jest.fn().mockReturnValue(Promise.resolve([])); + ctx.ctrl.datasource.metricFindQuery = jest.fn().mockReturnValue( + new Promise(() => { + throw new Error(); + }) + ); + }); + + it('getAltSegments should handle autocomplete errors', async () => { + await expect(async () => { + await ctx.ctrl.getAltSegments(0, 'any'); + expect(mockDispatch).toBeCalledWith( + expect.objectContaining({ + type: 'appNotifications/notifyApp', + }) + ); + }).not.toThrow(); + }); + + it('getAltSegments should display the error message only once', async () => { + await ctx.ctrl.getAltSegments(0, 'any'); + expect(mockDispatch.mock.calls.length).toBe(1); + + await ctx.ctrl.getAltSegments(0, 'any'); + expect(mockDispatch.mock.calls.length).toBe(1); + }); + + it('checkOtherSegments should handle autocomplete errors', async () => { + await expect(async () => { + await ctx.ctrl.checkOtherSegments(1, false); + expect(mockDispatch).toBeCalledWith( + expect.objectContaining({ + type: 'appNotifications/notifyApp', + }) + ); + }).not.toThrow(); + }); + + it('checkOtherSegments should display the error message only once', async () => { + await ctx.ctrl.checkOtherSegments(1, false); + expect(mockDispatch.mock.calls.length).toBe(1); + + await ctx.ctrl.checkOtherSegments(1, false); + expect(mockDispatch.mock.calls.length).toBe(1); + }); + }); + describe('when autocomplete for tags is not available', () => { silenceConsoleOutput(); beforeEach(() => { - ctx.ctrl.datasource.getTagsAutoComplete.mockReturnValue( + ctx.datasource.metricFindQuery = jest.fn().mockReturnValue(Promise.resolve([])); + ctx.datasource.getTagsAutoComplete = jest.fn().mockReturnValue( new Promise(() => { throw new Error(); })