Thursday, May 26, 2011

How to add Azure Diagnostics Trace

There are numerous ways to log and trace your application. Both build in with the framework, like debug and trace (listeners), and third parties like log4net, Elmah. Common for all these scenarios, is the writing to file or windows event log. Useful features like rolling files, and event logs that only grows to a given size is a must for productions systems.

Moving to the cloud and Azure this becomes a bit new. Where is the log written now? And how can I access the log? There is no easy way of accessing the file system, and behind the scene there might even be multiple instances of servers. Once I got this working, nothing was really strange or difficult. But googling around, and reading blogs sometimes made me and my code even more confused. This is apparently a mine field of typos, and changes from one version to another. What seemed to work for some, surely did not for me.

I will walk you through the steps needed to make a successful entry in Azure Storage, and how to read them.

First the cloud needs a setting. Here I got redirected in every other way for each blog I read. This worked for me.

Entries in web.config:

   1: <system.diagnostics>



   2:   <trace autoflush="true">



   3:     <listeners>



   4:       <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"



   5:         name="AzureDiagnostics"  >



   6:         <filter type="" />



   7:       </add>



   8:     </listeners>



   9:   </trace>



  10: </system.diagnostics>




The class WebRole.cs:





   1: public class WebRole : RoleEntryPoint



   2: {



   3:     public override bool OnStart()



   4:     {



   5:         // To enable the AzureLocalStorageTraceListner, uncomment relevent section in the web.config  



   6:         DiagnosticMonitorConfiguration diagnosticConfig = DiagnosticMonitor.GetDefaultInitialConfiguration();



   7:         diagnosticConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);



   8:         diagnosticConfig.Directories.DataSources.Add(AzureLocalStorageTraceListener.GetLogDirectory());



   9:  



  10:         // For information on handling configuration changes



  11:         // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.



  12:         diagnosticConfig.Logs.ScheduledTransferPeriod = TimeSpan.FromSeconds(15);



  13:         diagnosticConfig.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;



  14:         DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", diagnosticConfig);



  15:         Trace.TraceInformation("OnStart completed.");



  16:  



  17:         return base.OnStart();



  18:     }



  19: }





ServiceConfiguration.cscfg:





   1: <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=myaccountname;AccountKey=longcryptingstringwithlotsofnumbersandchars" />





The name should be “Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString”. Quite a few blog posts have an other setting name, but this must be on previous versions. The value replaces the default setting “UseDevelopmentStorage=true”. The settings for AccountName and AccountKey are found where you created the storage account:



azure



 



From now on tracing should be as easy as



Trace.TraceInformation("Add some trace info.");





Reading the log I found that Azure Diagnostic Manager from Cerebrata. They also have an online tool Cloud Storage Studio. A screenshot from the first mentioned looks like this:



image



























Mission complete. My traces are now logged to the cloud. Once completed this is nothing much or complex. If only I had this recipe in advance..

Wednesday, May 18, 2011

WCF Azure and Connection Strings

Moving to Azure some changes to the old way of using web.config must be done. Connection strings and applications settings that used to be in the web.config, might have to move to the cloud as well.

A rule of thumb is that settings that change with each deployment could still be in the web.config. But settings that remains constants, but are different in staging and production must be in the ConfigurationSettings in ServiceConfiguration.cscfg.

ServiceDefinition.csdef:
<ConfigurationSettings>
  <Setting name="MyConnectionString" />
</ConfigurationSettings>

ServiceConfiguration.cscfg:
<ConfigurationSettings>
  <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
  <Setting name="MyConnectionString" value="server=tcp:XXX.database.windows.net; database=YYY; user id=ZZZ@XXX; password=***" />
</ConfigurationSettings>

Inside your code you can access this setting like this:

var connectionString = Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue("MyConnectionString");

SQL Azure

Moving the database to the cloud was trivial. Everything behavous more or less the same from Visual Studio and SQL Server Management Studio. I have discovered a few odd issues. I guess most of them actually are related to the the Management Studio, not the database in the cloud.

For instance if you create a table, the designer are not available yet. So you stick with T-SQL statements. If you right click on the table, and select “Script table as –> Create to –> New query editor window” you could end up with a script like this:

CREATE TABLE [dbo].[Person2](
[Id] [
int] IDENTITY(1,1) NOT NULL,
[FirstName] [varchar](
50) NOT NULL,
[LastName] [varchar](
50) NOT NULL,
[BornDate] [date] NOT NULL,
[AddressLine1] [varchar](
50) NULL,
[AddressLine2] [varchar](
50) NULL,
[PostalCodeNumber] [varchar](
4) NULL,
[PostalCodeName] [varchar](
50) NULL,
[Gender] [varchar](
10) NOT NULL,
[Received] [date] NULL,
[DeadDate] [date] NULL,
[ReservationCode] [varchar](
3) NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX
= OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)


And if you try to run this, you will actually end up with an error message




Keyword or statement option 'pad_index' is not supported in this version of SQL Server.



Remove the part WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) and everything works just fine.



The statement “SELECT *  FROM [MyCloud].[dbo].[Person]” from Management Studio works just fine if the correct databaseimage is selected in the upper left corner. But if you disconnect and reconnect, the default database ‘master’ is selected. And eventhough the select statement has the [MyCloud] database spesified, you will get the error “Reference to database and/or server name in 'MyCloud.dbo.Person' is not supported in this version of SQL Server.” Which is kind of confusion.