代码之家  ›  专栏  ›  技术社区  ›  Poul K. Sørensen

如何使用EtwProviders使ETW与用于服务结构的VM规模集的ARM模板一起工作

  •  1
  • Poul K. Sørensen  · 技术社区  · 10 年前

    这是由azure门户创建的VM Scale Set模板,它是创建服务结构集群的一部分,为了简单起见,省略了一些元素。

    {
      "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与所有内置事件一起传输到表存储?

    1 回复  |  直到 10 年前
        1
  •  3
  •   Poul K. Sørensen    10 年前

    并排到 Microsoft-ServiceFabric-Actors Microsoft-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"
        }
      }
    ],
    

    我选择将服务和参与者的两个示例EventSource合并为一个:

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