add profiler attach message
authorDavid Mason <davmason@microsoft.com>
Thu, 16 May 2019 22:12:40 +0000 (15:12 -0700)
committerDavid Mason <davmason@microsoft.com>
Sat, 18 May 2019 10:08:45 +0000 (03:08 -0700)
src/Microsoft.Diagnostics.Tools.RuntimeClient/DiagnosticHelpers.cs
src/Microsoft.Diagnostics.Tools.RuntimeClient/Eventing/DiagnosticMessageType.cs

index 1ebaeeea669ce181faf3bfd84f4e1e2d126adcca..101696f28e43c7d0aa0e56dc7e135e5c93e575f7 100644 (file)
@@ -45,12 +45,78 @@ namespace Microsoft.Diagnostics.Tools.RuntimeClient
 
             byte[] serializedConfiguration;
             using (var stream = new MemoryStream())
-                serializedConfiguration = Serialize(header, stream, dumpName, dumpType, diagnostics);
+                serializedConfiguration = SerializeCoreDump(header, stream, dumpName, dumpType, diagnostics);
 
             return (int)EventPipeClient.SendCommand(processId, serializedConfiguration);
         }
 
-        private static byte[] Serialize(MessageHeader header, Stream stream, string dumpName, DumpType dumpType, bool diagnostics)
+        /// <summary>
+        /// Attach a profiler to the target process runtime.
+        /// </summary>
+        /// <param name="processId">.NET Core process id</param>
+        /// <param name="attachTimeout">The timeout (in ms) to wait while attempting to attach.</param>
+        /// <param name="profilerGuid">CLSID of the profiler to load</param>
+        /// <param name="profilerPath">Path to the profiler library on disk</param>
+        /// <param name="additionalData">additional data to pass to the profiler on attach</param>
+        /// <returns>HRESULT</returns>
+        public static int AttachProfiler(int processId, uint attachTimeout, Guid profilerGuid, string profilerPath, byte[] additionalData)
+        {
+            if (profilerGuid == null || profilerGuid == Guid.Empty)
+            {
+                throw new ArgumentException($"{nameof(profilerGuid)} must be a valid Guid");
+            }
+
+            if (String.IsNullOrEmpty(profilerPath))
+            {
+                throw new ArgumentException($"{nameof(profilerPath)} must be non-null");
+            }
+
+            var header = new MessageHeader {
+                RequestType = DiagnosticMessageType.AttachProfiler,
+                Pid = (uint)Process.GetCurrentProcess().Id,
+            };
+
+            byte[] serializedConfiguration;
+            using (var stream = new MemoryStream())
+            {
+                serializedConfiguration = SerializeProfilerAttach(header, stream, attachTimeout, profilerGuid, profilerPath, additionalData);
+            }
+
+            return (int)EventPipeClient.SendCommand(processId, serializedConfiguration);
+
+        }
+
+        private static byte[] SerializeProfilerAttach(MessageHeader header, MemoryStream stream, uint attachTimeout, Guid profilerGuid, string profilerPath, byte[] additionalData)
+        {
+            using (var bw = new BinaryWriter(stream))
+            {
+                bw.Write((uint)header.RequestType);
+                bw.Write(header.Pid);
+
+                bw.Write(attachTimeout);
+                bw.Write(profilerGuid.ToByteArray());
+                bw.WriteString(profilerPath);
+
+                if (additionalData == null)
+                {
+                    bw.Write(0);
+                }
+                else
+                {
+                    bw.Write(additionalData.Length);
+                    bw.Write(additionalData);
+                }
+
+                bw.Flush();
+                stream.Position = 0;
+
+                var bytes = new byte[stream.Length];
+                stream.Read(bytes, 0, bytes.Length);
+                return bytes;
+            }
+        }
+
+        private static byte[] SerializeCoreDump(MessageHeader header, Stream stream, string dumpName, DumpType dumpType, bool diagnostics)
         {
             using (var bw = new BinaryWriter(stream))
             {
index 8693f5e690e0db37de5338540e4d114b7fabf6ed..2bce8154b71e6d25292097ff4c7abf90bfd487d2 100644 (file)
@@ -14,6 +14,10 @@ namespace Microsoft.Diagnostics.Tools.RuntimeClient
         /// </summary>
         GenerateCoreDump = 1,
         /// <summary>
+        /// Attaches a profiler to an existing process
+        /// </summary>
+        AttachProfiler,
+        /// <summary>
         /// Starts an EventPipe session that writes events to a file when the session is stopped or the application exits.
         /// </summary>
         StartEventPipeTracing = 1024,