1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Lambdaのタイムアウトを検知する (Terraform)

Last updated at Posted at 2024-09-22

概要

  • AWS Lambda のタイムアウトを検知する実装を解説します
  • 実装の Terraform コードサンプルを提供します
  • CloudWatchLogs MetricFilter におけるハックをお伝えします

AWS Lambdaのタイムアウトを検知する実装

想定ケース

以下のように、EventBridge経由でLabmdaを実行するケースを考えます

architecture

引用:

Lambdaの仕様

Lambdaは以下の仕様を持っています

  • タイムアウト設定のデフォルト値は 3 秒です
  • 最大値の 900 秒 (15 分) まで 1 秒単位で調整できます
  • タイムアウトエラーとなった場合、2回までリトライされます

望ましくないシナリオ

  • Lambdaの処理時間は、ユーザー数に比例する
  • ユーザー数が漸増する
  • あるタイミングからLambdaのタイムアウト+リトライが発生し始める
  • 上記を検知する機構がない

発生する問題

このシナリオにより、以下のような問題が生じます

  • Lambdaの処理が完了できていないことに気づけない
  • 意味のないリトライにより、コストが増加する

解決方法

本質的にはタイムアウトが起こらないように処理の並行化などを検討すべきでしょうが、
まずは最低限タイムアウトが発生しないように、タイムアウトの時間を伸ばします

その上で、将来的なタイムアウトを検知できる機構を実装しておきましょう

実装の概要

実装の概要は以下の通りです
なお、最後の通知先はビジネスニーズによると思いますので、本記事では解説しません

  • タイムアウト時、CloudWatchLogsに"Task timed out"というログが出力される
  • 上記を検出するCloudWatchLogs MetricFilterを作成する
  • MetricFilterを検知してSNSトピックに通知するMetricAlarmを設定する
  • (Option) SNSの送信先をChatBotにすることでSlackに通知する

概要図

lambda-timeout-notification.jpg

実装のTerraformコードサンプル

それでは、実装のTerraform コードサンプルを提供します

CloudWatchLogs MetricFilter

"Task timed out"を検知するMetricFilterを作成します

// NOTE: Lambdaのタイムアウトを検知。以下のAWS re:Postを参考に作成
// https://repost.aws/ja/knowledge-center/lambda-verify-invocation-timeouts
resource "aws_cloudwatch_log_metric_filter" "sample_task_timed_out" {
  log_group_name = "/aws/lambda/${local.lambda_name}"
  name           = "${local.lambda_name}-task-timed-out"
  pattern        = "Task timed out"

  // 任意で設定可。CloudWatchLogs MetricAlarmで利用する
  metric_transformation {
    name      = "TaskTimedOut"
    namespace = ${local.lambda_name}
    value     = 1
  }
}

CloudWatchLogs MetricAlarm & SNS Topic

作成したMetricFilterを検知するMetricAlarmを作成します

resource "aws_cloudwatch_metric_alarm" "sample_task_timed_out" {
  alarm_name          = "${local.lambda_name}-task-timed-out"
  namespace           = local.lambda_name
  metric_name         = "TaskTimedOut"
  statistic           = "Sum"
  threshold           = 1
  period              = 60
  evaluation_periods  = 1
  datapoints_to_alarm = 1
  comparison_operator = "GreaterThanOrEqualToThreshold"
  alarm_actions       = [aws_sns_topic.sample_task_timed_out.arn]
  ok_actions          = [aws_sns_topic.sample_task_timed_out.arn]
  insufficient_data_actions = [aws_sns_topic.sample_task_timed_out.arn]
  alarm_description   = <<-EOT
                          ## Lambdaがタイムアウトしました
                          Lambdaがタイムアウトし、処理は完了しませんでした
                          開発者までお知らせください
                        EOT
}

resource "aws_sns_topic" "sample_task_timed_out" {
  name = "alert-${local.lambda_name}-task-timed-out"
}

CloudWatchLogs MetricFilterにおけるハック

ところで、この"Task timed out"では検知できずにタイムアウトが発生する場合がありました
原因は正直よくわからないのですが、その場合は"status": "timeout"がログに出力されるようです
仮に偽陽性になっても運用開始後に調整できるので、一旦このパターンも検出できるようにしました
同じ問題にお困りの方は参考にしてみてください

以下はterrafromのコード例です

// NOTE: 上記のフィルターでは検出できないLambdaのタイムアウトのパターンがあるため、"status": "timeout"の場合も検知
resource "aws_cloudwatch_log_metric_filter" "sample_status_timeout" {
  log_group_name = "/aws/lambda/${local.lambda_name}"
  name           = "${local.lambda_name}-status-timeout"
  pattern        = "\"\\\"status\\\":\\\"timeout\\\"\""

  metric_transformation {
    name      = "StatusTimeout"
    namespace = local.lambda_name
    value     = 1
  }
}

resource "aws_cloudwatch_metric_alarm" "sample_status_timeout" {
  alarm_name          = "${local.lambda_name}-status-timeout"
  namespace           = local.lambda_name
  metric_name         = "StatusTimeout"
  statistic           = "Sum"
  threshold           = 1
  period              = 60
  evaluation_periods  = 1
  datapoints_to_alarm = 1
  comparison_operator = "GreaterThanOrEqualToThreshold"
  alarm_actions       = [aws_sns_topic.sample_task_timed_out.arn]
  ok_actions          = [aws_sns_topic.sample_task_timed_out.arn]
  insufficient_data_actions = [aws_sns_topic.sample_task_timed_out.arn]
  alarm_description   = <<-EOT
                          ## Lambdaがタイムアウトしました
                          Lambdaがタイムアウトし、処理は完了しませんでした
                          開発者までお知らせください
                        EOT
}

参考

以下の記事を参考にしました

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?