diff --git a/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs new file mode 100644 index 0000000000000..253e1dc07c4a9 --- /dev/null +++ b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginLogger.cs @@ -0,0 +1,46 @@ +// 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 Microsoft.CodeAnalysis.Internal.Log; + +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 enum ActionInfo + { + GetInheritanceMarginMembers, + } + + public static void LogGenerateBackgroundInheritanceInfo(TimeSpan elapsedTime) + => s_histogramLogAggregator.IncreaseCount( + ActionInfo.GetInheritanceMarginMembers, Convert.ToDecimal(elapsedTime.TotalMilliseconds)); + + public static void LogInheritanceTargetsMenuOpen() + => Logger.Log(FunctionId.InheritanceMargin_TargetsMenuOpen, KeyValueLogMessage.Create(LogType.UserAction)); + + public static void LogNavigateToTarget() + => Logger.Log(FunctionId.InheritanceMargin_NavigateToTarget, KeyValueLogMessage.Create(LogType.UserAction)); + + public static void ReportTelemetry() + { + Logger.Log(FunctionId.InheritanceMargin_GetInheritanceMemberItems, + KeyValueLogMessage.Create( + m => + { + var histogramLogAggragator = s_histogramLogAggregator.GetValue(ActionInfo.GetInheritanceMarginMembers); + if (histogramLogAggragator != null) + { + m[$"{ActionInfo.GetInheritanceMarginMembers}.BucketSize"] = histogramLogAggragator.BucketSize; + m[$"{ActionInfo.GetInheritanceMarginMembers}.BucketCount"] = histogramLogAggragator.BucketCount; + m[$"{ActionInfo.GetInheritanceMarginMembers}.Bucket"] = histogramLogAggragator.GetBucketsAsString(); + } + })); + } + } +} diff --git a/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginTaggerProvider.cs b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginTaggerProvider.cs index 6aef7dbc06c96..4ff5dade292f2 100644 --- a/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginTaggerProvider.cs +++ b/src/VisualStudio/Core/Def/InheritanceMargin/InheritanceMarginTaggerProvider.cs @@ -10,7 +10,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor; -using Microsoft.CodeAnalysis.Editor.Implementation.Classification; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; using Microsoft.CodeAnalysis.Editor.Shared.Tagging; @@ -18,10 +17,10 @@ using Microsoft.CodeAnalysis.Editor.Tagging; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.InheritanceMargin; -using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; +using Microsoft.VisualStudio.LanguageServices.InheritanceMargin; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Tagging; @@ -105,20 +104,21 @@ protected override async Task ProduceTagsAsync( return; } - var inheritanceMemberItems = ImmutableArray.Empty; - using (Logger.LogBlock(FunctionId.InheritanceMargin_GetInheritanceMemberItems, cancellationToken, LogLevel.Information)) - { - inheritanceMemberItems = await inheritanceMarginInfoService.GetInheritanceMemberItemsAsync( - document, - spanToTag.SnapshotSpan.Span.ToTextSpan(), - cancellationToken).ConfigureAwait(false); - } + var spanToSearch = spanToTag.SnapshotSpan.Span.ToTextSpan(); + var stopwatch = SharedStopwatch.StartNew(); + var inheritanceMemberItems = await inheritanceMarginInfoService.GetInheritanceMemberItemsAsync( + document, + spanToSearch, + cancellationToken).ConfigureAwait(false); + var elapsed = stopwatch.Elapsed; if (inheritanceMemberItems.IsEmpty) { return; } + InheritanceMarginLogger.LogGenerateBackgroundInheritanceInfo(elapsed); + // One line might have multiple members to show, so group them. // For example: // interface IBar { void Foo1(); void Foo2(); } diff --git a/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginContextMenu.xaml.cs b/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginContextMenu.xaml.cs index 1ea77074d85b6..94bb125878b0b 100644 --- a/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginContextMenu.xaml.cs +++ b/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginContextMenu.xaml.cs @@ -8,13 +8,11 @@ using System.Windows; using System.Windows.Controls; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editor; using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.FindUsages; -using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.TestHooks; -using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.LanguageServices.InheritanceMargin; using Microsoft.VisualStudio.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.InheritanceMargin.MarginGlyph @@ -49,7 +47,7 @@ private void TargetMenuItem_OnClick(object sender, RoutedEventArgs e) { if (e.OriginalSource is MenuItem { DataContext: TargetMenuItemViewModel viewModel }) { - Logger.Log(FunctionId.InheritanceMargin_NavigateToTarget, KeyValueLogMessage.Create(LogType.UserAction)); + InheritanceMarginLogger.LogNavigateToTarget(); var token = _listener.BeginAsyncOperation(nameof(TargetMenuItem_OnClick)); TargetMenuItem_OnClickAsync(viewModel).CompletesAsyncOperation(token); @@ -79,7 +77,7 @@ private async Task TargetMenuItem_OnClickAsync(TargetMenuItemViewModel viewModel private void TargetsSubmenu_OnOpen(object sender, RoutedEventArgs e) { - Logger.Log(FunctionId.InheritanceMargin_TargetsMenuOpen, KeyValueLogMessage.Create(LogType.UserAction)); + InheritanceMarginLogger.LogInheritanceTargetsMenuOpen(); } } } diff --git a/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginGlyph.cs b/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginGlyph.cs index 6e511c8d749a6..9f3adb12ca9d4 100644 --- a/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginGlyph.cs +++ b/src/VisualStudio/Core/Def/InheritanceMargin/MarginGlyph/InheritanceMarginGlyph.cs @@ -11,9 +11,9 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Host; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.LanguageServices.InheritanceMargin; using Microsoft.VisualStudio.PlatformUI; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Text.Classification; @@ -179,7 +179,7 @@ private void ContextMenu_OnOpen(object sender, RoutedEventArgs e) // -> Target4 // If the first level of the context menu contains a TargetMenuItemViewModel, it means here it is case 1, // user is viewing the targets menu. - Logger.Log(FunctionId.InheritanceMargin_TargetsMenuOpen, KeyValueLogMessage.Create(LogType.UserAction)); + InheritanceMarginLogger.LogInheritanceTargetsMenuOpen(); } } diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index ccead2d180960..6c26cdd5ed64d 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -32,6 +32,7 @@ using Microsoft.VisualStudio.LanguageServices.Implementation.SyncNamespaces; using Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource; using Microsoft.VisualStudio.LanguageServices.Implementation.UnusedReferences; +using Microsoft.VisualStudio.LanguageServices.InheritanceMargin; using Microsoft.VisualStudio.LanguageServices.StackTraceExplorer; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -316,6 +317,7 @@ private static void ReportSessionWideTelemetry() AsyncCompletionLogger.ReportTelemetry(); CompletionProvidersLogger.ReportTelemetry(); ChangeSignatureLogger.ReportTelemetry(); + InheritanceMarginLogger.ReportTelemetry(); } private void DisposeVisualStudioServices()