/src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/EventProviderTraceListener.cs

https://gitlab.com/unofficial-mirrors/PowerShell · C# · 288 lines · 215 code · 42 blank · 31 comment · 44 complexity · 96bf85ccc721fdd33f8f7385c076da52 MD5 · raw file

  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License.
  3. using System.Text;
  4. using System.Globalization;
  5. using System.Diagnostics.CodeAnalysis;
  6. namespace System.Diagnostics.Eventing
  7. {
  8. public class EventProviderTraceListener : TraceListener
  9. {
  10. //
  11. // The listener uses the EtwProvider base class.
  12. // Because Listener data is not schematized at the moment the listener will
  13. // log events using WriteMessageEvent method.
  14. //
  15. // Because WriteMessageEvent takes a string as the event payload
  16. // all the overridden logging methods convert the arguments into strings.
  17. // Event payload is "delimiter" separated, which can be configured
  18. //
  19. //
  20. private EventProvider _provider;
  21. private const string s_nullStringValue = "null";
  22. private const string s_nullStringComaValue = "null,";
  23. private const string s_nullCStringValue = ": null";
  24. private string _delimiter = ";";
  25. private const uint s_keyWordMask = 0xFFFFFF00;
  26. private const int s_defaultPayloadSize = 512;
  27. [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
  28. public string Delimiter
  29. {
  30. get
  31. {
  32. return _delimiter;
  33. }
  34. [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
  35. set
  36. {
  37. if (value == null)
  38. throw new ArgumentNullException("Delimiter");
  39. if (value.Length == 0)
  40. throw new ArgumentException(DotNetEventingStrings.Argument_NeedNonemptyDelimiter);
  41. _delimiter = value;
  42. }
  43. }
  44. /// <summary>
  45. /// This method creates an instance of the ETW provider.
  46. /// The guid argument must be a valid GUID or a format exception will be
  47. /// thrown when creating an instance of the ControlGuid.
  48. /// We need to be running on Vista or above. If not an
  49. /// PlatformNotSupported exception will be thrown by the EventProvider.
  50. /// </summary>
  51. public EventProviderTraceListener(string providerId)
  52. {
  53. InitProvider(providerId);
  54. }
  55. public EventProviderTraceListener(string providerId, string name)
  56. : base(name)
  57. {
  58. InitProvider(providerId);
  59. }
  60. public EventProviderTraceListener(string providerId, string name, string delimiter)
  61. : base(name)
  62. {
  63. if (delimiter == null)
  64. throw new ArgumentNullException("delimiter");
  65. if (delimiter.Length == 0)
  66. throw new ArgumentException(DotNetEventingStrings.Argument_NeedNonemptyDelimiter);
  67. _delimiter = delimiter;
  68. InitProvider(providerId);
  69. }
  70. private void InitProvider(string providerId)
  71. {
  72. Guid controlGuid = new Guid(providerId);
  73. //
  74. // Create The ETW TraceProvider
  75. //
  76. _provider = new EventProvider(controlGuid);
  77. }
  78. //
  79. // override Listener methods
  80. //
  81. public sealed override void Flush()
  82. {
  83. }
  84. public sealed override bool IsThreadSafe
  85. {
  86. get
  87. {
  88. return true;
  89. }
  90. }
  91. protected override void Dispose(bool disposing)
  92. {
  93. if (disposing)
  94. {
  95. _provider.Close();
  96. }
  97. }
  98. public sealed override void Write(string message)
  99. {
  100. if (!_provider.IsEnabled())
  101. {
  102. return;
  103. }
  104. _provider.WriteMessageEvent(message, (byte)TraceEventType.Information, 0);
  105. }
  106. public sealed override void WriteLine(string message)
  107. {
  108. Write(message);
  109. }
  110. //
  111. // For all the methods below the string to be logged contains:
  112. // m_delimiter separated data converted to string
  113. //
  114. // The source parameter is ignored.
  115. //
  116. public sealed override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
  117. {
  118. if (!_provider.IsEnabled())
  119. {
  120. return;
  121. }
  122. if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, null))
  123. {
  124. return;
  125. }
  126. StringBuilder dataString = new StringBuilder(s_defaultPayloadSize);
  127. if (data != null)
  128. {
  129. dataString.Append(data.ToString());
  130. }
  131. else
  132. {
  133. dataString.Append(s_nullCStringValue);
  134. }
  135. _provider.WriteMessageEvent(dataString.ToString(),
  136. (byte)eventType,
  137. (long)eventType & s_keyWordMask);
  138. }
  139. public sealed override void TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, int id, params object[] data)
  140. {
  141. if (!_provider.IsEnabled())
  142. {
  143. return;
  144. }
  145. if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, null))
  146. {
  147. return;
  148. }
  149. int index;
  150. StringBuilder dataString = new StringBuilder(s_defaultPayloadSize);
  151. if ((data != null) && (data.Length > 0))
  152. {
  153. for (index = 0; index < (data.Length - 1); index++)
  154. {
  155. if (data[index] != null)
  156. {
  157. dataString.Append(data[index].ToString());
  158. dataString.Append(Delimiter);
  159. }
  160. else
  161. {
  162. dataString.Append(s_nullStringComaValue);
  163. }
  164. }
  165. if (data[index] != null)
  166. {
  167. dataString.Append(data[index].ToString());
  168. }
  169. else
  170. {
  171. dataString.Append(s_nullStringValue);
  172. }
  173. }
  174. else
  175. {
  176. dataString.Append(s_nullStringValue);
  177. }
  178. _provider.WriteMessageEvent(dataString.ToString(),
  179. (byte)eventType,
  180. (long)eventType & s_keyWordMask);
  181. }
  182. public sealed override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
  183. {
  184. if (!_provider.IsEnabled())
  185. {
  186. return;
  187. }
  188. if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, null))
  189. {
  190. return;
  191. }
  192. _provider.WriteMessageEvent(String.Empty,
  193. (byte)eventType,
  194. (long)eventType & s_keyWordMask);
  195. }
  196. public sealed override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
  197. {
  198. if (!_provider.IsEnabled())
  199. {
  200. return;
  201. }
  202. if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, null))
  203. {
  204. return;
  205. }
  206. StringBuilder dataString = new StringBuilder(s_defaultPayloadSize);
  207. dataString.Append(message);
  208. _provider.WriteMessageEvent(dataString.ToString(),
  209. (byte)eventType,
  210. (long)eventType & s_keyWordMask);
  211. }
  212. public sealed override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
  213. {
  214. if (!_provider.IsEnabled())
  215. {
  216. return;
  217. }
  218. if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, null))
  219. {
  220. return;
  221. }
  222. if (args == null)
  223. {
  224. _provider.WriteMessageEvent(format,
  225. (byte)eventType,
  226. (long)eventType & s_keyWordMask);
  227. }
  228. else
  229. {
  230. _provider.WriteMessageEvent(String.Format(CultureInfo.InvariantCulture, format, args),
  231. (byte)eventType,
  232. (long)eventType & s_keyWordMask);
  233. }
  234. }
  235. public override void Fail(string message, string detailMessage)
  236. {
  237. StringBuilder failMessage = new StringBuilder(message);
  238. if (detailMessage != null)
  239. {
  240. failMessage.Append(" ");
  241. failMessage.Append(detailMessage);
  242. }
  243. this.TraceEvent(null, null, TraceEventType.Error, 0, failMessage.ToString());
  244. }
  245. }
  246. }