|
// 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);
}
}
}
|