자습서: Azure Monitor를 사용하여 App Service 앱 문제 해결

이 자습서에서는 Azure Monitor를 사용하여 App Service 앱의 문제를 해결하는 방법을 보여줍니다. 샘플 앱에는 메모리를 소모하고 HTTP 500 오류가 발생하는 코드가 포함되어 있으므로 Azure Monitor를 사용하여 문제를 진단하고 해결할 수 있습니다. 완료되면 Azure Monitor와 통합된 App Service on Linux에서 샘플 앱이 실행됩니다.

Azure Monitor는 클라우드 및 온-프레미스 환경에서 원격 분석을 수집, 분석 및 작동하기 위한 종합적인 솔루션을 제공하여 애플리케이션 및 서비스의 가용성과 성능을 극대화합니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • Azure Monitor를 사용하여 웹앱 구성
  • Log Analytics에 콘솔 로그 보내기
  • 로그 쿼리를 사용하여 웹앱 오류 식별 및 해결

이 자습서의 단계는 macOS, Linux, Windows에서 수행할 수 있습니다.

Azure를 구독하고 있지 않다면 시작하기 전에 Azure 체험 계정을 만듭니다.

필수 조건

이 자습서를 완전히 학습하려면 다음이 필요합니다.

Azure 리소스 만들기

먼저 여러 명령을 로컬로 실행하여 이 자습서에서 사용할 샘플 앱을 설정합니다. 이러한 명령은 Azure 리소스를 만들고, 배포 사용자를 만들고, 샘플 앱을 Azure에 배포합니다. 배포 사용자를 만드는 과정에서 제공된 암호를 묻는 메시지가 표시됩니다.

az group create --name myResourceGroup --location "South Central US"
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

Azure Monitor 구성

Log Analytics 작업 영역 만들기

이제 샘플 앱을 Azure App Service에 배포했으므로 문제가 발생할 때 앱 문제를 해결할 수 있도록 모니터링 기능을 구성합니다. Azure Monitor는 로그 데이터를 Log Analytics 작업 영역에 저장합니다. 작업 영역은 데이터 및 구성 정보를 포함하는 컨테이너입니다.

이 단계에서는 앱을 사용하여 Azure Monitor를 구성하기 위해 Log Analytics 작업 영역을 만듭니다.

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

진단 설정 만들기

진단 설정을 사용하면 로그 쿼리를 사용하여 다른 모니터링 데이터를 분석하기 위해 특정 Azure 서비스에 대한 메트릭을 Azure Monitor 로그에 수집할 수 있습니다. 이 자습서에서는 웹 서버 및 표준 출력/오류 로그를 사용하도록 설정합니다. 로그 유형 및 설명의 전체 목록은 지원되는 로그 유형을 참조하세요.

다음 명령을 실행하여 AppServiceConsoleLogs(표준 출력/오류) 및 AppServiceHTTPLogs(웹 서버 로그)에 대한 진단 설정을 만듭니다. <app-name><workspace-name>을 사용자 고유의 값으로 바꿉니다.

참고 항목

처음 두 명령인 resourceIDworkspaceIDaz monitor diagnostic-settings create 명령에 사용되는 변수입니다. 이 명령에 대한 자세한 내용은 Azure CLI를 사용하여 진단 설정 만들기를 참조하세요.

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}]'

앱 문제 해결

http://<app-name>.azurewebsites.net으로 이동합니다.

ImageConverter 샘플 앱은 포함된 이미지를 JPG에서 PNG로 변환합니다. 이 자습서의 코드에는 버그가 의도적으로 배치되었습니다. 이미지가 충분하게 선택되면 이미지 변환 중에 앱에서 HTTP 500 오류를 생성합니다. 이 시나리오는 개발 단계에서 고려되지 않았다고 가정합니다. Azure Monitor를 사용하여 이 오류를 해결합니다.

앱 작동 확인

이미지를 변환하려면 Tools를 클릭하고 Convert to PNG를 선택합니다.

도구를 클릭하고 PNG로 변환 선택

처음 두 이미지를 선택하고 convert를 클릭합니다. 이렇게 하면 성공적으로 변환됩니다.

처음 두 이미지 선택

앱 중단

이제 두 이미지를 성공적으로 변환하여 앱을 확인했으므로 처음 5개의 이미지를 변환하려고 합니다.

처음 5개 이미지 변환

이 작업이 실패하고 개발 중에 테스트되지 않은 HTTP 500 오류가 생성됩니다.

변환하면 HTTP 500 오류가 발생합니다.

로그 쿼리를 사용하여 Azure Monitor 로그 보기

Log Analytics 작업 영역에서 사용할 수 있는 로그를 확인해 보겠습니다.

Log Analytics 작업 영역 링크를 클릭하여 Azure Portal의 작업 영역에 액세스합니다.

Azure Portal에서 Log Analytics 작업 영역을 선택합니다.

로그 쿼리

로그 쿼리를 사용하면 Azure Monitor 로그에서 수집된 데이터의 값을 완벽하게 적용할 수 있습니다. 로그 쿼리를 사용하여 AppServiceHTTPLogs 및 AppServiceConsoleLogs 모두에서 로그를 식별합니다. 로그 쿼리에 대한 자세한 내용은 로그 쿼리 개요를 참조하세요.

로그 쿼리를 사용하여 AppServiceHTTPLogs 보기

이제 앱에 액세스했으므로 AppServiceHTTPLogs에 있는 HTTP 요청과 연결된 데이터를 살펴보겠습니다.

  1. 왼쪽 탐색 영역에서 Logs를 클릭합니다.

Logs Anlytics 작업 영역 로그

  1. appservice를 검색하고 AppServiceHTTPLogs를 두 번 클릭합니다.

로그 분석 작업 영역 테이블

  1. Run을 클릭합니다.

Log Analytics 작업 영역의 App Service HTTP 로그

AppServiceHTTPLogs 쿼리는 지난 24시간 동안의 모든 요청을 반환합니다. ScStatus 열에는 HTTP 상태가 포함되어 있습니다. HTTP 500 오류를 진단하려면 아래와 같이 ScStatus를 500으로 제한하고 쿼리를 실행합니다.

AppServiceHTTPLogs
| where ScStatus == 500

로그 쿼리를 사용하여 AppServiceConsoleLogs 보기

이제 HTTP 500을 확인했으므로 앱의 표준 출력/오류를 살펴보겠습니다. 이러한 로그는 'AppServiceConsoleLogs'에 있습니다.

(1) +를 클릭하여 새 쿼리를 만듭니다.

(2) AppServiceConsoleLogs 테이블을 두 번 클릭하고, Run을 클릭합니다.

5개의 이미지를 변환하면 서버 오류가 발생하므로 아래와 같이 오류에 대해 ResultDescription을 필터링하여 앱에서 오류도 기록하는지 확인할 수 있습니다.

AppServiceConsoleLogs |
where ResultDescription  contains "error" 

ResultDescription 열에 다음 오류가 표시됩니다.

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>.azurewebsites.net/

AppServiceHTTPLogs 및 AppServiceConsoleLogs 조인

HTTP 500 및 표준 오류를 모두 식별했으므로 이러한 메시지 간에 상관 관계가 있는지 확인해야 합니다. 다음으로, TimeGenerated 타임스탬프를 기준으로 테이블을 조인합니다.

참고 항목

다음 작업을 수행하는 쿼리가 준비되었습니다.

  • 500 오류에 대해 HTTPLogs 필터링
  • 콘솔 로그 쿼리
  • TimeGenerated를 기준으로 테이블 조인

다음 쿼리를 실행합니다.

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;

ResultDescription 열에 웹 서버 오류와 동시에 다음 오류가 표시됩니다.

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>.azurewebsites.net/

메시지 상태 메모리가 process.php의 20번 줄에서 모두 소모되었습니다. 이제 HTTP 500 오류 중에 애플리케이션에서 오류를 생성했음을 확인했습니다. 문제를 식별하는 코드를 살펴보겠습니다.

오류 식별

로컬 디렉터리에서 process.php를 열고 20번 줄을 살펴봅니다.

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

첫 번째 $imgArray[$x] 인수는 변환이 필요한 모든 JPG를 포함하는 변수(메모리 내)입니다. 그러나 imagepng에서는 모든 이미지가 아니라 일부 이미지만 변환하면 됩니다. 이미지를 미리 로드할 필요가 없으며, 메모리 소모로 인해 HTTP 500이 발생할 수 있습니다. 필요에 따라 이미지를 로드하여 문제가 해결되는지 확인하도록 코드를 업데이트해 보겠습니다. 다음으로, 코드를 개선하여 메모리 문제를 해결합니다.

앱 수정

로컬로 코드 업데이트 및 다시 배포

메모리 소모를 처리하기 위해 process.php를 다음과 같이 변경합니다.

<?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);
}

Git에서 변경 내용을 커밋한 다음 Azure에 코드 변경 내용을 푸시합니다.

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

Azure 앱 찾아보기

http://<app-name>.azurewebsites.net으로 이동합니다.

이미지를 변환하면 HTTP 500 오류가 더 이상 생성되지 않습니다.

Azure App Service에서 실행 중인 PHP 앱

리소스 정리

이전 단계에서는 리소스 그룹에서 Azure 리소스를 만들었습니다. 나중에 이러한 리소스가 필요하지 않을 것 같으면 Cloud Shell에서 다음 명령을 실행하여 리소스 그룹을 삭제합니다.

az group delete --name myResourceGroup

이 명령을 실행하는 데 1분 정도 걸릴 수 있습니다.

다음 명령을 사용하여 진단 설정을 삭제합니다.

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

학습한 내용은 다음과 같습니다.

  • Azure Monitor를 사용하여 웹앱 구성
  • Log Analytics에 로그 보내기
  • 로그 쿼리를 사용하여 웹앱 오류 식별 및 해결

다음 단계