Side by side to the Microsoft-ServiceFabric-Actors
and Microsoft-ServiceFabric-Services
providers one can add your own event source names.
"EtwEventSourceProviderConfiguration": [
{
"provider": "Microsoft-ServiceFabric-Actors",
"scheduledTransferKeywordFilter": "1",
"scheduledTransferPeriod": "PT5M",
"DefaultEvents": {
"eventDestination": "ServiceFabricReliableActorEventTable"
}
},
{
"provider": "S-Innovations-Azure-MessageProcessor-ServiceFabric",
"scheduledTransferPeriod": "PT5M",
"DefaultEvents": {
"eventDestination": "SInnovationsServiceFabricMessageProcessor"
}
},
{
"provider": "Microsoft-ServiceFabric-Services",
"scheduledTransferPeriod": "PT5M",
"DefaultEvents": {
"eventDestination": "ServiceFabricReliableServiceEventTable"
}
}
],
and I choose to combine the two sample EventSources from Services and Actors into one:
namespace SInnovations.Azure.MessageProcessor.ServiceFabric.Tracing
{
using System;
using System.Diagnostics.Tracing;
using System.Fabric;
using System.Threading.Tasks;
using Microsoft.ServiceFabric.Actors;
using Microsoft.ServiceFabric.Services.Runtime;
[EventSource(Name = "S-Innovations-Azure-MessageProcessor-ServiceFabric")]
internal sealed class ServiceFabricEventSource : EventSource
{
public static readonly ServiceFabricEventSource Current = new ServiceFabricEventSource();
static ServiceFabricEventSource()
{
// A workaround for the problem where ETW activities do not get tracked until Tasks infrastructure is initialized.
// This problem will be fixed in .NET Framework 4.6.2.
Task.Run(() => { }).Wait();
}
// Instance constructor is private to enforce singleton semantics
private ServiceFabricEventSource() : base() { }
#region Keywords
// Event keywords can be used to categorize events.
// Each keyword is a bit flag. A single event can be associated with multiple keywords (via EventAttribute.Keywords property).
// Keywords must be defined as a public class named 'Keywords' inside EventSource that uses them.
public static class Keywords
{
public const EventKeywords HostInitialization = (EventKeywords)0x1L;
public const EventKeywords Requests = (EventKeywords)0x2L;
public const EventKeywords ServiceInitialization = (EventKeywords)0x4L;
}
#endregion
#region Events
// Define an instance method for each event you want to record and apply an [Event] attribute to it.
// The method name is the name of the event.
// Pass any parameters you want to record with the event (only primitive integer types, DateTime, Guid & string are allowed).
// Each event method implementation should check whether the event source is enabled, and if it is, call WriteEvent() method to raise the event.
// The number and types of arguments passed to every event method must exactly match what is passed to WriteEvent().
// Put [NonEvent] attribute on all methods that do not define an event.
// For more information see https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.aspx
[NonEvent]
public void Message(string message, params object[] args)
{
if (this.IsEnabled())
{
string finalMessage = string.Format(message, args);
Message(finalMessage);
}
}
private const int MessageEventId = 1;
[Event(MessageEventId, Level = EventLevel.Informational, Message = "{0}")]
public void Message(string message)
{
if (this.IsEnabled())
{
WriteEvent(MessageEventId, message);
}
}
[NonEvent]
public void ActorMessage(StatelessActor actor, string message, params object[] args)
{
if (this.IsEnabled())
{
string finalMessage = string.Format(message, args);
ActorMessage(
actor.GetType().ToString(),
actor.Id.ToString(),
actor.ActorService.ServiceInitializationParameters.CodePackageActivationContext.ApplicationTypeName,
actor.ActorService.ServiceInitializationParameters.CodePackageActivationContext.ApplicationName,
actor.ActorService.ServiceInitializationParameters.ServiceTypeName,
actor.ActorService.ServiceInitializationParameters.ServiceName.ToString(),
actor.ActorService.ServiceInitializationParameters.PartitionId,
actor.ActorService.ServiceInitializationParameters.InstanceId,
FabricRuntime.GetNodeContext().NodeName,
finalMessage);
}
}
[NonEvent]
public void ActorMessage(StatefulActorBase actor, string message, params object[] args)
{
if (this.IsEnabled())
{
string finalMessage = string.Format(message, args);
ActorMessage(
actor.GetType().ToString(),
actor.Id.ToString(),
actor.ActorService.ServiceInitializationParameters.CodePackageActivationContext.ApplicationTypeName,
actor.ActorService.ServiceInitializationParameters.CodePackageActivationContext.ApplicationName,
actor.ActorService.ServiceInitializationParameters.ServiceTypeName,
actor.ActorService.ServiceInitializationParameters.ServiceName.ToString(),
actor.ActorService.ServiceInitializationParameters.PartitionId,
actor.ActorService.ServiceInitializationParameters.ReplicaId,
FabricRuntime.GetNodeContext().NodeName,
finalMessage);
}
}
[NonEvent]
public void ServiceMessage(StatelessService service, string message, params object[] args)
{
if (this.IsEnabled())
{
string finalMessage = string.Format(message, args);
ServiceMessage(
service.ServiceInitializationParameters.ServiceName.ToString(),
service.ServiceInitializationParameters.ServiceTypeName,
service.ServiceInitializationParameters.InstanceId,
service.ServiceInitializationParameters.PartitionId,
service.ServiceInitializationParameters.CodePackageActivationContext.ApplicationName,
service.ServiceInitializationParameters.CodePackageActivationContext.ApplicationTypeName,
FabricRuntime.GetNodeContext().NodeName,
finalMessage);
}
}
[NonEvent]
public void ServiceMessage(StatefulService service, string message, params object[] args)
{
if (this.IsEnabled())
{
string finalMessage = string.Format(message, args);
ServiceMessage(
service.ServiceInitializationParameters.ServiceName.ToString(),
service.ServiceInitializationParameters.ServiceTypeName,
service.ServiceInitializationParameters.ReplicaId,
service.ServiceInitializationParameters.PartitionId,
service.ServiceInitializationParameters.CodePackageActivationContext.ApplicationName,
service.ServiceInitializationParameters.CodePackageActivationContext.ApplicationTypeName,
FabricRuntime.GetNodeContext().NodeName,
finalMessage);
}
}
// For very high-frequency events it might be advantageous to raise events using WriteEventCore API.
// This results in more efficient parameter handling, but requires explicit allocation of EventData structure and unsafe code.
// To enable this code path, define UNSAFE conditional compilation symbol and turn on unsafe code support in project properties.
private const int ServiceMessageEventId = 2;
[Event(ServiceMessageEventId, Level = EventLevel.Informational, Message = "{7}")]
private
#if UNSAFE
unsafe
#endif
void ServiceMessage(
string serviceName,
string serviceTypeName,
long replicaOrInstanceId,
Guid partitionId,
string applicationName,
string applicationTypeName,
string nodeName,
string message)
{
#if !UNSAFE
WriteEvent(ServiceMessageEventId, serviceName, serviceTypeName, replicaOrInstanceId, partitionId, applicationName, applicationTypeName, nodeName, message);
#else
const int numArgs = 8;
fixed (char* pServiceName = serviceName, pServiceTypeName = serviceTypeName, pApplicationName = applicationName, pApplicationTypeName = applicationTypeName, pNodeName = nodeName, pMessage = message)
{
EventData* eventData = stackalloc EventData[numArgs];
eventData[0] = new EventData { DataPointer = (IntPtr) pServiceName, Size = SizeInBytes(serviceName) };
eventData[1] = new EventData { DataPointer = (IntPtr) pServiceTypeName, Size = SizeInBytes(serviceTypeName) };
eventData[2] = new EventData { DataPointer = (IntPtr) (&replicaOrInstanceId), Size = sizeof(long) };
eventData[3] = new EventData { DataPointer = (IntPtr) (&partitionId), Size = sizeof(Guid) };
eventData[4] = new EventData { DataPointer = (IntPtr) pApplicationName, Size = SizeInBytes(applicationName) };
eventData[5] = new EventData { DataPointer = (IntPtr) pApplicationTypeName, Size = SizeInBytes(applicationTypeName) };
eventData[6] = new EventData { DataPointer = (IntPtr) pNodeName, Size = SizeInBytes(nodeName) };
eventData[7] = new EventData { DataPointer = (IntPtr) pMessage, Size = SizeInBytes(message) };
WriteEventCore(ServiceMessageEventId, numArgs, eventData);
}
#endif
}
private const int ServiceTypeRegisteredEventId = 3;
[Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}", Keywords = Keywords.ServiceInitialization)]
public void ServiceTypeRegistered(int hostProcessId, string serviceType)
{
WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType);
}
private const int ServiceHostInitializationFailedEventId = 4;
[Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed", Keywords = Keywords.ServiceInitialization)]
public void ServiceHostInitializationFailed(string exception)
{
WriteEvent(ServiceHostInitializationFailedEventId, exception);
}
// A pair of events sharing the same name prefix with a "Start"/"Stop" suffix implicitly marks boundaries of an event tracing activity.
// These activities can be automatically picked up by debugging and profiling tools, which can compute their execution time, child activities,
// and other statistics.
private const int ServiceRequestStartEventId = 5;
[Event(ServiceRequestStartEventId, Level = EventLevel.Informational, Message = "Service request '{0}' started", Keywords = Keywords.Requests)]
public void ServiceRequestStart(string requestTypeName)
{
WriteEvent(ServiceRequestStartEventId, requestTypeName);
}
private const int ServiceRequestStopEventId = 6;
[Event(ServiceRequestStopEventId, Level = EventLevel.Informational, Message = "Service request '{0}' finished", Keywords = Keywords.Requests)]
public void ServiceRequestStop(string requestTypeName)
{
WriteEvent(ServiceRequestStopEventId, requestTypeName);
}
private const int ServiceRequestFailedEventId = 7;
[Event(ServiceRequestFailedEventId, Level = EventLevel.Error, Message = "Service request '{0}' failed", Keywords = Keywords.Requests)]
public void ServiceRequestFailed(string requestTypeName, string exception)
{
WriteEvent(ServiceRequestFailedEventId, exception);
}
// For very high-frequency events it might be advantageous to raise events using WriteEventCore API.
// This results in more efficient parameter handling, but requires explicit allocation of EventData structure and unsafe code.
// To enable this code path, define UNSAFE conditional compilation symbol and turn on unsafe code support in project properties.
private const int ActorMessageEventId = 8;
[Event(ActorMessageEventId, Level = EventLevel.Informational, Message = "{9}")]
private
#if UNSAFE
unsafe
#endif
void ActorMessage(
string actorType,
string actorId,
string applicationTypeName,
string applicationName,
string serviceTypeName,
string serviceName,
Guid partitionId,
long replicaOrInstanceId,
string nodeName,
string message)
{
#if !UNSAFE
WriteEvent(
ActorMessageEventId,
actorType,
actorId,
applicationTypeName,
applicationName,
serviceTypeName,
serviceName,
partitionId,
replicaOrInstanceId,
nodeName,
message);
#else
const int numArgs = 10;
fixed (char* pActorType = actorType, pActorId = actorId, pApplicationTypeName = applicationTypeName, pApplicationName = applicationName, pServiceTypeName = serviceTypeName, pServiceName = serviceName, pNodeName = nodeName, pMessage = message)
{
EventData* eventData = stackalloc EventData[numArgs];
eventData[0] = new EventData { DataPointer = (IntPtr) pActorType, Size = SizeInBytes(actorType) };
eventData[1] = new EventData { DataPointer = (IntPtr) pActorId, Size = SizeInBytes(actorId) };
eventData[2] = new EventData { DataPointer = (IntPtr) pApplicationTypeName, Size = SizeInBytes(applicationTypeName) };
eventData[3] = new EventData { DataPointer = (IntPtr) pApplicationName, Size = SizeInBytes(applicationName) };
eventData[4] = new EventData { DataPointer = (IntPtr) pServiceTypeName, Size = SizeInBytes(serviceTypeName) };
eventData[5] = new EventData { DataPointer = (IntPtr) pServiceName, Size = SizeInBytes(serviceName) };
eventData[6] = new EventData { DataPointer = (IntPtr) (&partitionId), Size = sizeof(Guid) };
eventData[7] = new EventData { DataPointer = (IntPtr) (&replicaOrInstanceId), Size = sizeof(long) };
eventData[8] = new EventData { DataPointer = (IntPtr) pNodeName, Size = SizeInBytes(nodeName) };
eventData[9] = new EventData { DataPointer = (IntPtr) pMessage, Size = SizeInBytes(message) };
WriteEventCore(ActorMessageEventId, numArgs, eventData);
}
#endif
}
private const int ActorHostInitializationFailedEventId = 9;
[Event(ActorHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Actor host initialization failed", Keywords = Keywords.HostInitialization)]
public void ActorHostInitializationFailed(string exception)
{
WriteEvent(ActorHostInitializationFailedEventId, exception);
}
#endregion
#region Private Methods
#if UNSAFE
private int SizeInBytes(string s)
{
if (s == null)
{
return 0;
}
else
{
return (s.Length + 1) * sizeof(char);
}
}
#endif
#endregion
}
}