From 52a76073f53ac0f1000783958b22ca4eaeb05827 Mon Sep 17 00:00:00 2001 From: Benjin Dubishar Date: Wed, 6 Sep 2023 11:56:53 -0700 Subject: [PATCH] Adding Query Store Service bindings on ADS side (#24167) * Checkpoint * Adding docstrings * Updating comments --- extensions/mssql/src/constants.ts | 1 + extensions/mssql/src/contracts.ts | 246 +++++++++++++++++ extensions/mssql/src/mssql.d.ts | 253 +++++++++++++++++- extensions/mssql/src/mssql.proposed.d.ts | 1 + extensions/mssql/src/mssqlApiFactory.ts | 5 +- .../mssql/src/queryStore/queryStoreService.ts | 220 +++++++++++++++ extensions/mssql/src/sqlToolsServer.ts | 4 +- 7 files changed, 722 insertions(+), 8 deletions(-) create mode 100644 extensions/mssql/src/queryStore/queryStoreService.ts diff --git a/extensions/mssql/src/constants.ts b/extensions/mssql/src/constants.ts index 7ebc926b8bb7..10c57a67d318 100644 --- a/extensions/mssql/src/constants.ts +++ b/extensions/mssql/src/constants.ts @@ -26,6 +26,7 @@ export const SqlAssessmentService = 'sqlAssessmentService'; export const NotebookConvertService = 'notebookConvertService'; export const AzureBlobService = 'azureBlobService'; export const ObjectManagementService = 'objectManagementService'; +export const QueryStoreService = 'queryStoreService'; // CONFIGURATION VALUES ////////////////////////////////////////////////////////// export const configObjectExplorerGroupBySchemaFlagName = 'mssql.objectExplorer.groupBySchema'; diff --git a/extensions/mssql/src/contracts.ts b/extensions/mssql/src/contracts.ts index 643208542b82..c04a1e0ee068 100644 --- a/extensions/mssql/src/contracts.ts +++ b/extensions/mssql/src/contracts.ts @@ -1722,3 +1722,249 @@ export class DidChangeEncryptionIVKeyParams { export namespace EncryptionKeysChangedNotification { export const type = new NotificationType('connection/encryptionKeysChanged'); } + +// ------------------------------- < Query Store > ------------------------------------ +//#region Query Store + +//#region Functions + +export namespace GetRegressedQueriesSummaryRequest { + export const type = new RequestType('queryStore/getRegressedQueriesSummary'); +} + +export namespace GetRegressedQueriesDetailedSummaryRequest { + export const type = new RequestType('queryStore/getRegressedQueriesDetailedSummary'); +} + +export namespace GetTrackedQueriesReportRequest { + export const type = new RequestType('queryStore/getTrackedQueriesReport'); +} + +export namespace GetHighVariationQueriesSummaryRequest { + export const type = new RequestType('queryStore/getHighVariationQueriesSummary'); +} + +export namespace GetHighVariationQueriesDetailedSummaryRequest { + export const type = new RequestType('queryStore/getHighVariationQueriesDetailedSummary'); +} + +export namespace GetHighVariationQueriesDetailedSummaryWithWaitStatsRequest { + export const type = new RequestType('queryStore/getHighVariationQueriesDetailedSummaryWithWaitStats'); +} + +export namespace GetTopResourceConsumersSummaryRequest { + export const type = new RequestType('queryStore/getTopResourceConsumersSummary'); +} + +export namespace GetTopResourceConsumersDetailedSummaryRequest { + export const type = new RequestType('queryStore/getTopResourceConsumersDetailedSummary'); +} + +export namespace GetTopResourceConsumersDetailedSummaryWithWaitStatsRequest { + export const type = new RequestType('queryStore/getTopResourceConsumersDetailedSummaryWithWaitStats'); +} + +export namespace GetPlanSummaryChartViewRequest { + export const type = new RequestType('queryStore/getPlanSummaryChartView'); +} + +export namespace GetPlanSummaryGridViewRequest { + export const type = new RequestType('queryStore/getPlanSummaryGridView'); +} + +export namespace GetForcedPlanRequest { + export const type = new RequestType('queryStore/getForcedPlan'); +} + +export namespace GetForcedPlanQueriesReportRequest { + export const type = new RequestType('queryStore/getForcedPlanQueriesReport'); +} + +export namespace GetOverallResourceConsumptionReportRequest { + export const type = new RequestType('queryStore/getOverallResourceConsumptionReport'); +} + +//#endregion + +//#region Parameters + +/** + * Base class for a Query Store report parameters + */ +export interface QueryStoreReportParams { + /** + * Connection URI for the database + */ + connectionOwnerUri: string; +} + +/** + * Base class for parameters for a report type that uses QueryConfigurationBase for its configuration + */ +export interface QueryConfigurationParams extends QueryStoreReportParams { + /** + * Metric to summarize + */ + selectedMetric: mssql.Metric; + /** + * Statistic to calculate on SelecticMetric + */ + selectedStatistic: mssql.Statistic; + /** + * Number of queries to return if ReturnAllQueries is not set + */ + topQueriesReturned: number; + /** + * True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + */ + returnAllQueries: boolean; + /** + * Minimum number of query plans for a query to included in the report + */ + minNumberOfQueryPlans: number; +} + +/** + * Parameters for getting a Regressed Queries report + */ +export interface GetRegressedQueriesReportParams extends QueryConfigurationParams { + /** + * Time interval during which to look for performance regressions for the report + */ + timeIntervalRecent: mssql.TimeInterval; + /** + * Time interval during which to establish baseline performance for the report + */ + timeIntervalHistory: mssql.TimeInterval; + /** + * Minimum number of executions for a query to be included + */ + minExecutionCount: number; +} + +/** + * Base class for parameters for a report that can be ordered by a specified column + */ +export interface OrderableQueryConfigurationParams extends QueryConfigurationParams { + /** + * Name of the column to order results by + */ + orderByColumnId: string; + /** + * Direction of the result ordering + */ + descending: boolean; +} + +/** + * Parameters for getting a Tracked Queries report + */ +export interface GetTrackedQueriesReportParams { + /** + * Search text for a query + */ + querySearchText: string; +} + +/** + * Parameters for getting a High Variation Queries report + */ +export interface GetHighVariationQueriesReportParams extends OrderableQueryConfigurationParams { + /** + * Time interval for the report + */ + timeInterval: mssql.TimeInterval; +} + +/** + * Parameters for getting a Top Resource Consumers report + */ +export interface GetTopResourceConsumersReportParams extends OrderableQueryConfigurationParams { + /** + * Time interval for the report + */ + timeInterval: mssql.TimeInterval; +} + +/** + * Parameters for getting a Plan Summary + */ +export interface GetPlanSummaryParams extends QueryStoreReportParams { + /** + * Query ID to view a summary of plans for + */ + queryId: number; + /** + * Mode of the time interval search + */ + timeIntervalMode: mssql.PlanTimeIntervalMode; + /** + * Time interval for the report + */ + timeInterval: mssql.TimeInterval; + /** + * Metric to summarize + */ + selectedMetric: mssql.Metric; + /** + * Statistic to calculate on SelecticMetric + */ + selectedStatistic: mssql.Statistic; +} + +/** + * Parameters for getting the grid view of a Plan Summary + */ +export interface GetPlanSummaryGridViewParams extends GetPlanSummaryParams { + /** + * Name of the column to order results by + */ + orderByColumnId: string; + /** + * Direction of the result ordering + */ + descending: boolean; +} + +/** + * Parameters for getting the forced plan for a query + */ +export interface GetForcedPlanParams extends QueryStoreReportParams { + /** + * Query ID to view the plan for + */ + queryId: number; + /** + * Plan ID to view + */ + planId: number; +} + +/** + * Parameters for getting a Forced Plan Queries report + */ +export interface GetForcedPlanQueriesReportParams extends OrderableQueryConfigurationParams { + /** + * Time interval for the report + */ + timeInterval: mssql.TimeInterval; +} + +/** + * Parameters for getting an Overall Resource Consumption report + */ +export interface GetOverallResourceConsumptionReportParams extends QueryConfigurationParams { + /** + * Time interval for the report + */ + specifiedTimeInterval: mssql.TimeInterval; + /** + * Bucket interval for the report + */ + specifiedBucketInterval: mssql.BucketInterval; +} + +//#endregion + +//#endregion +// ------------------------------- ----------------------------------- diff --git a/extensions/mssql/src/mssql.d.ts b/extensions/mssql/src/mssql.d.ts index ecfd56db97d1..4a45981623ca 100644 --- a/extensions/mssql/src/mssql.d.ts +++ b/extensions/mssql/src/mssql.d.ts @@ -56,7 +56,7 @@ declare module 'mssql' { getChildren(refreshChildren: boolean): ITreeNode[] | Thenable; } - //#region --- schema compare + //#region --- Schema Compare export interface SchemaCompareResult extends azdata.ResultStatus { operationId: string; areEqual: boolean; @@ -203,7 +203,7 @@ declare module 'mssql' { //#endregion - //#region --- dacfx + //#region --- DacFx export const enum ExtractTarget { dacpac = 0, file = 1, @@ -294,7 +294,7 @@ declare module 'mssql' { //#endregion - //#region --- Sql Projects + //#region --- SQL Projects /** * Interface for working with .sqlproj files @@ -621,7 +621,6 @@ declare module 'mssql' { moveNoneItem(projectUri: string, path: string, destinationPath: string): Promise; } - //#region Results export interface GetDatabaseReferencesResult extends azdata.ResultStatus { @@ -847,6 +846,8 @@ declare module 'mssql' { } //#endregion + //#region --- Blob storage + export interface CreateSasResponse { sharedAccessSignature: string; } @@ -864,7 +865,9 @@ declare module 'mssql' { createSas(connectionUri: string, blobContainerUri: string, blobStorageKey: string, storageAccountName: string, expirationDate: string): Promise; } - // Object Management - Begin. + //#endregion + + //#region --- Object Management export namespace ObjectManagement { /** @@ -1024,5 +1027,243 @@ declare module 'mssql' { databaseFilePaths: string[]; owner: string; } - // Object Management - End. + //#endregion + + //#region --- Query Store + + export interface IQueryStoreService { + /** + * Gets the query for a Regressed Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeIntervalRecent Time interval during which to look for performance regressions for the report + * @param timeIntervalHistory Time interval during which to establish baseline performance for the report + * @param minExecutionCount Minimum number of executions for a query to be included + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getRegressedQueriesSummary(connectionOwnerUri: string, timeIntervalRecent: TimeInterval, timeIntervalHistory: TimeInterval, minExecutionCount: number, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + + /** + * Gets the query for a detailed Regressed Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeIntervalRecent Time interval during which to look for performance regressions for the report + * @param timeIntervalHistory Time interval during which to establish baseline performance for the report + * @param minExecutionCount Minimum number of executions for a query to be included + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getRegressedQueriesDetailedSummary(connectionOwnerUri: string, timeIntervalRecent: TimeInterval, timeIntervalHistory: TimeInterval, minExecutionCount: number, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + + /** + * Gets the query for a Tracked Queries report + * @param querySearchText Search text for a query + */ + getTrackedQueriesReport(querySearchText: string): Promise; + + /** + * Gets the query for a High Variation Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getHighVariationQueriesSummary(connectionOwnerUri: string, timeInterval: TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + + /** + * Gets the query for a detailed High Variation Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getHighVariationQueriesDetailedSummary(connectionOwnerUri: string, timeInterval: TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + + /** + * Gets the query for a Top Resource Consumers report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getTopResourceConsumersSummary(connectionOwnerUri: string, timeInterval: TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + + /** + * Gets the query for a detailed Top Resource Consumers report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getTopResourceConsumersDetailedSummary(connectionOwnerUri: string, timeInterval: TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + + /** + * Gets the query for a Plan Summary chart view + * @param connectionOwnerUri Connection URI for the database + * @param queryId Query ID to view a summary of plans for + * @param timeIntervalMode Mode of the time interval search + * @param timeInterval Time interval for the report + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + */ + getPlanSummaryChartView(connectionOwnerUri: string, queryId: number, timeIntervalMode: PlanTimeIntervalMode, timeInterval: TimeInterval, selectedMetric: Metric, selectedStatistic: Statistic): Promise; + + /** + * Gets the query for a Plan Summary grid view + * @param connectionOwnerUri Connection URI for the database + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param queryId Query ID to view a summary of plans for + * @param timeIntervalMode Mode of the time interval search + * @param timeInterval Time interval for the report + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + */ + getPlanSummaryGridView(connectionOwnerUri: string, orderByColumnId: string, descending: boolean, queryId: number, timeIntervalMode: PlanTimeIntervalMode, timeInterval: TimeInterval, selectedMetric: Metric, selectedStatistic: Statistic): Promise; + + /** + * Gets the query to view a forced plan + * @param connectionOwnerUri Connection URI for the database + * @param queryId Query ID to view the plan for + * @param planId Plan ID to view + */ + getForcedPlan(connectionOwnerUri: string, queryId: number, planId: number): Promise; + + /** + * Gets the query for a Forced Plan Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getForcedPlanQueriesReport(connectionOwnerUri: string, timeInterval: TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + + /** + * Gets the query for an Overall Resource Consumption report + * @param connectionOwnerUri Connection URI for the database + * @param specifiedTimeInterval Time interval for the report + * @param specifiedBucketInterval Bucket interval for the report + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + getOverallResourceConsumptionReport(connectionOwnerUri: string, specifiedTimeInterval: TimeInterval, specifiedBucketInterval: BucketInterval, selectedMetric: Metric, selectedStatistic: Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise; + } + + //#region Results + + /** + * Result containing a finalized query for a report + */ + export interface QueryStoreQueryResult extends azdata.ResultStatus { + /** + * Finalized query for a report + */ + query: string; + } + + //#endregion + + //#region Types + + export const enum BucketInterval { // values from SSMS: $\Sql\ssms\core\QueryStoreModel\Common\BucketInterval.cs + Minute = 0, + Hour = 1, + Day = 2, + Week = 3, + Month = 4, + Automatic = 5 + } + + export const enum PlanTimeIntervalMode { // values from SSMS: $\Sql\ssms\core\QueryStoreModel\PlanSummary\PlanSummaryConfiguration.cs + SpecifiedRange = 0, + AllHistory = 1 + } + + export const enum Metric { // values from SSMS: $\Sql\ssms\core\QueryStoreModel\Common\Metric.cs + CPUTime = 0, + Duration = 1, + LogicalWrites = 2, + LogicalReads = 3, + MemoryConsumption = 4, + PhysicalReads = 5, + ExecutionCount = 6, + ClrTime = 7, + Dop = 8, + RowCount = 9, + LogMemoryUsed = 10, + TempDbMemoryUsed = 11, + WaitTime = 12 + } + + export const enum Statistic { // values from SSMS: $\Sql\ssms\core\QueryStoreModel\Common\Statistic.cs + Avg = 0, + Min = 1, + Max = 2, + Stdev = 3, + Last = 4, + Total = 5, + Variation = 6 + } + + export const enum TimeIntervalOptions // values from SSMS: $\Sql\ssms\core\QueryStoreModel\Common\TimeInterval.cs + { + Last5Minutes = 0, + Last15Minutes = 1, + Last30Minutes = 2, + LastHour = 3, + Last12Hours = 4, + LastDay = 5, + Last2Days = 6, + LastWeek = 7, + Last2Weeks = 8, + LastMonth = 9, + Last3Months = 10, + Last6Months = 11, + LastYear = 12, + AllTime = 13, + Custom = 14 + } + + export interface TimeInterval { + startDateTimeInUtc?: string, + endDateTimeInUtc?: string, + timeIntervalOptions?: TimeIntervalOptions + } + + //#endregion + + //#endregion } diff --git a/extensions/mssql/src/mssql.proposed.d.ts b/extensions/mssql/src/mssql.proposed.d.ts index 454f91e48b05..ee37188afbd8 100644 --- a/extensions/mssql/src/mssql.proposed.d.ts +++ b/extensions/mssql/src/mssql.proposed.d.ts @@ -22,6 +22,7 @@ declare module 'mssql' { export interface IExtension { readonly sqlAssessment: ISqlAssessmentService; + readonly queryStore: IQueryStoreService; } export interface ISqlAssessmentService { diff --git a/extensions/mssql/src/mssqlApiFactory.ts b/extensions/mssql/src/mssqlApiFactory.ts index d05f95ccaef6..509e0bce298a 100644 --- a/extensions/mssql/src/mssqlApiFactory.ts +++ b/extensions/mssql/src/mssqlApiFactory.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { AppContext } from './appContext'; -import { IExtension, ICmsService, IDacFxService, ISqlProjectsService, ISchemaCompareService, ILanguageExtensionService, ISqlAssessmentService, IAzureBlobService } from 'mssql'; +import { IExtension, ICmsService, IDacFxService, ISqlProjectsService, ISchemaCompareService, ILanguageExtensionService, ISqlAssessmentService, IAzureBlobService, IQueryStoreService } from 'mssql'; import * as constants from './constants'; import { SqlToolsServer } from './sqlToolsServer'; @@ -33,6 +33,9 @@ export function createMssqlApi(context: AppContext, sqlToolsServer: SqlToolsServ }, get azureBlob() { return context.getService(constants.AzureBlobService); + }, + get queryStore() { + return context.getService(constants.QueryStoreService); } }; } diff --git a/extensions/mssql/src/queryStore/queryStoreService.ts b/extensions/mssql/src/queryStore/queryStoreService.ts new file mode 100644 index 000000000000..aa621d1816a1 --- /dev/null +++ b/extensions/mssql/src/queryStore/queryStoreService.ts @@ -0,0 +1,220 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as mssql from 'mssql'; +import * as constants from '../constants'; +import * as Utils from '../utils'; +import * as contracts from '../contracts'; + +import { AppContext } from '../appContext'; +import { BaseService, ISqlOpsFeature, SqlOpsDataClient } from 'dataprotocol-client'; +import { ClientCapabilities } from 'vscode-languageclient'; + +export class QueryStoreService extends BaseService implements mssql.IQueryStoreService { + public static asFeature(context: AppContext): ISqlOpsFeature { + return class extends QueryStoreService { + constructor(client: SqlOpsDataClient) { + super(context, client); + } + + fillClientCapabilities(capabilities: ClientCapabilities): void { + Utils.ensure(capabilities, 'queryStore')!.queryStore = true; + } + + initialize(): void { + } + }; + } + + private constructor(context: AppContext, client: SqlOpsDataClient) { + super(client); + context.registerService(constants.QueryStoreService, this); + } + + /** + * Gets the query for a Regressed Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeIntervalRecent Time interval during which to look for performance regressions for the report + * @param timeIntervalHistory Time interval during which to establish baseline performance for the report + * @param minExecutionCount Minimum number of executions for a query to be included + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getRegressedQueriesSummary(connectionOwnerUri: string, timeIntervalRecent: mssql.TimeInterval, timeIntervalHistory: mssql.TimeInterval, minExecutionCount: number, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetRegressedQueriesReportParams = { connectionOwnerUri: connectionOwnerUri, timeIntervalRecent: timeIntervalRecent, timeIntervalHistory: timeIntervalHistory, minExecutionCount: minExecutionCount, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetRegressedQueriesSummaryRequest.type, params); + } + + /** + * Gets the query for a detailed Regressed Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeIntervalRecent Time interval during which to look for performance regressions for the report + * @param timeIntervalHistory Time interval during which to establish baseline performance for the report + * @param minExecutionCount Minimum number of executions for a query to be included + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getRegressedQueriesDetailedSummary(connectionOwnerUri: string, timeIntervalRecent: mssql.TimeInterval, timeIntervalHistory: mssql.TimeInterval, minExecutionCount: number, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetRegressedQueriesReportParams = { connectionOwnerUri: connectionOwnerUri, timeIntervalRecent: timeIntervalRecent, timeIntervalHistory: timeIntervalHistory, minExecutionCount: minExecutionCount, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetRegressedQueriesDetailedSummaryRequest.type, params); + } + + /** + * Gets the query for a Tracked Queries report + * @param querySearchText Search text for a query + */ + public async getTrackedQueriesReport(querySearchText: string): Promise { + const params: contracts.GetTrackedQueriesReportParams = { querySearchText: querySearchText }; + return await this.runWithErrorHandling(contracts.GetTrackedQueriesReportRequest.type, params); + } + + /** + * Gets the query for a High Variation Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getHighVariationQueriesSummary(connectionOwnerUri: string, timeInterval: mssql.TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetHighVariationQueriesReportParams = { connectionOwnerUri: connectionOwnerUri, timeInterval: timeInterval, orderByColumnId: orderByColumnId, descending: descending, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetHighVariationQueriesSummaryRequest.type, params); + } + + /** + * Gets the query for a detailed High Variation Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getHighVariationQueriesDetailedSummary(connectionOwnerUri: string, timeInterval: mssql.TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetHighVariationQueriesReportParams = { connectionOwnerUri: connectionOwnerUri, timeInterval: timeInterval, orderByColumnId: orderByColumnId, descending: descending, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetHighVariationQueriesDetailedSummaryRequest.type, params); + } + + /** + * Gets the query for a Top Resource Consumers report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getTopResourceConsumersSummary(connectionOwnerUri: string, timeInterval: mssql.TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetTopResourceConsumersReportParams = { connectionOwnerUri: connectionOwnerUri, timeInterval: timeInterval, orderByColumnId: orderByColumnId, descending: descending, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetTopResourceConsumersSummaryRequest.type, params); + } + + /** + * Gets the query for a detailed Top Resource Consumers report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getTopResourceConsumersDetailedSummary(connectionOwnerUri: string, timeInterval: mssql.TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetTopResourceConsumersReportParams = { connectionOwnerUri: connectionOwnerUri, timeInterval: timeInterval, orderByColumnId: orderByColumnId, descending: descending, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetTopResourceConsumersDetailedSummaryRequest.type, params); + } + + /** + * Gets the query for a Plan Summary chart view + * @param connectionOwnerUri Connection URI for the database + * @param queryId Query ID to view a summary of plans for + * @param timeIntervalMode Mode of the time interval search + * @param timeInterval Time interval for the report + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + */ + public async getPlanSummaryChartView(connectionOwnerUri: string, queryId: number, timeIntervalMode: mssql.PlanTimeIntervalMode, timeInterval: mssql.TimeInterval, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic): Promise { + const params: contracts.GetPlanSummaryParams = { connectionOwnerUri: connectionOwnerUri, queryId: queryId, timeIntervalMode: timeIntervalMode, timeInterval: timeInterval, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic }; + return await this.runWithErrorHandling(contracts.GetPlanSummaryChartViewRequest.type, params); + } + + /** + * Gets the query for a Plan Summary grid view + * @param connectionOwnerUri Connection URI for the database + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param queryId Query ID to view a summary of plans for + * @param timeIntervalMode Mode of the time interval search + * @param timeInterval Time interval for the report + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + */ + public async getPlanSummaryGridView(connectionOwnerUri: string, orderByColumnId: string, descending: boolean, queryId: number, timeIntervalMode: mssql.PlanTimeIntervalMode, timeInterval: mssql.TimeInterval, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic): Promise { + const params: contracts.GetPlanSummaryGridViewParams = { connectionOwnerUri: connectionOwnerUri, orderByColumnId: orderByColumnId, descending: descending, queryId: queryId, timeIntervalMode: timeIntervalMode, timeInterval: timeInterval, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic }; + return await this.runWithErrorHandling(contracts.GetPlanSummaryGridViewRequest.type, params); + } + + /** + * Gets the query to view a forced plan + * @param connectionOwnerUri Connection URI for the database + * @param queryId Query ID to view the plan for + * @param planId Plan ID to view + */ + public async getForcedPlan(connectionOwnerUri: string, queryId: number, planId: number): Promise { + const params: contracts.GetForcedPlanParams = { connectionOwnerUri: connectionOwnerUri, queryId: queryId, planId: planId }; + return await this.runWithErrorHandling(contracts.GetForcedPlanRequest.type, params); + } + + /** + * Gets the query for a Forced Plan Queries report + * @param connectionOwnerUri Connection URI for the database + * @param timeInterval Time interval for the report + * @param orderByColumnId Name of the column to order results by + * @param descending Direction of the result ordering + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getForcedPlanQueriesReport(connectionOwnerUri: string, timeInterval: mssql.TimeInterval, orderByColumnId: string, descending: boolean, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetForcedPlanQueriesReportParams = { connectionOwnerUri: connectionOwnerUri, timeInterval: timeInterval, orderByColumnId: orderByColumnId, descending: descending, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetForcedPlanQueriesReportRequest.type, params); + } + + /** + * Gets the query for an Overall Resource Consumption report + * @param connectionOwnerUri Connection URI for the database + * @param specifiedTimeInterval Time interval for the report + * @param specifiedBucketInterval Bucket interval for the report + * @param selectedMetric Metric to summarize + * @param selectedStatistic Statistic to calculate on SelecticMetric + * @param topQueriesReturned Number of queries to return if ReturnAllQueries is not set + * @param returnAllQueries True to include all queries in the report; false to only include the top queries, up to the value specified by TopQueriesReturned + * @param minNumberOfQueryPlans Minimum number of query plans for a query to included in the report + */ + public async getOverallResourceConsumptionReport(connectionOwnerUri: string, specifiedTimeInterval: mssql.TimeInterval, specifiedBucketInterval: mssql.BucketInterval, selectedMetric: mssql.Metric, selectedStatistic: mssql.Statistic, topQueriesReturned: number, returnAllQueries: boolean, minNumberOfQueryPlans: number): Promise { + const params: contracts.GetOverallResourceConsumptionReportParams = { connectionOwnerUri: connectionOwnerUri, specifiedTimeInterval: specifiedTimeInterval, specifiedBucketInterval: specifiedBucketInterval, selectedMetric: selectedMetric, selectedStatistic: selectedStatistic, topQueriesReturned: topQueriesReturned, returnAllQueries: returnAllQueries, minNumberOfQueryPlans: minNumberOfQueryPlans }; + return await this.runWithErrorHandling(contracts.GetOverallResourceConsumptionReportRequest.type, params); + } +} diff --git a/extensions/mssql/src/sqlToolsServer.ts b/extensions/mssql/src/sqlToolsServer.ts index f7f5cb9134a1..26b69769131d 100644 --- a/extensions/mssql/src/sqlToolsServer.ts +++ b/extensions/mssql/src/sqlToolsServer.ts @@ -31,6 +31,7 @@ import { AzureBlobService } from './azureBlob/azureBlobService'; import { ErrorDiagnosticsProvider } from './errorDiagnostics/errorDiagnosticsProvider'; import { SqlProjectsService } from './sqlProjects/sqlProjectsService'; import { ObjectManagementService } from './objectManagement/objectManagementService'; +import { QueryStoreService } from './queryStore/queryStoreService'; const localize = nls.loadMessageBundle(); const outputChannel = vscode.window.createOutputChannel(Constants.serviceName); @@ -249,7 +250,8 @@ function getClientOptions(context: AppContext): ClientOptions { ExecutionPlanServiceFeature, // ServerContextualizationServiceFeature, // LEWISSANCHEZ TODO: Put this provider back once STS changes are complete ErrorDiagnosticsProvider.asFeature(context), - ObjectManagementService.asFeature(context) + ObjectManagementService.asFeature(context), + QueryStoreService.asFeature(context) ], outputChannel: outputChannel, // Automatically reveal the output channel only in dev mode, so that the users are not impacted and issues can still be caught during development.