What’s In This Chapter?
Whenever you write an application, you debug or diagnose it. The reasons for this are numerous—from bugs to performance issues to testing changes in your algorithms or code. Windows Azure provides both debugging and diagnostic capabilities, and you can use both together to get to the root cause of any issues that arise in your application. In addition, Visual Studio provides rich tools so that your debugging does not need to happen against the live instance of your service; you can debug against an emulated environment, which makes the debugging process available anytime and anywhere.
Windows Azure Diagnostics enables you to collect data about your Azure application so that you can use that data to debug, troubleshoot, measure performance, or perform other development tasks. You can run Windows Azure Diagnostics locally or remotely and configure it separately from your Azure application. This flexibility enables you to work with diagnostics without changing your Azure application. In addition, you can transfer Windows Azure Diagnostics either on a schedule or on-demand to a Windows Azure storage account, which allows you to persist and build a data warehouse of performance metrics over time.
Windows Azure Diagnostics enables you to collect a number of different logs including the Windows Azure logs, IIS logs, and Windows Azure Diagnostics infrastructure logs, in addition to other sources, such as the Windows Event log and crash dumps. Beyond logs, you can also use tracing and debugging to help you understand where issues may occur in your code. Optionally, you can also leverage performance counters to understand the health of your Azure application. These performance counters can either be built-in or custom performance counters that you create.
For debugging you have your choice to either debug:
Although both have their merits, debugging is easier against your local instance while leveraging diagnostics as a viable alternative to an attached debugger for your production Azure instances running in the cloud.
Your local debugging session may not uncover all your issues because it is fundamentally different from running your code in the cloud. For example, your network or machine utilization is different locally versus running in the Microsoft datacenter. Therefore, if your application fails because of an overloaded network or starvation for resources, you may not find those issues when performing a local debugging session.
Because debugging is based on the built-in Visual Studio debugger, you do not need to perform special steps to start debugging except setting a breakpoint and starting your application with debugging enabled.
Intellitrace is a feature of Visual Studio 2010 Ultimate that enables you to debug your applications by showing you events that occurred during the running of your application and the context surrounding those events. You can configure Intellitrace for the events to collect and allow for the collection of additional data, such as parameters and return values.
Configuring Intellitrace is easy with Azure. Check the Enable Intellitrace for .NET 4 Roles box that turns on Intellitrace for your Azure deployment, as shown in Figure 16-1.
When enabled, you need to deploy your solution for Azure. When initialized, you can view the Intellitrace logs from your Azure instance, as shown in Figure 16-2.
Using the Intellitrace logs, you can track down both the events and calls that happened in your instance and look back in time to understand what went wrong. Intellitrace is a little bit like the movie Back to the Future in that you can go back in time and understand the events that lead to the current situation, the variables and threads involved, and the state of the machine at the time. You should not use Intellitrace on production instances of your Azure application because it will slow performance.
Beside Intellitrace, you can also use profiling to debug your applications. One restriction is that you can use only Intellitrace or profiling but not both at the same time. Many times you should first use Intellitrace to look for any exceptions in your application and try to fix those exceptions. Then, you can enable profiling, which can help you identify the most time-consuming areas in your code.
With Azure profiling, you can activate the following settings, as shown in Figure 16-3.
After you deploy your Azure instance and initialize it, you can have Visual Studio download the profiling data and view the profiling reports. From there, you can troubleshoot your application to understand where the biggest demands of resources or time take place. Figure 16-4 shows a profiling report against an Azure instance.
When you work with your Azure applications, there are times when you want to collect diagnostics about your application for debugging or troubleshooting purposes. By allowing you to collect diagnostic information and persisting that information, Azure ensures that your application runs at the optimal configuration over time without forcing an intrusive process.
To configure Azure Diagnostics, you need to import the Azure Diagnostics module into your service model. This is as simple as adding an Import element to your ServiceDefinition.csdef file, as shown in the following code:
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="MyHostedService" xmlns="http://schemas.microsoft.com/ ServiceHosting/2008/10/ServiceDefinition"> <WebRole name="WebRole1"> <Imports> <Import moduleName="Diagnostics" /> </Imports> </WebRole> </ServiceDefinition>
If you persist your diagnostic information to your Azure Storage account, you must also specify a connection string in your ServiceConfiguration.cscfg file so that Azure knows how to export the diagnostic log and store it in Azure storage. The XML for the connection string is shown in the following code block. It shows how to use the storage emulator for storage and then shows passing in an account name and key to store the log in an Azure storage account.
<?xml version="1.0" encoding="utf-8"?> <ServiceConfiguration serviceName="AzureService" xmlns="http://schemas.microsoft.com /ServiceHosting/2008/10/ServiceConfiguration" osFamily="1" osVersion="*"> <Role name="WebRole1"> <Instances count="1" /> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" /> </ConfigurationSettings> </Role> </ServiceConfiguration> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=AccountName; AccountKey=AccountKey"/> </ConfigurationSettings>
Be default, Azure does not collect all available diagnostics data so that it can save system resources. Table 16-1 shows which diagnostics data is collected and how that data is formatted.
Data Source | Default Collection | Format |
Windows Azure Logs | Yes | Table |
IIS Logs | Yes | Blob |
Infrastructure Logs | Yes | Table |
Event Logs | No | Table |
Failed request logs | No | Blob |
Performance Counters | No | Table |
Crash Dumps | No | Blob |
Custom Logs | No | Blob |
To add the logs not collected by default, you need to perform different procedures based on the type of log. The next sections step through collecting each of the different nondefault logs.
To collect IIS failed requests, you need to modify the web.config for your web role in Azure. You must add code to the system.webServer section to include the providers you want to track, such as Authentication, CGI, Security, and so on. In addition, you can configure the HTTP status codes that you want for collection. The following code shows how to modify the system.webServer section to turn on the IIS failed request collection.
<tracing> <traceFailedRequests> <add path="*"> <traceAreas> <add provider="ASP" verbosity="Verbose" /> <add provider="ASPNET" areas="Infrastructure,Module,Page, AppServices" verbosity="Verbose" /> <add provider="ISAPI Extension" verbosity="Verbose" /> <add provider="WWW Server" areas="Authentication, Security, Filter, StaticFile, CGI, Compression, Cache, RequestNotifications, Module" verbosity="Verbose" /> </traceAreas> <failureDefinitions statusCodes="400-599" /> </add> </traceFailedRequests> </tracing>
To collect the event log information, you need to write a bit of code after you deploy your Azure instance with the diagnostic monitoring enabled. To do this, you want to make sure your code references the Microsoft.WindowsAzure.Diagnostics.dll file. Then, you write code in your OnStart method for your role to configure the diagnostics module and add in your Windows Event Log datasource, such as System or Application. The following code shows you how to configure the Application event log. You cannot access the Security event log because of the locked down permissions that your Azure service accounts runs under.
using Microsoft.WindowsAzure.Diagnostics; var diags = DiagnosticMonitor.GetDefaultInitialConfiguration(); diags.WindowsEventLog.DataSources.Add(“Application!*”); //Set the timeframe for collection diags.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(1); //Restart the Diagnostic monitor with changes DiagnosticMonitor.Start( “Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString”, diags);
A couple caveats exist when working with event log collection:
//Put true for complete crash dump collection Microsoft.WindowsAzure.Diagnostics.CrashDumps.EnableCollection(false);
Azure also enables you to use tracing as a means to monitor the execution of your code. You can use three classes: System.Diagnostics.Trace, System.Diagnostics.Debug, and System.Diagnostics.TraceSource to trace your application. To do so, you initialize the trace listener. If you use Visual Studio, this step is done for you, but if you use a different tool, the following code shows how to configure the trace listener in your web.config or app.config file.
<system.diagnostics> <trace> <listeners> <add type= "Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics"> <filter type="" /> </add> </listeners> </trace> </system.diagnostics>
When enabled, you can use Trace statements to write out to the trace log. For example, if you want to write out a statement to the trace log, you can use Trace.WriteLine to add a new text line to the trace log.
In addition to using diagnostics and tracing, you can also use the performance monitor to track the performance of key counters in your Azure applications. As with the other methods, you must modify your OnStart method in your web role to enable your performance counter monitoring. As with event logs, you must specify the path to your performance counters. For example, if you want to collect the % Processor Time, the path would be Processor(_Total)\% Processor Time, or if you want to collect the available memory, you use MemoryAvailable MBytes. The easiest way to figure out these paths is to use performance monitor to view these counters and construct their paths from the user interface navigation.
When you have your path, you can configure Azure Diagnostics to start collecting your performance counters similar to the way you did for the other diagnostic technologies, as shown in the following code:
using Microsoft.WindowsAzure.Diagnostics; var diags = DiagnosticMonitor.GetDefaultInitialConfiguration(); diags.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration() { CounterSpecifier = @"Processor(_Total)\% Processor Time", SampleRate = TimeSpan.FromSeconds(5) }); diags.PerformanceCounters.ScheduledTransferPeriod = TimeSpan.FromSeconds(1d); diags.PerformanceCounters.BufferQuotaInMB = 512; //Set the timeframe for collection diags.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(1); //Restart the Diagnostic monitor with changes DiagnosticMonitor.Start(“ Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString”, diags);
Viewing your logs is straightforward whether you use the local debugging environment or your Azure Storage Account using Visual Studio. In the Server Explorer in Visual Studio, you can open either your local storage environment or the Azure Storage environment to view both your blobs and your tables. Make sure that you enable your Azure Storage account by using the Properties dialog for your Web Role in Visual Studio and provide the account and key for your Azure Storage account, as shown in Figure 16-6.
You also must configure Azure to ship the logs over to your storage account by modifying the WebRole.cs under the OnStart() method, as shown earlier in the chapter. After you make all these changes, you can deploy your solution to Azure and start viewing your logs in Visual Studio, as shown in Figure 16-7.
When working with diagnostics, try to leverage as many tools as you can to quickly configure and deploy your diagnostic settings and code. Visual Studio provides a number of tools (such as Intellitrace, discussed earlier in the chapter) but there are also third-party tools that you should consider. Windows Azure MMC is a tool that enables you to monitor and manage your Azure deployment. You can upload, deploy, or upgrade your Azure instances. You can also configure the diagnostics for Azure, which may be faster than writing all the configuration code. You can find the MMC tool at http://wapmmc.codeplex.com/. Figure 16-8 shows the Windows Azure MMC interface.
In this chapter, you learned how to monitor and debug your Azure applications. By leveraging technologies such as Intellitrace, profiling, and diagnostics, you can ensure that your Azure applications run in a scalable manner, and if you do encounter errors, you can figure out those errors more quickly.