Diagnostics and monitoring for services and applications that don’t run in the cloud doesn’t require a special attention since you have physical access to the production server, more or less, it depends on how you’ve decided to host them. But in the cloud there are several challenges with diagnostics like:
- Many instances
- They move around
- Massive amount of data
- Can’t remote desktop in
- No remote tools (yet)
So Microsoft have implemented a monitoring agent (MonAgentHost.exe) which runs on each instance in the cloud. The agent is started automatically by default. The listener is wired up in the app/web.config, like any other TraceListener. More you need to define a storage account connection string for this listener. In a nutshell it works in 5 steps:
- 1.Role instance starts and by default the monitoring agent is started too.
- 2.Diagnostic Monitor Starts
- 3.Monitor must be configured at start time or remotely any time using service configuration file.
- 4.Monitor starts to buffer data locally. The user might set a quota, too.
- 5.User initiates transfer to storage. The transfer can be scheduled or on demand. I recommend a scheduled transfer. In this way diagnostics storage is up to date with live locally data.
Below is the table with items that can be monitored in the cloud, if they are activated by default or not and the storage destination type.
|
Data Source |
Default |
Destination |
|
Trace Logs |
Enabled |
Azure Table |
|
Diagnostic Infrastructure Logs |
Enabled |
Azure Table |
|
IIS Logs |
Enabled |
Blob |
|
Performance Counters |
Disabled |
Azure Table |
|
Windows Event Logs |
Disabled |
Azure Table |
|
IIS Failed Request Logs |
Disabled |
Blob |
|
Crash Dumps |
Disabled |
Blob |
|
Arbitrary Files |
Disabled |
Blob |
Implementing Azure Diagnostics:
First Diagnostic Agent is loaded as an Azure module the ServiceDefinition.csdef:
Then module expects a connection string:
Attention, a production connection string must be https! Like this:
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;
AccountName=YOURACCOUNT;AccountKey=YOURKEY" />
The common pattern to configure diagnostics suppose:
- Get Config
- From default
- Current running
- Make a change to the config
- If changed within the instance it will affect only that instance. Don’t forget to start the agent immediately
- If changed from outside for all roles then
- change the central file
- agent notices a change and reloads
- affects all instances of the role
- Start the Diagnostics agent with the new configuration
The code:
Method 1:
- I’ve set up a transfer to the storage every one minute
- Also I’ve added “System” and “Application” transfer from Event Viewer
- //—————————————-method 1—————————-//
- //get config
- CloudStorageAccount storageAcc = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"));
- RoleInstanceDiagnosticManager ridm = storageAcc.CreateRoleInstanceDiagnosticManager(RoleEnvironment.DeploymentId,
- RoleEnvironment.CurrentRoleInstance.Role.Name, RoleEnvironment.CurrentRoleInstance.Id);
- DiagnosticMonitorConfiguration dmc = ridm.GetCurrentConfiguration();
- //change config
- // Transfer logs to storage every minute
- dmc.Logs.ScheduledTransferPeriod = tsTenSeconds;
- dmc.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = tsTenSeconds;
- dmc.Directories.ScheduledTransferPeriod = tsTenSeconds;
- dmc.WindowsEventLog.ScheduledTransferPeriod = tsTenSeconds;
- dmc.WindowsEventLog.DataSources.Add("System!*");
- dmc.WindowsEventLog.DataSources.Add("Application!*");
- dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Information;
- ridm.SetCurrentConfiguration(dmc);
- //—————————————-end method 1—————————-//
Method 2:
- I’ve loaded the default configuration and I’ve set up a scheduled transfer
- //—————————————-method 2—————————-//
- // Start up the diagnostic manager with the given configuration
- DiagnosticMonitorConfiguration dmc = DiagnosticMonitor.GetDefaultInitialConfiguration();
- dmc.Logs.ScheduledTransferPeriod = tsTenSeconds;
- // Transfer verbose, critical, etc. logs
- dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;
- DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", dmc);
- //—————————————-end method 2—————————-//
Method 3:
- I’ve created a custom listener that writes log entries in a dedicated Azure table
- //—————————————-method 3—————————-//
- CloudStorageAccount storageAcc = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"));
- CloudTableClient tableStorage = storageAcc.CreateCloudTableClient();
- tableStorage.CreateTableIfNotExist(TableStorageTraceListener.DIAGNOSTICS_TABLE);
- AzureDiagnostics.TableStorageTraceListener listener =
- new AzureDiagnostics.TableStorageTraceListener("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString")
- {
- Name = "TableStorageTraceListener"
- };
- System.Diagnostics.Trace.Listeners.Add(listener);
- System.Diagnostics.Trace.AutoFlush = true;
- Trace.Listeners.Add(new DiagnosticMonitorTraceListener());
- //—————————————-end method 3—————————-//
Full code available here.
Visualizing the data
You might use Azure Storage Explorer to explore diagnostics storage account or you can use Cerebrata’s Azure Diagnostics Manager which is a dedicated tool for diagnostics management. It will display a more friendly UI than the Storage Explorer: