MegaBites-AI/Windows-powershell
0308
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 