Skip to content

Commit 540285c

Browse files
chsienkiJoeRobich
andauthored
Add more ETW events to trace assembly loading (#78840)
* Add more ETW events to trace assembly loading * Update src/Compilers/Core/Portable/CodeAnalysisEventSource.Common.cs Co-authored-by: Joey Robichaud <[email protected]> * Put correct alc reference * Use binary literals --------- Co-authored-by: Joey Robichaud <[email protected]>
1 parent 5d591c0 commit 540285c

File tree

4 files changed

+91
-13
lines changed

4 files changed

+91
-13
lines changed

src/Compilers/Core/Portable/CodeAnalysisEventSource.Common.cs

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ internal sealed partial class CodeAnalysisEventSource : EventSource
1111
{
1212
public static class Keywords
1313
{
14-
public const EventKeywords Performance = (EventKeywords)1;
15-
public const EventKeywords Correctness = (EventKeywords)2;
14+
public const EventKeywords Performance = (EventKeywords)0b001;
15+
public const EventKeywords Correctness = (EventKeywords)0b010;
16+
public const EventKeywords AnalyzerLoading = (EventKeywords)0b100;
1617
}
1718

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

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

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

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

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

116+
[Event(13, Message = "Request add Analyzer reference '{0}' to project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
117+
internal void AnalyzerReferenceRequestAddToProject(string path, string projectName) => WriteEvent(13, path, projectName);
118+
119+
[Event(14, Message = "Analyzer reference '{0}' was added to project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
120+
internal void AnalyzerReferenceAddedToProject(string path, string projectName) => WriteEvent(14, path, projectName);
121+
122+
[Event(15, Message = "Request remove Analyzer reference '{0}' from project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
123+
internal void AnalyzerReferenceRequestRemoveFromProject(string path, string projectName) => WriteEvent(15, path, projectName);
124+
125+
[Event(16, Message = "Analyzer reference '{0}' was removed from project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
126+
internal void AnalyzerReferenceRemovedFromProject(string path, string projectName) => WriteEvent(16, path, projectName);
127+
128+
[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)]
129+
internal unsafe void AnanlyzerReferenceRedirected(string redirectorType, string originalPath, string newPath, string project)
130+
{
131+
if (IsEnabled())
132+
{
133+
fixed (char* redirectorTypeBytes = redirectorType)
134+
fixed (char* originalPathBytes = originalPath)
135+
fixed (char* newPathBytes = newPath)
136+
fixed (char* projectBytes = project)
137+
{
138+
Span<EventData> data =
139+
[
140+
GetEventDataForString(redirectorType, redirectorTypeBytes),
141+
GetEventDataForString(originalPath, originalPathBytes),
142+
GetEventDataForString(newPath, newPathBytes),
143+
GetEventDataForString(project, projectBytes),
144+
];
145+
146+
fixed (EventData* dataPtr = data)
147+
{
148+
WriteEventCore(eventId: 17, data.Length, dataPtr);
149+
}
150+
}
151+
}
152+
}
153+
154+
[Event(18, Message = "ALC for directory '{0}': Assembly '{1}' was resolved by '{2}' ", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
155+
internal unsafe void ResolvedAssembly(string directory, string assemblyName, string resolver, string filePath, string alc)
156+
{
157+
if (IsEnabled())
158+
{
159+
fixed (char* directoryBytes = directory)
160+
fixed (char* assemblyNameBytes = assemblyName)
161+
fixed (char* resolverBytes = resolver)
162+
fixed (char* filePathBytes = filePath)
163+
fixed (char* alcBytes = alc)
164+
{
165+
Span<EventData> data =
166+
[
167+
GetEventDataForString(directory, directoryBytes),
168+
GetEventDataForString(assemblyName, assemblyNameBytes),
169+
GetEventDataForString(resolver, resolverBytes),
170+
GetEventDataForString(filePath, filePathBytes),
171+
GetEventDataForString(alc, alcBytes),
172+
];
173+
174+
fixed (EventData* dataPtr = data)
175+
{
176+
WriteEventCore(eventId: 18, data.Length, dataPtr);
177+
}
178+
}
179+
}
180+
}
181+
182+
[Event(19, Message = "ALC for directory '{0}': Failed to resolve assembly '{1}' ", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
183+
internal unsafe void ResolveAssemblyFailed(string directory, string assemblyName) => WriteEvent(19, directory, assemblyName);
184+
115185
private static unsafe EventData GetEventDataForString(string value, char* ptr)
116186
{
117187
fixed (char* ptr2 = value)

src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ private partial Assembly Load(AssemblyName assemblyName, string resolvedPath)
8787
{
8888
if (!_loadContextByDirectory.TryGetValue(fullDirectoryPath, out loadContext))
8989
{
90-
CodeAnalysisEventSource.Log.CreateAssemblyLoadContext(fullDirectoryPath);
9190
loadContext = new DirectoryLoadContext(fullDirectoryPath, this);
91+
CodeAnalysisEventSource.Log.CreateAssemblyLoadContext(fullDirectoryPath, loadContext.ToString());
9292
_loadContextByDirectory[fullDirectoryPath] = loadContext;
9393
}
9494
}
@@ -179,11 +179,11 @@ private partial void DisposeWorker()
179179
try
180180
{
181181
context.Unload();
182-
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory);
182+
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory, context.ToString());
183183
}
184184
catch (Exception ex) when (FatalError.ReportAndCatch(ex, ErrorSeverity.Critical))
185185
{
186-
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContextException(context.Directory, ex.ToString());
186+
CodeAnalysisEventSource.Log.DisposeAssemblyLoadContextException(context.Directory, ex.ToString(), context.ToString());
187187
}
188188
}
189189

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

217+
CodeAnalysisEventSource.Log.ResolveAssemblyFailed(Directory, assemblyName.ToString());
216218
return null;
217219
}
218220

src/Compilers/Core/Portable/DiagnosticAnalyzer/IAnalyzerPathResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
namespace Microsoft.CodeAnalysis
1717
{
1818
/// <summary>
19-
/// This interface gives the host the ability to control the actaul path used to load an analyzer into the
19+
/// This interface gives the host the ability to control the actual path used to load an analyzer into the
2020
/// compiler.
2121
///
2222
/// Instances of these types are considered in the order they are added to the <see cref="AnalyzerAssemblyLoader"/>.

src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProject.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,7 @@ private void OnDynamicFileInfoUpdated(object? sender, string dynamicFilePath)
10541054
public void AddAnalyzerReference(string fullPath)
10551055
{
10561056
CompilerPathUtilities.RequireAbsolutePath(fullPath, nameof(fullPath));
1057+
CodeAnalysisEventSource.Log.AnalyzerReferenceRequestAddToProject(fullPath, DisplayName);
10571058

10581059
var mappedPaths = GetMappedAnalyzerPaths(fullPath);
10591060

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

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

1103+
CodeAnalysisEventSource.Log.AnalyzerReferenceRequestRemoveFromProject(fullPath, DisplayName);
1104+
11011105
var mappedPaths = GetMappedAnalyzerPaths(fullPath);
11021106

11031107
bool containsSdkCodeStyleAnalyzers;
@@ -1125,6 +1129,7 @@ public void RemoveAnalyzerReference(string fullPath)
11251129
foreach (var mappedFullPath in mappedPaths)
11261130
{
11271131
_projectAnalyzerPaths.Remove(mappedFullPath);
1132+
CodeAnalysisEventSource.Log.AnalyzerReferenceRemovedFromProject(fullPath, DisplayName);
11281133

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

0 commit comments

Comments
 (0)