procurement-ingest/terraform/po_alarms.tf

270 lines
8.9 KiB
HCL

resource "aws_cloudwatch_log_metric_filter" "po_sender_auth_rejected" {
name = local.po_sender_auth_filter_name
log_group_name = aws_cloudwatch_log_group.po_email_processor.name
pattern = "\"sender_auth_rejected\""
metric_transformation {
name = "po-email-processor-sender-auth-rejected"
namespace = "Seahaven/ProcurementIngest"
value = "1"
default_value = "0"
}
}
resource "aws_cloudwatch_metric_alarm" "po_email_processor_errors" {
alarm_name = "po-email-processor-errors"
alarm_description = "po-email-processor async invocation errors"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "Errors"
namespace = "AWS/Lambda"
period = 300
statistic = "Sum"
threshold = 0
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_email_processor.function_name
}
}
resource "aws_cloudwatch_metric_alarm" "po_email_processor_throttles" {
alarm_name = "po-email-processor-throttles"
alarm_description = "po-email-processor invocation throttles"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "Throttles"
namespace = "AWS/Lambda"
period = 300
statistic = "Sum"
threshold = 0
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_email_processor.function_name
}
}
resource "aws_cloudwatch_metric_alarm" "po_email_processor_dlq" {
alarm_name = "po-email-processor-dlq-messages"
alarm_description = "po-email-processor DLQ has messages (dropped PO emails)"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "ApproximateNumberOfMessagesVisible"
namespace = "AWS/SQS"
period = 300
statistic = "Maximum"
threshold = 0
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
QueueName = aws_sqs_queue.po_email_processor_dlq.name
}
}
resource "aws_cloudwatch_metric_alarm" "po_email_processor_duration" {
alarm_name = "po-email-processor-duration"
alarm_description = "po-email-processor p99 duration approaching the 60s timeout"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 3
datapoints_to_alarm = 2
metric_name = "Duration"
namespace = "AWS/Lambda"
period = 300
extended_statistic = "p99"
threshold = 45000
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_email_processor.function_name
}
}
resource "aws_cloudwatch_metric_alarm" "po_email_processor_sender_auth_rejected" {
alarm_name = "po-email-processor-sender-auth-rejected"
alarm_description = "po-email-processor rejected inbound mail on sender authentication (possible allowlist/DKIM-domain drift silently dropping real mail)"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 6
datapoints_to_alarm = 2
metric_name = "po-email-processor-sender-auth-rejected"
namespace = "Seahaven/ProcurementIngest"
period = 300
statistic = "Sum"
threshold = 1
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
}
resource "aws_cloudwatch_metric_alarm" "po_email_processor_fallback_rate" {
alarm_name = "po-email-processor-template-fallback-rate"
alarm_description = "po-email-processor deterministic-template coverage collapse: >20% of parses fell back to the Bedrock AI extractor"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 4
datapoints_to_alarm = 2
threshold = 20
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
metric_query {
id = "expr_1"
expression = "IF((FILL(fb,0)+FILL(tmpl,0))>=8, 100*FILL(fb,0)/(FILL(fb,0)+FILL(tmpl,0)), 0)"
label = "TemplateFallbackRatePct"
return_data = true
}
metric_query {
id = "fb"
metric {
metric_name = "ParseOutcome"
namespace = "Seahaven/PoIngest"
period = 21600
stat = "Sum"
dimensions = {
ParseMethod = "ai_fallback"
}
}
return_data = false
}
metric_query {
id = "tmpl"
metric {
metric_name = "ParseOutcome"
namespace = "Seahaven/PoIngest"
period = 21600
stat = "Sum"
dimensions = {
ParseMethod = "template"
}
}
return_data = false
}
}
resource "aws_cloudwatch_metric_alarm" "po_email_processor_ai_fallback_rejected" {
alarm_name = "po-email-processor-ai-fallback-rejected"
alarm_description = "po-email-processor is rejecting Bedrock AI-fallback output at the validation gate (possible prompt-injection probing or template drift silently dropping real mail)"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 4
datapoints_to_alarm = 2
threshold = 1
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
metric_query {
id = "expr_1"
expression = "IF(FILL(rej,0)>=1, FILL(rej,0), 0)"
label = "AiFallbackRejectedCount"
return_data = true
}
metric_query {
id = "rej"
metric {
metric_name = "ParseOutcome"
namespace = "Seahaven/PoIngest"
period = 21600
stat = "Sum"
dimensions = {
ParseMethod = "ai_fallback_rejected"
}
}
return_data = false
}
}
resource "aws_cloudwatch_metric_alarm" "po_web_ui_throttles" {
alarm_name = "po-web-ui-throttles"
alarm_description = "po-web-ui invocation throttles"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "Throttles"
namespace = "AWS/Lambda"
period = 300
statistic = "Sum"
threshold = 0
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_web_ui.function_name
}
}
resource "aws_cloudwatch_metric_alarm" "po_web_ui_duration" {
alarm_name = "po-web-ui-duration"
alarm_description = "po-web-ui p99 duration approaching the 60s timeout"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 3
datapoints_to_alarm = 2
metric_name = "Duration"
namespace = "AWS/Lambda"
period = 300
extended_statistic = "p99"
threshold = 45000
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_web_ui.function_name
}
}
resource "aws_cloudwatch_metric_alarm" "po_site_extractor_errors" {
alarm_name = "po-ingest-site-extractor-errors"
alarm_description = "po-ingest-site-extractor invocation errors"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "Errors"
namespace = "AWS/Lambda"
period = 300
statistic = "Sum"
threshold = 0
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_site_extractor.function_name
}
}
resource "aws_cloudwatch_metric_alarm" "po_site_extractor_throttles" {
alarm_name = "po-ingest-site-extractor-throttles"
alarm_description = "po-ingest-site-extractor invocation throttles"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "Throttles"
namespace = "AWS/Lambda"
period = 300
statistic = "Sum"
threshold = 0
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_site_extractor.function_name
}
}
resource "aws_cloudwatch_metric_alarm" "po_site_extractor_duration" {
alarm_name = "po-ingest-site-extractor-duration"
alarm_description = "po-ingest-site-extractor p99 duration approaching the 60s timeout"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 3
datapoints_to_alarm = 2
metric_name = "Duration"
namespace = "AWS/Lambda"
period = 300
extended_statistic = "p99"
threshold = 45000
treat_missing_data = "notBreaching"
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
dimensions = {
FunctionName = aws_lambda_function.po_site_extractor.function_name
}
}