Por que um painel?
Você não precisa de um painel para usar o CloudPeek: as predefinições e os widgets de IA funcionam sem um. Um painel vale a pena quando você quer escolher exatamente quais métricas acompanhar: suas próprias métricas personalizadas, recursos específicos, matemática de métricas, limites ou alarmes que você escolher. Encontrar o namespace e as dimensões certos, escrever matemática de métricas e definir limites é muito mais fácil com um teclado e uma tela grande, e o CloudWatch já tem a ferramenta para isso.
Assim, um painel do CloudWatch é simplesmente a sua lista do que acompanhar:
- Cada widget é algo que você pode fixar. Um widget agrupa uma ou mais métricas: a CPU de três instâncias em um gráfico de linhas, seus cinco maiores custos em um gráfico de barras, uma taxa de erros calculada a partir de duas métricas em um número.
- Cada painel é um conjunto de widgets que andam juntos. Um por serviço, um para gastos, um para a escala de plantão. Você pode fixar widgets de quantos painéis e contas quiser.
- Um painel é JSON puro, então pode ser definido no CloudFormation, no Terraform, no AWS CDK ou em qualquer outra coisa que consiga escrever uma string, e implantado com os serviços que monitora.
Já tem painéis? Fixe widgets direto deles. Ou crie um pequeno só para o celular, apenas com os widgets que você quer ver de relance.
Projetar no console da AWS
- Abra o console do CloudWatch, escolha Painéis › Criar painel e dê um nome a ele.
- Escolha um tipo de widget: Linha, Área empilhada, Número, Medidor, Barra, Pizza, Tabela, Texto ou Status do alarme. Todos funcionam no CloudPeek (consulte a referência de widgets).
- Na aba Procurar, escolha um namespace, como ApplicationELB ou um dos seus, e marque as métricas que você quer neste widget.
- Na aba Métricas em gráfico, defina a estatística, o período e o rótulo de cada métrica. Escolha Adicionar matemática para uma expressão como uma taxa de erros e desmarque as entradas que você não quer desenhar.
- Na aba Opções, adicione anotações horizontais para os limites e defina o mínimo e o máximo do eixo Y. Um medidor precisa dos dois.
- Escolha Criar widget, dê a ele um título curto e salve o painel com Salvar.
Abra o painel no CloudPeek e cada widget aparece como vai ficar na sua Tela de Início. Fixe os que quiser ou adicione-os com Criar Widget › De um Painel (consulte Criar um widget).
Facilite a leitura no celular
Um widget na Tela de Início tem poucos centímetros de largura. Alguns hábitos facilitam muito a leitura:
- Uma pergunta por widget. “A API está saudável?” fica mais legível como um número de taxa de erros e um medidor de latência do que como um gráfico com oito linhas.
- Poucas séries por gráfico. Nos widgets médios e grandes, a legenda lista até quatro séries e depois “Mais N”. Um widget pequeno não tem legenda.
- Títulos curtos. No iPhone e no iPad, o widget em linha da Tela Bloqueada mostra cerca de 18 caracteres do título, e o circular, cerca de 8.
- Escolha a visualização certa para uma olhada rápida. Um número com
"sparkline": truemostra o valor mais recente e sua tendência; um medidor o mostra dentro de um intervalo que você define; um gráfico de barras classifica itens. Veja como cada tipo fica. - Defina o intervalo que importa. O
startdo próprio widget substitui o do painel e, sem nenhum dos dois, o CloudPeek mostra as últimas 3 horas. Todo widget informa a janela de tempo que abrange. - Rótulos em vez de IDs. Dê às métricas um
label, para que a legenda diga “Checkout API” em vez de “app/checkout-api/50dc6c495c0c9188”. Um rótulo dinâmico como${PROP('Dim.ServiceName')}dá a cada série o nome do valor de uma dimensão.
Exemplo: um painel de saúde da API
Três widgets para um Application Load Balancer: a taxa de erros como número, a latência p99 como medidor e as solicitações comparadas aos erros em um gráfico de linhas. No CloudPeek, eles ficam assim:
{
"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" } ]
]
}
}
]
}
- Taxa de erros: a expressão
100 * FILL(m2, 0) / m1divide as respostas 5xx pelas solicitações.FILLconta um período sem erros como zero em vez de deixar uma lacuna. As duas entradas têm"visible": false, então só a taxa é mostrada. - Latência: um medidor usa o
mine omaxdo eixo Y como intervalo (de 0 a 2 segundos aqui). Sem eles, o CloudPeek considera de 0 a 100. - Solicitações e erros:
"yAxis": "right"dá à contagem de 5xx sua própria escala, para que um punhado de erros não fique achatado diante de milhares de solicitações."."repete o valor da mesma posição na linha acima. - Substitua
app/checkout-api/50dc6c495c0c9188pelo nome do seu balanceador de carga, que está no ARN dele depois deloadbalancer/, ou deixe o CloudFormation ou o Terraform preenchê-lo, como mostrado abaixo.
Gerenciar como código
Projete um painel no console até ele ficar do jeito certo e depois copie o JSON dele em Ações › Visualizar/editar origem para o seu código de infraestrutura. A partir daí, ele é revisado, versionado e implantado junto com os serviços que monitora, e fica igual em todas as contas e regiões onde você o implanta.
Você não precisa colocar os painéis em código. Um painel que você edita no console também é lido pelo CloudPeek na próxima atualização.
Se um painel for gerenciado pelo CloudFormation ou pelo Terraform, trate o console como um rascunho: as alterações que você salva nele são substituídas na próxima implantação. Teste uma ideia no console e depois copie a origem de volta para o seu código (Ações › Visualizar/editar origem).
Mantenha o JSON no controle de versão e implante-o com put-dashboard. Para começar com um painel que você projetou no console:
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 substitui o painel inteiro, então o arquivo é sempre a versão completa e definitiva.
Um AWS::CloudWatch::Dashboard recebe o JSON como string. Envolva-o em !Sub e você pode preencher valores da mesma pilha, como a dimensão do balanceador de carga, em vez de colar IDs:
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é oAWS::ElasticLoadBalancingV2::LoadBalancerdo mesmo modelo; oLoadBalancerFullNamedele é exatamente o valor que a dimensãoLoadBalancerdo CloudWatch espera.- Dentro de
!Sub, o CloudFormation lê cada${…}como uma variável dele. Escreva um rótulo dinâmico do CloudWatch como${LAST}na forma${!LAST}. - Os painéis são globais, mas cada widget indica sua região.
${AWS::Region}usa a região da pilha.
Um aws_cloudwatch_dashboard recebe o JSON como string. Escreva-o em HCL e envolva-o em jsonencode, e você pode usar referências, variáveis e expressões for em vez de colar IDs:
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" }],
]
}
},
]
})
}
- O
arn_suffixde umaws_lbé exatamente o valor que a dimensãoLoadBalancerdo CloudWatch espera. - O Terraform lê
${…}em uma string como interpolação. Escreva um rótulo dinâmico do CloudWatch como${LAST}na forma$${LAST}. - Prefere manter o JSON em um arquivo?
dashboard_body = file("api-health.json")também funciona, outemplatefile()para preencher valores. - Para colocar sob o Terraform um painel que você criou no console, adicione um bloco
importcom o nome dele comoidou executeterraform import aws_cloudwatch_dashboard.checkout_api Checkout-API.
O AWS CDK, o Pulumi e outras ferramentas funcionam da mesma forma: qualquer coisa que consiga definir o corpo de um painel pode definir o que o CloudPeek mostra.
Como as alterações chegam ao seu celular
- Sempre que um widget fixado é atualizado a partir da AWS, o CloudPeek lê o painel de novo, então uma alteração que você salva no console ou implanta a partir do código aparece na próxima atualização. Para vê-la na hora, toque no botão de atualizar do widget.
- Os widgets no CloudPeek acompanham o widget de painel de origem quando você o move, redimensiona, muda o título dele ou altera as métricas. Se o CloudPeek não conseguir identificar qual widget era, ele continua mostrando a última versão que encontrou.
- Um título ou uma região que você deu ao widget na prévia de Criar Widget, e um título, uma região ou um intervalo de tempo que você escolheu com Editar no CloudPeek, são mantidos e aplicados sobre o que o painel tiver (consulte Editar um widget).
- Se você excluir ou renomear o painel, o widget mantém os últimos dados e mostra Painel excluído.
- Adicionar o mesmo widget de novo reconecta os widgets da Tela de Início que o mostravam (consulte Adicionar o mesmo widget de novo).