Capturing Azure Webapp application log in Azure Log Analytics

Let’s assume that you have webapp deployed as an app service in Azure. It would be great if we could utilize Log Analytics to capture logs. Currently it is possible to capture various types of details: Windows metrics, infrastructure logs etc., however, Log Analytics is unable to capture application logs. However, by using Webjob or Function we can push logs to OMS manually. Let’s go.

Webapp setup

First, we need to modify application to capture logs in storage. We need to reconfigure Trace so Azure can handle its results. In MVC or WebAPI application we need to add listener in configuration file:

Next, we go to Azure Portal, choose our Webapp, go to Diagnostic Logs and enable Application Logging (Blob). We need to configure the storage connection string (so we need to create storage account).

Effect: when you try to log something using Trace, there will be a file in storage. File is appended and rolled each hour.

Okay, we have logs stored in Azure. Now its time to capture them and push to OMS.

Capturing

In order to capture file we can simply use Webjob or Azure Function. We can use storage trigger so the function will be executed each time there is new file or existing one is modified.

Unfortunately:

  • Storage trigger is not guaranteed to execute every time.
  • There also might be delays.
  • We don’t have information whether the file is new or modified.
  • Trigger works simply by scanning whole storage container. It might result in slower response times if you have lots of logs. Also, scan results are stored in the storage.

Good thing is dead letter queue. In case of failure, trigger will execute up to five times and if we are still unable to process the file it will be moved to special queue with poisoned files.

Here goes the code for pushing file to Log Analytics:

You can also introduce Service Bus and push there message after finding new blob. Service Bus guarantees that the message will not get lost.

You can also use Azure Function instead of Webjob — it might be simpler.