top of page

Crea métricas personalizadas para trabajos de AWS Glue

  • victoriagimenez5
  • 29 jul
  • 3 Min. de lectura

Actualizado: 19 ago

ree


Como sabes, CloudWatch te permite publicar métricas personalizadas desde tus aplicaciones. Estas son métricas que no son proporcionadas directamente por los servicios de AWS.


Tradicionalmente, estas métricas se publicaban llamando a la API PutMetricData de CloudWatch desde tu aplicación, generalmente usando el SDK de AWS para el lenguaje de tu preferencia.


Con el nuevo formato de métricas embebidas de CloudWatch (EMF), puedes simplemente incluir las métricas personalizadas dentro de los logs que tu aplicación envía a CloudWatch, y CloudWatch extraerá automáticamente estas métricas de los registros. Luego, puedes graficarlas desde la consola de CloudWatch e incluso configurar alarmas y notificaciones como lo harías con cualquier métrica estándar.


Esto funciona en cualquier entorno desde el cual envíes logs a CloudWatch: instancias EC2, máquinas on-prem, contenedores Docker/Kubernetes en ECS/EKS, funciones Lambda, etc.


En este caso, nos centraremos en crear métricas personalizadas para las ejecuciones de trabajos de AWS Glue. El objetivo final es crear una alarma de CloudWatch para identificar si una ejecución fue exitosa o no. La siguiente solución lo resuelve:



""

Infraestructura

Creamos la infraestructura y los permisos necesarios con Terraform:


Regla de evento y destino

hcl

resource "aws_cloudwatch_event_rule" "custom_glue_job_metrics" {
 name        = "CustomGlueJobMetrics"
 description = "Create custom metrics from glue job events
 is_enabled = true

 event_pattern = jsonencode({
       "source": ["aws.glue"],
       "detail-type": ["Glue Job State Change"] 
   })
}


resource "aws_cloudwatch_event_target" "custom_glue_job_metrics" {
 target_id = "CustomGlueJobMetrics"
 rule      = aws_cloudwatch_event_rule.custom_glue_job_metrics.name
 arn       = aws_lambda_function.custom_glue_job_metrics.arn

 retry_policy {
   maximum_event_age_in_seconds = 3600
   maximum_retry_attempts       = 0
 }
}





Lambda y permisos

resource "aws_lambda_function" "custom_glue_job_metrics" {
 function_name    = "CustomGlueJobMetrics"
 filename         = "python/handler.zip"
 source_code_hash = filebase64sha256("python/handler.zip")
 role             = aws_iam_role.custom_glue_job_metrics.arn
 handler          = "handler.handler"
 runtime          = "python3.9"
 timeout          = 90

 tracing_config {
   mode = "PassThrough"
 }
}

resource "aws_lambda_permission" "allow_cloudwatch" {
 statement_id  = "AllowExecutionFromCloudWatch"
 action        = "lambda:InvokeFunction"
 function_name = aws_lambda_function.custom_glue_job_metrics.function_name
 principal     = "events.amazonaws.com"
 source_arn    = aws_cloudwatch_event_rule.custom_glue_job_metrics.arn
}


Roles y políticas IAM



resource "aws_iam_role" "custom_glue_job_metrics" {
 name   = "CustomGlueJobMetrics"
 assume_role_policy = jsonencode({
     Version : "2012-10-17",
     Statement : [{
         Effect : "Allow",
         Principal : {
           Service : "lambda.amazonaws.com"
         },
         Action : "sts:AssumeRole"
       }]
 })
}

resource "aws_iam_role_policy" "custom_glue_job_metrics" {
 name  = "CustomGlueJobMetrics"
 role  = aws_iam_role.custom_glue_job_metrics.id

 policy = jsonencode({
   Version : "2012-10-17",
   Statement : [{
       Effect : "Allow",
       Action : [
         "logs:CreateLogGroup",
         "logs:CreateLogStream",
         "logs:PutLogEvents"
       ],
       Resource : "arn:aws:logs:*:*:*"
     }]
 })
}



Ya con esto, hemos creado la regla de eventos, su destino, una función Lambda (donde se ejecutará handler.py) y sus permisos necesarios.

Usamos el Event Bus por defecto.

Código Python

from aws_embedded_metrics import metric_scope


@metric_scope
def handler(event, _context, metrics):
   glue_job_name = event["detail"]["jobName"]
   glue_job_run_id = event["detail"]["jobRunId"]

   metrics.set_namespace(f"GlueBasicMetrics")
   metrics.set_dimensions(
       {"JobName": glue_job_name}, {"JobName": glue_job_name, "JobRunId": glue_job_run_id}
   )

   if event["detail-type"] == "Glue Job State Change":
       state = event["detail"]["state"]

       if state not in ["SUCCEEDED", "FAILED", "TIMEOUT", "STOPPED"]:
           raise AttributeError("State is not supported.")

       metrics.put_metric(key=state.capitalize(), value=1, unit="Count"
       if state == "SUCCEEDED":
           metrics.put_metric(key="Failed", value=0, unit="Count")
       else:
           metrics.put_metric(key="Succeeded", value=0, unit="Count")


Este código crea un nuevo namespace (GlueBasicMetrics) dentro de CloudWatch con dos dimensiones (JobName y JobName, JobRunId). Se actualiza cada vez que se ejecuta un Glue Job, ya que el evento "Glue Job State Change" es el que dispara la Lambda.


Instalación de módulos y librerías

Como vimos en Terraform, importamos el código como un archivo .zip. Es fundamental que el código Python, el módulo aws-embedded-metrics y cualquier otra dependencia estén al mismo nivel dentro del .zip.



""

Instalación del módulo:

pip3 install aws-embedded-metrics
Alarma de CloudWatch

Ahora que tenemos las métricas, creamos la alarma de CloudWatch para detectar fallos en la ejecución:


resource "aws_cloudwatch_metric_alarm" "job_failed" {
 alarm_name          = "EtlJobFailed"
 metric_name         = "Failed"
 namespace           = "GlueBasicMetrics"
 period              = "60"
 statistic           = "Sum"
 comparison_operator = "GreaterThanOrEqualToThreshold"
 threshold           = "1"
 evaluation_periods  = "1"
 treat_missing_data  = "ignore"

 dimensions = {
   JobName = "IotEtlTransformationJob"
 }

 alarm_actions = ["aws_sns_topic.mail.arn", "aws_sns_topic.chatbot.arn"]

}

}

En este ejemplo, usamos una lista de temas SNS para enviar notificaciones por email o chatbot. Asegúrate de crear los tópicos necesarios para activar las alertas.


Conclusión

¡Y eso es todo!


Con unas pocas líneas de Terraform y Python, creamos una solución que monitorea el estado de ejecución de Glue Jobs, publica métricas personalizadas en CloudWatch y lanza alarmas automáticas en caso de fallo.

Esta práctica te ayuda a cumplir con los Pilares de Eficiencia Operativa y Eficiencia del Rendimiento del Well-Architected Framework de AWS.


""





Martín Carletti


Cloud Engineer


Teracloud









If you want to know more about Cloudwatch, we suggest checking Your AWS invoice is getting bigger and bigger because of CloudWatch Logs, and you don't know why? To learn more about cloud computing, visit our blog for first-hand insights from our team. If you need an AWS-certified team to deploy, scale, or provision your IT resources to the cloud seamlessly, send us a message here.




 
 
bottom of page