Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
PSTelemetryWrapper.cs151 linesDownload Raw Back to utils
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#if LEGACYTELEMETRY5 6using System.Reflection;7using System.Diagnostics.Tracing;8 9namespace System.Management.Automation.Internal10{11    /// <summary>12    /// This wrapper is for encapsulating all the internal details of Asimov-compatible telemetry in Windows Threshold.13    /// </summary>14    internal static class TelemetryWrapper15    {16        private static readonly PSObject s_eventSourceInstance;17        private static readonly object s_eventSourceOptionsForWrite;18 19        /// <summary>20        /// Performing EventSource initialization in the Static Constructor since this is thread safe.21        /// Static constructors are guaranteed to be run only once per application domain, before any instances of a class are created or any static members are accessed.22        /// https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/static-constructors.23        /// </summary>24        static TelemetryWrapper()25        {26            try27            {28                // We build against CLR4.5 so we can run on Win7/Win8, but we want to use apis added to CLR 4.6.29                // So we use reflection, and if that fails, we just silently skip logging our telemetry.30 31                var diagnosticsTracingAssembly = typeof(EventSource).Assembly;32 33                Type eventSourceSettingsType = diagnosticsTracingAssembly.GetType("System.Diagnostics.Tracing.EventSourceSettings");34                if (eventSourceSettingsType == null)35                {36                    // Probably on CLR 4.5.37                    return;38                }39 40                // Beyond here, we skip the null checks because we're pretty sure we have CLR 4.6 and everything41                // should work, but if it doesn't, we're still safe because of the catch.42 43                // Get the enum EventSourceSettings.EtwSelfDescribingEventFormat, but skip reflection to get the integer44                // value, that can't change.45                const int EtwSelfDescribingEventFormat = 8;46                var eventSourceSettingsEnumObject = Enum.ToObject(eventSourceSettingsType, EtwSelfDescribingEventFormat);47 48                // Create instance of the class EventSource with Provider name of "Microsoft-PowerShell-Telemetry"49                // Supply this eventSourceTrait to EventSource constructor to enable Asimov type events50                var eventSource = (EventSource)Activator.CreateInstance(typeof(EventSource),51                    new object[] {"Microsoft-PowerShell-Telemetry",52                                  eventSourceSettingsEnumObject,53                                  new[] { "ETW_GROUP", "{4f50731a-89cf-4782-b3e0-dce8c90476ba}" }});54 55                // Wrap in PSObject so we can invoke a method dynamically using our binder (the C# dynamic binder fails for some reason.)56                s_eventSourceInstance = new PSObject(eventSource);57 58                // Initialize EventSourceOptions for Writing informational messages59                // WdiContext will ensure Universal Telemetry Client [UTC] will upload telemetry messages to Cosmos/xPert pipeline60 61                // MeasuresKeyword is to indicate that event is for understanding measures and reporting scenarios.62                // This keyword results in the generation of Asimov compatible events for telemetry63                // Refer ~\minkernel\published\internal\telemetry\MicrosoftTelemetry.h64                const Int64 measuresKeyword = 0x0000400000000000;65 66                // Create Instance of EventSourceOptions struct67                Type eventSourceOptionsType = diagnosticsTracingAssembly.GetType("System.Diagnostics.Tracing.EventSourceOptions");68                s_eventSourceOptionsForWrite = Activator.CreateInstance(eventSourceOptionsType, null);69 70                // Set the Level and Keywords properties71                eventSourceOptionsType.GetProperty("Level").SetValue(s_eventSourceOptionsForWrite, EventLevel.Informational, null);72                eventSourceOptionsType.GetProperty("Keywords").SetValue(s_eventSourceOptionsForWrite, measuresKeyword, null);73            }74            catch75            {76                // If there are any exceptions, just disable tracing completely by making sure these are both null77                s_eventSourceInstance = null;78                s_eventSourceOptionsForWrite = null;79            }80        }81 82        internal static bool IsEnabled83        {84            get { return s_eventSourceInstance != null && ((EventSource)s_eventSourceInstance.BaseObject).IsEnabled(); }85        }86 87        /// <summary>88        /// TRACEMESSAGE is the Generic method to use to log messages using UTC [Universal Telemetry Client] in Windows Threshold89        /// TRACEMESSAGE calls into EventSource.Write dynamically - https://msdn.microsoft.com/library/dn823293(v=vs.110).aspx.90        /// </summary>91 92        // EventSource data gets raised on the Client containing OS Environment information and supplied arguments as "data"93        // Events are queued and uploaded to Cosmos/xPert.94        // Format of data generated on the Client:95        // {96        //    "ver": "2.1",97        //    "name": "Microsoft.Windows.PowerShell.CONSOLEHOST_START",98        //    "time": "2015-03-06T20:41:46.6967701Z",99        //    "popSample": 100.000000,100        //    "epoch": "5",101        //    "seqNum": 82463,102        //    "flags": 257,103        //    "os": "Windows",104        //    "osVer": "10.0.10031.0.amd64fre.winmain.150227-1817",105        //    "appId": "W:0000f519feec486de87ed73cb92d3cac802400000000!0000aec24258aebc46e867b932f05b64f025f8a07965!powershell.exe",106        //    "appVer": "2015/02/28:04:23:34!80bc5!powershell.exe",107        //    "ext": {108        //        "device": {109        //            "localId": "s:F4FDD2F5-88CD-444A-B815-19D530BF81E7",110        //            "deviceClass": "Windows.Server"111        //        },112        //        "user": {113        //            "localId": "w:72CEA7E7-5A30-ACFF-DD99-002A4B24DDDA"114        //        },115        //        "utc": {116        //            "stId": "8BA1217F-5700-4034-A79B-9AEAD39AE0BF",117        //            "aId": "C63E5819-5520-0000-4D0C-6DC62055D001",118        //            "cat": 562949953421312,119        //            "flags": 0120        //        }121        //    },122        //    "data": {123        //        "PSVersion": "5.0"124        //    }125        // }126 127        public static void TraceMessage<T>(string message, T arguments)128        {129            if (s_eventSourceOptionsForWrite != null)130            {131                try132                {133                    // EventSourceInstance is cast to dynamic so we can call a generic method added in CLR 4.6.134                    // We use dynamic to get the benefits of call site caching (we can avoid looking up the generic135                    // method on each call).136                    // We use a PSObject wrapper to force calling the PowerShell binder because the C# binder fails137                    // for an unknown reason.138 139                    // The ETW provider GUID for events written here is: 5037b0a0-3a31-5cd2-ff19-103e9f160a74140                    ((dynamic)s_eventSourceInstance).Write(message, s_eventSourceOptionsForWrite, arguments);141                }142                catch143                {144                    // No-op on issues arising from calling EventSource.Write<T>145                }146            }147        }148    }149}150#endif151