This is a follow on post from Beginning Azure Diagnostics, updating those code snippets that are somewhat outmoded. The code in the previous example still works, but as I will explain, is not the optimal way to achieve what it sets out to do.

DiagnosticMonitor – RoleInstanceDiagnosticMonitor

The main change surrounds the previous use of DiagnosticMonitor. Previously you had to manually start this process (by calling the Start static method). In version 1.3 of the Azure SDK, this is done automatically as the role starts up, and so “Starting” the DiagnosticMonitor is an unnecessary thing to do. That means if we no longer call Start, we need to find a new way of committing our configuration changes to the diagnostics infrastructure. This is done by creating an instance of RoleInstanceDiagnosticManager, which is a reference to the DiagnosticManager already running in the current Role, and calling a method called SetCurrentConfiguration, passing in our config.

Configuration Publishers

Additionally, since we are not using the DiagnosticManager, we get the option to create a CloudStorageAccount in a different way, using the CloudStorageAccount.Parse(string) method. This bypasses the need we had to have the below line of code, which was always a work around related to using the method DiagnosticManager.Start(string configName, DiagnosticMonitorConfiguration config);

CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)));

Instead, we can use the Parse function as below:

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"));

How to do it now

We create a RoleInstanceDiagnosticManager using an extension method on the CloudStorageAccount type, called CreateRoleInstanceDiagnosticManager. If you cannot find the method named CreateRoleInstanceDiagnosticManager, you must make sure you have added the using Microsoft.WindowsAzure.Diagnostics.Management; namespace import to your class.

We can update the DiagnosticMonitorConfiguration in much the same way as we did previously, setting ScheduleTransferPeriod as appropriate for those sets of diagnostics data that we are interested in. The only difference is that when seeking to instantiate a DiagnosticMonitorConfiguration, we no longer need to use DiagnosticMonitor.GetDefaultConfiguration(), but can instead access the configuration from the RoleInstanceDiagnosticManager with roleInstanceDiagnosticManager.GetCurrentConfiguration();.

Finally we can then commit the updates to the running diagnostic manager with roleInstanceDiagnosticManager.SetCurrentConfiguration(config);

The below is how I set up my diagnostics in a WebRole.cs OnStart method. Note that in order to get the diagnostics running immediately, I add a TraceListener to the AppDomain that WebRole.cs runs in. Not doing so would mean WADLogsTable is not created, since the Trace information written in WebRole.cs is not listened to by any DiagnosticMonitorTraceListener – even though one is eventually loaded for ASP.NET. The alternative to adding one programmatically is to add the TraceListener to WaIISHost.exe.config

DiagnosticMonitorTraceListener tmpListener = new DiagnosticMonitorTraceListener();
string wadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(wadConnectionString));

RoleInstanceDiagnosticManager roleInstanceDiagnosticManager = storageAccount.CreateRoleInstanceDiagnosticManager(RoleEnvironment.DeploymentId, RoleEnvironment.CurrentRoleInstance.Role.Name, RoleEnvironment.CurrentRoleInstance.Id);

DiagnosticMonitorConfiguration config = roleInstanceDiagnosticManager.GetCurrentConfiguration();
// should never be null, but this is a fallback in case it is. I recommend removing this in a production
// deployment
if (null == config)
config = DiagnosticMonitor.GetDefaultInitialConfiguration();

config.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1D);
config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Undefined;
config.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = LogLevel.Warning;
config.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1D);
config.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1D);

System.Diagnostics.Trace.TraceInformation("Diagnostics Running");