This is the third and final entry on this series on logging from an Azure hosted service.
These topics included:
1. Synchronizing a log file to blob storage
2. Using a custom log4net appender to write directly to table storage
3. Logging to the Trace log and synchronizing to table storage
These solutions are in order of complexity (in my opinion). Each topic outlines the structure of the solution, how to implement it, and the pros/cons of the solution compared to the others.
3. Logging to the Trace log
I left this solution for last not because of ease-of-use, the setup for trace logging is fairly simple, to me this is the most complex because of the amount of components in place.
There are a number of features built into the Azure Diagnostics Module. The purpose of this module is to forward valuable diagnostic information to a storage account, there it can be reviewed manually or consumed by an application like System Center Operations Manager. Trace logs are included in the diagnostic data that can be managed by the Azure Diagnostics Module. This final solution involves setting up the diagnostics monitor, configuring a Trace Listener, and finally configuring log4net to write to the Trace Log. This includes a few steps so in summary this is the path of the log message.
log4net >> Trace Log >> Diagnostics Listener >> Diagnostics Monitor >> Table Storage
A similar solution can be configured with Event Logs which has the following flow.
log4net >> Event Log >> Diagnostic Monitor >> Table Storage
Setup
This example will mainly use the app.config file for the Trace Listener configuration but this could also be done programmatically with the Trace static class.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="TraceAppender" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="TraceAppender" />
</root>
</log4net>
<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>
</configuration>
Once the Diagnostic Monitor Trace Listener is setup the trace messages will be sent to the diagnostic monitor. The following code will setup and start the monitor.
public override bool OnStart()
{
var diagnostics = DiagnosticMonitor.GetDefaultInitialConfiguration();
diagnostics.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;
diagnostics.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
CloudStorageAccount account = CloudStorageAccount.Parse(
RoleEnvironment.GetConfigurationSettingValue(
"Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"));
DiagnosticMonitor.Start(account, diagnostics);
return base.OnStart();
}
Setting the Verbose level allows the log4net appender and filters to set logging level, this will allow all messages through to the logger. The Logs property configures the Trace logs, to setup the event logs use the .WindowsEventLogs property. Finally to configure log4net and write messages use the following code. This is the same code in all the solutions.
private ILog _logger;
public override void Run()
{
XmlConfigurator.Configure();
_logger = LogManager.GetLogger(GetType());
_logger.Info("Starting Worker Role");
while (true)
{
Thread.Sleep(10000);
_logger.Info("Waiting 10 Seconds");
}
}
Pros / Cons
Pros: This solution requires very little setup and can be done with mainly configuration. The log messages are stored in Table Storage, the message rows contain lots of information about the logging level, process and other Azure hosted service information. The biggest pro for this solution is that the log messages can be consumed by System Center Operations Manager. Also, the log tables can be managed with the PowerShell cmdlets.
Cons: If not configured correctly this solution can be difficult to debug, mainly due to the amount of components involved. Compared to Part 2 (straight to Table Storage) you have no control over the columns which makes querying for trends very difficult, even impossible since Table Storage does not support a “contains” clause.
Like all of the solutions the need to be combined with a log management system to archive or truncate the log messages. This is more important with Azure storage because you are charged per GB of storage.
Summary
I hope this series has given you some information on logging from an Azure Hosted Service. I know writing them has helped me work through some of the subtle differences in the logging mechanisms.
There are a variety of solutions for logging and diagnostics in Azure, the most common are the three presented. If you have any questions about the solutions please leave a comment or contact me on Twitter @tyler_gd.
As always, thank you for reading.