はじめに
今回はAzureでデプロイしている仮想マシンから任意のログを収集し、Azure上の機能でアラートを出す方法をご紹介します。
検証用のPowerShellスクリプトも添付いたしますので、検証したい方はこの記事に沿って検証ができるようにハンズオンとして構成しております。
対象読者
- Azureを使用する現場に従事している方
- Azureの資格勉強をしている方
- Azureに興味がある方
- クラウドに興味がある方
免責事項
ハンズオンにあたって料金がかかります。筆者が記事作成の間リソースを使用した分で200円ほどでした。記事の最後にリソースの削除の仕方も解説しておりますので、ハンズオンが終了したら削除を実施してもらうようお願いします。
また、Azureの画面に関しては、2024年08月22日時点のものを使用しております。
使用サービス・技術
・Azure Monitor
Microsoft Azure上のリソースやアプリケーションのパフォーマンスと可用性を監視・管理するサービスです。メトリクスやログを収集・分析し、問題を早期に発見して対応を促すアラート通知する機能を持ちます。
・Azure Monitor エージェント(以下、AMA)
Azure環境における監視データを収集するためのエージェントです。仮想マシンやコンテナからメトリクスやログを集め、Azure Monitorに送信します。
・データ収集ルール(以下、DCR)
Azure Monitorにおいて監視データを収集するための設定ルールです。DCRを使用すると、(AMA)などを通じて収集するデータの種類、送信先(例えばLog AnalyticsワークスペースやAzure Monitor Metrics)を柔軟に指定できます。
・データ収集エンドポイント(以下、DCE)
Azure Monitorがさまざまなソースからメトリック、ログ、イベントなどのデータを収集するためのエンドポイントです。これらのエンドポイントを通じて、Azureリソースやオンプレミス環境、およびハイブリッドクラウド環境からデータを収集し、監視と診断に役立てることができます。
・Log Analyticsワークスペース(以下、ワークスペース)
Azure Monitorの一部として提供されるデータストレージと分析のプラットフォームです。Azureリソースやアプリケーションから収集されたログやメトリクスデータを集中管理し、クエリやダッシュボードを通じてデータの分析や可視化を行います。
・クストクエリ言語(以下、KQL)
Azure MonitorやLog Analyticsなどで使用されるクエリ言語です。大量のログデータやメトリクスデータを効率的に検索、フィルタ、集計、可視化するために設計されています。SQLに似た構文を持ち、ログの解析、異常検出、トレンド分析などに強力です。
・アラートルール
Azure Monitorで定義される監視ルールであり、特定の条件やしきい値を満たした際に通知や自動アクションをトリガーする仕組みです。システムの異常やリソースの過剰利用などを迅速に検知し、運用チームに通知を送ったり、指定の自動化プロセスを実行したりできます。
1. 要件
独自のアプリケーションのログをAzure上に収集・分析し、アラートを出したい。
お客様の要件は、アプリケーションが出力するテキストログをAzure上に収集し、その中で異常を示す文言があった場合メールでアラートを出したいという要件でした。
2. 解決策
AMAとDCRでカスタムログを収集し、KQLを使ってアラートを定義する
AzureではAMAをVMにインストールし、DCRを定義することでワークスペースにログを収集することができます。
ログを収集できればKQLで検索できるようになるので、KQLの検索結果を使ってアラートを定義することで、要件を満たすことができます。
3. ハンズオン
それでは実際に設定していきます。
3-1.VM作成
まず、ログを出力するためのWindows serverインスタンスを起動します。
Azureポータルを開き、VM作成画面を開きます。

「基本」タブでリソースグループ・仮想マシン名・イメージ・管理者アカウント情報等を入力します。


VMへの接続が成功したら、この記事に添付しているログ生成スクリプトをVM内のデスクトップに貼り付けます。

Powershellの画面が開き、ログが生成されます。もし入力が要求された場合「A」と入力してEnterを押してください。
C:\log\testファイルが作成され、ログが10秒ごとに追記されていきます。

ログファイルは以下のような形式になっています。
2022-12-31T01:00:00.1234567Z | Computer=TestVM01 | Log=Service stop
2022-12-31T01:01:00.1234567Z | Computer=TestVM01 | Log=Service start
2022-12-31T01:02:00.1234567Z | Computer=TestVM01 | Log=Service stop
Powershellは実行したままにしておいてください。
3-2以降で、こちらのログファイルをAzureに収集するように設定していきます。
3-2.ワークスペースの作成
Azureポータルから[Log Analyticsワークスペース]に移動します。

3-3.DCEの作成
3-4.カスタムテーブルの作成
Powershellで開きます。(CloudShell用のストレージアカウントは無くても大丈夫です。)

以下のスクリプトでワークスペースにカスタムテーブルを作成します。{}で囲まれた部分は環境によって異なるので、適宜置き換えてください。
$tableParams = @'
{
"properties": {
"schema": {
"name": "{TableName}_CL",
"columns": [
{
"name": "TimeGenerated",
"type": "DateTime"
},
{
"name": "RawData",
"type": "String"
},
{
"name": "HostName",
"type": "String"
},
{
"name": "Log",
"type": "String"
}
]
}
}
}
'@
Invoke-AzRestMethod -Path "/subscriptions/{subscriptionID}/resourcegroups/{resourcegroup}/providers/microsoft.operationalinsights/workspaces/{WorkspaceName}/tables/{TableName}_CL?api-version=2021-12-01-preview" -Method PUT -payload $tableParams
参考までに、筆者は以下のように編集しました。※サブスクリプションIDなどは環境によって異なるので、適宜編集してください。
$tableParams = @'
{
"properties": {
"schema": {
"name": "Test_CL",
"columns": [
{
"name": "TimeGenerated",
"type": "DateTime"
},
{
"name": "RawData",
"type": "String"
},
{
"name": "HostName",
"type": "String"
},
{
"name": "Log",
"type": "String"
}
]
}
}
}
'@
Invoke-AzRestMethod -Path "/subscriptions/4400b795-f4d1-42d3-8862-90e1cd037744/resourcegroups/testvm_group/providers/microsoft.operationalinsights/workspaces/testLA/tables/Test_CL?api-version=2021-12-01-preview" -Method PUT -payload $tableParams
3-5.DCRの作成
「基本」タブの各項目を入力し、[次へ:リソース]をクリックします。

VMが追加されたことを確認し、[次へ:収集と配信]をクリックします。

「収集と配信」タブで、[+データソースの追加]をクリックします。

[データソースの種類] にて [カスタムテキストログ] を選択します。
[ファイルパターン] にて収集先のログファイル パスを指定します。
今回はWindows上のテキストログを取得することを想定し、以下のパスを入力します
C:\log\test.log
[テーブル名] には3-4で作成したテーブル名 (_CL 含む) を指定します。
[Transform] には、以下のクエリを設定してデータを整形します。
source| extend TimeGenerated = now()| parse RawData with * "Computer="HostName "| " *| parse RawData with * "Log="Log"
「ターゲット」タブにて3-2で作成したワークスペースを追加し、[データソースの追加]をクリックします。

3-6.データ収集の確認
データが収集できているか確認します。(※データ収集はDCRを作成してから、10~30分ほどかかります。最長で2時間かかることもあるみたいです。)
新しいクエリ右側の[・・・]→[スコープの変更]をクリックします。

「範囲の選択」画面にて3-2で作成したワークスペースを選択し、[適用]をクリックします。

以下のクエリを入力し、実行します。結果が表示されれば、問題なく収集できています。
Test_CL
3-7.アラートルールの作成
最後に、Azureに収集したログを使用してアラートを設定します。
今回は、Logテーブルに"Service stop"という文言が記録されたときにアラートが出るように設定します。
[アラート]→[作成]→[アラートルール]をクリックします。

「リソースの選択」にて、3-2で作成したワークスペースを選択します。

「条件」タブ内のシグナル名で「カスタムログ検索」を選択します。

「ログ」画面が開くので、以下のクエリを入力し、[アラートの編集を続行する]をクリックします。

「条件」タブの残りの項目を以下のように入力し、[次へ:アクション]をクリックします。

「アクション」タブにて[アクショングループの作成]をクリックします。

「アクショングループの作成」画面が開くので、「基本」タブの項目を入力し、[次へ:通知>]をクリックします。

「通知」タブの「通知タイプ」で[電子メール/SMS メッセージ/プッシュ/音声]を選択します。

開いた「電子メール/SMS メッセージ/プッシュ/音声」画面で通知先を設定します。

「アラートの作成」画面に戻るので、[次へ:詳細>]をクリックします。

「詳細」タブで各項目を入力し、[確認及び作成]をクリックします。

3-8.アラートの確認
アラートが発報されるか確認します。
アラートが発報されると「アラート」画面に以下のように表示されます。

以上で、すべての設定が完了しました。
3-9.リソースの削除
ハンズオンが終了したら、課金が発生しないようにリソースを削除しておきましょう。
Azureポータルから[リソースグループ]をクリックします。

しばらくして、以下のように通知が来たらリソースの削除完了です。

おわりに
今回は、VM内の任意のログをAzureに収集してアラートを定義する方法を紹介しました。
設定によってはオンプレミスの任意のログも収集することができます。
アプリケーションのログもAzureで収集して一元的にアラートを出すことができるので、便利です。
現場で私と同じような機会があれば、上記ハンズオンを参考にして使用してみてください。
使用するPowershellスクリプト
下記のスクリプトをテクストファイルに貼り付け保存して使用してください。
# ログファイルのパスを指定
$logFilePath = "C:\log\test.log"
# ディレクトリが存在しない場合は作成
$logDirectory = [System.IO.Path]::GetDirectoryName($logFilePath)
if (-not (Test-Path $logDirectory)) {
New-Item -Path $logDirectory -ItemType Directory -Force
}
# タイムスタンプを取得する関数
function Get-Timestamp {
return (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffffff")
}
# ホスト名を取得
$hostname = [System.Net.Dns]::GetHostName()
# ログメッセージを追加する関数
function Write-Log {
param (
[string]$logMessage
)
$timestamp = Get-Timestamp
$message = "$timestamp | Computer=$hostname | Log=$logMessage"
$maxRetries = 5
$retryCount = 0
$retryDelay = 1 # seconds
while ($retryCount -lt $maxRetries) {
try {
$fileStream = [System.IO.File]::Open($logFilePath, [System.IO.FileMode]::Append, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Read)
$writer = New-Object System.IO.StreamWriter($fileStream)
$writer.WriteLine($message)
$writer.Close()
$fileStream.Close()
break
} catch {
$retryCount++
Start-Sleep -Seconds $retryDelay
} finally {
if ($writer -ne $null) {
$writer.Close()
}
if ($fileStream -ne $null) {
$fileStream.Close()
}
}
}
if ($retryCount -ge $maxRetries) {
Write-Error "Failed to write log after $maxRetries attempts."
}
}
# 無限ループで10秒毎にログを書き込む
while ($true) {
Write-Log "Service stop"
Start-Sleep -Seconds 10
Write-Log "Service start"
Start-Sleep -Seconds 10
}






























