Paneles

Diseñar paneles

Cuando las plantillas y los widgets de IA no bastan, un panel de CloudWatch te permite elegir tus métricas en una pantalla grande, con el selector de métricas, los cálculos y los umbrales de CloudWatch, y mantenerlas en CloudFormation o Terraform.

Actualizado el 19 de octubre de 2026

¿Por qué un panel?

No necesitas un panel para usar CloudPeek: las plantillas y los widgets de IA funcionan sin él. Un panel merece la pena cuando quieres elegir exactamente qué métricas vigilar: tus propias métricas personalizadas, recursos concretos, cálculos de métricas, umbrales o las alarmas que elijas. Encontrar el espacio de nombres y las dimensiones correctos, escribir cálculos de métricas y definir umbrales es mucho más fácil con un teclado y una pantalla grande, y CloudWatch ya tiene la herramienta para ello.

Un panel de CloudWatch es entonces, sencillamente, tu lista de lo que quieres vigilar:

  • Cada widget es algo que puedes fijar. Un widget agrupa una o varias métricas: la CPU de tres instancias en un gráfico de líneas, tus cinco mayores costos en un gráfico de barras, una tasa de errores calculada a partir de dos métricas en un número.
  • Cada panel es un conjunto de widgets que van juntos. Uno por servicio, uno para el gasto, otro para las guardias. Puedes fijar desde tantos paneles y cuentas como quieras.
  • Un panel es JSON sin más, así que se puede definir en CloudFormation, Terraform, el AWS CDK o cualquier otra herramienta que pueda escribir una cadena, e implementar junto con los servicios que vigila.

¿Ya tienes paneles? Fija directamente desde ellos. O crea uno pequeño solo para tu teléfono, únicamente con los widgets que quieres ver de un vistazo.

Diséñalo en la consola de AWS

  1. Abre la consola de CloudWatch, elige Paneles › Crear panel y ponle un nombre.
  2. Elige un tipo de widget: Líneas, Área apilada, Número, Indicador, Barras, Circular, Tabla, Texto o Estado de alarma. Todos funcionan en CloudPeek (consulta la referencia de widgets).
  3. En la pestaña Examinar, elige un espacio de nombres, como ApplicationELB o uno propio, y marca las métricas que quieras en este widget.
  4. En la pestaña Métricas diagramadas, define la estadística, el período y la etiqueta de cada métrica. Elige Agregar cálculo para una expresión como una tasa de errores, y desmarca las entradas que no quieras dibujar.
  5. En la pestaña Opciones, añade anotaciones horizontales para los umbrales y establece los límites del eje Y. Un indicador necesita tanto un mínimo como un máximo.
  6. Elige Crear widget, dale un título corto y guarda el panel con Guardar.

Abre el panel en CloudPeek y verás cada widget tal como quedará en tu pantalla de inicio. Fija los que quieras o añádelos con Crear widget › Desde un panel (consulta Crear un widget).

Que se lea bien en un teléfono

Un widget de la pantalla de inicio mide unos pocos centímetros. Unos cuantos hábitos lo hacen mucho más fácil de leer:

  • Una pregunta por widget. «¿Funciona bien la API?» se lee mejor como un número con la tasa de errores y un indicador de latencia que como un gráfico con ocho líneas.
  • Pocas series por gráfico. En los widgets medianos y grandes, la leyenda muestra hasta cuatro series y después «+N más». Un widget pequeño no tiene leyenda.
  • Títulos cortos. En el iPhone y el iPad, el widget en línea de la pantalla bloqueada conserva unos 18 caracteres del título, y el circular, unos 8.
  • Elige la vista según lo que quieras ver de un vistazo. Un número con "sparkline": true muestra el último valor y su tendencia; un indicador lo muestra frente a un rango que tú defines; un gráfico de barras ordena elementos. Consulta cómo se ve cada tipo.
  • Define el intervalo que te interesa. El start propio de un widget prevalece sobre el del panel y, si no hay ninguno, CloudPeek muestra las últimas 3 horas. Cada widget indica qué intervalo abarca.
  • Mejor etiquetas que ID. Pon una etiqueta (label) a las métricas para que la leyenda diga «Checkout API» en lugar de «app/checkout-api/50dc6c495c0c9188». Una etiqueta dinámica como ${PROP('Dim.ServiceName')} nombra cada serie según el valor de una dimensión.

Ejemplo: un panel de estado de una API

Tres widgets para un Application Load Balancer: la tasa de errores como número, la latencia p99 como indicador y las solicitudes frente a los errores en un gráfico de líneas. En CloudPeek se ven así:

La tasa de errores se calcula a partir de dos métricas ocultas; la línea de 5xx tiene su propia escala a la derecha.
api-health.jsonDescargar
{
  "start": "-PT3H",
  "widgets": [
    {
      "type": "metric",
      "x": 0,
      "y": 0,
      "width": 6,
      "height": 6,
      "properties": {
        "title": "5xx error rate",
        "view": "singleValue",
        "region": "us-east-1",
        "period": 300,
        "sparkline": true,
        "metrics": [
          [ { "expression": "100 * FILL(m2, 0) / m1", "label": "Errors (%)", "id": "e1" } ],
          [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "app/checkout-api/50dc6c495c0c9188", { "stat": "Sum", "id": "m1", "visible": false } ],
          [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "stat": "Sum", "id": "m2", "visible": false } ]
        ]
      }
    },
    {
      "type": "metric",
      "x": 6,
      "y": 0,
      "width": 6,
      "height": 6,
      "properties": {
        "title": "Latency p99",
        "view": "gauge",
        "region": "us-east-1",
        "stat": "p99",
        "period": 300,
        "yAxis": { "left": { "min": 0, "max": 2 } },
        "metrics": [
          [ "AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", "app/checkout-api/50dc6c495c0c9188", { "label": "p99 (s)" } ]
        ]
      }
    },
    {
      "type": "metric",
      "x": 12,
      "y": 0,
      "width": 12,
      "height": 6,
      "properties": {
        "title": "Requests and errors",
        "view": "timeSeries",
        "region": "us-east-1",
        "stat": "Sum",
        "period": 300,
        "metrics": [
          [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "app/checkout-api/50dc6c495c0c9188", { "label": "Requests" } ],
          [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "label": "5xx", "yAxis": "right", "color": "#d62728" } ]
        ]
      }
    }
  ]
}
  • Tasa de errores: la expresión 100 * FILL(m2, 0) / m1 divide las respuestas 5xx entre las solicitudes. FILL cuenta un período sin errores como cero en lugar de dejar un hueco. Las dos entradas tienen "visible": false, así que solo se muestra la tasa.
  • Latencia: un indicador usa el min y el max del eje Y como rango (aquí, de 0 a 2 segundos). Sin ellos, CloudPeek supone de 0 a 100.
  • Solicitudes y errores: "yAxis": "right" da al recuento de 5xx su propia escala, para que unos pocos errores no queden aplastados frente a miles de solicitudes. "." repite el valor de la misma posición en la fila anterior.
  • Sustituye app/checkout-api/50dc6c495c0c9188 por el nombre de tu balanceador de carga que aparece en su ARN, después de loadbalancer/, o deja que CloudFormation o Terraform lo rellenen, como se explica más abajo.

Gestionarlo como código

Diseña un panel en la consola hasta que tenga el aspecto que quieres y luego copia su JSON desde Acciones › Ver/editar origen a tu código de infraestructura. A partir de ahí, se revisa, se versiona y se implementa junto con los servicios que supervisa, y es igual en todas las cuentas y regiones donde lo implementes.

No es obligatorio tener los paneles en código. Si editas un panel en la consola, CloudPeek también recoge los cambios en su siguiente actualización.

Si un panel sí se gestiona con CloudFormation o Terraform, usa la consola como borrador: los cambios que guardes allí se sobrescriben en la siguiente implementación. Prueba una idea en la consola y luego vuelve a copiar el origen en tu código (Acciones › Ver/editar origen).

Guarda el JSON en el control de versiones e impleméntalo con put-dashboard. Para partir de un panel que diseñaste en la consola:

Shell
aws cloudwatch get-dashboard \
  --dashboard-name Checkout-API \
  --query DashboardBody --output text > api-health.json

aws cloudwatch put-dashboard \
  --dashboard-name Checkout-API \
  --dashboard-body file://api-health.json

put-dashboard reemplaza el panel entero, así que el archivo siempre refleja el panel completo.

Un AWS::CloudWatch::Dashboard recibe el JSON como cadena. Envuélvelo en !Sub y podrás rellenar valores de la misma pila, como la dimensión del balanceador de carga, en lugar de pegar ID:

CloudFormation
  CheckoutApiDashboard:
    Type: AWS::CloudWatch::Dashboard
    Properties:
      DashboardName: Checkout-API
      DashboardBody: !Sub
        - |
          {
            "start": "-PT3H",
            "widgets": [
              {
                "type": "metric", "x": 0, "y": 0, "width": 6, "height": 6,
                "properties": {
                  "title": "5xx error rate",
                  "view": "singleValue",
                  "region": "${AWS::Region}",
                  "period": 300,
                  "sparkline": true,
                  "metrics": [
                    [ { "expression": "100 * FILL(m2, 0) / m1", "label": "Errors (%)", "id": "e1" } ],
                    [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "${Alb}", { "stat": "Sum", "id": "m1", "visible": false } ],
                    [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "stat": "Sum", "id": "m2", "visible": false } ]
                  ]
                }
              },
              {
                "type": "metric", "x": 6, "y": 0, "width": 6, "height": 6,
                "properties": {
                  "title": "Latency p99",
                  "view": "gauge",
                  "region": "${AWS::Region}",
                  "stat": "p99",
                  "period": 300,
                  "yAxis": { "left": { "min": 0, "max": 2 } },
                  "metrics": [
                    [ "AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", "${Alb}", { "label": "p99 (s)" } ]
                  ]
                }
              },
              {
                "type": "metric", "x": 12, "y": 0, "width": 12, "height": 6,
                "properties": {
                  "title": "Requests and errors",
                  "view": "timeSeries",
                  "region": "${AWS::Region}",
                  "stat": "Sum",
                  "period": 300,
                  "metrics": [
                    [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "${Alb}", { "label": "Requests" } ],
                    [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "label": "5xx", "yAxis": "right", "color": "#d62728" } ]
                  ]
                }
              }
            ]
          }
        - Alb: !GetAtt LoadBalancer.LoadBalancerFullName
  • LoadBalancer es el AWS::ElasticLoadBalancingV2::LoadBalancer de la misma plantilla de CloudFormation; su LoadBalancerFullName es exactamente el valor que espera la dimensión LoadBalancer de CloudWatch.
  • Dentro de !Sub, CloudFormation interpreta cada ${…} como una de sus propias variables. Escribe una etiqueta dinámica de CloudWatch como ${LAST} así: ${!LAST}.
  • Los paneles son globales, pero cada widget indica su región. ${AWS::Region} usa la de la pila.

Un aws_cloudwatch_dashboard recibe el JSON como cadena. Escríbelo en HCL y envuélvelo en jsonencode, y podrás usar referencias, variables y expresiones for en lugar de pegar ID:

Terraform
resource "aws_lb" "checkout" {
  name    = "checkout-api"
  subnets = ["subnet-11111111", "subnet-22222222"]
}

locals {
  alb    = aws_lb.checkout.arn_suffix # the LoadBalancer dimension: app/checkout-api/…
  region = "us-east-1"                # where the load balancer is
}

resource "aws_cloudwatch_dashboard" "checkout_api" {
  dashboard_name = "Checkout-API"
  dashboard_body = jsonencode({
    start = "-PT3H"
    widgets = [
      {
        type = "metric", x = 0, y = 0, width = 6, height = 6
        properties = {
          title     = "5xx error rate"
          view      = "singleValue"
          region    = local.region
          period    = 300
          sparkline = true
          metrics = [
            [{ expression = "100 * FILL(m2, 0) / m1", label = "Errors (%)", id = "e1" }],
            ["AWS/ApplicationELB", "RequestCount", "LoadBalancer", local.alb, { stat = "Sum", id = "m1", visible = false }],
            [".", "HTTPCode_Target_5XX_Count", ".", ".", { stat = "Sum", id = "m2", visible = false }],
          ]
        }
      },
      {
        type = "metric", x = 6, y = 0, width = 6, height = 6
        properties = {
          title  = "Latency p99"
          view   = "gauge"
          region = local.region
          stat   = "p99"
          period = 300
          yAxis  = { left = { min = 0, max = 2 } }
          metrics = [
            ["AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", local.alb, { label = "p99 (s)" }],
          ]
        }
      },
      {
        type = "metric", x = 12, y = 0, width = 12, height = 6
        properties = {
          title  = "Requests and errors"
          view   = "timeSeries"
          region = local.region
          stat   = "Sum"
          period = 300
          metrics = [
            ["AWS/ApplicationELB", "RequestCount", "LoadBalancer", local.alb, { label = "Requests" }],
            [".", "HTTPCode_Target_5XX_Count", ".", ".", { label = "5xx", yAxis = "right", color = "#d62728" }],
          ]
        }
      },
    ]
  })
}
  • El arn_suffix de un aws_lb es exactamente el valor que espera la dimensión LoadBalancer de CloudWatch.
  • Terraform interpreta ${…} dentro de una cadena como una interpolación. Escribe una etiqueta dinámica de CloudWatch como ${LAST} así: $${LAST}.
  • ¿Prefieres tener el JSON en un archivo? dashboard_body = file("api-health.json") también funciona, o templatefile() para rellenar valores.
  • Para pasar a Terraform un panel que creaste en la consola, añade un bloque import con su nombre como id, o ejecuta terraform import aws_cloudwatch_dashboard.checkout_api Checkout-API.

AWS CDK, Pulumi y otras herramientas funcionan igual: cualquier cosa que pueda establecer el cuerpo de un panel puede definir lo que muestra CloudPeek.

Cómo llegan los cambios a tu teléfono

  • Cada vez que un widget fijado se actualiza desde AWS, CloudPeek vuelve a leer el panel, así que un cambio que guardes en la consola o implementes desde código aparece en la siguiente actualización. Para verlo al momento, toca el botón de actualizar del widget.
  • Los widgets de CloudPeek siguen a su widget del panel cuando lo mueves, le cambias el tamaño o el título, o cambias sus métricas. Si CloudPeek no puede saber cuál era, sigue mostrando la última versión que encontró.
  • Un título o una región que le diste en la vista previa de Crear widget, y un título, una región o un intervalo de tiempo que elegiste con Editar en CloudPeek, se mantienen y se aplican a lo que tenga el panel (consulta Editar un widget).
  • Si eliminas el panel o le cambias el nombre, el widget conserva sus últimos datos y muestra Panel eliminado.
  • Al añadir de nuevo el mismo widget, se vuelven a conectar los widgets de la pantalla de inicio que lo mostraban (consulta Añadir de nuevo el mismo widget).