대시보드를 사용하는 이유
CloudPeek을 사용하는 데 대시보드가 꼭 필요하지는 않습니다. 프리셋과 AI 위젯은 대시보드 없이 작동합니다. 대시보드는 감시할 지표를 정확히 고르고 싶을 때 유용합니다. 직접 만든 사용자 지정 지표, 특정 리소스, 지표 수학, 임계값, 직접 고른 경보 등이 그렇습니다. 올바른 네임스페이스와 차원을 찾고, 지표 수학을 작성하고, 임계값을 설정하는 일은 키보드와 큰 화면에서 훨씬 쉬우며, CloudWatch에는 이미 이를 위한 도구가 있습니다.
그러면 CloudWatch 대시보드는 감시할 항목의 목록일 뿐입니다.
- 각 위젯은 고정할 수 있는 단위입니다. 위젯은 하나 이상의 지표를 묶습니다. 인스턴스 3개의 CPU를 선 차트 하나에, 가장 큰 비용 5개를 막대 차트 하나에, 두 지표로 계산한 오류율을 숫자 하나에 담을 수 있습니다.
- 각 대시보드는 함께 묶이는 위젯의 모음입니다. 서비스마다 하나, 지출용 하나, 온콜 담당용 하나. 원하는 만큼 여러 대시보드와 계정에서 고정할 수 있습니다.
- 대시보드는 일반 JSON이므로 CloudFormation, Terraform, AWS CDK 등 문자열을 작성할 수 있는 모든 도구로 정의하고, 감시하는 서비스와 함께 배포할 수 있습니다.
이미 대시보드가 있나요? 바로 고정하세요. 또는 한눈에 보고 싶은 위젯만 담은 휴대폰 전용 작은 대시보드를 만드세요.
AWS 콘솔에서 설계
- CloudWatch 콘솔을 열고 대시보드 › 대시보드 생성을 선택한 다음 이름을 지정하세요.
- 위젯 유형을 선택하세요. 선, 누적 영역, 숫자, 게이지, 막대, 파이, 표, 텍스트 또는 경보 상태 중에서 선택할 수 있으며, 모두 CloudPeek에서 작동합니다(위젯 참조 페이지 참조).
- 찾아보기 탭에서 ApplicationELB나 직접 만든 네임스페이스 등 네임스페이스를 고른 다음, 이 위젯에 표시할 지표를 선택하세요.
- 그래프로 표시된 지표 탭에서 각 지표의 통계, 기간, 레이블을 설정하세요. 오류율 같은 표현식을 만들려면 수학 추가를 선택하고, 그래프에 표시하지 않을 입력 지표는 선택을 해제하세요.
- 옵션 탭에서 임계값에 대한 수평 주석을 추가하고 Y축 한도를 설정하세요. 게이지에는 최소값과 최대값이 모두 필요합니다.
- 위젯 생성을 선택하고 짧은 제목을 지정한 다음 대시보드를 저장하세요.
CloudPeek에서 대시보드를 열면 모든 위젯이 홈 화면에 표시될 모습 그대로 그려집니다. 원하는 위젯을 고정하거나 위젯 만들기 › 대시보드에서로 추가하세요(위젯 만들기 참조).
휴대폰에서 읽기 쉽게 만들기
홈 화면의 위젯은 너비가 몇 센티미터에 불과합니다. 몇 가지 습관만 들이면 훨씬 읽기 쉬워집니다.
- 위젯 하나에 질문 하나. “API가 정상인가요?”라는 질문은 선 8개가 그려진 그래프 하나보다 오류율 숫자와 지연 시간 게이지로 보는 편이 더 읽기 쉽습니다.
- 그래프당 시리즈는 적게. 중형 및 대형 위젯의 범례에는 시리즈가 최대 4개까지 표시되고, 나머지는 “외 N개”로 표시됩니다. 소형 위젯에는 범례가 아예 없습니다.
- 짧은 제목. iPhone 및 iPad에서 잠금 화면의 인라인 위젯은 제목을 약 18자, 원형 위젯은 약 8자까지 표시합니다.
- 한눈에 알아보기 쉬운 표시 방식 선택.
"sparkline": true설정을 사용한 숫자는 최신 값과 추세를, 게이지는 설정한 범위 안에서의 값을 보여 주고, 막대 차트는 항목의 순위를 보여 줍니다. 각 유형의 모양을 참조하세요. - 관심 있는 범위 설정. 위젯 자체의
start는 대시보드의 값보다 우선하며, 둘 다 없으면 CloudPeek은 지난 3시간을 표시합니다. 모든 위젯에는 표시하는 시간 범위가 나와 있습니다. - ID보다 레이블. 지표에
label을 지정하면 범례에 “app/checkout-api/50dc6c495c0c9188” 대신 “Checkout API”가 표시됩니다.${PROP('Dim.ServiceName')}같은 동적 레이블은 각 시리즈의 이름을 차원 값으로 지정합니다.
예시: API 상태 대시보드
Application Load Balancer용 위젯 3개입니다. 오류율은 숫자로, p99 지연 시간은 게이지로, 요청 수와 오류 수는 선 차트로 표시합니다. CloudPeek에서는 다음과 같이 보입니다.
{
"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" } ]
]
}
}
]
}
- 오류율: 표현식
100 * FILL(m2, 0) / m1은 5xx 응답 수를 요청 수로 나눕니다.FILL은 오류가 없는 기간을 빈칸으로 두지 않고 0으로 계산합니다. 두 입력 모두"visible": false로 설정되어 있으므로 비율만 표시됩니다. - 지연 시간: 게이지는 Y축의
min과max를 범위로 사용합니다(여기서는 0~2초). 이 값이 없으면 CloudPeek은 0~100으로 간주합니다. - 요청 및 오류:
"yAxis": "right"는 5xx 수에 별도의 눈금을 부여하므로, 몇 건 안 되는 오류가 수천 건의 요청에 묻혀 평평해지지 않습니다."."은 바로 위 행의 같은 위치에 있는 값을 반복합니다. app/checkout-api/50dc6c495c0c9188을 로드 밸런서 ARN에서loadbalancer/뒤에 오는 이름으로 바꾸거나, 아래와 같이 CloudFormation 또는 Terraform이 채우도록 하세요.
코드로 관리
원하는 모습이 될 때까지 콘솔에서 대시보드를 설계한 다음, 작업 › 소스 보기/편집에서 JSON을 복사하여 인프라 코드에 넣으세요. 그러면 대시보드가 모니터링하는 서비스와 함께 검토, 버전 관리, 배포되며, 배포하는 모든 계정과 리전에서 동일하게 유지됩니다.
대시보드를 꼭 코드로 관리할 필요는 없습니다. 콘솔에서 편집한 대시보드도 마찬가지로 CloudPeek이 다음 새로고침 때 반영합니다.
대시보드를 CloudFormation이나 Terraform으로 관리하고 있다면 콘솔은 연습장으로만 사용하세요. 콘솔에서 저장한 변경 사항은 다음 배포 때 덮어써집니다. 콘솔에서 아이디어를 시도해 본 다음 소스를 다시 코드에 복사하세요(작업 › 소스 보기/편집).
JSON을 버전 관리 시스템에 보관하고 put-dashboard로 배포하세요. 콘솔에서 설계한 대시보드를 바탕으로 시작하려면:
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는 대시보드 전체를 교체하므로 파일이 항상 대시보드의 완전한 원본이 됩니다.
AWS::CloudWatch::Dashboard는 JSON을 문자열로 받습니다. !Sub로 감싸면 ID를 붙여 넣는 대신 로드 밸런서의 차원 값처럼 같은 스택의 값을 채워 넣을 수 있습니다.
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는 같은 템플릿에 있는AWS::ElasticLoadBalancingV2::LoadBalancer이며, 그LoadBalancerFullName이 바로 CloudWatch의LoadBalancer차원에 필요한 값입니다.!Sub안에서 CloudFormation은 모든${…}를 자체 변수로 읽습니다.${LAST}같은 CloudWatch 동적 레이블은${!LAST}로 작성하세요.- 대시보드는 글로벌 리소스이지만 각 위젯은 자체 리전을 지정합니다.
${AWS::Region}은 스택의 리전을 사용합니다.
aws_cloudwatch_dashboard는 JSON을 문자열로 받습니다. HCL로 작성하고 jsonencode로 감싸면 ID를 붙여 넣는 대신 참조, 변수, for 표현식을 사용할 수 있습니다.
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" }],
]
}
},
]
})
}
aws_lb의arn_suffix가 바로 CloudWatch의LoadBalancer차원에 필요한 값입니다.- Terraform은 문자열 안의
${…}를 보간으로 읽습니다.${LAST}같은 CloudWatch 동적 레이블은$${LAST}로 작성하세요. - JSON을 파일로 보관하고 싶으신가요?
dashboard_body = file("api-health.json")도 작동하며, 값을 채워 넣으려면templatefile()을 사용하면 됩니다. - 콘솔에서 만든 대시보드를 Terraform으로 관리하려면 대시보드 이름을
id로 지정한import블록을 추가하거나terraform import aws_cloudwatch_dashboard.checkout_api Checkout-API를 실행하세요.
AWS CDK, Pulumi 등 다른 도구도 같은 방식으로 작동합니다. 대시보드 본문을 설정할 수 있는 도구라면 무엇이든 CloudPeek에 표시할 내용을 정의할 수 있습니다.
변경 사항이 휴대폰에 반영되는 방식
- 고정된 위젯이 AWS에서 새로고침될 때마다 CloudPeek은 대시보드를 다시 읽으므로, 콘솔에서 저장하거나 코드로 배포한 변경 사항은 다음 새로고침 때 표시됩니다. 바로 확인하려면 위젯의 새로고침 버튼을 탭하세요.
- 대시보드 위젯을 이동하거나, 크기를 조정하거나, 제목을 바꾸거나, 지표를 변경해도 CloudPeek의 위젯은 해당 대시보드 위젯을 따라갑니다. CloudPeek이 어떤 위젯이었는지 알 수 없으면 마지막으로 찾은 버전을 계속 표시합니다.
- 위젯 만들기의 미리보기에서 지정한 제목이나 리전, 그리고 CloudPeek의 편집에서 선택한 제목, 리전 또는 시간 범위는 그대로 유지되며, 대시보드의 내용이 무엇이든 그 위에 적용됩니다(위젯 편집하기 참조).
- 대시보드를 삭제하거나 이름을 바꾸면 위젯은 마지막 데이터를 유지하고 대시보드 삭제됨이라고 표시합니다.
- 같은 위젯을 다시 추가하면 그 위젯을 표시하던 홈 화면 위젯이 다시 연결됩니다(같은 위젯 다시 추가하기 참조).