mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
limit the data size for chart rendering (#14949)
* limit the rows feed to charts * add telemetry and option to hide * fix typo * updates * comments * notebook fix
This commit is contained in:
@@ -2,33 +2,34 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/chartView';
|
||||
|
||||
import { IPanelView } from 'sql/base/browser/ui/panel/panel';
|
||||
import { Insight } from './insight';
|
||||
import QueryRunner from 'sql/workbench/services/query/common/queryRunner';
|
||||
import { ICellValue, VisualizationOptions } from 'sql/workbench/services/query/common/query';
|
||||
import { ChartOptions, IChartOption, ControlType } from './chartOptions';
|
||||
import { Extensions, IInsightRegistry, IInsightData } from 'sql/platform/dashboard/browser/insightRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { attachSelectBoxStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { CreateInsightAction, CopyAction, SaveImageAction, IChartActionContext, ConfigureChartAction } from 'sql/workbench/contrib/charts/browser/actions';
|
||||
import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox';
|
||||
import { IInsightOptions, ChartType, InsightType } from 'sql/workbench/contrib/charts/common/interfaces';
|
||||
import { IPanelView } from 'sql/base/browser/ui/panel/panel';
|
||||
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||
import { ITaskbarContent, Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||
import { Extensions, IInsightData, IInsightRegistry } from 'sql/platform/dashboard/browser/insightRegistry';
|
||||
import { ChartState } from 'sql/workbench/common/editor/query/chartState';
|
||||
import { ConfigureChartAction, CopyAction, CreateInsightAction, IChartActionContext, SaveImageAction } from 'sql/workbench/contrib/charts/browser/actions';
|
||||
import { getChartMaxRowCount } from 'sql/workbench/contrib/charts/browser/utils';
|
||||
import { ChartType, IInsightOptions, InsightType } from 'sql/workbench/contrib/charts/common/interfaces';
|
||||
import { ICellValue, VisualizationOptions } from 'sql/workbench/services/query/common/query';
|
||||
import QueryRunner from 'sql/workbench/services/query/common/queryRunner';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ChartOptions, ControlType, IChartOption } from './chartOptions';
|
||||
import { Insight } from './insight';
|
||||
|
||||
|
||||
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
|
||||
|
||||
@@ -89,7 +90,8 @@ export class ChartView extends Disposable implements IPanelView {
|
||||
@IContextViewService private _contextViewService: IContextViewService,
|
||||
@IThemeService private _themeService: IThemeService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@INotificationService private readonly _notificationService: INotificationService
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService
|
||||
) {
|
||||
super();
|
||||
this.taskbarContainer = DOM.$('div.taskbar-container');
|
||||
@@ -195,7 +197,7 @@ export class ChartView extends Disposable implements IPanelView {
|
||||
public chart(dataId: { batchId: number, resultId: number }) {
|
||||
this.state.dataId = dataId;
|
||||
this._currentData = dataId;
|
||||
this.shouldGraph();
|
||||
this.fetchData();
|
||||
}
|
||||
|
||||
layout(dimension: DOM.Dimension): void {
|
||||
@@ -209,7 +211,7 @@ export class ChartView extends Disposable implements IPanelView {
|
||||
|
||||
public set queryRunner(runner: QueryRunner) {
|
||||
this._queryRunner = runner;
|
||||
this.shouldGraph();
|
||||
this.fetchData();
|
||||
}
|
||||
|
||||
public setData(rows: ICellValue[][], columns: string[]): void {
|
||||
@@ -228,7 +230,7 @@ export class ChartView extends Disposable implements IPanelView {
|
||||
}
|
||||
}
|
||||
|
||||
private shouldGraph() {
|
||||
private fetchData(): void {
|
||||
// Check if we have the necessary information
|
||||
if (this._currentData && this._queryRunner) {
|
||||
// check if we are being asked to graph something that is available
|
||||
@@ -236,7 +238,7 @@ export class ChartView extends Disposable implements IPanelView {
|
||||
if (batch) {
|
||||
let summary = batch.resultSetSummaries[this._currentData.resultId];
|
||||
if (summary) {
|
||||
this._queryRunner.getQueryRows(0, summary.rowCount, this._currentData.batchId, this._currentData.resultId).then(d => {
|
||||
this._queryRunner.getQueryRows(0, Math.min(getChartMaxRowCount(this._configurationService), summary.rowCount), this._currentData.batchId, this._currentData.resultId).then(d => {
|
||||
let rows = d.rows;
|
||||
let columns = summary.columnInfo.map(c => c.columnName);
|
||||
this.setData(rows, columns);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Extensions, IConfigurationRegistry, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
|
||||
|
||||
const chartsConfiguration: IConfigurationNode = {
|
||||
id: 'builtinCharts',
|
||||
type: 'object',
|
||||
title: nls.localize('builtinChartsConfigurationTitle', "Built-in Charts"),
|
||||
properties: {
|
||||
'builtinCharts.maxRowCount': {
|
||||
type: 'number',
|
||||
default: 300,
|
||||
description: nls.localize('builtinCharts.maxRowCountDescription', "The maximum number of rows for charts to display. Warning: increasing this may impact performance.")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
configurationRegistry.registerConfiguration(chartsConfiguration);
|
||||
@@ -46,3 +46,7 @@ export interface IInsightCtor {
|
||||
new <Services extends BrandedService[]>(container: HTMLElement, options: IInsightOptions, ...services: Services): IInsight;
|
||||
readonly types: Array<InsightType | ChartType>;
|
||||
}
|
||||
|
||||
export interface IChartsConfiguration {
|
||||
readonly maxRowCount: number;
|
||||
}
|
||||
|
||||
35
src/sql/workbench/contrib/charts/browser/utils.ts
Normal file
35
src/sql/workbench/contrib/charts/browser/utils.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IChartsConfiguration } from 'sql/workbench/contrib/charts/browser/interfaces';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
/**
|
||||
* Gets the max allowed row count for chart rendering.
|
||||
*/
|
||||
export function getChartMaxRowCount(configurationService: IConfigurationService): number {
|
||||
return configurationService.getValue<IChartsConfiguration>('builtinCharts').maxRowCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a toast notification about the max row count for chart has exceeded.
|
||||
*/
|
||||
export function notifyMaxRowCountExceeded(storageService: IStorageService, notificationService: INotificationService, configurationService: IConfigurationService): void {
|
||||
const storageKey = 'charts/ignoreMaxRowCountExceededNotification';
|
||||
if (!storageService.getBoolean(storageKey, StorageScope.GLOBAL, false)) {
|
||||
notificationService.prompt(Severity.Info,
|
||||
nls.localize('charts.maxAllowedRowsExceeded', "Maximum row count for built-in charts has been exceeded, only the first {0} rows are used. To configure the value, you can open user settings and search for: 'builtinCharts.maxRowCount'.", getChartMaxRowCount(configurationService)),
|
||||
[{
|
||||
label: nls.localize('charts.neverShowAgain', "Don't Show Again"),
|
||||
isSecondary: true,
|
||||
run: () => {
|
||||
storageService.store(storageKey, true, StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
}
|
||||
}]);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
|
||||
suite('Chart View', () => {
|
||||
test('initializes without error', () => {
|
||||
@@ -40,6 +41,7 @@ function createChartView(isQueryEditorChart: boolean): ChartView {
|
||||
const themeService = new TestThemeService();
|
||||
const instantiationService = new TestInstantiationService();
|
||||
const notificationService = new TestNotificationService();
|
||||
const configurationService = new TestConfigurationService();
|
||||
instantiationService.stub(IThemeService, themeService);
|
||||
return new ChartView(isQueryEditorChart, contextViewService, themeService, instantiationService, notificationService);
|
||||
return new ChartView(isQueryEditorChart, contextViewService, themeService, instantiationService, notificationService, configurationService);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user