Geeks With Blogs
Rohit Gupta Engaging talk on Microsoft Technologies ....My Resume

In Windows Azure, we have the DiagnosticMonitorTraceListener which can be used for writing diagnostics to Local resource (like a local storage in the Worker or Web Role) which can then be ultimately stored in Windows Azure Table/Blob storage (transferred automatically by the Diagnostics Monitor in Windows Azure based on config settings).

We could either configure the Diagnostic Monitor using Code (in Role Startup) or we can use a config file for the same (called diagnostics.wadcfg). The code configuration for enabling transfer of Logs to Azure table storage looks something like this:

   1: String wadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
   2: String customContainerName = "wad-custom-container";
   3:  
   4: DiagnosticMonitorConfiguration dmc = DiagnosticMonitor.GetDefaultInitialConfiguration();
   5:  
   6: LocalResource localResource = RoleEnvironment.GetLocalResource(localResourceName);
   7: String logPath = Path.Combine(localResource.RootPath, "Logs");
   8: DirectoryConfiguration directoryConfiguration = new DirectoryConfiguration()
   9: {
  10:     Container = customContainerName,
  11:     DirectoryQuotaInMB = localResource.MaximumSizeInMegabytes,
  12:     Path = logPath
  13: };
  14: dmc.Directories.DataSources.Add(directoryConfiguration);
  15: dmc.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  16:  
  17: dmc.Logs.BufferQuotaInMB = 100;
  18: dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  19: dmc.Logs.ScheduledTransferLogLevelFilter =  LogLevel.Verbose;
  20: DiagnosticMonitor.Start(wadConnectionString, dmc);
If we need to use a configuration file instead the config file needs to be placed in the %RoleEntryPoint% folder in the case of web roles or within %RoleEntryPoint%\bin folder for WorkerRoles. Alternatively in Visual Studio, just include this diagnostics.wadcfg file in the root folder and set the following properties:

diagnostics.wadcfg

If we use the config file, then we don’t need any custom code in the Role Startup. The config file would look like the following:

   1: <DiagnosticMonitorConfiguration xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration" configurationChangePollInterval="PT1M" overallQuotaInMB="4096">
   2:   <DiagnosticInfrastructureLogs bufferQuotaInMB="100" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT1H"/>
   3:   <WindowsEventLog bufferQuotaInMB="100" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT1H">
   4:     <DataSource name="Application!*"/>
   5:   </WindowsEventLog>
   6:   <Logs bufferQuotaInMB="100" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT1M"/>
   7:   <Directories bufferQuotaInMB="1024" scheduledTransferPeriod="PT1M">
   8:  
   9:     <!-- These three elements specify the special directories that are set up for the log types -->
  10:     <CrashDumps container="wad-crash-dumps" directoryQuotaInMB="256"/>
  11:     <FailedRequestLogs container="wad-frq" directoryQuotaInMB="256"/>
  12:     <IISLogs container="wad-iis-test" directoryQuotaInMB="256"/>
  13:  
  14:     <DataSources>
  15:       <DirectoryConfiguration container="wad-custom-container" directoryQuotaInMB="20">
  16:         <!--LocalResource specifies a path relative to a local resource defined in the service definition-->
  17:         <LocalResource name="CustomLoggingLocation" relativePath="Logs"/>
  18:       </DirectoryConfiguration>
  19:     </DataSources>
  20:   </Directories>
  21:  
  22:   <PerformanceCounters bufferQuotaInMB="100" scheduledTransferPeriod="PT20M">
  23:     <!-- The counter specifier is in the same format as the imperative diagnostics configuration API -->
  24:     <PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT10S"/>
  25:   </PerformanceCounters>
  26: </DiagnosticMonitorConfiguration>

This configuration is very similar to the default configuration that is stored in “wad-control-container” blob in Azure Blob storage for every deployment of our app.
Additionally, if we already have some custom configuration in “wad-control-container” we could get an instance of this configuration using RoleInstanceDiagnosticManager and then Update this configuration with the changes we need. Here is an example of doing the same:

   1: CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(wadConnectionString));
   2: var roleInstanceDiagnosticManager =
   3:     new RoleInstanceDiagnosticManager(cloudStorageAccount, RoleEnvironment.DeploymentId,
   4:                                       RoleEnvironment.CurrentRoleInstance.Role.Name,
   5:                                       RoleEnvironment.CurrentRoleInstance.Id);
   6:  
   7: DiagnosticMonitorConfiguration dmc = roleInstanceDiagnosticManager.GetCurrentConfiguration();
   8: LocalResource localResource = RoleEnvironment.GetLocalResource(localResourceName);
   9: String logPath = Path.Combine(localResource.RootPath, "Logs");
  10: DirectoryConfiguration directoryConfiguration = new DirectoryConfiguration()
  11: {
  12:     Container = customContainerName,
  13:     DirectoryQuotaInMB = localResource.MaximumSizeInMegabytes,
  14:     Path = logPath
  15: };
  16: dmc.Directories.DataSources.Add(directoryConfiguration);
  17: dmc.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  18:  
  19: dmc.Logs.BufferQuotaInMB = 100;
  20: dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  21: dmc.Logs.ScheduledTransferLogLevelFilter =  LogLevel.Verbose;
  22: roleInstanceDiagnosticManager.SetCurrentConfiguration(dmc);

Using DiagnosticMonitorTraceListener with Logging Application Block

We can use the same DiagnosticMonitorTraceListener as a TraceListener in Logging Application Block, the config for the same looks like this:

   1: <listeners>
   2:   <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   3:       listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.SystemDiagnosticsTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   4:        formatter="Text Formatter"
   5:        name="AzureDiagnostics">
   6:   </add>
   7: </listeners>

Then in C# code we could use such code for Logging:

   1: private static void Log(string module, string message, TraceEventType severity, params object[] args)
   2: {
   3:     string moduleSeverity = ConfigurationManager.AppSettings[module] ?? "";
   4:     if ((string.IsNullOrWhiteSpace(moduleSeverity) || moduleSeverity.Equals(severity.ToString().ToLower(), StringComparison.OrdinalIgnoreCase))
   5:         && Microsoft.Practices.EnterpriseLibrary.Logging.Logger.IsLoggingEnabled())
   6:     {
   7:         var msg = string.Format(message, args);
   8:         Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(msg, module, 1, 0, severity);
   9:     }
  10: }

The Sample configuration for Logging Application Block would look something like the following:

   1: <configuration>
   2:   <configSections>
   3:     <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
   4:   </configSections>
   5:   <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
   6:     <listeners>
   7:       <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   8:           listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   9:           source="SmartSAPConn" formatter="Text Formatter" log="" machineName="."
  10:           traceOutputOptions="None" />
  11:       <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  12:           listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.SystemDiagnosticsTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  13:            formatter="Text Formatter"
  14:            name="AzureDiagnostics">
  15:       </add>
  16:     </listeners>
  17:     <formatters>
  18:       <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  19:           template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
  20:           name="Text Formatter" />
  21:     </formatters>
  22:     <categorySources>
  23:       <add switchValue="All" name="General">
  24:         <listeners>
  25:           <add name="AzureDiagnostics" />
  26:         </listeners>
  27:       </add>
  28:     </categorySources>
  29:     <specialSources>
  30:       <allEvents switchValue="All" name="All Events" />
  31:       <notProcessed switchValue="All" name="Unprocessed Category" />
  32:       <errors switchValue="All" name="Logging Errors &amp; Warnings">
  33:         <listeners>
  34:           <add name="AzureDiagnostics" />
  35:         </listeners>
  36:       </errors>
  37:     </specialSources>
  38:   </loggingConfiguration>  
  39: </configuration>

Once we do this, at the configured interval in diagnostics.wadcfg file, the log records will get recorded in Azure table storage in “WADLogsTable” which gets created automatically by the DiagnosticsMonitor.
If we used Directory Logging then that would get persisted in Blob storage in a custom Blob container (in our case it would be wad-custom-container)

Posted on Thursday, September 22, 2011 7:38 AM | Back to top


Comments on this post: Using Logging Application Block with Windows Azure

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Rohit Gupta | Powered by: GeeksWithBlogs.net