File: Telemetry\CodeMarkerLogger.cs
Web Access
Project: src\src\VisualStudio\Core\Def\Microsoft.VisualStudio.LanguageServices_rmjjt0xj_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices)
// 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;
using System.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.Internal.Performance;
using CodeMarkerId = System.Int32;
 
namespace Microsoft.VisualStudio.LanguageServices.Telemetry;
 
internal sealed class CodeMarkerLogger : ILogger
{
    public static readonly CodeMarkerLogger Instance = new CodeMarkerLogger();
 
    private static readonly Dictionary<FunctionId, List<Tuple<CodeMarkerId, CodeMarkerId>>> s_blockMap
        = new Dictionary<FunctionId, List<Tuple<CodeMarkerId, CodeMarkerId>>>()
        {
            { FunctionId.NavigateTo_Search, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpNavigateToStartSearch, CodeMarkerEvent.perfVSCSharpNavigateToEndSearch),
                    Tuple.Create(CodeMarkerEvent.perfVBNavigateToStartSearch, CodeMarkerEvent.perfVBNavigateToEndSearch),
                }
            },
            { FunctionId.Rename_InlineSession, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpRenameStart, CodeMarkerEvent.perfVSCSharpRenameEnd)
                }
            },
            { FunctionId.Rename_FindLinkedSpans, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpRenameFindDefinitionStart, CodeMarkerEvent.perfVSCSharpRenameFindDefinitionEnd)
                }
            },
            { FunctionId.WinformDesigner_GenerateXML, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpGetXmlStart, CodeMarkerEvent.perfVSCSharpGetXmlEnd)
                }
            },
            { FunctionId.BackgroundCompiler_BuildCompilationsAsync, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpBatchedRequestsAdded, CodeMarkerEvent.perfVSCSharpBatchedRequestsCompleted),
                    Tuple.Create(CodeMarkerEvent.perfVBCompilerBackgroundThreadStart, CodeMarkerEvent.perfVBCompilerBackgroundThreadStop),
                }
            },
            { FunctionId.FindReference, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpFindAllReferencesStart, CodeMarkerEvent.perfVSCSharpFindAllReferencesEnd)
                }
            },
            { FunctionId.SmartTags_SmartTagInitializeFixes, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVBSmartTagInitializeFixesBegin, CodeMarkerEvent.perfVBSmartTagInitializeFixesEnd)
                }
            },
            { FunctionId.SmartTags_ApplyQuickFix, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVBApplyQuickFixBegin, CodeMarkerEvent.perfVBApplyQuickFixEnd),
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpGenerateTypeNoUIStart, CodeMarkerEvent.perfVSCSharpGenerateTypeNoUIEnd)
                }
            },
            { FunctionId.LineCommit_CommitRegion, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVBCompilerPrettyListBegin, CodeMarkerEvent.perfVBCompilerPrettyListEnd)
                }
            },
            { FunctionId.Tagger_Outlining_TagProducer_ProduceTags, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVBCompilerStartOutliningBegin, CodeMarkerEvent.perfVBCompilerStartOutliningEnd)
                }
            },
            { FunctionId.Tagger_LineSeparator_TagProducer_ProduceTags, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVBCompilerUpdateLineSeparatorsBegin, CodeMarkerEvent.perfVBCompilerUpdateLineSeparatorsEnd)
                }
            },
            { FunctionId.NavigationBar_ComputeModelAsync, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVBCompilerDropDownLoadBegin, CodeMarkerEvent.perfVBCompilerDropDownLoadEnd)
                }
            },
            { FunctionId.Completion_ModelComputer_DoInBackground, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpCompletionListStart, CodeMarkerEvent.perfVSCSharpCompletionListEnd),
                    Tuple.Create(CodeMarkerEvent.perfVBCompilerIntellisenseBegin, CodeMarkerEvent.perfVBCompilerIntellisenseEnd)
                }
            },
            { FunctionId.SignatureHelp_ModelComputation_UpdateModelInBackground, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpParamHelpStart, CodeMarkerEvent.perfVSCSharpParamHelpEnd)
                }
            },
            { FunctionId.Formatting_Format, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpFormatStart, CodeMarkerEvent.perfVSCSharpFormatEnd)
                }
            },
            { FunctionId.Formatting_ApplyResultToBuffer, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpCommitStart, CodeMarkerEvent.perfVSCSharpCommitEnd)
                }
            },
            { FunctionId.SmartTags_RefreshSession, new List<Tuple<CodeMarkerId, CodeMarkerId>>()
                {
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpIdleSynchronizeInstantaneousSmartTagsStart, CodeMarkerEvent.perfVSCSharpIdleSynchronizeInstantaneousSmartTagsEnd),
                    Tuple.Create(CodeMarkerEvent.perfVSCSharpIdleSynchronizeDelaySmartTagsStart, CodeMarkerEvent.perfVSCSharpIdleSynchronizeDelaySmartTagsEnd)
                }
            }
        };
 
    private static readonly Dictionary<FunctionId, List<CodeMarkerId>> s_map
        = new Dictionary<FunctionId, List<CodeMarkerId>>()
        {
            { FunctionId.Rename_InlineSession, new List<CodeMarkerId>() { CodeMarkerEvent.perfVBRenameSymbolEnd } },
            { FunctionId.BackgroundCompiler_BuildCompilationsAsync, new List<CodeMarkerId>() { CodeMarkerEvent.perfVBCompilerReachedBoundState, CodeMarkerEvent.perfVBCompilerReachedCompiledState } },
            { FunctionId.Completion_ModelComputer_DoInBackground, new List<CodeMarkerId>() { CodeMarkerEvent.perfVBIntelliXMLIndexingEnd } },
            { FunctionId.WorkCoordinator_AsyncWorkItemQueue_FirstItem, new List<CodeMarkerId>() { CodeMarkerEvent.perfVBCompilerRegisterDesignViewAttributeBegin, CodeMarkerEvent.perfVBCompilerCommitBegin } },
            { FunctionId.WorkCoordinator_AsyncWorkItemQueue_LastItem, new List<CodeMarkerId>() { CodeMarkerEvent.perfVBCompilerRegisterDesignViewAttributeEnd, CodeMarkerEvent.perfVBCompilerCommitEnd } },
            { FunctionId.Snippet_OnAfterInsertion, new List<CodeMarkerId>() { CodeMarkerEvent.perfVBInsertSnippetEnd } }
        };
 
    private static readonly Func<CodeMarkerId, CodeMarkerId> s_getter = i => i;
    private static Func<Tuple<CodeMarkerId, CodeMarkerId>, CodeMarkerId> s_startGetter => t => t.Item1;
    private static Func<Tuple<CodeMarkerId, CodeMarkerId>, CodeMarkerId> s_endGetter => t => t.Item2;
 
    private CodeMarkerLogger()
    {
    }
 
    public bool IsEnabled(FunctionId functionId)
        => Microsoft.Internal.Performance.CodeMarkers.Instance.IsEnabled && CanHandle(functionId);
 
    public void Log(FunctionId functionId, LogMessage logMessage)
        => FireCodeMarkers(s_map, functionId, s_getter);
 
    public void LogBlockStart(FunctionId functionId, LogMessage logMessage, int uniquePairId, CancellationToken cancellationToken)
        => FireCodeMarkers(s_blockMap, functionId, s_startGetter);
 
    public void LogBlockEnd(FunctionId functionId, LogMessage logMessage, int uniquePairId, int delta, CancellationToken cancellationToken)
    {
        FireCodeMarkers(s_map, functionId, s_getter);
        FireCodeMarkers(s_blockMap, functionId, s_endGetter);
    }
 
    private static bool CanHandle(FunctionId functionId)
        => s_map.ContainsKey(functionId) || s_blockMap.ContainsKey(functionId);
 
    private static void FireCodeMarkers<T>(Dictionary<FunctionId, List<T>> map, FunctionId functionId, Func<T, int> getter)
    {
        if (!map.TryGetValue(functionId, out var items))
        {
            return;
        }
 
        for (var i = 0; i < items.Count; i++)
        {
            var marker = getter(items[i]);
            Microsoft.Internal.Performance.CodeMarkers.Instance.CodeMarker(marker);
        }
    }
}