同样的 0.42,有人读成 420 毫秒,有人读成 0.42 毫秒
한국어 원문으로 표시합니다.
목표
진짜 Grafana 에 패널을 올려 단위 식별자를 직접 넣고, 쿼리가 내는 값의 크기와 단위가 맞는지 질의로 확인하고, 축의 범위와 로그 축을 손으로 만진 뒤, 운영에서 걷어 온 대시보드의 단위·축 결함 넷을 고쳐 제출합니다.
왜 중요한가
대시보드의 숫자는 쿼리가 옳아도 화면에서 틀릴 수 있다. Grafana 의 단위는 표시 규칙이지 변환 규칙이 아니라서, 초로 나오는 값에 밀리초 단위를 붙이면 값은 그대로인 채 이름만 천 배 작아진다. 비율도 0..1 과 0..100 이 서로 다른 단위이고, 바이트도 1024 로 줄이는 쪽과 1000 으로 줄이는 쪽이 다른 단위다. 화면에 보이는 이름과 JSON 에 들어가는 식별자가 다르다는 것까지 알아야 이 일을 파일로 남길 수 있다. 축은 그다음 자리다 - 바닥을 0 으로 고정하지 않으면 두 배도 안 되는 변동이 절벽처럼 보이고, 천장을 박아 두면 사고가 통째로 잘린다. 이 실습의 목적은 단위 이름을 외우는 것이 아니라, 패널 하나를 보고 '이 숫자는 무엇으로 읽히는가' 를 물을 수 있게 되는 것이다.
단계
lab-start-grafana로 Grafana 를 띄우고,/root/gfd-units/dash.json에 uid 가gfd-units인 대시보드를 만들어 Grafana 에 올리세요. 패널은 하나이고id는1, 타입은timeseries, 제목은p99 응답 시간 (단위 없음 - 비교용), 쿼리는histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h])))입니다. 이 패널에는 단위를 적지 마세요(뒤 단계에서도 그대로 둡니다 - 비교용입니다). 그리고/root/gfd-units/01-readings.tsv에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 두 칸<가정한 단위 식별자> <그 가정대로면 실제로 몇 초인가>를 적으세요. 가정할 단위는 순서대로s(초)·ms(밀리초)·m(분) 이고, 초로 환산한 값은 소수 여섯 자리까지 적습니다.- 같은 대시보드에 패널 셋을 더하세요.
id2 는 제목p99 응답 시간, 쿼리histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h]))),id3 은 제목5xx 비율, 쿼리sum(rate(http_requests_total{job="shop-api",status=~"5.."}[1h])) / sum(rate(http_requests_total{job="shop-api"}[1h])),id4 는 제목남은 디스크, 쿼리node_filesystem_avail_bytes{job="node",mountpoint="/data"}입니다. 셋 다 타입은timeseries이고, 각 패널의fieldConfig.defaults.unit에 그 값에 맞는 Grafana 단위 식별자를 적습니다. 지연은 초 단위로, 비율은 0 과 1 사이로, 디스크는 바이트로 나옵니다. 바이트는 1024 로 줄이는 쪽(IEC)을 쓰세요. 그리고/root/gfd-units/02-units.tsv에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 세 칸<패널 id> <단위 식별자> <이 단위를 고른 이유 15자 이상>을 적으세요. - 같은 대시보드에
id가5인 timeseries 패널을 더하세요. 제목은p99 응답 시간 (ms)이고, 같은 p99 를 밀리초 숫자로 내는 쿼리를 쓰고 단위 식별자는 밀리초 쪽을 씁니다. 그리고/root/gfd-units/03-scale.tsv에 머리글 없이 두 줄, 각 줄은 탭으로 나눈 두 칸<단위 식별자> <그 패널의 쿼리가 실제로 내는 값>을 적으세요. 첫 줄은 2단계의 초 패널, 둘째 줄은 이번 패널이고, 값은 소수 여섯 자리까지 적습니다. - 같은 대시보드에
id가6인 timeseries 패널을 더하세요. 제목은초당 요청 수, 쿼리는sum(rate(http_requests_total{job="shop-api"}[5m])), 단위 식별자는 처리량 갈래의requests/sec (rps)이고,fieldConfig.defaults.min을0으로 고정합니다. 반대로 2단계에서 만든id2 패널에는max를 넣지 마세요(넣었다면 지웁니다). 그리고/root/gfd-units/04-axis.tsv에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 두 칸으로rps_min·rps_max·swing_pct를 차례로 적으세요. 앞의 둘은 최근 12시간 동안 이 쿼리가 낸 가장 작은 값과 가장 큰 값(소수 세 자리),swing_pct는 (최댓값 빼기 최솟값) 나누기 최댓값 곱하기 100 입니다(소수 두 자리). - 같은 대시보드에
id가7인 timeseries 패널을 더하세요. 제목은지연과 오류 비율, 쿼리는 둘입니다 -refId가A인histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h])))(범례 이름p99)와refId가B인sum(rate(http_requests_total{job="shop-api",status=~"5.."}[1h])) / sum(rate(http_requests_total{job="shop-api"}[1h]))(범례 이름5xx). 패널 전체의 단위는 초로 두고,fieldConfig.overrides에 이름이5xx인 계열만 골라 단위를 0..1 비율로,custom.axisPlacement를right로 지정하세요. 그리고/root/gfd-units/05-override.tsv에 머리글 없이 두 줄, 각 줄은 탭으로 나눈 세 칸<범례 이름> <그 계열에 적용되는 단위 식별자> <축 위치>를 적으세요. 축 위치는left또는right입니다. - 같은 대시보드에
id가8인 timeseries 패널을 더하세요. 제목은핸들러별 초당 요청 수, 쿼리는sum by (handler) (rate(http_requests_total{job="shop-api"}[1h])), 단위는 처리량 갈래의requests/sec (rps)이고,fieldConfig.defaults.custom.scaleDistribution을{"type": "log", "log": 10}으로 지정합니다. 이 패널에는 최솟값을 0 으로 고정하지 마세요. 그리고/root/gfd-units/06-log.txt에 네 줄을 적으세요 -top=<가장 큰 핸들러의 값>,bottom=<가장 작은 핸들러의 값>(둘 다 소수 세 자리),ratio=<top 나누기 bottom, 소수 두 자리>,loss=<로그 축으로 바꾸면서 잃는 것, 40자 이상>. - 같은 대시보드에 패널 둘을 더하세요.
id9 는 제목디스크가 줄어드는 속도, 쿼리- deriv(node_filesystem_avail_bytes{job="node",mountpoint="/data"}[1h]), 단위는 1024 로 줄이는 쪽의 초당 바이트입니다.id10 은 제목디스크가 바닥날 때까지, 쿼리는 남은 바이트를 줄어드는 속도로 나눈 것이고 단위는 초입니다. 둘 다 타입은timeseries입니다. 그리고/root/gfd-units/07-derived.tsv에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 두 칸<단위 식별자> <그 쿼리가 내는 값>을 적으세요. 차례로 남은 바이트, 줄어드는 속도, 남은 시간이고 값은 소수 세 자리까지 적습니다. /opt/lab/gfd/gfd-units/broken.json은 운영에서 걷어 온 대시보드입니다(uidgfd-units-fix). 패널 넷 모두 단위나 축에 결함이 있습니다. 쿼리는 그대로 두어도 되고 바꿔도 되지만, 화면에 나오는 값과 단위가 서로 맞아야 합니다. 고친 대시보드를 uidgfd-units-fix로 Grafana 에 올리세요. 4번 패널(초당 요청 수)의 축은 최솟값을 0 으로 고정하고 천장은 걷어 냅니다. 그리고/root/gfd-units/08-report.tsv에 머리글 없이 네 줄, 각 줄은 탭으로 나눈 세 칸<패널 id> <결함 코드> <무엇이 틀렸었나, 20자 이상이고 숫자를 하나 이상 포함>을 적으세요. 결함 코드는scale(값의 크기와 단위가 어긋남)·category(단위 갈래가 틀림)·axis(축 때문에 잘림) 셋 중 하나이고, 줄은 패널 id 순서입니다.
참고
- 작업 디렉터리는
/root/gfd-units입니다. Grafana 는lab-start-grafana로 띄우고, 웹 미리보기 3000번 포트로 눈으로도 볼 수 있습니다. - 대시보드는 화면에서 만들어도 되고 API 로 올려도 됩니다. 채점기는 어느 쪽으로 만들었는지 묻지 않고 Grafana 에 올라간 결과만 봅니다. 올린 결과는
curl -s http://127.0.0.1:3000/api/dashboards/uid/gfd-units | jq '.dashboard.panels'로 확인합니다. - 패널의
datasource는 비워 두세요. 데이터소스 uid 는 파드마다 다르게 만들어지고, 비워 두면 기본 데이터소스(Prometheus)를 씁니다. 굳이 적어야 한다면curl -s localhost:3000/api/datasources | jq -r '.[0].uid'로 얻습니다. - 단위 식별자 표는
/opt/lab/gfd/gfd-units/unit-picker.md에 있습니다 - 이 파드의 Grafana 에서 그대로 뽑은 것이라 화면 드롭다운과 같은 목록입니다. 8단계에서 고칠 대시보드는 /opt/lab/gfd/gfd-units/broken.json 입니다. - 이 환경은 패널이 실제로 그려진 그림을 판정하지 못합니다(이미지 렌더러가 없습니다). 채점기는 대시보드 JSON 모델과 쿼리 결과만 봅니다. 눈으로 볼 것은 웹 미리보기로 직접 여세요.
- 흔한 실수: 단위만 바꾸고 쿼리를 그대로 두는 것. 단위는 값을 변환하지 않습니다.
- 흔한 실수: 축의 최댓값을 '보기 좋으라고' 박아 두는 것. 사고는 언제나 그 천장 위에서 일어납니다.
- Configure standard options · Configure overrides · Time series - Axis options · Dashboard JSON model · Prometheus - Query functions
단위를 적지 않은 패널을 올리고, 같은 숫자를 세 가지로 읽어 본다
lab-start-grafana 로 Grafana 를 띄우고, /root/gfd-units/dash.json 에 uid 가 gfd-units 인 대시보드를 만들어 Grafana 에 올리세요. 패널은 하나이고 id 는 1, 타입은 timeseries, 제목은 p99 응답 시간 (단위 없음 - 비교용), 쿼리는 histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h]))) 입니다. 이 패널에는 단위를 적지 마세요(뒤 단계에서도 그대로 둡니다 - 비교용입니다). 그리고 /root/gfd-units/01-readings.tsv 에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 두 칸 <가정한 단위 식별자> <그 가정대로면 실제로 몇 초인가> 를 적으세요. 가정할 단위는 순서대로 s(초)·ms(밀리초)·m(분) 이고, 초로 환산한 값은 소수 여섯 자리까지 적습니다.
대시보드는 웹 미리보기(3000번 포트)에서 만들어도 되고 API 로 올려도 됩니다. API 는 curl -s -XPOST -H 'Content-Type: application/json' -d @파일 http://127.0.0.1:3000/api/dashboards/db 이고 보내는 몸통은 {"dashboard": {...}, "overwrite": true} 모양입니다. 패널의 datasource 를 비워 두면 기본 데이터소스(Prometheus)를 씁니다. 환산은 곱셈 한 번입니다 - 분이라고 가정하면 그 숫자만큼의 분이므로 60을 곱합니다.
단위 식별자를 실제로 넣는다
같은 대시보드에 패널 셋을 더하세요. id 2 는 제목 p99 응답 시간, 쿼리 histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h]))), id 3 은 제목 5xx 비율, 쿼리 sum(rate(http_requests_total{job="shop-api",status=~"5.."}[1h])) / sum(rate(http_requests_total{job="shop-api"}[1h])), id 4 는 제목 남은 디스크, 쿼리 node_filesystem_avail_bytes{job="node",mountpoint="/data"} 입니다. 셋 다 타입은 timeseries 이고, 각 패널의 fieldConfig.defaults.unit 에 그 값에 맞는 Grafana 단위 식별자를 적습니다. 지연은 초 단위로, 비율은 0 과 1 사이로, 디스크는 바이트로 나옵니다. 바이트는 1024 로 줄이는 쪽(IEC)을 쓰세요. 그리고 /root/gfd-units/02-units.tsv 에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 세 칸 <패널 id> <단위 식별자> <이 단위를 고른 이유 15자 이상> 을 적으세요.
화면에 보이는 이름과 JSON 에 들어가는 식별자는 다릅니다. /opt/lab/gfd/gfd-units/unit-picker.md 에 이 파드의 Grafana 에서 그대로 뽑은 표가 있습니다. 비율은 0 과 1 사이인지 0 과 100 사이인지로 갈리고, 바이트는 1024 로 줄이는 쪽과 1000 으로 줄이는 쪽이 서로 다른 식별자입니다. 값의 크기가 궁금하면 promq "<쿼리>" 로 먼저 던져 보세요.
단위는 값을 바꾸지 않는다 - 밀리초로 보이려면 무엇을 곱해야 하나
같은 대시보드에 id 가 5 인 timeseries 패널을 더하세요. 제목은 p99 응답 시간 (ms) 이고, 같은 p99 를 밀리초 숫자로 내는 쿼리를 쓰고 단위 식별자는 밀리초 쪽을 씁니다. 그리고 /root/gfd-units/03-scale.tsv 에 머리글 없이 두 줄, 각 줄은 탭으로 나눈 두 칸 <단위 식별자> <그 패널의 쿼리가 실제로 내는 값> 을 적으세요. 첫 줄은 2단계의 초 패널, 둘째 줄은 이번 패널이고, 값은 소수 여섯 자리까지 적습니다.
단위는 표시 규칙이지 변환 규칙이 아닙니다. 초로 나오는 값에 밀리초 단위만 붙이면 화면의 숫자는 그대로이고 이름만 바뀝니다 - 천 배 작게 읽히는 패널이 됩니다. 값을 밀리초로 만들려면 쿼리에서 곱해야 합니다. 두 값은 정확히 1000배 차이가 나야 합니다.
0 에서 시작해야 하는 축과, 천장을 씌우면 안 되는 축
같은 대시보드에 id 가 6 인 timeseries 패널을 더하세요. 제목은 초당 요청 수, 쿼리는 sum(rate(http_requests_total{job="shop-api"}[5m])), 단위 식별자는 처리량 갈래의 requests/sec (rps) 이고, fieldConfig.defaults.min 을 0 으로 고정합니다. 반대로 2단계에서 만든 id 2 패널에는 max 를 넣지 마세요(넣었다면 지웁니다). 그리고 /root/gfd-units/04-axis.tsv 에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 두 칸으로 rps_min·rps_max·swing_pct 를 차례로 적으세요. 앞의 둘은 최근 12시간 동안 이 쿼리가 낸 가장 작은 값과 가장 큰 값(소수 세 자리), swing_pct 는 (최댓값 빼기 최솟값) 나누기 최댓값 곱하기 100 입니다(소수 두 자리).
12시간 동안의 최솟값·최댓값은 부분 쿼리로 구합니다 - min_over_time((<쿼리>)[12h:5m]) 처럼 씁니다. 축을 자동으로 두면 y축이 최솟값에서 시작해, 두 배도 안 되는 변동이 화면 높이를 가득 채웁니다. 반대로 최댓값을 박아 두면 그 위에서 일어난 사고가 통째로 잘려 나갑니다 - 선을 덜 출렁이게 하고 싶다면 하드 최댓값 대신 Soft max 를 씁니다.
한 패널에 단위가 다른 둘을 올린다
같은 대시보드에 id 가 7 인 timeseries 패널을 더하세요. 제목은 지연과 오류 비율, 쿼리는 둘입니다 - refId 가 A 인 histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h]))) (범례 이름 p99)와 refId 가 B 인 sum(rate(http_requests_total{job="shop-api",status=~"5.."}[1h])) / sum(rate(http_requests_total{job="shop-api"}[1h])) (범례 이름 5xx). 패널 전체의 단위는 초로 두고, fieldConfig.overrides 에 이름이 5xx 인 계열만 골라 단위를 0..1 비율로, custom.axisPlacement 를 right 로 지정하세요. 그리고 /root/gfd-units/05-override.tsv 에 머리글 없이 두 줄, 각 줄은 탭으로 나눈 세 칸 <범례 이름> <그 계열에 적용되는 단위 식별자> <축 위치> 를 적으세요. 축 위치는 left 또는 right 입니다.
오버라이드 한 칸은 {"matcher": {"id": "byName", "options": "<범례 이름>"}, "properties": [{"id": "unit", "value": "..."}, ...]} 모양입니다. 범례 이름은 타깃의 legendFormat 으로 정합니다. 오버라이드 없이 겹치면 두 계열이 한 축을 나눠 쓰게 되고, 0.004 짜리 비율은 0.3 짜리 지연 옆에서 바닥에 붙은 직선이 됩니다.
로그 축을 쓰는 자리와, 그때 잃는 것
같은 대시보드에 id 가 8 인 timeseries 패널을 더하세요. 제목은 핸들러별 초당 요청 수, 쿼리는 sum by (handler) (rate(http_requests_total{job="shop-api"}[1h])), 단위는 처리량 갈래의 requests/sec (rps) 이고, fieldConfig.defaults.custom.scaleDistribution 을 {"type": "log", "log": 10} 으로 지정합니다. 이 패널에는 최솟값을 0 으로 고정하지 마세요. 그리고 /root/gfd-units/06-log.txt 에 네 줄을 적으세요 - top=<가장 큰 핸들러의 값>, bottom=<가장 작은 핸들러의 값>(둘 다 소수 세 자리), ratio=<top 나누기 bottom, 소수 두 자리>, loss=<로그 축으로 바꾸면서 잃는 것, 40자 이상>.
핸들러 넷의 값은 promq "sum by (handler) (rate(http_requests_total{job="shop-api"}[1h]))" 로 한 번에 볼 수 있고, 가장 큰 값과 가장 작은 값은 max(...)·min(...) 으로 감싸면 바로 나옵니다. 로그 축에서 0 은 그릴 수 없습니다 - 그래서 최솟값 0 고정과 로그 축은 같이 쓸 수 없습니다. 잃는 것을 적을 때는 '같은 세로 거리가 무엇을 뜻하게 되는가' 를 생각해 보세요.
응용 ① - 나눗셈의 결과에는 어떤 단위가 붙나
같은 대시보드에 패널 둘을 더하세요. id 9 는 제목 디스크가 줄어드는 속도, 쿼리 - deriv(node_filesystem_avail_bytes{job="node",mountpoint="/data"}[1h]), 단위는 1024 로 줄이는 쪽의 초당 바이트입니다. id 10 은 제목 디스크가 바닥날 때까지, 쿼리는 남은 바이트를 줄어드는 속도로 나눈 것이고 단위는 초입니다. 둘 다 타입은 timeseries 입니다. 그리고 /root/gfd-units/07-derived.tsv 에 머리글 없이 세 줄, 각 줄은 탭으로 나눈 두 칸 <단위 식별자> <그 쿼리가 내는 값> 을 적으세요. 차례로 남은 바이트, 줄어드는 속도, 남은 시간이고 값은 소수 세 자리까지 적습니다.
바이트를 초당 바이트로 나누면 초가 남습니다 - 단위는 쿼리의 산수를 따라갑니다. 줄어드는 속도는 deriv 로 구하고, 값이 음수로 나오므로 앞에 빼기를 붙여 양수로 만듭니다. 초당 바이트는 바이트와 다른 갈래의 단위입니다(Data 가 아니라 Data rate). 바이트 단위를 그대로 붙이면 화면이 '4 GiB' 라고 말하지만 실제 뜻은 '초당 4 GiB' 입니다.
응용 ② - 운영 대시보드의 단위·축 결함을 전부 고쳐 제출한다
/opt/lab/gfd/gfd-units/broken.json 은 운영에서 걷어 온 대시보드입니다(uid gfd-units-fix). 패널 넷 모두 단위나 축에 결함이 있습니다. 쿼리는 그대로 두어도 되고 바꿔도 되지만, 화면에 나오는 값과 단위가 서로 맞아야 합니다. 고친 대시보드를 uid gfd-units-fix 로 Grafana 에 올리세요. 4번 패널(초당 요청 수)의 축은 최솟값을 0 으로 고정하고 천장은 걷어 냅니다. 그리고 /root/gfd-units/08-report.tsv 에 머리글 없이 네 줄, 각 줄은 탭으로 나눈 세 칸 <패널 id> <결함 코드> <무엇이 틀렸었나, 20자 이상이고 숫자를 하나 이상 포함> 을 적으세요. 결함 코드는 scale(값의 크기와 단위가 어긋남)·category(단위 갈래가 틀림)·axis(축 때문에 잘림) 셋 중 하나이고, 줄은 패널 id 순서입니다.
1번은 초로 나오는 값에 밀리초가 붙어 있고, 2번은 0..1 비율에 0..100 백분율이 붙어 있습니다. 둘 다 고치는 방법이 두 가지입니다 - 단위를 값에 맞추거나, 값을 단위에 맞게 곱하거나. 어느 쪽이든 됩니다. 3번은 초당 바이트인데 바이트 단위가 붙어 있습니다(갈래가 다릅니다). 4번은 단위는 맞는데 축에 천장이 씌워져 실제 트래픽이 잘립니다 - 12시간 최댓값을 먼저 재 보세요. cp /opt/lab/gfd/gfd-units/broken.json /root/gfd-units/fixed.json 으로 사본을 뜨고 고쳐서 올리면 됩니다.