Azure API Apps Diagnostics - azure-web-app-service

I have an Azure API App that needs to log trace data, so have chosen to use Azure Diagnostics and .Net System.Diagnostics.Trace.
The trace message logs to Table Storage, but the Event Id field is 0. The documentation online suggests 0 is the default value, but I cannot see an obvious way to set the Event Id.
Trace.TraceError, Trace.TraceInformation and Trace.TraceWarning only take a string or a formatted message.
Would some know if it is possible to set the Event Id and if so how?
Thanks
Andy

Although I cannot take credit for the answer, I thought I should post the answer I found here: https://blogs.msdn.microsoft.com/mcsuksoldev/2014/09/04/adding-trace-to-azure-web-sites-and-web-jobs/
Basically you use the System.Diagnostics.TraceSource type and call the TraceEvent() method. Although this won't work without some configuration first.
There are three trace listeners to be aware of, although for just TableStorage it is only the first:
AzureTableTraceListener
AzureBlobTraceListener
AzureDriveTraceListener
You will need to install the nuget package: Microsoft.WindowsAzure.WebSites.Diagnostics
The code example from the link above is:
public static readonly TraceSource Operational = new TraceSource("Operational");
Operational.TraceEvent(TraceEventType.Verbose, 101, "TraceEvent WebSite Operational");
For the TraceSource to log to TableStorage you need to add the following to the web.config:
<system.diagnostics>
<sharedListeners>
<add name="AzureTableTraceListener" type="Microsoft.WindowsAzure.WebSites.Diagnostics.AzureTableTraceListener, Microsoft.WindowsAzure.WebSites.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</sharedListeners>
<sources>
<source name="Operational" switchName="OperationalSourceSwitch" switchType="System.Diagnostics.SourceSwitch">
<listeners>
<add name="AzureTableTraceListener"/>
<add name="AzureBlobTraceListener"/>
</listeners>
</source>
</sources>
<switches>
<add name="OperationalSourceSwitch" value="All" />
</switches>
<trace autoflush="true" indentsize="4" />
Andy

Related

Why is CloudConfigurationManager using my Cloud.cscfg instead of Local.cscfg too?

I do realise that his question was asked and answered, but unfortunately the solution of complete clean, rebuild, restart.. doesn't work in my case and my lowly reputation doesn't allow me to comment. So I am I think compelled to ask it again with my info.
Sample code:
CloudStorageAccount storageAccount;
string settings = CloudConfigurationManager.GetSetting("StorageConnectionString");
storageAccount = CloudStorageAccount.Parse(settings);
I have my web.config section like this:
<appSettings>
<add key="owin:AppStartup" value="zzzz" />
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=xxxx;AccountKey=yyyy"/>
</appSettings>
In the ServiceConfiguration.Cloud.cscfg I have:
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=nnnn" />
<Setting name="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=xxxx;AccountKey=yyyy"/>
</ConfigurationSettings>
and in the ServiceConfiguration.Local.cscfg I have:
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
<Setting name="StorageConnectionString" value="UseDevelopmentStorage=true" />
</ConfigurationSettings>
I converted this to an Azure project from a standard MVC web project in order to use the Azure storage blobs etc. I am finding that no matter what I seem to do it always uses the Azure storage.
As I step through the code snippet above.. I can clearly see the returned connection string as the one coming from the web.config app setting... I feel I must be doing something fundamentally wrong or missing something..?
A small point (maybe?) as I converted the project over, there was an error message (on a pop up and not saveable) about a connection string error and it not working. I hadn't even created this particular connection string at that time and the only other one (for localDB does work). That however is in the web.config section and as it ain't broke I didn't fix it to go into the ..
Any help would be appreciated.
Further Addition, from the comments by Igorek below, I did check the Role settings and they appear to be correct.
Then .. after a lot of messing around, some experiments which still didn't work, I've taken a step back. I actually don't want a cloud service, I ended up with one because I thought I needed one to access Blobs and Queues, I had already decided that WebJobs seems like the way to go first to keep as abstracted as possible.
So I have rolled back to prior to the Web SITE that I had before and found but I still CAN'T seem to get it to use development storage.. although I imagine that CLoudConfigurationManager probably doesn't handle Web Sites? Any tips?
Check into settings of your Role within the cloud project. It will have a default for which configuration it starts with. Simply swap from Cloud to Local.

Clear steps for setting up Azure Diagnostics

I am trying to get diagnostics tracing working, but I am confused about necessary steps I have to follow. I will present what I have done until now:
In app.config I have following:
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="ProfileTrace" switchName="profileTraceSwitch" switchType="System.Diagnostics.SourceSwitch">
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics">
<filter type="" initializeData="Warning" />
</add>
<add name="LogFileListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="..\..\..\skype.portal.profile.log" traceOutputOptions="ProcessId, ThreadId" />
</listeners>
</source>
</sources>
<switches>
<add name="profileTraceSwitch" value="Verbose"/>
</switches>
</system.diagnostics>
In Service.Definition I have following:
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
In Service.Configuration I have:
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<snip>;AccountKey=<snip>" />
I have following confusion right now. As you can see in app.config I tried to add a filter for DiagnosticMonitorTraceListener to trace only Warnings, but this filter was ignored. I found this post, which suggests to use custom trace listener that derives from DiagnosticMonitorTraceListener http://social.msdn.microsoft.com/forums/wpapps/en-us/92ed1175-d6b7-4173-a224-0f7eb3e99481/diagnosticmonitortracelistener-ignors-filter
On the other hand in following official link from microsoft http://msdn.microsoft.com/en-us/library/ee758610.aspx they leave filter type empty:
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener,
Microsoft.WindowsAzure.Diagnostics,
Version=1.0.0.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35"
name="AzureDiagnostics">
<filter type="" />
</add>
Then they mention about configuring Logs property http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.diagnostics.diagnosticmonitorconfiguration.logs.aspx where I see:
public override bool OnStart() {
......
// Filter the logs so that only error-level logs are transferred to persistent storage.
diagnosticConfiguration.Logs.ScheduledTransferLogLevelFilter = LogLevel.Error;
......
return base.OnStart();
}
}
So, I have following 2 questions:
In my current solution I haven't written any code on Start method of WorkerRole to configure Diagnostic Monitor, but after some searching I found that many people do this. I ran my project locally and I was able to see data stored in Azure WADLogsTable. So, is it mandatory to add Diagnostic Monitor configuration code to my Worker role or can I just have diagnostics.wadcfg?
Since filters for DiagnosticMonitorTraceListener in app.config file are ignored, if I skip the use of a custom trace listener that derives from DiagnosticMonitorTraceListener suggested here http://social.msdn.microsoft.com/forums/wpapps/en-us/92ed1175-d6b7-4173-a224-0f7eb3e99481/diagnosticmonitortracelistener-ignors-filter and use ScheduledTransferLogLevelFilter of Logs property in my WorkerRole, will I achieve the log filter I want? Or maybe filter in app.config and ScheduledTransferLogLevelFilter refer to 2 different kind of filters?
I would recommend against setting the Azure diagnostic configuration in code. Instead, I would recommend using the diagnostic.wadcfg file approach. You can find some info here - http://msdn.microsoft.com/en-us/library/hh411551.aspx. Visual Studio will help generate this file as well.
It is not mandatory to set any Azure diagnostic configuration in your role's OnStart() method.
Setting the ScheduledTransferLogLevelFilter should suffice. Plus, that also enables you to easily change the filter level at runtime if needed (via an API call, Visual Studio, or 3rd party tool like Cerebrata Azure Management Studio).

NServiceBus saga not handling messages on azure

I'm getting strange behavior of working NServiceBus sagas deployed on azure cloud service. They never get replied message, never wake up... although if it's deployed locally everything works fine, also sagas works correctly when it's on WebApi cloud service role...
public class EndpointConfiguration : IConfigureThisEndpoint, IWantCustomInitialization,
AsA_Worker, UsingTransport<AzureStorageQueue>
{
public void Init()
{
Feature.Disable<Gateway>();
Feature.Disable<SecondLevelRetries>();
Feature.Enable<TimeoutManager>();
Feature.Enable<Sagas>();
Configure.With()
.UsingContainer<AutofacContainerBuilder>()
.AzureConfigurationSource()
.AzureMessageQueue()
.QueuePerInstance()
.UseNHibernateSagaPersister()
.UseNHibernateSubscriptionPersister()
.UseNHibernateTimeoutPersister()
.UnicastBus();
}
}
that's my config for nsb
<configSections>
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
<section name="DBSubscriptionStorageConfig" type="NServiceBus.Config.DBSubscriptionStorageConfig, NServiceBus.NHibernate" />
<section name="NHibernateSagaPersisterConfig" type="NServiceBus.Config.NHibernateSagaPersisterConfig, NServiceBus.NHibernate" />
<section name="TimeoutPersisterConfig" type="NServiceBus.Config.TimeoutPersisterConfig, NServiceBus.NHibernate" />
</configSections>
<UnicastBusConfig>
<MessageEndpointMappings>
<add Messages="Service.InternalMessages" Endpoint="service" />
<add Messages="Messages" Endpoint="service" />
</MessageEndpointMappings>
</UnicastBusConfig>
<DBSubscriptionStorageConfig>
<NHibernateProperties>
<add Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider" />
<add Key="connection.driver_class" Value="NHibernate.Driver.SqlClientDriver" />
<add Key="connection.connection_string" Value="Data_Source;Connection Timeout=30;" />
<add Key="dialect" Value="NHibernate.Dialect.MsSql2008Dialect" />
<add Key="hbm2ddl.auto" Value="update" />
</NHibernateProperties>
</DBSubscriptionStorageConfig>
<NHibernateSagaPersisterConfig>
<NHibernateProperties>
<add Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider" />
<add Key="connection.driver_class" Value="NHibernate.Driver.SqlClientDriver" />
<add Key="connection.connection_string" Value="Data_Source;Connection Timeout=30;" />
<add Key="dialect" Value="NHibernate.Dialect.MsSql2008Dialect" />
<add Key="hbm2ddl.auto" Value="update" />
</NHibernateProperties>
</NHibernateSagaPersisterConfig>
<TimeoutPersisterConfig>
<NHibernateProperties>
<add Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider" />
<add Key="connection.driver_class" Value="NHibernate.Driver.SqlClientDriver" />
<add Key="connection.connection_string" Value="Data_Source;Connection Timeout=30;" />
<add Key="dialect" Value="NHibernate.Dialect.MsSql2008Dialect" />
<add Key="hbm2ddl.auto" Value="update" />
</NHibernateProperties>
</TimeoutPersisterConfig>
that's the configs that I'm using for persisters
NServiceBus.Hosting.Azure, NServiceBus.NHibernate, NServiceBus.Core, NServiceBus.Azure, NServiceBus all of v4.0.30319
I'm using AzureStorageQueue and also I'm sure that I have overridden ConfigureHowToFindSaga with proper ConfigureMapping and I'm replying message with all filed specified correctly...
I would be really appreciate for any ideas, thanks.
This will be an interesting one to figure out. I don't see anything obviously wrong.
So the symptoms are, it works locally (with the exact same config?) and it works when deployed in a webrole (are these the same saga's or different ones?).
Some background info on the latter: a webrole only differs from a worker role in that IIS is properly configured, that's it. This also means that in a webrole, your code is running in 2 places, in an IIS process and in the roleentrypoint process. So you may want to validate that you're actually hosting in a roleentrypoint (namespace NServiceBus.Azure.Hosting and not the default azure sdk one.)
If you're sure the initialisation is done in the right place, you may want to check if you get any errors in the azure logs?
If that doesn't give more detail, you can also enable intellitrace in your solution and download the traces to see what is going on in more detail.
And as a last option, you can also use windbg on the azure instance (RDP'd in) to debug in real time.
Hope any of the above helps!

Azure project lost endpoints and uses default now?

A weird thing happened to my project. I have an Azure WCF project which basically consists of the WebRole and the Azure project. Azure Project contains ServiceDefinition.csdef which in turn contains stuff like endpoint information.
I was playing around in my WebRole and manually set an endpoint there. However, my original issue, due to a stupid user error, did not require this. After I removed the endpoint devinition from web.config, my webrole still gets bound to port 6627 instead of the two endpoints described in my Azure project (80 & 8080). I can't find that port being mentioned anywhere so I'm guessing it is the default.
Here's the part of the web.config that I edited (the removed part is in comments). How do I revert back to getting the configuration from the Azure project?
<system.serviceModel>
<!-- services>
<service name="MyWebRole.MyService" behaviorConfiguration="MyWebRole.BasicUserInformationBehavior">
<endpoint address="" binding="mexHttpBinding" contract="MyWebRole.IMyService"/>
</service>
</services -->
<extensions>
<behaviorExtensions>
<add name="userInformationProcessor" type="MyWebRole.BasicUserInformationBehaviorExtensionElement, MyWebRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<bindings />
<client />
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<userInformationProcessor />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
[Edit] More information on the subject! The problem is related to compute emulator no longer starting at all! I don't know why the service works then, but I guess it's running it IIS alone.
I think the solution as mentioned in the comment is that you have to set up the Windows Azure project as the startup project not the webrole.

Logging of OpenRasta exceptions in IIS

How can I enable logging of any exceptions that occur in my handlers, or codecs etc. in IIS?
When googling for that, I found a couple of different ways on how to setup tracing. One of those actually worked, but the trace file (xml) is not very user-friendly. I'd like to have something like a standard text log file that I can view and manipulate using standard tools.
OpenRasta uses TraceSources to log requests, so you can use any implementation of log files for tracesources by providing the right configuration in your web.config.
<system.diagnostics>
<sources>
<source name="openrasta" switchName="OpenRasta">
<listeners>
<add name="ErrorLog" />
</listeners>
</source>
</sources>
<switches>
<!--<add name="OpenRasta" value="Warning,Error"/>-->
<add name="OpenRasta" value="All"/>
</switches>
<sharedListeners>
<add name="ErrorLog"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\myListener.log" />
</sharedListeners>
</system.diagnostics>
I'm not sure however what you mean by standard text log files. Standard log files use standard logs that IIS generates itself already, this part of your logging does not change and is configured the usual way in IIS.

Resources