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