Tutorial: Troubleshoot an App Service app with Azure Monitor

This tutorial shows how to troubleshoot an App Service app using Azure Monitor. The sample app includes code meant to exhaust memory and cause HTTP 500 errors, so you can diagnose and fix the problem using Azure Monitor. When you're finished, you have a sample app running on App Service on Linux integrated with Azure Monitor.

Azure Monitor maximizes the availability and performance of your applications and services by delivering a comprehensive solution for collecting, analyzing, and acting on telemetry from your cloud and on-premises environments.

In this tutorial, you learn how to:

  • Configure a web app with Azure Monitor
  • Send console logs to Log Analytics
  • Use Log queries to identify and troubleshoot web app errors

You can follow the steps in this tutorial on macOS, Linux, Windows.

If you don't have an Azure subscription, create a trial account before you begin.

Prerequisites

To complete this tutorial, you need:

Create Azure resources

First, you run several commands locally to set up a sample app to use with this tutorial. The commands create Azure resources, create a deployment user, and deploy the sample app to Azure. You're prompted for the password supplied as a part of the creation of the deployment user.

az group create --name myResourceGroup --location "China East"
az webapp deployment user set --user-name <username> --password <password>
az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku B1 --is-linux
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app-name> --runtime "PHP|8.1" --deployment-local-git
az webapp config appsettings set --name <app-name> --resource-group myResourceGroup --settings DEPLOYMENT_BRANCH='main'
git clone https://github.com/Azure-Samples/App-Service-Troubleshoot-Azure-Monitor
cd App-Service-Troubleshoot-Azure-Monitor
git branch -m main
git remote add azure <url-from-app-webapp-create>
git push azure main

Configure Azure Monitor

Create a Log Analytics Workspace

Now that you've deployed the sample app to Azure App Service, you configure monitoring capability to troubleshoot the app when problems arise. Azure Monitor stores log data in a Log Analytics workspace. A workspace is a container that includes data and configuration information.

In this step, you create a Log Analytics workspace to configure Azure Monitor with your app.

az monitor log-analytics workspace create --resource-group myResourceGroup --workspace-name myMonitorWorkspace

Create a diagnostic setting

Diagnostic settings can be used to collect metrics for certain Azure services into Azure Monitor Logs for analysis with other monitoring data using log queries. For this tutorial, you enable the web server and standard output/error logs. See supported log types for a complete list of log types and descriptions.

You run the following commands to create diagnostic settings for AppServiceConsoleLogs (standard output/error) and AppServiceHTTPLogs (web server logs). Replace <app-name> and <workspace-name> with your values.

Note

The first two commands, resourceID and workspaceID, are variables to be used in the az monitor diagnostic-settings create command. See Create diagnostic settings using Azure CLI for more information on this command.

resourceID=$(az webapp show -g myResourceGroup -n <app-name> --query id --output tsv)

workspaceID=$(az monitor log-analytics workspace show -g myResourceGroup --workspace-name <workspace-name> --query id --output tsv)

az monitor diagnostic-settings create --resource $resourceID \
 --workspace $workspaceID \
 -n myMonitorLogs \
 --logs '[{"category": "AppServiceConsoleLogs", "enabled": true},
  {"category": "AppServiceHTTPLogs", "enabled": true}]'

Troubleshoot the app

Browse to http://<app-name>.chinacloudsites.cn.

The sample app, ImageConverter, converts included images from JPG to PNG. A bug has been deliberately placed in the code for this tutorial. If you select enough images, the app produces an HTTP 500 error during image conversion. Imagine this scenario wasn't considered during the development phase. You'll use Azure Monitor to troubleshoot the error.

Verify the app works

To convert images, click Tools and select Convert to PNG.

Click Tools and select Convert to PNG

Select the first two images and click convert. This converts successfully.

Select the first two images

Break the app

Now that you've verified the app by converting two images successfully, we try to convert the first five images.

Convert first five images

This action fails and produces a HTTP 500 error that wasn't tested during development.

The convert will result in a HTTP 500 error

Use log query to view Azure Monitor logs

Let's see what logs are available in the Log Analytics workspace.

Click this Log Analytics workspace link to access your workspace in the Azure portal.

In the Azure portal, select your Log Analytics workspace.

Log queries

Log queries help you to fully apply the value of the data collected in Azure Monitor Logs. You use log queries to identify the logs in both AppServiceHTTPLogs and AppServiceConsoleLogs. See the log query overview for more information on log queries.

View AppServiceHTTPLogs with log query

Now that we've accessed the app, let's view the data associated with HTTP requests, found in the AppServiceHTTPLogs.

  1. Click Logs from the left-hand navigation.

Log Anlytics Worksace Logs

  1. Search for appservice and double-click AppServiceHTTPLogs.

Log analytics Workspace Tables

  1. Click Run.

Log Analytics Workspace App Service HTTP Logs

The AppServiceHTTPLogs query returns all requests in the past 24-hours. The column ScStatus contains the HTTP status. To diagnose the HTTP 500 errors, limit the ScStatus to 500 and run the query, as shown below:

AppServiceHTTPLogs
| where ScStatus == 500

View AppServiceConsoleLogs with log query

Now that you've confirmed the HTTP 500s, let's take a look at the standard output/errors from the app. These logs are found in `AppServiceConsoleLogs'.

(1) Click + to create a new query.

(2) Double-click the AppServiceConsoleLogs table and click Run.

Since converting five images results in server errors, you can see if the app is also writing errors by filtering ResultDescription for errors, as show below:

AppServiceConsoleLogs |
where ResultDescription  contains "error" 

In the ResultDescription column, you see the following error:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted 
(tried to allocate 16384 bytes) in /home/site/wwwroot/process.php on line 20, 
referer: http://<app-name>.chinacloudsites.cn/

Join AppServiceHTTPLogs and AppServiceConsoleLogs

Now that you've identified both HTTP 500s and standard errors, you need to confirm if there's a correlation between these messages. Next, you join the tables together based on the time stamp, TimeGenerated.

Note

A query has been prepared for you that does the following:

  • Filters HTTPLogs for 500 errors
  • Queries console logs
  • Joins the tables on TimeGenerated

Run the following query:

let myHttp = AppServiceHTTPLogs | where  ScStatus == 500 | project TimeGen=substring(TimeGenerated, 0, 19), CsUriStem, ScStatus;  

let myConsole = AppServiceConsoleLogs | project TimeGen=substring(TimeGenerated, 0, 19), ResultDescription;

myHttp | join myConsole on TimeGen | project TimeGen, CsUriStem, ScStatus, ResultDescription;

In the ResultDescription column, you'll see the following error at the same time as web server errors:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted 
(tried to allocate 16384 bytes) in /home/site/wwwroot/process.php on line 20, 
referer: http://<app-name>.chinacloudsites.cn/

The message states memory has been exhausted on line 20 of process.php. You've now confirmed that the application produced an error during the HTTP 500 error. Let's take a look at the code to identify the problem.

Identify the error

In the local directory, open the process.php and look at line 20.

imagepng($imgArray[$x], $filename);

The first argument, $imgArray[$x], is a variable holding all JPGs (in-memory) needing conversion. However, imagepng only needs the image being converted and not all images. Pre-loading images is not necessary and may be causing the memory exhaustion, leading to HTTP 500s. Let's update the code to load images on-demand to see if it resolves the issue. Next, you improve the code to address the memory problem.

Fix the app

Update locally and redeploy the code

You make the following changes to process.php to handle the memory exhaustion:

<?php

//Retrieve query parameters
$maxImages = $_GET['images'];
$imgNames  = explode(",",$_GET['imgNames']);

//Load JPEGs into an array (in memory)
for ($x=0; $x<$maxImages; $x++){
    $filename = './images/converted_' . substr($imgNames[$x],0,-4) . '.png';
    imagepng(imagecreatefromjpeg("./images/" . $imgNames[$x]), $filename);
}

Commit your changes in Git, and then push the code changes to Azure.

git commit -am "Load images on-demand in process.php"
git push azure main

Browse to the Azure app

Browse to http://<app-name>.chinacloudsites.cn.

Converting images should not longer produce the HTTP 500 errors.

PHP app running in Azure App Service

Clean up resources

In the preceding steps, you created Azure resources in a resource group. If you don't expect to need these resources in the future, delete the resource group by running the following command in the local Azure CLI:

az group delete --name myResourceGroup

This command may take a minute to run.

Delete the diagnostic setting with the following command:

az monitor diagnostic-settings delete --resource $resourceID -n myMonitorLogs

What you learned:

  • Configured a web app with Azure Monitor
  • Sent logs to Log Analytics
  • Used log queries to identify and troubleshoot web app errors

Next steps