Skip to content

Commit

Permalink
Query Store Service (#2171)
Browse files Browse the repository at this point in the history
* Checkpoint

* Checkpoint

* Checkpoint

* checkpoint

* Hooking in calls to QueryExecutionService

* adding cases

* Fleshing out report handlers

* Adding parameter converters

* Adding sqlparam declarations for Top Resource Consumers and Forced Plans

* swapping to object-object to centralize conversion for sqlparams

* Adding sqlparams for GetTrackedQueries

* Added sqlparams for High Variation

* Added Overall ResourceConumption

* Adding params for regressed queries

* Removing WithWaitStats calls, since they're automatically used within QSM when waitstats is an available statistic#

* Adding PlanSummary handlers

* cleaning up orderable queries

* initial test mockout

* adding basic (incorrect) parameter translation

* first test passing, datetimeoffset swapped to ISO format

* Adding test baselines

* Updating nuget package

* Adding get/set

* Adding get/set for result object

* Switching to parameter-less constructor

* Swapping TimeInterval for string-based BasicTimeInterval

* Removing unnecessary usings

* Adding back params comments

* Fixing up request docstrings

* comment tweak

* fix tests failing in pipeline because of line endings not matching

* removing unnecessary usings

* Setting tests to generate queries in UTC for test stability

* Normalizing line endings

---------

Co-authored-by: Kim Santiago <[email protected]>
  • Loading branch information
Benjin and kisantia authored Sep 1, 2023
1 parent c0a0f27 commit 25c18d3
Show file tree
Hide file tree
Showing 16 changed files with 2,263 additions and 0 deletions.
1 change: 1 addition & 0 deletions Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<PackageReference Update="Microsoft.SqlServer.Assessment" Version="[1.1.17]" />
<PackageReference Update="Microsoft.SqlServer.Migration.Assessment" Version="1.0.20230301.46" />
<PackageReference Update="Microsoft.SqlServer.Migration.Logins" Version="1.0.20230407.56" />
<PackageReference Update="Microsoft.SqlServer.Management.QueryStoreModel" Version="163.26.1" />
<PackageReference Update="Microsoft.SqlServer.Management.SqlParser" Version="170.9.0" />
<PackageReference Update="Microsoft.SqlServer.Migration.Tde" Version="1.0.0-preview.1.0.20230720.98" />
<PackageReference Update="Microsoft.Azure.OperationalInsights" Version="1.0.0" />
Expand Down
Binary file not shown.
4 changes: 4 additions & 0 deletions src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using Microsoft.SqlTools.ServiceLayer.ObjectManagement;
using Microsoft.SqlTools.ServiceLayer.Profiler;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.QueryStore;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare;
using Microsoft.SqlTools.ServiceLayer.Scripting;
using Microsoft.SqlTools.ServiceLayer.ServerConfigurations;
Expand Down Expand Up @@ -175,6 +176,9 @@ private static void InitializeRequestHandlersAndServices(ServiceHost serviceHost
SqlProjectsService.Instance.InitializeService(serviceHost);
serviceProvider.RegisterSingleService(SqlProjectsService.Instance);

QueryStoreService.Instance.InitializeService(serviceHost);
serviceProvider.RegisterSingleService(QueryStoreService.Instance);

serviceHost.InitializeRequestHandlers();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" />
<PackageReference Include="Microsoft.Data.SqlClient" />
<PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" />
<PackageReference Include="Microsoft.SqlServer.Management.QueryStoreModel" />
<PackageReference Include="Microsoft.SqlServer.Management.SmoMetadataProvider" />
<PackageReference Include="Microsoft.SqlServer.SqlManagementObjects" />
<PackageReference Include="Microsoft.SqlServer.Management.SqlParser" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#nullable disable

using System;
using Microsoft.SqlServer.Management.QueryStoreModel.Common;

namespace Microsoft.SqlTools.ServiceLayer.QueryStore
{
/// <summary>
/// Represents a TimeInterval with strings for the start and end times instead of DateTimeOffsets for JRPC compatibility
/// </summary>
public class BasicTimeInterval
{
/// <summary>
/// Start time of this time interval, in ISO 8601 format (<code>ToString("O")</code>).
/// This property is ignored unless TimeIntervalOptions is set to Custom.
/// </summary>
public string StartDateTimeInUtc { get; set; } = null;

/// <summary>
/// End time of this time interval, in ISO 8601 format (<code>ToString("O")</code>).
/// This property is ignored unless TimeIntervalOptions is set to Custom.
/// </summary>
public string EndDateTimeInUtc { get; set; } = null;

/// <summary>
/// Time interval type. Unless set to Custom, then StartDateTimeInUtc and EndDateTimeInUtc are ignored.
/// </summary>
public TimeIntervalOptions TimeIntervalOptions { get; set; } = TimeIntervalOptions.Custom;

public TimeInterval Convert()
{
if (TimeIntervalOptions == TimeIntervalOptions.Custom
&& !String.IsNullOrWhiteSpace(StartDateTimeInUtc)
&& !String.IsNullOrWhiteSpace(EndDateTimeInUtc))
{
return new TimeInterval(DateTimeOffset.Parse(StartDateTimeInUtc), DateTimeOffset.Parse(EndDateTimeInUtc));
}
else if (TimeIntervalOptions != TimeIntervalOptions.Custom
&& String.IsNullOrWhiteSpace(StartDateTimeInUtc)
&& String.IsNullOrWhiteSpace(EndDateTimeInUtc))
{
return new TimeInterval(TimeIntervalOptions);
}
else
{
throw new InvalidOperationException($"{nameof(BasicTimeInterval)} was not populated correctly: '{TimeIntervalOptions}', '{StartDateTimeInUtc}' - '{EndDateTimeInUtc}'");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlServer.Management.QueryStoreModel.ForcedPlanQueries;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;

#nullable disable

namespace Microsoft.SqlTools.ServiceLayer.QueryStore.Contracts
{
/// <summary>
/// Parameters for getting a Forced Plan Queries report
/// </summary>
public class GetForcedPlanQueriesReportParams : OrderableQueryConfigurationParams<ForcedPlanQueriesConfiguration>
{
/// <summary>
/// Time interval for the report
/// </summary>
public BasicTimeInterval TimeInterval { get; set; }

public override ForcedPlanQueriesConfiguration Convert()
{
ForcedPlanQueriesConfiguration config = base.Convert();
config.TimeInterval = TimeInterval.Convert();

return config;
}
}

/// <summary>
/// Gets the query for a Forced Plan Queries report
/// </summary>
public class GetForcedPlanQueriesReportRequest
{
public static readonly RequestType<GetForcedPlanQueriesReportParams, QueryStoreQueryResult> Type
= RequestType<GetForcedPlanQueriesReportParams, QueryStoreQueryResult>.Create("queryStore/getForcedPlanQueriesReport");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlServer.Management.QueryStoreModel.HighVariation;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;

#nullable disable

namespace Microsoft.SqlTools.ServiceLayer.QueryStore.Contracts
{
/// <summary>
/// Parameters for getting a High Variation Queries report
/// </summary>
public class GetHighVariationQueriesReportParams : OrderableQueryConfigurationParams<HighVariationConfiguration>
{
/// <summary>
/// Time interval for the report
/// </summary>
public BasicTimeInterval TimeInterval { get; set; }

public override HighVariationConfiguration Convert()
{
HighVariationConfiguration config = base.Convert();
config.TimeInterval = TimeInterval.Convert();

return config;
}
}

/// <summary>
/// Gets the query for a High Variation Queries report
/// </summary>
public class GetHighVariationQueriesSummaryRequest
{
public static readonly RequestType<GetHighVariationQueriesReportParams, QueryStoreQueryResult> Type
= RequestType<GetHighVariationQueriesReportParams, QueryStoreQueryResult>.Create("queryStore/getHighVariationQueriesSummary");
}

/// <summary>
/// Gets the query for a detailed High Variation Queries report
/// </summary>
public class GetHighVariationQueriesDetailedSummaryRequest
{
public static readonly RequestType<GetHighVariationQueriesReportParams, QueryStoreQueryResult> Type
= RequestType<GetHighVariationQueriesReportParams, QueryStoreQueryResult>.Create("queryStore/getHighVariationQueriesDetailedSummary");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlServer.Management.QueryStoreModel.Common;
using Microsoft.SqlServer.Management.QueryStoreModel.OverallResourceConsumption;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;

#nullable disable

namespace Microsoft.SqlTools.ServiceLayer.QueryStore.Contracts
{
/// <summary>
/// Parameters for getting an Overall Resource Consumption report
/// </summary>
public class GetOverallResourceConsumptionReportParams : QueryConfigurationParams<OverallResourceConsumptionConfiguration>
{
/// <summary>
/// Time interval for the report
/// </summary>
public BasicTimeInterval SpecifiedTimeInterval { get; set; }

/// <summary>
/// Bucket interval for the report
/// </summary>
public BucketInterval SpecifiedBucketInterval { get; set; }

public override OverallResourceConsumptionConfiguration Convert()
{
OverallResourceConsumptionConfiguration result = base.Convert();

result.SpecifiedTimeInterval = SpecifiedTimeInterval.Convert();
result.SelectedBucketInterval = SpecifiedBucketInterval;

return result;
}
}

/// <summary>
/// Gets the query for an Overall Resource Consumption report
/// </summary>
public class GetOverallResourceConsumptionReportRequest
{
public static readonly RequestType<GetOverallResourceConsumptionReportParams, QueryStoreQueryResult> Type
= RequestType<GetOverallResourceConsumptionReportParams, QueryStoreQueryResult>.Create("queryStore/getOverallResourceConsumptionReport");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlServer.Management.QueryStoreModel.RegressedQueries;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;

#nullable disable

namespace Microsoft.SqlTools.ServiceLayer.QueryStore.Contracts
{
/// <summary>
/// Parameters for getting a Regressed Queries report
/// </summary>
public class GetRegressedQueriesReportParams : QueryConfigurationParams<RegressedQueriesConfiguration>
{
/// <summary>
/// Time interval during which to look for performance regressions for the report
/// </summary>
public BasicTimeInterval TimeIntervalRecent { get; set; }

/// <summary>
/// Time interval during which to establish baseline performance for the report
/// </summary>
public BasicTimeInterval TimeIntervalHistory { get; set; }

/// <summary>
/// Minimum number of executions for a query to be included
/// </summary>
public long MinExecutionCount { get; set; }

public override RegressedQueriesConfiguration Convert()
{
RegressedQueriesConfiguration result = base.Convert();

result.TimeIntervalRecent = TimeIntervalRecent.Convert();
result.TimeIntervalHistory = TimeIntervalHistory.Convert();
result.MinExecutionCount = MinExecutionCount;

return result;
}
}

/// <summary>
/// Gets the query for a Regressed Queries report
/// </summary>
public class GetRegressedQueriesSummaryRequest
{
public static readonly RequestType<GetRegressedQueriesReportParams, QueryStoreQueryResult> Type
= RequestType<GetRegressedQueriesReportParams, QueryStoreQueryResult>.Create("queryStore/getRegressedQueriesSummary");
}

/// <summary>
/// Gets the query for a detailed Regressed Queries report
/// </summary>
public class GetRegressedQueriesDetailedSummaryRequest
{
public static readonly RequestType<GetRegressedQueriesReportParams, QueryStoreQueryResult> Type
= RequestType<GetRegressedQueriesReportParams, QueryStoreQueryResult>.Create("queryStore/getRegressedQueriesDetailedSummary");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlServer.Management.QueryStoreModel.TopResourceConsumers;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;

#nullable disable

namespace Microsoft.SqlTools.ServiceLayer.QueryStore.Contracts
{
/// <summary>
/// Parameters for getting a Top Resource Consumers report
/// </summary>
public class GetTopResourceConsumersReportParams : OrderableQueryConfigurationParams<TopResourceConsumersConfiguration>
{
/// <summary>
/// Time interval for the report
/// </summary>
public BasicTimeInterval TimeInterval { get; set; }

public override TopResourceConsumersConfiguration Convert()
{
TopResourceConsumersConfiguration result = base.Convert();
result.TimeInterval = TimeInterval.Convert();

return result;
}
}

/// <summary>
/// Gets the query for a Top Resource Consumers report
/// </summary>
public class GetTopResourceConsumersSummaryRequest
{
public static readonly RequestType<GetTopResourceConsumersReportParams, QueryStoreQueryResult> Type
= RequestType<GetTopResourceConsumersReportParams, QueryStoreQueryResult>.Create("queryStore/getTopResourceConsumersSummary");
}

/// <summary>
/// Gets the query for a detailed Top Resource Consumers report
/// </summary>
public class GetTopResourceConsumersDetailedSummaryRequest
{
public static readonly RequestType<GetTopResourceConsumersReportParams, QueryStoreQueryResult> Type
= RequestType<GetTopResourceConsumersReportParams, QueryStoreQueryResult>.Create("queryStore/getTopResourceConsumersDetailedSummary");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlTools.Hosting.Protocol.Contracts;

#nullable disable

namespace Microsoft.SqlTools.ServiceLayer.QueryStore.Contracts
{
/// <summary>
/// Parameters for getting a Tracked Queries report
/// </summary>
public class GetTrackedQueriesReportParams
{
/// <summary>
/// Search text for a query
/// </summary>
public string QuerySearchText { get; set; }
}

/// <summary>
/// Gets the query for a Tracked Queries report
/// </summary>
public class GetTrackedQueriesReportRequest
{
public static readonly RequestType<GetTrackedQueriesReportParams, QueryStoreQueryResult> Type
= RequestType<GetTrackedQueriesReportParams, QueryStoreQueryResult>.Create("queryStore/getTrackedQueriesReport");
}
}
Loading

0 comments on commit 25c18d3

Please sign in to comment.