🙄

C# .NETでCloudWatchログイベントをフィルタして取得する

2023/02/19に公開

フレームワーク

.NET 6

検証パッケージ

AWSSDK.CloudWatchLogs (3.7.104.20)

準備

ローカル環境で検証を行う場合は、configとcredentialsファイルを用意する必要があります(AWSSDKを利用する際は基本的に必要になる)

シンプルに実装

/// <summary>
/// CloudWatchの/xxxx/xxxxxxxxロググループに出力されている直近1時間のERRORログを取りたい
/// </summary>
public async Task<List<string>> LogEventsRequest()
{
    // リクエストに必要なパラメータ
    var requestParam = new Amazon.CloudWatchLogs.Model.FilterLogEventsRequest()
    {
	StartTime = DateTimeOffset.Now.AddHours(-1).ToUnixTimeMilliseconds(),
	FilterPattern = "ERROR",
	LogGroupName = "/xxxx/xxxxxxxx",
    };

    using (var client = new Amazon.CloudWatchLogs.AmazonCloudWatchLogsClient())
    {
	// ログイベントのリクエスト
	var response = await client.FilterLogEventsAsync(requestParam);

	// 取得後のログは、response.Events内でJson形式になっているのでDeserializeが必要
	var eventMessages = response.Events.Select(x => System.Text.Json.JsonSerializer.Deserialize<Log>(x.Message));

	// ログ文字列のみを返す
	return eventMessages.Select(x => x.Message).ToList();
    }
}

// JSONのDeserialize用 状況に応じて変更してください
public record Log(string Message);

CloudWatch側で扱うログイベントが多い場合の実装

FilterLogEventsは以下の制限があるので、ログの規模が大きい場合は複数回に分けてリクエストを行います

By default, this operation returns as many log events as can fit in 1 MB (up to 10,000 log events) or all the events found within the specified time range.

注意点: FilterLogEventsは1リクエスト1MB制限がありますが、無制限にリクエストを行うと個人では払えない額の料金を請求されることがあるので注意してください。

/// <summary>
/// CloudWatchの/xxxx/xxxxxxxxロググループに出力されている直近1時間のERRORログを取りたい
/// </summary>
public async Task<List<string>> LogEventsRequest()
{
    // リクエストに必要なパラメータ
    var requestParam = new Amazon.CloudWatchLogs.Model.FilterLogEventsRequest()
    {
	StartTime = DateTimeOffset.Now.AddHours(-1).ToUnixTimeMilliseconds(),
	FilterPattern = "ERROR",
	LogGroupName = "/xxxx/xxxxxxxx",
    };

    var messages = new List<string>();
    using (var client = new Amazon.CloudWatchLogs.AmazonCloudWatchLogsClient())
    {
	var nextToken = string.Empty;
	const int MAX_LOOP_COUNT = 10;
	for (var i = 0; i < MAX_LOOP_COUNT; i++)
	{
	    if (!string.IsNullOrEmpty(nextToken))
		requestParam.NextToken = nextToken;

	    // ログイベントのリクエスト
	    var response = await client.FilterLogEventsAsync(requestParam);

	    // NextTokenを利用して、次回のリクエストで続きからのログを取得します
	    nextToken = response.NextToken;

	    // 取得後のログは、response.Events内でJson形式になっているのでDeserializeが必要
	    var eventMessages = response.Events.Select(x => System.Text.Json.JsonSerializer.Deserialize<Log>(x.Message));

	    // ログ文字列のみを利用
	    messages.AddRange(eventMessages.Select(x => x.Message).ToList());
	}
    }

    return messages;
}

// JSONのDeserialize用 状況に応じて変更してください
public record Log(string Message);

参考

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatchLogs/latest/APIReference/API_FilterLogEvents.html

Discussion