Introduction
In the first part of these series, I talked about built-in diagnostics features of Windows Azure platform and mentioned that it gives high-level diagnostic information; for detail troubleshooting information a custom logging capability is recommended. In this post, I will propose a solution that writes custom/detail logs to Azure storage tables. Please note that this post is only relevant to web sites – web sites that are hosted in Windows Azure platform.
Context
This post is not going to be about discussing “Everything is going to cloud?” or “Public vs Private Cloud” thing. However, in order to give you the solution standing, I would like to give you the big picture; and there it is
Source: http://www.notsotrivial.net/blog/image.axd?picture=image_38.png
Windows Azure SDK 1.0 and 2.0 editions comes with Microsoft.WindowsAzure.Diagnostics API that is built on top of ETW (Event Tracing for Windows) let’s write diagnostic information through the listeners. However, I could not use it for the web site, I was getting this exception when configure to use Azure diagnostics:
"SecurityException: The source was not found, but some or all event logs could not be searched. To create the source, you need permission to read all event logs to make sure that the new source name is unique. Inaccessible logs: Security"
As the message implies, I need to change permission levels as discussed here. But, that can’t be used for the web sites, but for Windows Azure cloud services (web and worker roles). For underlying design difference, please visit here. By design, you can’t run web sites with elevated permissions and can not RDP.
Proposed Solution
Ok, that should be enough background info. Let’s action.
Step 1: Create a storage account
Step 2: Write custom logging component
- In order to use storage table, we need a service context object. To construct it, we need at least those:
- Account name -defined above
- Account key (Primary or Secondary) -defined above
- Table name Add connection string - your wish
- Construct the service context
1:static Logger()
2: {
3: var storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
4: var tableClient = storageAccount.CreateCloudTableClient();
5:
6: tableName = "LogTrace";
7: tableClient.CreateTableIfNotExist(tableName);
8: serviceContext = tableClient.GetDataServiceContext();
9: }
- Create an entity holds log properties, sample here
1:publicclass TraceLog : TableServiceEntity
2: {
3:publicstring Message { get; set; }
4:publicstring Type { get; set; }
5:publicint Code { get; set; }
6:public DateTime TimeStamp { get; set; }
7: }
- And the method for log functionality
1:publicstaticvoid LogTrace(string message, EventLogEntryType type)
2: {
3: LogEntry(message, type, 7018);
4: }
5:
6:privatestaticvoid LogEntry(string message, EventLogEntryType etype, int eCode)
7: {
8:string type = etype == EventLogEntryType.Error
9: ? "Error"
10: : etype == EventLogEntryType.Warning ? "Warning" : "Information";
11:string pkey = string.Format("{0:D10}", DateTime.Now.Ticks >> 30);
12:string rkey = string.Format("{0:D19}", DateTime.Now.Ticks);
13:
14: serviceContext.AddObject(tableName, new TraceLog { PartitionKey = pkey, RowKey = rkey, Message = message, Type = type, Code = eCode, TimeStamp = DateTime.Now });
15: serviceContext.SaveChanges(SaveChangesOptions.ContinueOnError);
16: }
Step 3: Validation
Now, to test the solution, all we need to call the method; here I am calling from Application_Start() in the global.asax to trace when the application starts
1:protectedvoid Application_Start()
2: {
3: AreaRegistration.RegisterAllAreas();
4:
5: WebApiConfig.Register(GlobalConfiguration.Configuration);
6: FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
7: RouteConfig.RegisterRoutes(RouteTable.Routes);
8: BundleConfig.RegisterBundles(BundleTable.Bundles);
9: AuthConfig.RegisterAuth();
10:
11: Helpers.Logger.LogTrace("Web site started on server", EventLogEntryType.Information);
12: }
Press F5:), voila! I am able to see the entry in the storage table from the Storage Explorer tool as seen below (table name set to 'TraceLog'):
Conclusion
In this post, I stated that Azure diagnostic API is not usable for web sites and then shared a solution that writes custom logs to Windows Azure storage table with Geo-Replication capability. Hope you like it and happy clouding!
References: