From deda2b2956cd76227525111f3b81c66f164cb2c9 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Tue, 21 Jun 2022 10:06:47 -0700 Subject: [PATCH] Revert "Merge pull request #61669 from jasonmalinowski/log-aggregator-cleanups" This reverts commit 1c13b397495c59b95d01bcf7d8c86b2b779da381, reversing changes made to ff8175f4b65300b3de3b82c596e08cfbc903604a. --- .../AsyncCompletion/AsyncCompletionLogger.cs | 57 ++++++----- .../AsyncCompletion/CompletionSource.cs | 6 +- .../AsyncCompletion/ItemManager.cs | 4 +- .../AbstractChangeSignatureService.cs | 2 +- .../ChangeSignatureTelemetryLogger.cs | 67 +++++++------ .../Log/CompletionProvidersLogger.cs | 45 +++++---- ...ExtensionMethodImportCompletionProvider.cs | 7 +- .../AbstractTypeImportCompletionProvider.cs | 7 +- .../ExtensionMethodImportCompletionHelper.cs | 10 +- .../SerializableUnimportedExtensionMethods.cs | 13 ++- .../EditAndContinue/DebuggingSession.cs | 2 +- .../SolutionCrawler/SolutionCrawlerLogger.cs | 47 ++++----- .../SolutionCrawlerRegistrationService.cs | 2 +- ...oordinator.IncrementalAnalyzerProcessor.cs | 8 +- .../SolutionCrawler/WorkCoordinator.cs | 4 +- ...sticAnalyzerService_IncrementalAnalyzer.cs | 2 +- .../Handler/RequestTelemetryLogger.cs | 16 +-- .../InheritanceMarginLogger.cs | 6 +- .../CommonFixAllState.cs | 2 +- .../Core/Portable/Log/CorrelationIdFactory.cs | 19 ---- .../Portable/Log/HistogramLogAggregator.cs | 18 ++-- .../Portable/Log/StatisticLogAggregator.cs | 13 +-- .../Core/Portable/Log/StatisticResult.cs | 90 ----------------- .../Workspace/Solution/SolutionLogger.cs | 2 +- .../Core/Log/AbstractLogAggregator.cs | 97 +++++++++++++++++-- ...CountLogAggregator.cs => LogAggregator.cs} | 10 +- .../Core/WorkspaceExtensions.projitems | 2 +- 27 files changed, 256 insertions(+), 302 deletions(-) delete mode 100644 src/Workspaces/Core/Portable/Log/CorrelationIdFactory.cs delete mode 100644 src/Workspaces/Core/Portable/Log/StatisticResult.cs rename src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/{CountLogAggregator.cs => LogAggregator.cs} (85%) diff --git a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs index 8bc051446a7d6..bcd12a505f7cc 100644 --- a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs +++ b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs @@ -2,16 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using Microsoft.CodeAnalysis.Internal.Log; namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.AsyncCompletion { internal static class AsyncCompletionLogger { - private static readonly CountLogAggregator s_countLogAggregator = new(); - private static readonly StatisticLogAggregator s_statisticLogAggregator = new(); - private static readonly HistogramLogAggregator s_histogramLogAggregator = new(25, 500); + private static readonly LogAggregator s_logAggregator = new(); + private static readonly StatisticLogAggregator s_statisticLogAggregator = new(); + private static readonly HistogramLogAggregator s_histogramLogAggregator = new(25, 500); private enum ActionInfo { @@ -45,60 +44,60 @@ private enum ActionInfo internal static void LogImportCompletionGetContext(bool isBlocking, bool delayed) { - s_countLogAggregator.IncreaseCount(ActionInfo.SessionWithTypeImportCompletionEnabled); + s_logAggregator.IncreaseCount((int)ActionInfo.SessionWithTypeImportCompletionEnabled); if (isBlocking) - s_countLogAggregator.IncreaseCount(ActionInfo.SessionWithImportCompletionBlocking); + s_logAggregator.IncreaseCount((int)ActionInfo.SessionWithImportCompletionBlocking); if (delayed) - s_countLogAggregator.IncreaseCount(ActionInfo.SessionWithImportCompletionDelayed); + s_logAggregator.IncreaseCount((int)ActionInfo.SessionWithImportCompletionDelayed); } internal static void LogSessionWithDelayedImportCompletionIncludedInUpdate() => - s_countLogAggregator.IncreaseCount(ActionInfo.SessionWithDelayedImportCompletionIncludedInUpdate); + s_logAggregator.IncreaseCount((int)ActionInfo.SessionWithDelayedImportCompletionIncludedInUpdate); - internal static void LogAdditionalTicksToCompleteDelayedImportCompletionDataPoint(TimeSpan timeSpan) => - s_histogramLogAggregator.LogTime(ActionInfo.AdditionalTicksToCompleteDelayedImportCompletion, timeSpan); + internal static void LogAdditionalTicksToCompleteDelayedImportCompletionDataPoint(int count) => + s_histogramLogAggregator.IncreaseCount((int)ActionInfo.AdditionalTicksToCompleteDelayedImportCompletion, count); internal static void LogDelayedImportCompletionIncluded() => - s_countLogAggregator.IncreaseCount(ActionInfo.SessionWithTypeImportCompletionEnabled); + s_logAggregator.IncreaseCount((int)ActionInfo.SessionWithTypeImportCompletionEnabled); internal static void LogExpanderUsage() => - s_countLogAggregator.IncreaseCount(ActionInfo.ExpanderUsageCount); + s_logAggregator.IncreaseCount((int)ActionInfo.ExpanderUsageCount); internal static void LogGetDefaultsMatchTicksDataPoint(int count) => - s_statisticLogAggregator.AddDataPoint(ActionInfo.GetDefaultsMatchTicks, count); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.GetDefaultsMatchTicks, count); - internal static void LogSourceInitializationTicksDataPoint(TimeSpan elapsed) + internal static void LogSourceInitializationTicksDataPoint(int count) { - s_statisticLogAggregator.AddDataPoint(ActionInfo.SourceInitializationTicks, elapsed); - s_histogramLogAggregator.LogTime(ActionInfo.SourceInitializationTicks, elapsed); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.SourceInitializationTicks, count); + s_histogramLogAggregator.IncreaseCount((int)ActionInfo.SourceInitializationTicks, count); } - internal static void LogSourceGetContextTicksDataPoint(TimeSpan elapsed, bool isCanceled) + internal static void LogSourceGetContextTicksDataPoint(int count, bool isCanceled) { var key = isCanceled ? ActionInfo.SourceGetContextCanceledTicks : ActionInfo.SourceGetContextCompletedTicks; - s_statisticLogAggregator.AddDataPoint(key, elapsed); - s_histogramLogAggregator.LogTime(key, elapsed); + s_statisticLogAggregator.AddDataPoint((int)key, count); + s_histogramLogAggregator.IncreaseCount((int)key, count); } - internal static void LogItemManagerSortTicksDataPoint(TimeSpan elapsed) + internal static void LogItemManagerSortTicksDataPoint(int count) { - s_statisticLogAggregator.AddDataPoint(ActionInfo.ItemManagerSortTicks, elapsed); - s_histogramLogAggregator.LogTime(ActionInfo.ItemManagerSortTicks, elapsed); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ItemManagerSortTicks, count); + s_histogramLogAggregator.IncreaseCount((int)ActionInfo.ItemManagerSortTicks, count); } - internal static void LogItemManagerUpdateDataPoint(TimeSpan elapsed, bool isCanceled) + internal static void LogItemManagerUpdateDataPoint(int count, bool isCanceled) { var key = isCanceled ? ActionInfo.ItemManagerUpdateCanceledTicks : ActionInfo.ItemManagerUpdateCompletedTicks; - s_statisticLogAggregator.AddDataPoint(key, elapsed); - s_histogramLogAggregator.LogTime(key, elapsed); + s_statisticLogAggregator.AddDataPoint((int)key, count); + s_histogramLogAggregator.IncreaseCount((int)key, count); } internal static void ReportTelemetry() @@ -107,7 +106,7 @@ internal static void ReportTelemetry() { foreach (var kv in s_statisticLogAggregator) { - var info = kv.Key.ToString("f"); + var info = ((ActionInfo)kv.Key).ToString("f"); var statistics = kv.Value.GetStatisticResult(); m[CreateProperty(info, nameof(StatisticResult.Maximum))] = statistics.Maximum; @@ -117,15 +116,15 @@ internal static void ReportTelemetry() m[CreateProperty(info, nameof(StatisticResult.Count))] = statistics.Count; } - foreach (var kv in s_countLogAggregator) + foreach (var kv in s_logAggregator) { - var mergeInfo = kv.Key.ToString("f"); + var mergeInfo = ((ActionInfo)kv.Key).ToString("f"); m[mergeInfo] = kv.Value.GetCount(); } foreach (var kv in s_histogramLogAggregator) { - var info = kv.Key.ToString("f"); + var info = ((ActionInfo)kv.Key).ToString("f"); m[$"{info}.BucketSize"] = kv.Value.BucketSize; m[$"{info}.MaxBucketValue"] = kv.Value.MaxBucketValue; m[$"{info}.Buckets"] = kv.Value.GetBucketsAsString(); diff --git a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CompletionSource.cs b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CompletionSource.cs index 6b784a4f8b06a..3119a4534f0b2 100644 --- a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CompletionSource.cs +++ b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CompletionSource.cs @@ -143,7 +143,7 @@ public AsyncCompletionData.CompletionStartData InitializeCompletion( } finally { - AsyncCompletionLogger.LogSourceInitializationTicksDataPoint(stopwatch.Elapsed); + AsyncCompletionLogger.LogSourceInitializationTicksDataPoint((int)stopwatch.Elapsed.TotalMilliseconds); } } @@ -311,7 +311,7 @@ public async Task GetCompletionContextAsync( // There could be a race around the usage of this stopwatch, I ignored it since we just need a rough idea: // we always log the time even if the stopwatch's not started regardless of whether expand items are included intially // (that number can be obtained via another property.) - AsyncCompletionLogger.LogAdditionalTicksToCompleteDelayedImportCompletionDataPoint(stopwatch.Elapsed); + AsyncCompletionLogger.LogAdditionalTicksToCompleteDelayedImportCompletionDataPoint((int)stopwatch.ElapsedMilliseconds); return result; }, cancellationToken); @@ -346,7 +346,7 @@ public async Task GetCompletionContextAsync( } finally { - AsyncCompletionLogger.LogSourceGetContextTicksDataPoint(totalStopWatch.Elapsed, isCanceled: cancellationToken.IsCancellationRequested); + AsyncCompletionLogger.LogSourceGetContextTicksDataPoint((int)totalStopWatch.Elapsed.TotalMilliseconds, isCanceled: cancellationToken.IsCancellationRequested); } static VSCompletionContext CombineCompletionContext(VSCompletionContext context1, VSCompletionContext context2) diff --git a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/ItemManager.cs b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/ItemManager.cs index e102cad5684b2..a66f2eaff3c7b 100644 --- a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/ItemManager.cs +++ b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/ItemManager.cs @@ -36,7 +36,7 @@ public Task> SortCompletionListAsync( // Sort by default comparer of Roslyn CompletionItem var sortedItems = data.InitialList.OrderBy(CompletionItemData.GetOrAddDummyRoslynItem).ToImmutableArray(); - AsyncCompletionLogger.LogItemManagerSortTicksDataPoint(stopwatch.Elapsed); + AsyncCompletionLogger.LogItemManagerSortTicksDataPoint((int)stopwatch.Elapsed.TotalMilliseconds); return Task.FromResult(sortedItems); } @@ -101,7 +101,7 @@ public Task> SortCompletionListAsync( } finally { - AsyncCompletionLogger.LogItemManagerUpdateDataPoint(stopwatch.Elapsed, isCanceled: cancellationToken.IsCancellationRequested); + AsyncCompletionLogger.LogItemManagerUpdateDataPoint((int)stopwatch.Elapsed.TotalMilliseconds, isCanceled: cancellationToken.IsCancellationRequested); } } } diff --git a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs index a3b9b8668f7ce..9f23f66e57ba0 100644 --- a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs +++ b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs @@ -427,7 +427,7 @@ private static async Task> FindChangeSignatureR } telemetryTimer.Stop(); - ChangeSignatureLogger.LogCommitInformation(telemetryNumberOfDeclarationsToUpdate, telemetryNumberOfReferencesToUpdate, telemetryTimer.Elapsed); + ChangeSignatureLogger.LogCommitInformation(telemetryNumberOfDeclarationsToUpdate, telemetryNumberOfReferencesToUpdate, (int)telemetryTimer.ElapsedMilliseconds); return (currentSolution, confirmationMessage); } diff --git a/src/Features/Core/Portable/ChangeSignature/ChangeSignatureTelemetryLogger.cs b/src/Features/Core/Portable/ChangeSignature/ChangeSignatureTelemetryLogger.cs index 634980d055b5b..58c09b0537c93 100644 --- a/src/Features/Core/Portable/ChangeSignature/ChangeSignatureTelemetryLogger.cs +++ b/src/Features/Core/Portable/ChangeSignature/ChangeSignatureTelemetryLogger.cs @@ -4,7 +4,6 @@ #nullable disable -using System; using Microsoft.CodeAnalysis.Internal.Log; namespace Microsoft.CodeAnalysis.ChangeSignature @@ -15,9 +14,9 @@ internal class ChangeSignatureLogger private const string Minimum = nameof(Minimum); private const string Mean = nameof(Mean); - private static readonly CountLogAggregator s_countLogAggregator = new(); - private static readonly StatisticLogAggregator s_statisticLogAggregator = new(); - private static readonly HistogramLogAggregator s_histogramLogAggregator = new(bucketSize: 1000, maxBucketValue: 30000); + private static readonly LogAggregator s_logAggregator = new(); + private static readonly StatisticLogAggregator s_statisticLogAggregator = new(); + private static readonly HistogramLogAggregator s_histogramLogAggregator = new(bucketSize: 1000, maxBucketValue: 30000); internal enum ActionInfo { @@ -63,31 +62,31 @@ internal enum ActionInfo } internal static void LogChangeSignatureDialogLaunched() => - s_countLogAggregator.IncreaseCount(ActionInfo.ChangeSignatureDialogLaunched); + s_logAggregator.IncreaseCount((int)ActionInfo.ChangeSignatureDialogLaunched); internal static void LogChangeSignatureDialogCommitted() => - s_countLogAggregator.IncreaseCount(ActionInfo.ChangeSignatureDialogCommitted); + s_logAggregator.IncreaseCount((int)ActionInfo.ChangeSignatureDialogCommitted); internal static void LogAddParameterDialogLaunched() => - s_countLogAggregator.IncreaseCount(ActionInfo.AddParameterDialogLaunched); + s_logAggregator.IncreaseCount((int)ActionInfo.AddParameterDialogLaunched); internal static void LogAddParameterDialogCommitted() => - s_countLogAggregator.IncreaseCount(ActionInfo.AddParameterDialogCommitted); + s_logAggregator.IncreaseCount((int)ActionInfo.AddParameterDialogCommitted); internal static void LogTransformationInformation(int numOriginalParameters, int numParametersAdded, int numParametersRemoved, bool anyParametersReordered) { LogTransformationCombination(numParametersAdded > 0, numParametersRemoved > 0, anyParametersReordered); - s_countLogAggregator.IncreaseCountBy(ActionInfo.CommittedSession_OriginalParameterCount, numOriginalParameters); + s_logAggregator.IncreaseCountBy((int)ActionInfo.CommittedSession_OriginalParameterCount, numOriginalParameters); if (numParametersAdded > 0) { - s_countLogAggregator.IncreaseCountBy(ActionInfo.CommittedSessionWithAdded_NumberAdded, numParametersAdded); + s_logAggregator.IncreaseCountBy((int)ActionInfo.CommittedSessionWithAdded_NumberAdded, numParametersAdded); } if (numParametersRemoved > 0) { - s_countLogAggregator.IncreaseCountBy(ActionInfo.CommittedSessionWithRemoved_NumberRemoved, numParametersRemoved); + s_logAggregator.IncreaseCountBy((int)ActionInfo.CommittedSessionWithRemoved_NumberRemoved, numParametersRemoved); } } @@ -96,103 +95,103 @@ private static void LogTransformationCombination(bool parametersAdded, bool para // All three transformations if (parametersAdded && parametersRemoved && parametersReordered) { - s_countLogAggregator.IncreaseCount(ActionInfo.CommittedSessionAddedRemovedReordered); + s_logAggregator.IncreaseCount((int)ActionInfo.CommittedSessionAddedRemovedReordered); return; } // Two transformations if (parametersAdded && parametersRemoved) { - s_countLogAggregator.IncreaseCount(ActionInfo.CommittedSessionAddedRemovedOnly); + s_logAggregator.IncreaseCount((int)ActionInfo.CommittedSessionAddedRemovedOnly); return; } if (parametersAdded && parametersReordered) { - s_countLogAggregator.IncreaseCount(ActionInfo.CommittedSessionAddedReorderedOnly); + s_logAggregator.IncreaseCount((int)ActionInfo.CommittedSessionAddedReorderedOnly); return; } if (parametersRemoved && parametersReordered) { - s_countLogAggregator.IncreaseCount(ActionInfo.CommittedSessionRemovedReorderedOnly); + s_logAggregator.IncreaseCount((int)ActionInfo.CommittedSessionRemovedReorderedOnly); return; } // One transformation if (parametersAdded) { - s_countLogAggregator.IncreaseCount(ActionInfo.CommittedSessionAddedOnly); + s_logAggregator.IncreaseCount((int)ActionInfo.CommittedSessionAddedOnly); return; } if (parametersRemoved) { - s_countLogAggregator.IncreaseCount(ActionInfo.CommittedSessionRemovedOnly); + s_logAggregator.IncreaseCount((int)ActionInfo.CommittedSessionRemovedOnly); return; } if (parametersReordered) { - s_countLogAggregator.IncreaseCount(ActionInfo.CommittedSessionReorderedOnly); + s_logAggregator.IncreaseCount((int)ActionInfo.CommittedSessionReorderedOnly); return; } } - internal static void LogCommitInformation(int numDeclarationsUpdated, int numCallSitesUpdated, TimeSpan elapsedTime) + internal static void LogCommitInformation(int numDeclarationsUpdated, int numCallSitesUpdated, int elapsedMS) { - s_countLogAggregator.IncreaseCount(ActionInfo.ChangeSignatureCommitCompleted); + s_logAggregator.IncreaseCount((int)ActionInfo.ChangeSignatureCommitCompleted); - s_countLogAggregator.IncreaseCountBy(ActionInfo.CommittedSessionNumberOfDeclarationsUpdated, numDeclarationsUpdated); - s_countLogAggregator.IncreaseCountBy(ActionInfo.CommittedSessionNumberOfCallSitesUpdated, numCallSitesUpdated); + s_logAggregator.IncreaseCountBy((int)ActionInfo.CommittedSessionNumberOfDeclarationsUpdated, numDeclarationsUpdated); + s_logAggregator.IncreaseCountBy((int)ActionInfo.CommittedSessionNumberOfCallSitesUpdated, numCallSitesUpdated); - s_statisticLogAggregator.AddDataPoint(ActionInfo.CommittedSessionCommitElapsedMS, (int)elapsedTime.TotalMilliseconds); - s_histogramLogAggregator.LogTime(ActionInfo.CommittedSessionCommitElapsedMS, elapsedTime); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.CommittedSessionCommitElapsedMS, elapsedMS); + s_histogramLogAggregator.IncreaseCount((int)ActionInfo.CommittedSessionCommitElapsedMS, elapsedMS); } internal static void LogAddedParameterTypeBinds() { - s_countLogAggregator.IncreaseCount(ActionInfo.AddedParameterTypeBinds); + s_logAggregator.IncreaseCount((int)ActionInfo.AddedParameterTypeBinds); } internal static void LogAddedParameterRequired() { - s_countLogAggregator.IncreaseCount(ActionInfo.AddedParameterRequired); + s_logAggregator.IncreaseCount((int)ActionInfo.AddedParameterRequired); } internal static void LogAddedParameter_ValueExplicit() { - s_countLogAggregator.IncreaseCount(ActionInfo.AddedParameterValueExplicit); + s_logAggregator.IncreaseCount((int)ActionInfo.AddedParameterValueExplicit); } internal static void LogAddedParameter_ValueExplicitNamed() { - s_countLogAggregator.IncreaseCount(ActionInfo.AddedParameterValueExplicitNamed); + s_logAggregator.IncreaseCount((int)ActionInfo.AddedParameterValueExplicitNamed); } internal static void LogAddedParameter_ValueTODO() { - s_countLogAggregator.IncreaseCount(ActionInfo.AddedParameterValueTODO); + s_logAggregator.IncreaseCount((int)ActionInfo.AddedParameterValueTODO); } internal static void LogAddedParameter_ValueOmitted() { - s_countLogAggregator.IncreaseCount(ActionInfo.AddedParameterValueOmitted); + s_logAggregator.IncreaseCount((int)ActionInfo.AddedParameterValueOmitted); } internal static void ReportTelemetry() { Logger.Log(FunctionId.ChangeSignature_Data, KeyValueLogMessage.Create(m => { - foreach (var kv in s_countLogAggregator) + foreach (var kv in s_logAggregator) { - var info = kv.Key.ToString("f"); + var info = ((ActionInfo)kv.Key).ToString("f"); m[info] = kv.Value.GetCount(); } foreach (var kv in s_statisticLogAggregator) { - var info = kv.Key.ToString("f"); + var info = ((ActionInfo)kv.Key).ToString("f"); var statistics = kv.Value.GetStatisticResult(); m[CreateProperty(info, Maximum)] = statistics.Maximum; @@ -202,7 +201,7 @@ internal static void ReportTelemetry() foreach (var kv in s_histogramLogAggregator) { - var info = kv.Key.ToString("f"); + var info = ((ActionInfo)kv.Key).ToString("f"); m[$"{info}.BucketSize"] = kv.Value.BucketSize; m[$"{info}.MaxBucketValue"] = kv.Value.MaxBucketValue; m[$"{info}.Buckets"] = kv.Value.GetBucketsAsString(); diff --git a/src/Features/Core/Portable/Completion/Log/CompletionProvidersLogger.cs b/src/Features/Core/Portable/Completion/Log/CompletionProvidersLogger.cs index eab198df2b957..f0f0030f34b4e 100644 --- a/src/Features/Core/Portable/Completion/Log/CompletionProvidersLogger.cs +++ b/src/Features/Core/Portable/Completion/Log/CompletionProvidersLogger.cs @@ -2,17 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using Microsoft.CodeAnalysis.Internal.Log; namespace Microsoft.CodeAnalysis.Completion.Log { internal static class CompletionProvidersLogger { - private static readonly StatisticLogAggregator s_statisticLogAggregator = new(); - private static readonly CountLogAggregator s_countLogAggregator = new(); + private static readonly StatisticLogAggregator s_statisticLogAggregator = new(); + private static readonly LogAggregator s_logAggregator = new(); - private static readonly HistogramLogAggregator s_histogramLogAggregator = new(bucketSize: 50, maxBucketValue: 1000); + private static readonly HistogramLogAggregator s_histogramLogAggregator = new(bucketSize: 50, maxBucketValue: 1000); internal enum ActionInfo { @@ -34,52 +33,52 @@ internal enum ActionInfo CommitUsingDotToAddParenthesis } - internal static void LogTypeImportCompletionTicksDataPoint(TimeSpan elapsed) + internal static void LogTypeImportCompletionTicksDataPoint(int count) { - s_histogramLogAggregator.LogTime(ActionInfo.TypeImportCompletionTicks, elapsed); - s_statisticLogAggregator.AddDataPoint(ActionInfo.TypeImportCompletionTicks, elapsed); + s_histogramLogAggregator.IncreaseCount((int)ActionInfo.TypeImportCompletionTicks, count); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.TypeImportCompletionTicks, count); } internal static void LogTypeImportCompletionItemCountDataPoint(int count) => - s_statisticLogAggregator.AddDataPoint(ActionInfo.TypeImportCompletionItemCount, count); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.TypeImportCompletionItemCount, count); internal static void LogTypeImportCompletionReferenceCountDataPoint(int count) => - s_statisticLogAggregator.AddDataPoint(ActionInfo.TypeImportCompletionReferenceCount, count); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.TypeImportCompletionReferenceCount, count); internal static void LogTypeImportCompletionCacheMiss() => - s_countLogAggregator.IncreaseCount(ActionInfo.TypeImportCompletionCacheMissCount); + s_logAggregator.IncreaseCount((int)ActionInfo.TypeImportCompletionCacheMissCount); internal static void LogCommitOfTypeImportCompletionItem() => - s_countLogAggregator.IncreaseCount(ActionInfo.CommitsOfTypeImportCompletionItem); + s_logAggregator.IncreaseCount((int)ActionInfo.CommitsOfTypeImportCompletionItem); - internal static void LogExtensionMethodCompletionTicksDataPoint(TimeSpan total, TimeSpan getSymbols, TimeSpan createItems, bool isRemote) + internal static void LogExtensionMethodCompletionTicksDataPoint(int total, int getSymbols, int createItems, bool isRemote) { - s_histogramLogAggregator.LogTime(ActionInfo.ExtensionMethodCompletionTicks, total); - s_statisticLogAggregator.AddDataPoint(ActionInfo.ExtensionMethodCompletionTicks, total); + s_histogramLogAggregator.IncreaseCount((int)ActionInfo.ExtensionMethodCompletionTicks, total); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionTicks, total); if (isRemote) { - s_statisticLogAggregator.AddDataPoint(ActionInfo.ExtensionMethodCompletionRemoteTicks, total - getSymbols - createItems); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionRemoteTicks, (total - getSymbols - createItems)); } - s_statisticLogAggregator.AddDataPoint(ActionInfo.ExtensionMethodCompletionGetSymbolsTicks, getSymbols); - s_statisticLogAggregator.AddDataPoint(ActionInfo.ExtensionMethodCompletionCreateItemsTicks, createItems); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionGetSymbolsTicks, getSymbols); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionCreateItemsTicks, createItems); } internal static void LogExtensionMethodCompletionMethodsProvidedDataPoint(int count) => - s_statisticLogAggregator.AddDataPoint(ActionInfo.ExtensionMethodCompletionMethodsProvided, count); + s_statisticLogAggregator.AddDataPoint((int)ActionInfo.ExtensionMethodCompletionMethodsProvided, count); internal static void LogCommitOfExtensionMethodImportCompletionItem() => - s_countLogAggregator.IncreaseCount(ActionInfo.CommitsOfExtensionMethodImportCompletionItem); + s_logAggregator.IncreaseCount((int)ActionInfo.CommitsOfExtensionMethodImportCompletionItem); internal static void LogExtensionMethodCompletionPartialResultCount() => - s_countLogAggregator.IncreaseCount(ActionInfo.ExtensionMethodCompletionPartialResultCount); + s_logAggregator.IncreaseCount((int)ActionInfo.ExtensionMethodCompletionPartialResultCount); internal static void LogCommitUsingSemicolonToAddParenthesis() => - s_countLogAggregator.IncreaseCount(ActionInfo.CommitUsingSemicolonToAddParenthesis); + s_logAggregator.IncreaseCount((int)ActionInfo.CommitUsingSemicolonToAddParenthesis); internal static void LogCommitUsingDotToAddParenthesis() => - s_countLogAggregator.IncreaseCount(ActionInfo.CommitUsingDotToAddParenthesis); + s_logAggregator.IncreaseCount((int)ActionInfo.CommitUsingDotToAddParenthesis); internal static void LogCustomizedCommitToAddParenthesis(char? commitChar) { @@ -110,7 +109,7 @@ internal static void ReportTelemetry() m[CreateProperty(info, nameof(statistics.Count))] = statistics.Count; } - foreach (var kv in s_countLogAggregator) + foreach (var kv in s_logAggregator) { var info = ((ActionInfo)kv.Key).ToString("f"); m[info] = kv.Value.GetCount(); diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractExtensionMethodImportCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractExtensionMethodImportCompletionProvider.cs index b1a4251494cc3..d052732ea2cde 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractExtensionMethodImportCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractExtensionMethodImportCompletionProvider.cs @@ -14,7 +14,6 @@ using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Completion.Providers { @@ -44,8 +43,7 @@ protected override async Task AddCompletionItemsAsync( var syntaxFacts = completionContext.Document.GetRequiredLanguageService(); if (TryGetReceiverTypeSymbol(syntaxContext, syntaxFacts, cancellationToken, out var receiverTypeSymbol)) { - var totalTime = SharedStopwatch.StartNew(); - + var ticks = Environment.TickCount; var inferredTypes = completionContext.CompletionOptions.TargetTypedCompletionFilter ? syntaxContext.InferredTypes : ImmutableArray.Empty; @@ -67,8 +65,9 @@ protected override async Task AddCompletionItemsAsync( completionContext.AddItems(result.CompletionItems.Select(i => Convert(i, receiverTypeKey))); // report telemetry: + var totalTicks = Environment.TickCount - ticks; CompletionProvidersLogger.LogExtensionMethodCompletionTicksDataPoint( - totalTime.Elapsed, result.GetSymbolsTime, result.CreateItemsTime, result.IsRemote); + totalTicks, result.GetSymbolsTicks, result.CreateItemsTicks, result.IsRemote); if (result.IsPartialResult) CompletionProvidersLogger.LogExtensionMethodCompletionPartialResultCount(); diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractTypeImportCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractTypeImportCompletionProvider.cs index 21b6828393396..2e39c11984bcf 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractTypeImportCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractTypeImportCompletionProvider.cs @@ -163,7 +163,7 @@ static bool ShouldAddItem( private class TelemetryCounter { - private readonly SharedStopwatch _elapsedTime; + private readonly int _tick; public int ItemsCount { get; set; } public int ReferenceCount { get; set; } @@ -171,7 +171,7 @@ private class TelemetryCounter public TelemetryCounter() { - _elapsedTime = SharedStopwatch.StartNew(); + _tick = Environment.TickCount; } public void Report() @@ -182,7 +182,8 @@ public void Report() } // cache miss still count towards the cost of completion, so we need to log regardless of it. - CompletionProvidersLogger.LogTypeImportCompletionTicksDataPoint(_elapsedTime.Elapsed); + var delta = Environment.TickCount - _tick; + CompletionProvidersLogger.LogTypeImportCompletionTicksDataPoint(delta); CompletionProvidersLogger.LogTypeImportCompletionItemCountDataPoint(ItemsCount); CompletionProvidersLogger.LogTypeImportCompletionReferenceCountDataPoint(ReferenceCount); } diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs index d7cb5c655c5ed..7eeb953a45410 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs @@ -90,7 +90,7 @@ public static async Task GetUnimportedEx bool isRemote, CancellationToken cancellationToken) { - var stopwatch = SharedStopwatch.StartNew(); + var ticks = Environment.TickCount; // First find symbols of all applicable extension methods. // Workspace's syntax/symbol index is used to avoid iterating every method symbols in the solution. @@ -98,15 +98,15 @@ public static async Task GetUnimportedEx document, position, receiverTypeSymbol, namespaceInScope, cancellationToken).ConfigureAwait(false); var (extentsionMethodSymbols, isPartialResult) = await symbolComputer.GetExtensionMethodSymbolsAsync(forceCacheCreation, hideAdvancedMembers, cancellationToken).ConfigureAwait(false); - var getSymbolsTime = stopwatch.Elapsed; - stopwatch = SharedStopwatch.StartNew(); + var getSymbolsTicks = Environment.TickCount - ticks; + ticks = Environment.TickCount; var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); var items = ConvertSymbolsToCompletionItems(compilation, extentsionMethodSymbols, targetTypes, cancellationToken); - var createItemsTime = stopwatch.Elapsed; + var createItemsTicks = Environment.TickCount - ticks; - return new SerializableUnimportedExtensionMethods(items, isPartialResult, getSymbolsTime, createItemsTime, isRemote); + return new SerializableUnimportedExtensionMethods(items, isPartialResult, getSymbolsTicks, createItemsTicks, isRemote); } public static async ValueTask BatchUpdateCacheAsync(ImmutableSegmentedList projects, CancellationToken cancellationToken) diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/SerializableUnimportedExtensionMethods.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/SerializableUnimportedExtensionMethods.cs index b7dc7a3362067..b8eee20c00241 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/SerializableUnimportedExtensionMethods.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/SerializableUnimportedExtensionMethods.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections.Immutable; using System.Runtime.Serialization; @@ -18,10 +17,10 @@ internal sealed class SerializableUnimportedExtensionMethods public readonly bool IsPartialResult; [DataMember(Order = 2)] - public readonly TimeSpan GetSymbolsTime; + public readonly int GetSymbolsTicks; [DataMember(Order = 3)] - public readonly TimeSpan CreateItemsTime; + public readonly int CreateItemsTicks; [DataMember(Order = 4)] public readonly bool IsRemote; @@ -29,14 +28,14 @@ internal sealed class SerializableUnimportedExtensionMethods public SerializableUnimportedExtensionMethods( ImmutableArray completionItems, bool isPartialResult, - TimeSpan getSymbolsTime, - TimeSpan createItemsTime, + int getSymbolsTicks, + int createItemsTicks, bool isRemote) { CompletionItems = completionItems; IsPartialResult = isPartialResult; - GetSymbolsTime = getSymbolsTime; - CreateItemsTime = createItemsTime; + GetSymbolsTicks = getSymbolsTicks; + CreateItemsTicks = createItemsTicks; IsRemote = isRemote; } } diff --git a/src/Features/Core/Portable/EditAndContinue/DebuggingSession.cs b/src/Features/Core/Portable/EditAndContinue/DebuggingSession.cs index 7ff73722dc34e..1f80311fa17b0 100644 --- a/src/Features/Core/Portable/EditAndContinue/DebuggingSession.cs +++ b/src/Features/Core/Portable/EditAndContinue/DebuggingSession.cs @@ -1042,7 +1042,7 @@ async Task GetTaskAsync(ProjectId projectId) private static void ReportTelemetry(DebuggingSessionTelemetry.Data data) { // report telemetry (fire and forget): - _ = Task.Run(() => DebuggingSessionTelemetry.Log(data, Logger.Log, CorrelationIdFactory.GetNextId)); + _ = Task.Run(() => DebuggingSessionTelemetry.Log(data, Logger.Log, LogAggregator.GetNextId)); } internal TestAccessor GetTestAccessor() diff --git a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs index c1e248b062b22..181cef3b13f01 100644 --- a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs +++ b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs @@ -134,10 +134,10 @@ public static void LogWorkCoordinatorShutdownTimeout(int correlationId) })); } - public static void LogWorkspaceEvent(CountLogAggregator logAggregator, WorkspaceChangeKind kind) + public static void LogWorkspaceEvent(LogAggregator logAggregator, int kind) => logAggregator.IncreaseCount(kind); - public static void LogWorkCoordinatorShutdown(int correlationId, CountLogAggregator logAggregator) + public static void LogWorkCoordinatorShutdown(int correlationId, LogAggregator logAggregator) { Logger.Log(FunctionId.WorkCoordinator_Shutdown, KeyValueLogMessage.Create(m => { @@ -145,23 +145,23 @@ public static void LogWorkCoordinatorShutdown(int correlationId, CountLogAggrega foreach (var kv in logAggregator) { - var change = kv.Key.ToString(); + var change = ((WorkspaceChangeKind)kv.Key).ToString(); m[change] = kv.Value.GetCount(); } })); } - public static void LogGlobalOperation(CountLogAggregator logAggregator) + public static void LogGlobalOperation(LogAggregator logAggregator) => logAggregator.IncreaseCount(GlobalOperation); - public static void LogActiveFileEnqueue(CountLogAggregator logAggregator) + public static void LogActiveFileEnqueue(LogAggregator logAggregator) => logAggregator.IncreaseCount(ActiveFileEnqueue); - public static void LogWorkItemEnqueue(CountLogAggregator logAggregator, ProjectId _) + public static void LogWorkItemEnqueue(LogAggregator logAggregator, ProjectId _) => logAggregator.IncreaseCount(ProjectEnqueue); public static void LogWorkItemEnqueue( - CountLogAggregator logAggregator, string language, DocumentId? documentId, InvocationReasons reasons, bool lowPriority, SyntaxPath? activeMember, bool added) + LogAggregator logAggregator, string language, DocumentId? documentId, InvocationReasons reasons, bool lowPriority, SyntaxPath? activeMember, bool added) { logAggregator.IncreaseCount(language); logAggregator.IncreaseCount(added ? NewWorkItem : UpdateWorkItem); @@ -183,16 +183,16 @@ public static void LogWorkItemEnqueue( } } - public static void LogHigherPriority(CountLogAggregator logAggregator, Guid documentId) + public static void LogHigherPriority(LogAggregator logAggregator, Guid documentId) { logAggregator.IncreaseCount(HigherPriority); logAggregator.IncreaseCount(ValueTuple.Create(HigherPriority, documentId)); } - public static void LogResetStates(CountLogAggregator logAggregator) + public static void LogResetStates(LogAggregator logAggregator) => logAggregator.IncreaseCount(ResetStates); - public static void LogIncrementalAnalyzerProcessorStatistics(int correlationId, Solution solution, CountLogAggregator logAggregator, ImmutableArray analyzers) + public static void LogIncrementalAnalyzerProcessorStatistics(int correlationId, Solution solution, LogAggregator logAggregator, ImmutableArray analyzers) { Logger.Log(FunctionId.IncrementalAnalyzerProcessor_Shutdown, KeyValueLogMessage.Create(m => { @@ -207,21 +207,22 @@ public static void LogIncrementalAnalyzerProcessorStatistics(int correlationId, if (key is string stringKey) { m[stringKey] = counter.GetCount(); + continue; } - else if (key is ValueTuple propertyNameAndId) + + if (key is ValueTuple propertyNameAndId) { var list = statMap.GetOrAdd(propertyNameAndId.Item1, _ => new List()); list.Add(counter.GetCount()); + continue; } - else - { - throw ExceptionUtilities.Unreachable; - } + + throw ExceptionUtilities.Unreachable; } foreach (var (propertyName, propertyValues) in statMap) { - var result = StatisticResult.FromList(propertyValues); + var result = LogAggregator.GetStatistics(propertyValues); m[CreateProperty(propertyName, Max)] = result.Maximum; m[CreateProperty(propertyName, Min)] = result.Minimum; @@ -252,19 +253,19 @@ private static int GetSolutionHash(Solution solution) private static string CreateProperty(string parent, string child) => parent + "." + child; - public static void LogProcessCloseDocument(CountLogAggregator logAggregator, Guid documentId) + public static void LogProcessCloseDocument(LogAggregator logAggregator, Guid documentId) { logAggregator.IncreaseCount(CloseDocument); logAggregator.IncreaseCount(ValueTuple.Create(CloseDocument, documentId)); } - public static void LogProcessOpenDocument(CountLogAggregator logAggregator, Guid documentId) + public static void LogProcessOpenDocument(LogAggregator logAggregator, Guid documentId) { logAggregator.IncreaseCount(OpenDocument); logAggregator.IncreaseCount(ValueTuple.Create(OpenDocument, documentId)); } - public static void LogProcessActiveFileDocument(CountLogAggregator logAggregator, Guid _, bool processed) + public static void LogProcessActiveFileDocument(LogAggregator logAggregator, Guid _, bool processed) { if (processed) { @@ -276,7 +277,7 @@ public static void LogProcessActiveFileDocument(CountLogAggregator logAg } } - public static void LogProcessDocument(CountLogAggregator logAggregator, Guid documentId, bool processed) + public static void LogProcessDocument(LogAggregator logAggregator, Guid documentId, bool processed) { if (processed) { @@ -290,10 +291,10 @@ public static void LogProcessDocument(CountLogAggregator logAggregator, logAggregator.IncreaseCount(ValueTuple.Create(ProcessDocument, documentId)); } - public static void LogProcessDocumentNotExist(CountLogAggregator logAggregator) + public static void LogProcessDocumentNotExist(LogAggregator logAggregator) => logAggregator.IncreaseCount(DocumentNotExist); - public static void LogProcessProject(CountLogAggregator logAggregator, Guid projectId, bool processed) + public static void LogProcessProject(LogAggregator logAggregator, Guid projectId, bool processed) { if (processed) { @@ -307,7 +308,7 @@ public static void LogProcessProject(CountLogAggregator logAggregator, G logAggregator.IncreaseCount(ValueTuple.Create(ProcessProject, projectId)); } - public static void LogProcessProjectNotExist(CountLogAggregator logAggregator) + public static void LogProcessProjectNotExist(LogAggregator logAggregator) => logAggregator.IncreaseCount(ProjectNotExist); } } diff --git a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerRegistrationService.cs b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerRegistrationService.cs index 18a1e2e3aba98..b5def68057044 100644 --- a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerRegistrationService.cs +++ b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerRegistrationService.cs @@ -62,7 +62,7 @@ public void EnsureRegistration(Workspace workspace, bool initializeLazily) { Contract.ThrowIfNull(workspace.Kind); - var correlationId = CorrelationIdFactory.GetNextId(); + var correlationId = LogAggregator.GetNextId(); lock (_gate) { diff --git a/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs b/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs index 2412aed423528..f4a317aceaad5 100644 --- a/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs +++ b/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs @@ -42,11 +42,7 @@ private partial class IncrementalAnalyzerProcessor // NOTE: IDiagnosticAnalyzerService can be null in test environment. private readonly Lazy _lazyDiagnosticAnalyzerService; - /// - /// The keys in this are either a string or a (string, Guid) tuple. See - /// for what is writing this out. - /// - private CountLogAggregator _logAggregator = new(); + private LogAggregator _logAggregator = new(); public IncrementalAnalyzerProcessor( IAsynchronousOperationListener listener, @@ -154,7 +150,7 @@ private IEnumerable GetOpenDocumentIds() => _registration.Workspace.GetOpenDocumentIds(); private void ResetLogAggregator() - => _logAggregator = new CountLogAggregator(); + => _logAggregator = new LogAggregator(); private void ReportPendingWorkItemCount() { diff --git a/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs b/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs index 9484183220b3e..cf3c7a1f63683 100644 --- a/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs +++ b/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs @@ -24,7 +24,7 @@ internal sealed partial class WorkCoordinator private readonly Registration _registration; private readonly object _gate = new(); - private readonly CountLogAggregator _logAggregator = new(); + private readonly LogAggregator _logAggregator = new(); private readonly IAsynchronousOperationListener _listener; private readonly IDocumentTrackingService _documentTrackingService; private readonly IWorkspaceConfigurationService? _workspaceConfigurationService; @@ -192,7 +192,7 @@ private bool NotOurShutdownToken(OperationCanceledException oce) private void ProcessEvent(WorkspaceChangeEventArgs args, string eventName) { - SolutionCrawlerLogger.LogWorkspaceEvent(_logAggregator, args.Kind); + SolutionCrawlerLogger.LogWorkspaceEvent(_logAggregator, (int)args.Kind); // TODO: add telemetry that record how much it takes to process an event (max, min, average and etc) switch (args.Kind) diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs index 4bb863a34fdbd..4a8469a9ee997 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs @@ -49,7 +49,7 @@ private DiagnosticIncrementalAnalyzer CreateIncrementalAnalyzerCallback(Workspac // subscribe to active context changed event for new workspace workspace.DocumentActiveContextChanged += OnDocumentActiveContextChanged; - return new DiagnosticIncrementalAnalyzer(this, CorrelationIdFactory.GetNextId(), workspace, AnalyzerInfoCache); + return new DiagnosticIncrementalAnalyzer(this, LogAggregator.GetNextId(), workspace, AnalyzerInfoCache); } private void OnDocumentActiveContextChanged(object? sender, DocumentActiveContextChangedEventArgs e) diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs index 1f6cd5520feb6..e53c233f0caa2 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestTelemetryLogger.cs @@ -24,7 +24,7 @@ internal sealed class RequestTelemetryLogger : IDisposable, ILspService /// /// Histogram to aggregate the time in queue metrics. /// - private readonly HistogramLogAggregator _queuedDurationLogAggregator; + private readonly HistogramLogAggregator _queuedDurationLogAggregator; /// /// Histogram to aggregate total request duration metrics. @@ -34,7 +34,7 @@ internal sealed class RequestTelemetryLogger : IDisposable, ILspService /// This provides highly detailed buckets when duration is in MS, but less detailed /// when the duration is in terms of seconds or minutes. /// - private readonly HistogramLogAggregator _requestDurationLogAggregator; + private readonly HistogramLogAggregator _requestDurationLogAggregator; /// /// Store request counters in a concurrent dictionary as non-mutating LSP requests can @@ -42,9 +42,9 @@ internal sealed class RequestTelemetryLogger : IDisposable, ILspService /// private readonly ConcurrentDictionary _requestCounters; - private readonly CountLogAggregator _findDocumentResults; + private readonly LogAggregator _findDocumentResults; - private readonly CountLogAggregator _usedForkedSolutionCounter; + private readonly LogAggregator _usedForkedSolutionCounter; private int _disposed; @@ -57,11 +57,11 @@ public RequestTelemetryLogger(string serverTypeName) // Buckets queued duration into 10ms buckets with the last bucket starting at 1000ms. // Queue times are relatively short and fall under 50ms, so tracking past 1000ms is not useful. - _queuedDurationLogAggregator = new HistogramLogAggregator(bucketSize: 10, maxBucketValue: 1000); + _queuedDurationLogAggregator = new HistogramLogAggregator(bucketSize: 10, maxBucketValue: 1000); // Since this is a log based histogram, these are appropriate bucket sizes for the log data. // A bucket at 1 corresponds to ~26ms, while the max bucket value corresponds to ~17minutes - _requestDurationLogAggregator = new HistogramLogAggregator(bucketSize: 1, maxBucketValue: 40); + _requestDurationLogAggregator = new HistogramLogAggregator(bucketSize: 1, maxBucketValue: 40); } public void UpdateFindDocumentTelemetryData(bool success, string? workspaceKind) @@ -87,10 +87,10 @@ public void UpdateTelemetryData( { // Find the bucket corresponding to the queued duration and update the count of durations in that bucket. // This is not broken down per method as time in queue is not specific to an LSP method. - _queuedDurationLogAggregator.LogTime(QueuedDurationKey, queuedDuration); + _queuedDurationLogAggregator.IncreaseCount(QueuedDurationKey, Convert.ToDecimal(queuedDuration.TotalMilliseconds)); // Store the request time metrics per LSP method. - _requestDurationLogAggregator.IncreaseCount(methodName, (int)ComputeLogValue(requestDuration.TotalMilliseconds)); + _requestDurationLogAggregator.IncreaseCount(methodName, Convert.ToDecimal(ComputeLogValue(requestDuration.TotalMilliseconds))); _requestCounters.GetOrAdd(methodName, (_) => new Counter()).IncrementCount(result); } diff --git a/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs index 0b38743b65005..253e1dc07c4a9 100644 --- a/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs +++ b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs @@ -10,7 +10,7 @@ namespace Microsoft.VisualStudio.LanguageServices.InheritanceMargin internal static class InheritanceMarginLogger { // 1 sec per bucket, and if it takes more than 1 min, then this log is considered as time-out in the last bucket. - private static readonly HistogramLogAggregator s_histogramLogAggregator = new(1000, 60000); + private static readonly HistogramLogAggregator s_histogramLogAggregator = new(1000, 60000); private enum ActionInfo { @@ -18,8 +18,8 @@ private enum ActionInfo } public static void LogGenerateBackgroundInheritanceInfo(TimeSpan elapsedTime) - => s_histogramLogAggregator.LogTime( - ActionInfo.GetInheritanceMarginMembers, elapsedTime); + => s_histogramLogAggregator.IncreaseCount( + ActionInfo.GetInheritanceMarginMembers, Convert.ToDecimal(elapsedTime.TotalMilliseconds)); public static void LogInheritanceTargetsMenuOpen() => Logger.Log(FunctionId.InheritanceMargin_TargetsMenuOpen, KeyValueLogMessage.Create(LogType.UserAction)); diff --git a/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/CommonFixAllState.cs b/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/CommonFixAllState.cs index 28ea1c9e3d971..9f051c30b102e 100644 --- a/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/CommonFixAllState.cs +++ b/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/CommonFixAllState.cs @@ -13,7 +13,7 @@ internal abstract partial class CommonFixAllState { - public int CorrelationId { get; } = CorrelationIdFactory.GetNextId(); + public int CorrelationId { get; } = LogAggregator.GetNextId(); public TFixAllProvider FixAllProvider { get; } public string? CodeActionEquivalenceKey { get; } public TProvider Provider { get; } diff --git a/src/Workspaces/Core/Portable/Log/CorrelationIdFactory.cs b/src/Workspaces/Core/Portable/Log/CorrelationIdFactory.cs deleted file mode 100644 index 702f148c1574c..0000000000000 --- a/src/Workspaces/Core/Portable/Log/CorrelationIdFactory.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; - -namespace Microsoft.CodeAnalysis.Internal.Log -{ - internal static class CorrelationIdFactory - { - private static int s_globalId; - - public static int GetNextId() - => Interlocked.Increment(ref s_globalId); - } -} diff --git a/src/Workspaces/Core/Portable/Log/HistogramLogAggregator.cs b/src/Workspaces/Core/Portable/Log/HistogramLogAggregator.cs index 9f04d3098f021..8643d926ddc15 100644 --- a/src/Workspaces/Core/Portable/Log/HistogramLogAggregator.cs +++ b/src/Workspaces/Core/Portable/Log/HistogramLogAggregator.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Internal.Log /// /// Defines a log aggregator to create a histogram /// - internal sealed class HistogramLogAggregator : AbstractLogAggregator.HistogramCounter> + internal sealed class HistogramLogAggregator : AbstractLogAggregator { private readonly int _bucketSize; private readonly int _maxBucketValue; @@ -32,19 +32,13 @@ public HistogramLogAggregator(int bucketSize, int maxBucketValue) protected override HistogramCounter CreateCounter() => new(_bucketSize, _maxBucketValue, _bucketCount); - public void IncreaseCount(TKey key, int value) + public void IncreaseCount(object key, decimal value) { var counter = GetCounter(key); counter.IncreaseCount(value); } - public void LogTime(TKey key, TimeSpan timeSpan) - { - var counter = GetCounter(key); - counter.IncreaseCount((int)timeSpan.TotalMilliseconds); - } - - public HistogramCounter? GetValue(TKey key) + public HistogramCounter? GetValue(object key) { TryGetCounter(key, out var counter); return counter; @@ -68,7 +62,7 @@ public HistogramCounter(int bucketSize, int maxBucketValue, int bucketCount) _buckets = new int[BucketCount]; } - public void IncreaseCount(int value) + public void IncreaseCount(decimal value) { var bucket = GetBucket(value); _buckets[bucket]++; @@ -92,9 +86,9 @@ public string GetBucketsAsString() return pooledStringBuilder.ToStringAndFree(); } - private int GetBucket(int value) + private int GetBucket(decimal value) { - var bucket = value / BucketSize; + var bucket = (int)Math.Floor(value / BucketSize); if (bucket >= BucketCount) { bucket = BucketCount - 1; diff --git a/src/Workspaces/Core/Portable/Log/StatisticLogAggregator.cs b/src/Workspaces/Core/Portable/Log/StatisticLogAggregator.cs index afe08bbbb0972..c0dad86c05102 100644 --- a/src/Workspaces/Core/Portable/Log/StatisticLogAggregator.cs +++ b/src/Workspaces/Core/Portable/Log/StatisticLogAggregator.cs @@ -4,27 +4,20 @@ #nullable disable -using System; - namespace Microsoft.CodeAnalysis.Internal.Log { - internal sealed class StatisticLogAggregator : AbstractLogAggregator.StatisticCounter> + internal sealed class StatisticLogAggregator : AbstractLogAggregator { protected override StatisticCounter CreateCounter() => new(); - public void AddDataPoint(TKey key, int value) + public void AddDataPoint(object key, int value) { var counter = GetCounter(key); counter.AddDataPoint(value); } - public void AddDataPoint(TKey key, TimeSpan timeSpan) - { - AddDataPoint(key, (int)timeSpan.TotalMilliseconds); - } - - public StatisticResult GetStaticticResult(TKey key) + public StatisticResult GetStaticticResult(object key) { if (TryGetCounter(key, out var counter)) { diff --git a/src/Workspaces/Core/Portable/Log/StatisticResult.cs b/src/Workspaces/Core/Portable/Log/StatisticResult.cs deleted file mode 100644 index 0c69d2bb708f9..0000000000000 --- a/src/Workspaces/Core/Portable/Log/StatisticResult.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -using System.Collections.Generic; -using System.Linq; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.Internal.Log -{ - internal struct StatisticResult - { - public static StatisticResult FromList(List values) - { - if (values.Count == 0) - { - return default; - } - - var max = int.MinValue; - var min = int.MaxValue; - - var total = 0; - for (var i = 0; i < values.Count; i++) - { - var current = values[i]; - max = max < current ? current : max; - min = min > current ? current : min; - - total += current; - } - - var mean = total / values.Count; - var median = values[values.Count / 2]; - - var range = max - min; - var mode = values.GroupBy(i => i).OrderByDescending(g => g.Count()).FirstOrDefault().Key; - - return new StatisticResult(max, min, median, mean, range, mode, values.Count); - } - - /// - /// maximum value - /// - public readonly int Maximum; - - /// - /// minimum value - /// - public readonly int Minimum; - - /// - /// middle value of the total data set - /// - public readonly int? Median; - - /// - /// average value of the total data set - /// - public readonly int Mean; - - /// - /// most frequent value in the total data set - /// - public readonly int? Mode; - - /// - /// difference between max and min value - /// - public readonly int Range; - - /// - /// number of data points in the total data set - /// - public readonly int Count; - - public StatisticResult(int max, int min, int? median, int mean, int range, int? mode, int count) - { - this.Maximum = max; - this.Minimum = min; - this.Median = median; - this.Mean = mean; - this.Range = range; - this.Mode = mode; - this.Count = count; - } - } -} diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionLogger.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionLogger.cs index 161afc1205301..c59b5ecfe193a 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionLogger.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionLogger.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.Logging { internal static class SolutionLogger { - private static readonly CountLogAggregator s_logAggregator = new(); + private static readonly LogAggregator s_logAggregator = new(); public static void UseExistingPartialProjectState() => s_logAggregator.IncreaseCount(nameof(UseExistingPartialProjectState)); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/AbstractLogAggregator.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/AbstractLogAggregator.cs index 0d4173983a3e6..4a17ae05cfdd3 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/AbstractLogAggregator.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/AbstractLogAggregator.cs @@ -17,31 +17,65 @@ namespace Microsoft.CodeAnalysis.Internal.Log /// /// helper class to aggregate some numeric value log in client side /// - internal abstract class AbstractLogAggregator : IEnumerable> + internal abstract class AbstractLogAggregator : IEnumerable> { - private readonly ConcurrentDictionary _map = new(concurrencyLevel: 2, capacity: 2); - private readonly Func _createCounter; + private static int s_globalId; + + private readonly ConcurrentDictionary _map = new(concurrencyLevel: 2, capacity: 2); + private readonly Func _createCounter; protected AbstractLogAggregator() { _createCounter = _ => CreateCounter(); } - protected abstract TValue CreateCounter(); + protected abstract T CreateCounter(); + + public static int GetNextId() + => Interlocked.Increment(ref s_globalId); + + public static StatisticResult GetStatistics(List values) + { + if (values.Count == 0) + { + return default; + } + + var max = int.MinValue; + var min = int.MaxValue; + + var total = 0; + for (var i = 0; i < values.Count; i++) + { + var current = values[i]; + max = max < current ? current : max; + min = min > current ? current : min; + + total += current; + } + + var mean = total / values.Count; + var median = values[values.Count / 2]; + + var range = max - min; + var mode = values.GroupBy(i => i).OrderByDescending(g => g.Count()).FirstOrDefault().Key; + + return new StatisticResult(max, min, median, mean, range, mode, values.Count); + } public bool IsEmpty => _map.IsEmpty; - public IEnumerator> GetEnumerator() + public IEnumerator> GetEnumerator() => _map.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); [PerformanceSensitive("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1279909", AllowCaptures = false)] - protected TValue GetCounter(TKey key) + protected T GetCounter(object key) => _map.GetOrAdd(key, _createCounter); - protected bool TryGetCounter(TKey key, out TValue counter) + protected bool TryGetCounter(object key, out T counter) { if (_map.TryGetValue(key, out counter)) { @@ -51,4 +85,53 @@ protected bool TryGetCounter(TKey key, out TValue counter) return false; } } + + internal struct StatisticResult + { + /// + /// maximum value + /// + public readonly int Maximum; + + /// + /// minimum value + /// + public readonly int Minimum; + + /// + /// middle value of the total data set + /// + public readonly int? Median; + + /// + /// average value of the total data set + /// + public readonly int Mean; + + /// + /// most frequent value in the total data set + /// + public readonly int? Mode; + + /// + /// difference between max and min value + /// + public readonly int Range; + + /// + /// number of data points in the total data set + /// + public readonly int Count; + + public StatisticResult(int max, int min, int? median, int mean, int range, int? mode, int count) + { + this.Maximum = max; + this.Minimum = min; + this.Median = median; + this.Mean = mean; + this.Range = range; + this.Mode = mode; + this.Count = count; + } + } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/CountLogAggregator.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/LogAggregator.cs similarity index 85% rename from src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/CountLogAggregator.cs rename to src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/LogAggregator.cs index dd948593ad580..96aa557eaf4ff 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/CountLogAggregator.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Log/LogAggregator.cs @@ -8,30 +8,30 @@ namespace Microsoft.CodeAnalysis.Internal.Log { - internal class CountLogAggregator : AbstractLogAggregator.Counter> + internal class LogAggregator : AbstractLogAggregator { protected override Counter CreateCounter() => new(); - public void SetCount(TKey key, int count) + public void SetCount(object key, int count) { var counter = GetCounter(key); counter.SetCount(count); } - public void IncreaseCount(TKey key) + public void IncreaseCount(object key) { var counter = GetCounter(key); counter.IncreaseCount(); } - public void IncreaseCountBy(TKey key, int value) + public void IncreaseCountBy(object key, int value) { var counter = GetCounter(key); counter.IncreaseCountBy(value); } - public int GetCount(TKey key) + public int GetCount(object key) { if (TryGetCounter(key, out var counter)) { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems index 84844e6a3cfe4..19eaa1d335c18 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems @@ -54,7 +54,7 @@ - +