Commit 64078b5b authored by Hirsch Singhal's avatar Hirsch Singhal Committed by GitHub
Browse files

Expose extra ETW Payload in ETW tracing (#220)

* Change ETW datacontract to expose custom payload.
Alters WebSocket parsing routine.

* StyleCop pass
parent 83d12b23
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -64,7 +64,8 @@ namespace Microsoft.Tools.WindowsDevicePortal
        /// <returns>Task tracking completion of the request.</returns>
        public async Task DeleteAppCrashDumpAsync(AppCrashDump crashdump)
        {
            await this.DeleteAsync(CrashDumpFileApi,
            await this.DeleteAsync(
                CrashDumpFileApi,
                string.Format("packageFullName={0}&fileName={1}", crashdump.PackageFullName, crashdump.Filename));
        }

@@ -99,13 +100,13 @@ namespace Microsoft.Tools.WindowsDevicePortal
        public async Task SetAppCrashDumpSettingsAsync(AppPackage app, bool enable = true)
        {
            string pfn = app.PackageFullName;
            await SetAppCrashDumpSettingsAsync(pfn, enable);
            await this.SetAppCrashDumpSettingsAsync(pfn, enable);
        }

        /// <summary>
        /// Set the crash settings for a sideloaded app. 
        /// </summary>
        /// <param name="packageFullname">The app to set crash settings for.</param>
        /// <param name="packageFullName">The app to set crash settings for.</param>
        /// <param name="enable">Whether to enable or disable crash collection for the app. </param>
        /// <returns>Task tracking completion of the request.</returns>
        public async Task SetAppCrashDumpSettingsAsync(string packageFullName, bool enable = true)
@@ -133,7 +134,7 @@ namespace Microsoft.Tools.WindowsDevicePortal
        public class AppCrashDumpSettings
        {
            /// <summary>
            /// Gets whether crash dumps are enabled for the app
            /// Gets a value indicating whether crash dumps are enabled for the app
            /// </summary>
            [DataMember(Name = "CrashDumpEnabled")]
            public bool CrashDumpEnabled
@@ -149,7 +150,6 @@ namespace Microsoft.Tools.WindowsDevicePortal
        [DataContract]
        public class AppCrashDump 
        {

            /// <summary>
            /// Gets the timestamp of the crash as a string.
            /// </summary>
+97 −43
Original line number Diff line number Diff line
@@ -69,13 +69,26 @@ namespace Microsoft.Tools.WindowsDevicePortal
        /// </summary>
        /// <param name="etwProvider">The provider to update the listening state of.</param>
        /// <param name="isEnabled">Determines whether the listening state should be enabled or disabled.</param>
        /// /// <param name="level">Verbosity level - 1 for least, 5 for most verbose. </param>
        /// <returns>Task for toggling the listening state of the specified provider.</returns>
        public async Task ToggleEtwProviderAsync(EtwProviderInfo etwProvider, bool isEnabled = true)
        public async Task ToggleEtwProviderAsync(EtwProviderInfo etwProvider, bool isEnabled = true, int level = 5)
        {
            await this.ToggleEtwProviderAsync(etwProvider.GUID, isEnabled, level);
        }

        /// <summary>
        /// Toggles the listening state of a specific provider on the realtime events WebSocket.
        /// </summary>
        /// <param name="etwProvider">The GUID of the provider to update the listening state of.</param>
        /// <param name="isEnabled">Determines whether the listening state should be enabled or disabled.</param>
        /// <param name="level">Verbosity level - 1 for least, 5 for most verbose. </param>
        /// <returns>Task for toggling the listening state of the specified provider.</returns>
        public async Task ToggleEtwProviderAsync(Guid etwProvider, bool isEnabled = true, int level = 5)
        {
            string action = isEnabled ? "enable" : "disable";
            string message = $"provider {etwProvider.GUID} {action}";
            string message = $"provider {etwProvider} {action} {level}";

            await this.InitializeRealtimeEventsWebSocket();
            await this.InitializeRealtimeEventsWebSocketAsync();
            await this.realtimeEventsWebSocket.SendMessageAsync(message);
        }

@@ -85,7 +98,7 @@ namespace Microsoft.Tools.WindowsDevicePortal
        /// <returns>Task for connecting to the WebSocket but not for listening to it.</returns>
        public async Task StartListeningForEtwEventsAsync()
        {
            await this.InitializeRealtimeEventsWebSocket();
            await this.InitializeRealtimeEventsWebSocketAsync();

            if (!this.isListeningForRealtimeEvents)
            {
@@ -115,7 +128,7 @@ namespace Microsoft.Tools.WindowsDevicePortal
        /// Creates a new <see cref="WebSocket{EtwEvents}"/> if it hasn't already been initialized.
        /// </summary>
        /// <returns>Task for connecting the ETW realtime event WebSocket.</returns>
        private async Task InitializeRealtimeEventsWebSocket()
        private async Task InitializeRealtimeEventsWebSocketAsync()
        {
            if (this.realtimeEventsWebSocket == null)
            {
@@ -155,77 +168,118 @@ namespace Microsoft.Tools.WindowsDevicePortal
        public class EtwEvents
        {
            /// <summary>
            /// Gets the event.
            /// Gets or sets the raw list of events.  Not for straight usage, as it's entirely unformatted. 
            /// </summary>
            [DataMember(Name = "Events")]
            public List<EtwEventInfo> Event { get; private set; }
            private List<Dictionary<string, string>> RawEvents { get; set; }

            /// <summary>
            /// Gets the event frequency.
            /// Saves the downconverted list of events 
            /// </summary>
            [DataMember(Name = "Frequency")]
            public long Frequency { get; private set; }
        }
            private List<EtwEventInfo> stashedList; 

            /// <summary>
        /// ETW Event Info.
            /// Get the list of ETW Events that occured in the last second. 
            /// </summary>
        [DataContract]
        public class EtwEventInfo
            public List<EtwEventInfo> Events
            {
                get
                {
                    if (this.stashedList != null)
                    {
                        return this.stashedList;
                    }

                    List<EtwEventInfo> events = new List<EtwEventInfo>();
                    foreach (Dictionary<string, string> dic in RawEvents )
                    {
                        events.Add(new EtwEventInfo(dic));
                    }

                    this.stashedList = events;
                    return this.stashedList;
                }
            }


            /// <summary>
            /// Gets the event latency.
            /// Gets the event frequency. 
            /// This is always 10 million (10000000) in RS2 devices.  
            /// </summary>
            [DataMember(Name = "EventLatency")]
            public int Latency { get; private set; }
            [DataMember(Name = "Frequency")]
            public long Frequency { get; private set; }
        }

        /// <summary>
            /// Gets the event payload.
        /// ETW Events Info. Allows strongly typed access to guaranteed fields 
        /// like ID or Timestamp, and raw (as string) access to all other 
        /// payload data, like Latency or PID. 
        /// </summary>
            [DataMember(Name = "EventPayload")]
            public string Payload { get; private set; }
        public class EtwEventInfo : Dictionary<string, string>
        {

            /// <summary>
            /// Gets the event persistence.
            ///  Initializes a new instance of the <see cref="EtwEventInfo" /> class.  Used by the DataContract at access time. 
            /// </summary>
            [DataMember(Name = "EventPersistence")]
            public int Persistence { get; private set; }
            /// <param name="dictionary">Base dictionary used to populate the object. </param>
            internal EtwEventInfo(IDictionary<string, string> dictionary) : base(dictionary)
            {
            }

            /// <summary>
            /// Gets the event identifer.
            /// </summary>
            [DataMember(Name = "ID")]
            public ushort ID { get; private set; }
            public ushort ID
            {
                get
                {
                    return ushort.Parse(this["ID"]);
                }
            }

            /// <summary>
            /// Gets the event keyword.
            /// </summary>
            [DataMember(Name = "Keyword")]
            public ulong Keyword { get; private set; }
            public ulong Keyword
            {
                get
                {
                    return ulong.Parse(this["Keyword"]);
                }
            }

            /// <summary>
            /// Gets the event level.
            /// </summary>
            [DataMember(Name = "Level")]
            public uint Level { get; private set; }
            public uint Level
            {
                get
                {
                    return uint.Parse(this["Level"]);
                }
            }

            /// <summary>
            /// Gets the event provider name.
            /// </summary>
            [DataMember(Name = "ProviderName")]
            public string Provider { get; private set; }

            /// <summary>
            /// Gets the event task name.
            /// </summary>
            [DataMember(Name = "TaskName")]
            public string Task { get; private set; }
            public string Provider
            {
                get
                {
                    return this["ProviderName"];
                }
            }

            /// <summary>
            /// Gets the event timestamp. 
            /// </summary>
            [DataMember(Name = "Timestamp")]
            public ulong Timestamp { get; private set; }
            public ulong Timestamp
            {
                get
                {
                    return ulong.Parse(this["Timestamp"]);
                }
            }
        }

        /// <summary>
@@ -251,7 +305,7 @@ namespace Microsoft.Tools.WindowsDevicePortal
            /// Gets provider guid.
            /// </summary>
            [DataMember(Name = "GUID")]
            public string GUID { get; private set; }
            public Guid GUID { get; private set; }

            /// <summary>
            /// Gets provider name.
+7 −1
Original line number Diff line number Diff line
@@ -153,7 +153,13 @@ namespace Microsoft.Tools.WindowsDevicePortal
                {
                    using (stream)
                    {
                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
                        DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings()
                        {
                            UseSimpleDictionaryFormat = true
                        };
                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), settings);
                        

                        T message = (T)serializer.ReadObject(stream);

                        this.WebSocketMessageReceived?.Invoke(