1

以下是Azure門戶創建的VM Scale Set模板,作爲創建服務結構集羣的一部分,其中一些元素爲簡單起見而省略。如何使用ARM模板使ETW與VM模板一起使用使用EtwProviders設置服務結構

{ 
    "type": "Microsoft.Compute/virtualMachineScaleSets", 
    "properties": { 
    "upgradePolicy": { 
     "mode": "Automatic" 
    }, 
    "virtualMachineProfile": { 
     "extensionProfile": { 
     "extensions": [ 
      { 
      "name": "[concat('ServiceFabricNodeVmExt','_vmNodeType0Name')]" 
      }, 
      { 
      "name": "[concat('InstallNET62VmExt','_vmNodeType0Name')]" 
      }, 
      { 
      "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]", 
      "properties": { 
       "type": "IaaSDiagnostics", 
       "autoUpgradeMinorVersion": true, 
       "protectedSettings": { 
       "storageAccountName": "[variables('applicationDiagnosticsStorageAccountName')]", 
       "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]", 
       "storageAccountEndPoint": "https://core.windows.net/" 
       }, 
       "publisher": "Microsoft.Azure.Diagnostics", 
       "settings": { 
       "WadCfg": { 
        "DiagnosticMonitorConfiguration": { 
        "overallQuotaInMB": "50000", 
        "EtwProviders": { 
         "EtwEventSourceProviderConfiguration": [ 
         { 
          "provider": "Microsoft-ServiceFabric-Actors", 
          "scheduledTransferKeywordFilter": "1", 
          "scheduledTransferPeriod": "PT5M", 
          "DefaultEvents": { 
          "eventDestination": "ServiceFabricReliableActorEventTable" 
          } 
         },       
         { 
          "provider": "Microsoft-ServiceFabric-Services", 
          "scheduledTransferPeriod": "PT5M", 
          "DefaultEvents": { 
          "eventDestination": "ServiceFabricReliableServiceEventTable" 
          } 
         } 
         ], 
         "EtwManifestProviderConfiguration": [ 
         { 
          "provider": "cbd93bc2-71e5-4566-b3a7-595d8eeca6e8", 
          "scheduledTransferLogLevelFilter": "Information", 
          "scheduledTransferKeywordFilter": "4611686018427387904", 
          "scheduledTransferPeriod": "PT5M", 
          "DefaultEvents": { 
          "eventDestination": "ServiceFabricSystemEventTable" 
          } 
         } 
         ] 
        } 
        } 
       }, 
       "StorageAccount": "[variables('applicationDiagnosticsStorageAccountName')]" 
       }, 
       "typeHandlerVersion": "1.5" 
      } 
      } 
     ] 
     }, 
     "networkProfile": {}, 
     "osProfile": {}, 
     "storageProfile": {} 
    } 
    }, 
    "sku": { 
    "name": "[variables('vmNodeType0Size')]", 
    "capacity": "5", 
    "tier": "Basic" 
    }, 
    "tags": { 
    "resourceType": "Service Fabric", 
    "clusterName": "[parameters('clusterName')]" 
    } 
} 

它通過將服務結構的所有內部事件發送到blob存儲中的EWT表來工作。

然後創建在Visual Studio中一個新的服務應用的織物時,創建用於應用程序日誌新的事件源:

[EventSource(Name = "MyCompany-MessageProcessor.ServiceFabricHost-StatelessServiceProcessor")] 
internal sealed class ServiceEventSource : EventSource 
{ 
    ... 
} 

沒有被轉印到表存儲。

谷歌搜索IaaSDiagnostics WadCfg EtwProviders沒有提供任何有關這些工作的文檔。

我們如何使EventSouces能夠轉移到表格存儲中,並且所有的事件內置?

+0

壞編輯它的標題犯了一個錯誤。在接受評論員方面做得很好。 –

回答

2

Microsoft-ServiceFabric-ActorsMicrosoft-ServiceFabric-Services並排提供者可以添加自己的事件源名稱。

"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" 
    } 
    } 
], 

,我選擇從服務和演員兩個樣品EventSources合併爲一個:

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 
    } 
}