You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
8.7 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.Tracing;
  4. using System.Fabric;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using Microsoft.ServiceFabric.Services.Runtime;
  9. namespace ApiGw_Base
  10. {
  11. [EventSource(Name = "MyCompany-eShopOnServiceFabricOcelote-ApiGw_Base")]
  12. internal sealed class ServiceEventSource : EventSource
  13. {
  14. public static readonly ServiceEventSource Current = new ServiceEventSource();
  15. static ServiceEventSource()
  16. {
  17. // A workaround for the problem where ETW activities do not get tracked until Tasks infrastructure is initialized.
  18. // This problem will be fixed in .NET Framework 4.6.2.
  19. Task.Run(() => { });
  20. }
  21. // Instance constructor is private to enforce singleton semantics
  22. private ServiceEventSource() : base() { }
  23. #region Keywords
  24. // Event keywords can be used to categorize events.
  25. // Each keyword is a bit flag. A single event can be associated with multiple keywords (via EventAttribute.Keywords property).
  26. // Keywords must be defined as a public class named 'Keywords' inside EventSource that uses them.
  27. public static class Keywords
  28. {
  29. public const EventKeywords Requests = (EventKeywords)0x1L;
  30. public const EventKeywords ServiceInitialization = (EventKeywords)0x2L;
  31. }
  32. #endregion
  33. #region Events
  34. // Define an instance method for each event you want to record and apply an [Event] attribute to it.
  35. // The method name is the name of the event.
  36. // Pass any parameters you want to record with the event (only primitive integer types, DateTime, Guid & string are allowed).
  37. // Each event method implementation should check whether the event source is enabled, and if it is, call WriteEvent() method to raise the event.
  38. // The number and types of arguments passed to every event method must exactly match what is passed to WriteEvent().
  39. // Put [NonEvent] attribute on all methods that do not define an event.
  40. // For more information see https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.aspx
  41. [NonEvent]
  42. public void Message(string message, params object[] args)
  43. {
  44. if (this.IsEnabled())
  45. {
  46. string finalMessage = string.Format(message, args);
  47. Message(finalMessage);
  48. }
  49. }
  50. private const int MessageEventId = 1;
  51. [Event(MessageEventId, Level = EventLevel.Informational, Message = "{0}")]
  52. public void Message(string message)
  53. {
  54. if (this.IsEnabled())
  55. {
  56. WriteEvent(MessageEventId, message);
  57. }
  58. }
  59. [NonEvent]
  60. public void ServiceMessage(ServiceContext serviceContext, string message, params object[] args)
  61. {
  62. if (this.IsEnabled())
  63. {
  64. string finalMessage = string.Format(message, args);
  65. ServiceMessage(
  66. serviceContext.ServiceName.ToString(),
  67. serviceContext.ServiceTypeName,
  68. GetReplicaOrInstanceId(serviceContext),
  69. serviceContext.PartitionId,
  70. serviceContext.CodePackageActivationContext.ApplicationName,
  71. serviceContext.CodePackageActivationContext.ApplicationTypeName,
  72. serviceContext.NodeContext.NodeName,
  73. finalMessage);
  74. }
  75. }
  76. // For very high-frequency events it might be advantageous to raise events using WriteEventCore API.
  77. // This results in more efficient parameter handling, but requires explicit allocation of EventData structure and unsafe code.
  78. // To enable this code path, define UNSAFE conditional compilation symbol and turn on unsafe code support in project properties.
  79. private const int ServiceMessageEventId = 2;
  80. [Event(ServiceMessageEventId, Level = EventLevel.Informational, Message = "{7}")]
  81. private
  82. #if UNSAFE
  83. unsafe
  84. #endif
  85. void ServiceMessage(
  86. string serviceName,
  87. string serviceTypeName,
  88. long replicaOrInstanceId,
  89. Guid partitionId,
  90. string applicationName,
  91. string applicationTypeName,
  92. string nodeName,
  93. string message)
  94. {
  95. #if !UNSAFE
  96. WriteEvent(ServiceMessageEventId, serviceName, serviceTypeName, replicaOrInstanceId, partitionId, applicationName, applicationTypeName, nodeName, message);
  97. #else
  98. const int numArgs = 8;
  99. fixed (char* pServiceName = serviceName, pServiceTypeName = serviceTypeName, pApplicationName = applicationName, pApplicationTypeName = applicationTypeName, pNodeName = nodeName, pMessage = message)
  100. {
  101. EventData* eventData = stackalloc EventData[numArgs];
  102. eventData[0] = new EventData { DataPointer = (IntPtr) pServiceName, Size = SizeInBytes(serviceName) };
  103. eventData[1] = new EventData { DataPointer = (IntPtr) pServiceTypeName, Size = SizeInBytes(serviceTypeName) };
  104. eventData[2] = new EventData { DataPointer = (IntPtr) (&replicaOrInstanceId), Size = sizeof(long) };
  105. eventData[3] = new EventData { DataPointer = (IntPtr) (&partitionId), Size = sizeof(Guid) };
  106. eventData[4] = new EventData { DataPointer = (IntPtr) pApplicationName, Size = SizeInBytes(applicationName) };
  107. eventData[5] = new EventData { DataPointer = (IntPtr) pApplicationTypeName, Size = SizeInBytes(applicationTypeName) };
  108. eventData[6] = new EventData { DataPointer = (IntPtr) pNodeName, Size = SizeInBytes(nodeName) };
  109. eventData[7] = new EventData { DataPointer = (IntPtr) pMessage, Size = SizeInBytes(message) };
  110. WriteEventCore(ServiceMessageEventId, numArgs, eventData);
  111. }
  112. #endif
  113. }
  114. private const int ServiceTypeRegisteredEventId = 3;
  115. [Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}", Keywords = Keywords.ServiceInitialization)]
  116. public void ServiceTypeRegistered(int hostProcessId, string serviceType)
  117. {
  118. WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType);
  119. }
  120. private const int ServiceHostInitializationFailedEventId = 4;
  121. [Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed", Keywords = Keywords.ServiceInitialization)]
  122. public void ServiceHostInitializationFailed(string exception)
  123. {
  124. WriteEvent(ServiceHostInitializationFailedEventId, exception);
  125. }
  126. // A pair of events sharing the same name prefix with a "Start"/"Stop" suffix implicitly marks boundaries of an event tracing activity.
  127. // These activities can be automatically picked up by debugging and profiling tools, which can compute their execution time, child activities,
  128. // and other statistics.
  129. private const int ServiceRequestStartEventId = 5;
  130. [Event(ServiceRequestStartEventId, Level = EventLevel.Informational, Message = "Service request '{0}' started", Keywords = Keywords.Requests)]
  131. public void ServiceRequestStart(string requestTypeName)
  132. {
  133. WriteEvent(ServiceRequestStartEventId, requestTypeName);
  134. }
  135. private const int ServiceRequestStopEventId = 6;
  136. [Event(ServiceRequestStopEventId, Level = EventLevel.Informational, Message = "Service request '{0}' finished", Keywords = Keywords.Requests)]
  137. public void ServiceRequestStop(string requestTypeName, string exception = "")
  138. {
  139. WriteEvent(ServiceRequestStopEventId, requestTypeName, exception);
  140. }
  141. #endregion
  142. #region Private methods
  143. private static long GetReplicaOrInstanceId(ServiceContext context)
  144. {
  145. StatelessServiceContext stateless = context as StatelessServiceContext;
  146. if (stateless != null)
  147. {
  148. return stateless.InstanceId;
  149. }
  150. StatefulServiceContext stateful = context as StatefulServiceContext;
  151. if (stateful != null)
  152. {
  153. return stateful.ReplicaId;
  154. }
  155. throw new NotSupportedException("Context type not supported.");
  156. }
  157. #if UNSAFE
  158. private int SizeInBytes(string s)
  159. {
  160. if (s == null)
  161. {
  162. return 0;
  163. }
  164. else
  165. {
  166. return (s.Length + 1) * sizeof(char);
  167. }
  168. }
  169. #endif
  170. #endregion
  171. }
  172. }