diff --git a/DllImportGenerator/DllImportGenerator/Diagnostics/Events.cs b/DllImportGenerator/DllImportGenerator/Diagnostics/Events.cs
new file mode 100644
index 000000000000..ef78d0bc86b4
--- /dev/null
+++ b/DllImportGenerator/DllImportGenerator/Diagnostics/Events.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Diagnostics.Tracing;
+
+namespace Microsoft.Interop.Diagnostics
+{
+ [EventSource(Name = "Microsoft-Interop-SourceGeneration-Events")]
+ internal sealed class Events : EventSource
+ {
+ public static class Keywords
+ {
+ public const EventKeywords SourceGeneration = (EventKeywords)1;
+ }
+
+ public static readonly Events Logger = new Events();
+
+ private const int StartSourceGenerationEventId = 1;
+ private const int StopSourceGenerationEventId = StartSourceGenerationEventId + 1;
+
+ private Events()
+ { }
+
+ ///
+ /// Utility function that wraps emitting start/stop events for the source generation event.
+ ///
+ /// The number of methods being generated
+ /// An instance that will fire the "stop" event when Disposed.
+ [NonEvent]
+ public static IDisposable SourceGenerationStartStop(int methodCount)
+ {
+ return new StartStopEvent(methodCount);
+ }
+
+ // N.B. The 'Start' and 'Stop' suffixes for event names (i.e. "xxxStart" and "xxxStop")
+ // have special meaning in EventSource. They enable creating 'activities' if they are
+ // paired and the Stop event's ID is +1 the Start event's ID.
+ // See https://blogs.msdn.microsoft.com/vancem/2015/09/14/exploring-eventsource-activity-correlation-and-causation-features/
+
+ ///
+ /// Indicates the interop's DllImport Roslyn Source Generator has started source generation.
+ ///
+ /// The number of methods being generated
+ [Event(StartSourceGenerationEventId, Level = EventLevel.Informational, Keywords = Keywords.SourceGeneration)]
+ public void SourceGenerationStart(int methodCount)
+ {
+ this.WriteEvent(StartSourceGenerationEventId, methodCount);
+ }
+
+ ///
+ /// Indicates the interop's DllImport Roslyn Source Generator has stopped source generation.
+ ///
+ [Event(StopSourceGenerationEventId, Level = EventLevel.Informational, Keywords = Keywords.SourceGeneration)]
+ public void SourceGenerationStop()
+ {
+ this.WriteEvent(StopSourceGenerationEventId);
+ }
+
+ private class StartStopEvent : IDisposable
+ {
+ public StartStopEvent(int methodCount) => Logger.SourceGenerationStart(methodCount);
+ public void Dispose() => Logger.SourceGenerationStop();
+ }
+ }
+}
diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs b/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs
index 1b4588f3fc05..141ff64b409b 100644
--- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs
+++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs
@@ -28,6 +28,9 @@ public void Execute(GeneratorExecutionContext context)
return;
}
+ // Fire the start/stop pair for source generation
+ using var _ = Diagnostics.Events.SourceGenerationStartStop(synRec.Methods.Count);
+
// Store a mapping between SyntaxTree and SemanticModel.
// SemanticModels cache results and since we could be looking at
// method declarations in the same SyntaxTree we want to benefit from