LabHub
배우기 러닝패스 코스

Grafana — ダッシュボードは問いだ

順位を問うパネルをテーブルに移す

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

선 그래프 넷이 겹친 대시보드를 받아, 순위를 묻는 패널을 표로 옮기고 reduce·organize·joinByField 변환으로 읽을 수 있는 모양을 만듭니다.

왜 중요한가

대시보드가 답해야 하는 질문은 크게 둘이다 — '언제부터 이랬나' 와 '어느 것이 가장 나쁜가'. 앞의 것은 시간에 따른 움직임이라 선 그래프가 맞지만, 뒤의 것은 한 순간의 정렬된 목록이라 선 그래프가 답하지 못한다. 계열 넷의 값이 서로 가까우면 선은 엉키고, 순위를 알려면 한 시각을 골라 값을 넷 읽고 머릿속에서 정렬해야 한다. 여덟 개가 되면 아무도 그 일을 하지 않는다. 표는 그 정렬을 화면이 대신 해 주는 모양이고, 변환은 시계열을 표가 읽을 수 있는 모양으로 바꾸는 도구다. 다만 모든 패널을 표로 바꾸면 더 나빠진다 — 옮길 것은 순위를 묻는 패널뿐이다.

단계

  1. lab-start-grafana 로 Grafana 를 띄우고, /opt/lab/gfd/gfd-table/ranking.json고치지 말고 그대로 Grafana 에 올리세요(uid 는 파일에 적힌 gfd-table, 패널 4개). curl/api/dashboards/db 에 POST 하면 됩니다. 올린 뒤 웹 프리뷰 3000번 포트로 한 번 열어 네 패널이 어떻게 보이는지 눈으로 확인해 두세요.
  2. 1번 패널은 핸들러 넷의 p95 를 겹쳐 그립니다. 지나간 시각을 하나 골라(지금보다 1시간 이상 앞, 6시간 이내) 그 순간의 p95 를 핸들러마다 재고, /root/gfd-table/02-rank.txtat= rank1= rank2= rank3= rank4= gap= 여섯 줄로 적으세요. at 은 epoch 초, rank1~rank4 는 p95 가 큰 것부터 순서대로 적은 핸들러 이름, gap 은 1등과 4등의 p95 차이(초)입니다.
  3. 먼저 표가 몇 줄이 되는지 재세요. 지나간 구간을 하나 골라(1시간 이상, 끝은 지금보다 앞) 1번 패널의 쿼리를 그 구간에 step 60 으로 던지고, /root/gfd-table/03-table.txtstart= end= series= points= rows= 다섯 줄을 적으세요 — series 는 같은 쿼리를 end 시각의 순간값으로 던졌을 때 돌아온 계열 수, points 는 구간 질의가 계열 하나에 돌려준 점 개수, rows 는 둘을 곱한 값입니다. 그리고 5번 패널을 새로 만드세요: typetable, 쿼리는 1번 패널과 같은 것을 formattable 로 두고 구간 질의로(instant 를 참으로 두지 말 것) 던집니다.
  4. 5번 패널에 reduce 변환을 붙이세요. transformations 배열에 idreduce 인 항목을 하나 두고, options.modeseriesToRows, options.reducerslastNotNull 하나만 담습니다. 쿼리는 그대로 구간 질의로 둡니다 — 줄이는 일을 변환이 하는지 보려는 것이니까요. 고친 대시보드를 저장하세요.
  5. 5번 패널의 transformations 배열에 reduce 뒤로 idorganize 인 항목을 하나 더 붙이세요. options.renameByName 에서 FieldLast * 두 열의 이름을 각각 다른 한국어 이름으로 바꾸고, options.indexByName 으로 그 두 열의 순서를 0 과 1 로 못박으세요. 고친 대시보드를 저장하세요.
  6. 6번 패널을 새로 만드세요. typetable, 쿼리는 둘입니다 — refIdA 인 것은 sum by (handler) (rate(http_requests_total{job="shop-api"}[5m])), refIdB 인 것은 1번 패널과 같은 p95 쿼리입니다. 두 쿼리 모두 instant 를 참으로, formattable 로 두세요. 그리고 transformationsidjoinByField 인 항목을 하나 두고 options.byFieldhandler, options.modeouter 로 하세요.
  7. 6번 패널의 기본 셀 표시(fieldConfig.defaults.custom.cellOptions.type)는 auto 로 두고, fieldConfig.overridesp95 값 열 하나만 지목하는 덮어쓰기를 하나 추가하세요. 덮어쓰기의 matcher.idbyName, properties 에는 custom.cellOptions(typecolor-background 로)와 thresholds(단계 2개 이상, 마지막 단계는 숫자 문턱) 를 담습니다. 그리고 /root/gfd-table/07-cells.txtrule1= rule2= rule3= 세 줄로 표의 셀에 색을 붙일 때 지켜야 할 규칙을 각 40자 이상, 서로 다르게 적으세요.
  8. 2번 패널(핸들러별 5xx 비율)도 순위를 묻는 패널입니다. typetable 로 바꾸고 쿼리는 그대로 둔 채 instant 를 참, formattable 로 하고, organize 변환으로 Time 열을 감추고(excludeByName 에서 Time 을 참으로) 남는 두 열의 이름을 바꾸세요. 4번 패널(전체 요청률)은 손대지 마세요 — 순위를 묻는 패널이 아닙니다. 그리고 지금 올라간 대시보드를 그대로 내려받아 /root/gfd-table/fixed.json 에 저장하고(.dashboard 본문만), /root/gfd-table/08-review.mdR1= 부터 R4= 까지 네 줄로 무엇을 왜 바꿨는지 각 30자 이상 적으세요.

참고

선 그래프 넷짜리 대시보드를 그대로 올린다

lab-start-grafana 로 Grafana 를 띄우고, /opt/lab/gfd/gfd-table/ranking.json고치지 말고 그대로 Grafana 에 올리세요(uid 는 파일에 적힌 gfd-table, 패널 4개). curl/api/dashboards/db 에 POST 하면 됩니다. 올린 뒤 웹 프리뷰 3000번 포트로 한 번 열어 네 패널이 어떻게 보이는지 눈으로 확인해 두세요.

저장 API 는 대시보드 본문을 dashboard 키 안에 담고 overwrite 를 함께 보냅니다. 파일에서 그 모양을 만드는 데는 jq -n --slurpfile 이 편합니다. Grafana 가 뜨는 데 몇십 초 걸리니 /api/health 가 답하는지 먼저 보세요.

선 그래프에서 순위를 읽어 본다

1번 패널은 핸들러 넷의 p95 를 겹쳐 그립니다. 지나간 시각을 하나 골라(지금보다 1시간 이상 앞, 6시간 이내) 그 순간의 p95 를 핸들러마다 재고, /root/gfd-table/02-rank.txtat= rank1= rank2= rank3= rank4= gap= 여섯 줄로 적으세요. at 은 epoch 초, rank1~rank4 는 p95 가 큰 것부터 순서대로 적은 핸들러 이름, gap 은 1등과 4등의 p95 차이(초)입니다.

한 순간의 값은 /api/v1/querytime= 을 함께 보내면 됩니다. 시각을 못박아 두어야 나중에 다시 재도 같은 값이 나옵니다. 응답의 metric.handlervalue[1] 을 함께 뽑아 sort -rn 으로 줄 세우면 순위가 바로 나옵니다. 네 값이 얼마나 가까운지 보고, 그것을 선 그래프에서 눈으로 가릴 수 있을지 생각해 보세요.

같은 질문을 표로 옮긴다

먼저 표가 몇 줄이 되는지 재세요. 지나간 구간을 하나 골라(1시간 이상, 끝은 지금보다 앞) 1번 패널의 쿼리를 그 구간에 step 60 으로 던지고, /root/gfd-table/03-table.txtstart= end= series= points= rows= 다섯 줄을 적으세요 — series 는 같은 쿼리를 end 시각의 순간값으로 던졌을 때 돌아온 계열 수, points 는 구간 질의가 계열 하나에 돌려준 점 개수, rows 는 둘을 곱한 값입니다. 그리고 5번 패널을 새로 만드세요: typetable, 쿼리는 1번 패널과 같은 것을 formattable 로 두고 구간 질의로(instant 를 참으로 두지 말 것) 던집니다.

구간 질의는 /api/v1/query_range 이고 start·end·step 을 함께 보냅니다. 돌아온 JSON 의 data.result[0].values 길이가 계열 하나의 점 개수입니다. 패널을 새로 만들 때는 대시보드를 내려받아 panels 배열에 하나 더하고 그대로 다시 저장하면 됩니다. gridPos 가 겹치지 않게 y 를 아래로 내려 두세요.

변환으로 계열마다 한 숫자만 남긴다

5번 패널에 reduce 변환을 붙이세요. transformations 배열에 idreduce 인 항목을 하나 두고, options.modeseriesToRows, options.reducerslastNotNull 하나만 담습니다. 쿼리는 그대로 구간 질의로 둡니다 — 줄이는 일을 변환이 하는지 보려는 것이니까요. 고친 대시보드를 저장하세요.

reduce 는 계열 하나를 숫자 하나로 줄입니다. seriesToRows 는 계열마다 한 줄을 만들고, 그 줄에는 계열 이름이 든 Field 열과 고른 계산값 열이 생깁니다. lastNotNull 의 열 이름은 Last * 입니다 — 다음 단계에서 이 이름을 씁니다. 변환은 대시보드 JSON 의 패널마다 있는 transformations 배열에 순서대로 들어갑니다.

열 이름과 순서를 사람이 읽을 수 있게 만든다

5번 패널의 transformations 배열에 reduce 뒤로 idorganize 인 항목을 하나 더 붙이세요. options.renameByName 에서 FieldLast * 두 열의 이름을 각각 다른 한국어 이름으로 바꾸고, options.indexByName 으로 그 두 열의 순서를 0 과 1 로 못박으세요. 고친 대시보드를 저장하세요.

organize 는 열을 감추고(excludeByName) 순서를 정하고(indexByName) 이름을 바꾸는(renameByName) 변환 하나입니다. 세 옵션 모두 열 이름을 열쇠로 하는 객체입니다. 변환은 배열에 적힌 순서대로 차례차례 적용되므로, 앞 변환이 만들어 낸 열 이름을 뒤 변환이 받게 됩니다. Field 는 계열 이름 열, Last * 는 마지막 값 열입니다.

두 쿼리를 라벨로 붙여 한 표에 놓는다

6번 패널을 새로 만드세요. typetable, 쿼리는 둘입니다 — refIdA 인 것은 sum by (handler) (rate(http_requests_total{job="shop-api"}[5m])), refIdB 인 것은 1번 패널과 같은 p95 쿼리입니다. 두 쿼리 모두 instant 를 참으로, formattable 로 두세요. 그리고 transformationsidjoinByField 인 항목을 하나 두고 options.byFieldhandler, options.modeouter 로 하세요.

순간값 질의는 계열마다 한 줄을 주므로 변환 없이도 표가 짧습니다 — 그래서 여기서는 reduce 가 필요 없습니다. 두 결과에 공통으로 있는 열은 라벨 이름 그대로 handler 입니다. 붙인 뒤 값 열은 Value #A·Value #B 로 구분됩니다. outer 는 한쪽에만 있는 줄도 남기고, inner 는 양쪽에 다 있는 줄만 남깁니다.

색은 문턱이 있는 열 하나에만 붙인다

6번 패널의 기본 셀 표시(fieldConfig.defaults.custom.cellOptions.type)는 auto 로 두고, fieldConfig.overridesp95 값 열 하나만 지목하는 덮어쓰기를 하나 추가하세요. 덮어쓰기의 matcher.idbyName, properties 에는 custom.cellOptions(typecolor-background 로)와 thresholds(단계 2개 이상, 마지막 단계는 숫자 문턱) 를 담습니다. 그리고 /root/gfd-table/07-cells.txtrule1= rule2= rule3= 세 줄로 표의 셀에 색을 붙일 때 지켜야 할 규칙을 각 40자 이상, 서로 다르게 적으세요.

패널 기본값에 색을 걸면 이름 열까지 칠해집니다. 색이 뜻을 가지려면 그 색이 문턱을 넘었다 는 말을 해야 하고, 그러려면 문턱이 있는 열에만 붙어야 합니다. 덮어쓰기는 fieldConfig.overrides 배열의 항목이고, 어느 열에 걸지는 matcher 가, 무엇을 바꿀지는 properties 가 정합니다. 조인 뒤 p95 값 열의 이름을 먼저 확인하세요.

아직 선으로 남은 순위 패널을 표로 바꾼다

2번 패널(핸들러별 5xx 비율)도 순위를 묻는 패널입니다. typetable 로 바꾸고 쿼리는 그대로 둔 채 instant 를 참, formattable 로 하고, organize 변환으로 Time 열을 감추고(excludeByName 에서 Time 을 참으로) 남는 두 열의 이름을 바꾸세요. 4번 패널(전체 요청률)은 손대지 마세요 — 순위를 묻는 패널이 아닙니다. 그리고 지금 올라간 대시보드를 그대로 내려받아 /root/gfd-table/fixed.json 에 저장하고(.dashboard 본문만), /root/gfd-table/08-review.mdR1= 부터 R4= 까지 네 줄로 무엇을 왜 바꿨는지 각 30자 이상 적으세요.

순간값 질의를 format: table 로 받으면 열은 Time·handler·Value 셋입니다. 한 순간의 목록에 시각 열은 아무 정보도 주지 않으니 감춥니다. 파일과 화면이 갈라지지 않게 하려면 고친 뒤에 다시 내려받아야 합니다. 기록의 네 줄은 각각 왜 표로 바꿨는지, 왜 순간값 질의인지, 어떤 변환을 왜 붙였는지, 어느 패널을 왜 선 그래프로 남겼는지를 적는 자리입니다.