Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 79 additions & 9 deletions src/Compilers/Core/Portable/CodeAnalysisEventSource.Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ internal sealed partial class CodeAnalysisEventSource : EventSource
{
public static class Keywords
{
public const EventKeywords Performance = (EventKeywords)1;
public const EventKeywords Correctness = (EventKeywords)2;
public const EventKeywords Performance = (EventKeywords)0b001;
public const EventKeywords Correctness = (EventKeywords)0b010;
public const EventKeywords AnalyzerLoading = (EventKeywords)0b100;
}

public static class Tasks
Expand Down Expand Up @@ -100,18 +101,87 @@ internal unsafe void NodeTransform(int nodeHashCode, string name, string tableTy
[Event(8, Message = "Server compilation {0} completed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.Compilation)]
internal void StopServerCompilation(string name) => WriteEvent(8, name);

[Event(9, Message = "ALC for directory '{0}' created", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.AnalyzerAssemblyLoader)]
internal void CreateAssemblyLoadContext(string directory) => WriteEvent(9, directory);
[Event(9, Message = "ALC for directory '{0}' created", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.AnalyzerAssemblyLoader)]
internal void CreateAssemblyLoadContext(string directory, string? alc) => WriteEvent(9, directory, alc);

[Event(10, Message = "ALC for directory '{0}' disposed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
internal void DisposeAssemblyLoadContext(string directory) => WriteEvent(10, directory);
[Event(10, Message = "ALC for directory '{0}' disposed", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
internal void DisposeAssemblyLoadContext(string directory, string? alc) => WriteEvent(10, directory, alc);

[Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.Performance, Level = EventLevel.Error, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
internal void DisposeAssemblyLoadContextException(string directory, string errorMessage) => WriteEvent(11, directory, errorMessage);
[Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Error, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
internal void DisposeAssemblyLoadContextException(string directory, string errorMessage, string? alc) => WriteEvent(11, directory, errorMessage, alc);

[Event(12, Message = "CreateNonLockingLoader", Keywords = Keywords.Performance, Level = EventLevel.Informational, Task = Tasks.AnalyzerAssemblyLoader)]
[Event(12, Message = "CreateNonLockingLoader", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational, Task = Tasks.AnalyzerAssemblyLoader)]
internal void CreateNonLockingLoader(string directory) => WriteEvent(12, directory);

[Event(13, Message = "Request add Analyzer reference '{0}' to project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
internal void AnalyzerReferenceRequestAddToProject(string path, string projectName) => WriteEvent(13, path, projectName);

[Event(14, Message = "Analyzer reference '{0}' was added to project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
internal void AnalyzerReferenceAddedToProject(string path, string projectName) => WriteEvent(14, path, projectName);

[Event(15, Message = "Request remove Analyzer reference '{0}' from project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
internal void AnalyzerReferenceRequestRemoveFromProject(string path, string projectName) => WriteEvent(15, path, projectName);

[Event(16, Message = "Analyzer reference '{0}' was removed from project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
internal void AnalyzerReferenceRemovedFromProject(string path, string projectName) => WriteEvent(16, path, projectName);

[Event(17, Message = "Analyzer reference was redirected by '{0}' from '{1}' to '{2}' for project '{3}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Verbose, Task = Tasks.BuildStateTable)]
internal unsafe void AnanlyzerReferenceRedirected(string redirectorType, string originalPath, string newPath, string project)
{
if (IsEnabled())
{
fixed (char* redirectorTypeBytes = redirectorType)
fixed (char* originalPathBytes = originalPath)
fixed (char* newPathBytes = newPath)
fixed (char* projectBytes = project)
{
Span<EventData> data =
[
GetEventDataForString(redirectorType, redirectorTypeBytes),
GetEventDataForString(originalPath, originalPathBytes),
GetEventDataForString(newPath, newPathBytes),
GetEventDataForString(project, projectBytes),
];

fixed (EventData* dataPtr = data)
{
WriteEventCore(eventId: 17, data.Length, dataPtr);
}
}
}
}

[Event(18, Message = "ALC for directory '{0}': Assembly '{1}' was resolved by '{2}' ", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
internal unsafe void ResolvedAssembly(string directory, string assemblyName, string resolver, string filePath, string alc)
{
if (IsEnabled())
{
fixed (char* directoryBytes = directory)
fixed (char* assemblyNameBytes = assemblyName)
fixed (char* resolverBytes = resolver)
fixed (char* filePathBytes = filePath)
fixed (char* alcBytes = alc)
{
Span<EventData> data =
[
GetEventDataForString(directory, directoryBytes),
GetEventDataForString(assemblyName, assemblyNameBytes),
GetEventDataForString(resolver, resolverBytes),
GetEventDataForString(filePath, filePathBytes),
GetEventDataForString(alc, alcBytes),
];

fixed (EventData* dataPtr = data)
{
WriteEventCore(eventId: 18, data.Length, dataPtr);
}
}
}
}

[Event(19, Message = "ALC for directory '{0}': Failed to resolve assembly '{1}' ", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
internal unsafe void ResolveAssemblyFailed(string directory, string assemblyName) => WriteEvent(19, directory, assemblyName);

private static unsafe EventData GetEventDataForString(string value, char* ptr)
{
fixed (char* ptr2 = value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ private partial Assembly Load(AssemblyName assemblyName, string resolvedPath)
{
if (!_loadContextByDirectory.TryGetValue(fullDirectoryPath, out loadContext))
{
CodeAnalysisEventSource.Log.CreateAssemblyLoadContext(fullDirectoryPath);
loadContext = new DirectoryLoadContext(fullDirectoryPath, this);
CodeAnalysisEventSource.Log.CreateAssemblyLoadContext(fullDirectoryPath, loadContext.ToString());
_loadContextByDirectory[fullDirectoryPath] = loadContext;
}
}
Expand Down Expand Up @@ -179,11 +179,11 @@ private partial void DisposeWorker()
try
{
context.Unload();
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory);
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory, context.ToString());
}
catch (Exception ex) when (FatalError.ReportAndCatch(ex, ErrorSeverity.Critical))
{
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContextException(context.Directory, ex.ToString());
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContextException(context.Directory, ex.ToString(), context.ToString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the value of context.ToString() tend to look like?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like "<name>" type #<count>

Our names are empty so you get something like "" Microsoft.CodeAnalysis.AnalyzerAssemblyLoader+DirectoryLoadContext #3"

}
}

Expand All @@ -209,10 +209,12 @@ public DirectoryLoadContext(string directory, AnalyzerAssemblyLoader loader)
var assembly = resolver.Resolve(_loader, assemblyName, this, Directory);
if (assembly is not null)
{
CodeAnalysisEventSource.Log.ResolvedAssembly(Directory, assemblyName.ToString(), resolver.GetType().Name, assembly.Location, GetLoadContext(assembly)!.ToString());
return assembly;
}
}

CodeAnalysisEventSource.Log.ResolveAssemblyFailed(Directory, assemblyName.ToString());
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
namespace Microsoft.CodeAnalysis
{
/// <summary>
/// This interface gives the host the ability to control the actaul path used to load an analyzer into the
/// This interface gives the host the ability to control the actual path used to load an analyzer into the
/// compiler.
///
/// Instances of these types are considered in the order they are added to the <see cref="AnalyzerAssemblyLoader"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,7 @@ private void OnDynamicFileInfoUpdated(object? sender, string dynamicFilePath)
public void AddAnalyzerReference(string fullPath)
{
CompilerPathUtilities.RequireAbsolutePath(fullPath, nameof(fullPath));
CodeAnalysisEventSource.Log.AnalyzerReferenceRequestAddToProject(fullPath, DisplayName);

var mappedPaths = GetMappedAnalyzerPaths(fullPath);

Expand Down Expand Up @@ -1084,6 +1085,7 @@ public void AddAnalyzerReference(string fullPath)
// Are we adding one we just recently removed? If so, we can just keep using that one, and avoid
// removing it once we apply the batch
_projectAnalyzerPaths.Add(mappedFullPath);
CodeAnalysisEventSource.Log.AnalyzerReferenceAddedToProject(mappedFullPath, DisplayName);

if (!_analyzersRemovedInBatch.Remove(mappedFullPath))
_analyzersAddedInBatch.Add(mappedFullPath);
Expand All @@ -1098,6 +1100,8 @@ public void RemoveAnalyzerReference(string fullPath)
if (string.IsNullOrEmpty(fullPath))
throw new ArgumentException("message", nameof(fullPath));

CodeAnalysisEventSource.Log.AnalyzerReferenceRequestRemoveFromProject(fullPath, DisplayName);

var mappedPaths = GetMappedAnalyzerPaths(fullPath);

bool containsSdkCodeStyleAnalyzers;
Expand Down Expand Up @@ -1125,6 +1129,7 @@ public void RemoveAnalyzerReference(string fullPath)
foreach (var mappedFullPath in mappedPaths)
{
_projectAnalyzerPaths.Remove(mappedFullPath);
CodeAnalysisEventSource.Log.AnalyzerReferenceRemovedFromProject(fullPath, DisplayName);

// This analyzer may be one we've just added in the same batch; in that case, just don't add it in
// the first place.
Expand Down Expand Up @@ -1175,6 +1180,7 @@ private OneOrMany<string> GetMappedAnalyzerPaths(string fullPath)
if (redirectedPath == null)
{
redirectedPath = currentlyRedirectedPath;
CodeAnalysisEventSource.Log.AnanlyzerReferenceRedirected(redirector.GetType().Name, fullPath, redirectedPath, DisplayName);
}
else if (redirectedPath != currentlyRedirectedPath)
{
Expand Down