이 문서는 Grafana를 관측 가능성(Observability)의 “시각화·통합 레이어” 관점에서 정리한 교재형 자료다. Grafana 자체의 구조 + LGTM 스택 + OpenTelemetry 연동에 초점을 둔다. OTel 기본기는 Learn → Monitoring → OpenTelemetry, LLM 관측은 Langfuse 문서를 함께 보면 좋다.
0. 목차
- Grafana란? 생태계에서의 위치
- 핵심 개념 — Data Source · Dashboard · Panel · Query
- LGTM 스택 (Loki · Grafana · Tempo · Mimir)
- 데이터 소스와 쿼리 언어 (PromQL · LogQL · TraceQL)
- 대시보드와 변수(Variables)
- OpenTelemetry 연동 (Alloy · OTLP)
- 세 신호의 상관관계 — Trace ↔ Log ↔ Metric 점프
- 알림(Alerting)
- 실전 셋업 (Docker Compose 예시)
- 운영 베스트 프랙티스
- Grafana OSS vs Cloud vs Enterprise
- 용어 사전 & 링크
1. Grafana란? 생태계에서의 위치
Grafana는 여러 데이터 소스의 시계열·로그·트레이스를 하나의 화면에서 조회·시각화·알림하는 오픈소스 대시보드 플랫폼이다. 데이터를 저장하지 않고, 여러 백엔드에 질의해 그려주는 “관측 가능성의 프론트엔드”다.
핵심: Grafana는 데이터 저장소가 아니다. Prometheus·Loki·Tempo·Elasticsearch 등 데이터 소스(백엔드)에 질의해 시각화하는 통합 레이어다. OTel이 “데이터를 만들어 보내는 표준”이라면, Grafana는 “그 데이터를 사람이 보는 창”이다.
[ 앱 + OTel SDK ]
│ OTLP
▼
[ OTel Collector / Grafana Alloy ]
├─► Tempo (트레이스 저장)
├─► Mimir/Prometheus (메트릭 저장)
└─► Loki (로그 저장)
│
▼ (데이터 소스로 질의)
[ Grafana ] ← 사람이 보는 대시보드·알림
2. 핵심 개념 — Data Source · Dashboard · Panel · Query
| 개념 | 의미 |
|---|---|
| Data Source | 데이터를 가져올 백엔드 연결 (Prometheus, Loki, Tempo, MySQL …) |
| Dashboard | 여러 패널을 모아둔 한 화면. JSON으로 정의·버전관리 가능 |
| Panel | 대시보드의 시각화 단위 (그래프·테이블·게이지·로그 뷰 등) |
| Query | 패널이 데이터 소스에 던지는 질의 (PromQL/LogQL/TraceQL 등) |
| Transformations | 질의 결과를 패널에서 가공(조인·계산·필터) |
| Variables | 대시보드 상단 드롭다운. 쿼리를 동적으로 바꿈 (예: $service) |
| Annotations | 그래프에 표시되는 이벤트 마커 (배포 시각 등) |
패널 유형 예: Time series, Stat, Gauge, Bar gauge, Table, Logs, Trace, Heatmap, State timeline, Node graph(서비스 토폴로지).
3. LGTM 스택 (Loki · Grafana · Tempo · Mimir)
Grafana Labs의 오픈소스 관측 스택. 머리글자 LGTM으로 외운다. OTel로 수집한 세 신호를 각자 받아 저장한다.
| 글자 | 제품 | 신호 | 설명 |
|---|---|---|---|
| L | Loki | Logs | 로그 집계. “Prometheus처럼 라벨로 인덱싱” — 본문은 인덱싱 안 해 저렴 |
| G | Grafana | — | 통합 시각화·알림 UI |
| T | Tempo | Traces | 분산 트레이스 저장. 오브젝트 스토리지 기반, 대용량·저비용 |
| M | Mimir | Metrics | Prometheus 호환 장기 저장소. 수평 확장·멀티테넌시 |
수집 에이전트는 Grafana Alloy(구 Grafana Agent)를 쓴다. Alloy는 OTel Collector 배포판의 일종으로, OTLP를 받아 LGTM으로 라우팅한다.
요점: “LGTM 스택 = OTel로 수집 → Tempo/Mimir/Loki에 저장 → Grafana로 본다.” Langfuse가 LLM 트레이스용 백엔드라면, Tempo/Mimir/Loki는 인프라·앱 일반용 백엔드다. Collector에서 양쪽으로 분기 가능.
4. 데이터 소스와 쿼리 언어
신호마다 질의 언어가 다르다. 셋 다 문법이 비슷해 한 번 익히면 전이된다.
| 데이터 소스 | 언어 | 예시 |
|---|---|---|
| Prometheus / Mimir | PromQL | rate(http_requests_total{job="api"}[5m]) |
| Loki | LogQL | {service="api"} |= "error" | json | line_format "{{.msg}}" |
| Tempo | TraceQL | { .service.name = "api" && duration > 1s } |
PromQL 기본 패턴
rate(metric[5m]) # 초당 증가율 (Counter)
histogram_quantile(0.99, # p99 지연시간 (Histogram)
sum(rate(http_duration_bucket[5m])) by (le))
sum by (status) (rate(http_requests_total[5m])) # 상태별 집계
LogQL/TraceQL도 {라벨선택} + 파이프 필터 구조를 공유한다. TraceQL은 duration·attribute 조건으로 “느린·에러 트레이스”를 정밀 검색할 때 강력하다.
5. 대시보드와 변수(Variables)
좋은 대시보드의 핵심은 변수(Variables)다. 상단 드롭다운으로 서비스·환경·인스턴스를 바꾸면 모든 패널이 따라 갱신된다.
# 변수 예: $service (Query 타입)
label_values(http_requests_total, service)
# 패널 쿼리에서 변수 사용
rate(http_requests_total{service="$service"}[5m])
| 변수 타입 | 용도 |
|---|---|
| Query | 데이터 소스에서 라벨 값 목록을 가져옴 (가장 흔함) |
| Custom | 직접 정의한 고정 목록 |
| Interval | $__interval 등 시간 범위 기반 |
| Data source | 데이터 소스 자체를 변수화 (멀티 환경) |
실전: 대시보드는 JSON 모델로 내보내 Git에 저장하면 “Dashboard as Code”가 된다. 프로비저닝(
provisioning/dashboards/) 또는 Terraform/Grafonnet으로 코드 관리 권장.
6. OpenTelemetry 연동 (Alloy · OTLP)
Grafana 스택은 OTLP를 1급으로 받는다. 앱은 OTLP로만 내보내고, 수집·라우팅은 Alloy(또는 표준 OTel Collector)가 담당한다.
6.1 Grafana Alloy로 OTLP 수신 → LGTM 라우팅
# Alloy 설정 (요지)
otelcol.receiver.otlp "default" {
grpc { endpoint = "0.0.0.0:4317" }
http { endpoint = "0.0.0.0:4318" }
output {
traces = [otelcol.exporter.otlp.tempo.input]
metrics = [otelcol.exporter.prometheus.mimir.input]
logs = [otelcol.exporter.loki.loki.input]
}
}
6.2 Grafana Cloud로 직접 OTLP 전송
export OTEL_EXPORTER_OTLP_ENDPOINT="https://otlp-gateway-<zone>.grafana.net/otlp"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <base64(instanceID:token)>"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
opentelemetry-instrument python app.py
표준 OTel 환경변수만으로 연동된다. Langfuse 연동과 패턴이 동일하다 — 차이는 엔드포인트/인증뿐.
7. 세 신호의 상관관계 — Trace ↔ Log ↔ Metric 점프
Grafana의 진짜 가치는 단일 패널이 아니라 신호 간 점프(correlation)다. OTel이 trace_id로 신호를 묶어두면, Grafana가 이를 클릭 한 번으로 연결한다.
| 기능 | 흐름 |
|---|---|
| Logs → Traces | Loki 로그의 trace_id → “Tempo에서 이 트레이스 열기” (Derived fields) |
| Traces → Logs | Tempo span → 같은 trace_id의 Loki 로그 조회 |
| Traces → Metrics | Tempo “Metrics” → span 기반 RED 메트릭(Rate/Error/Duration) |
| Exemplars | 메트릭 그래프의 점 → 그 순간의 대표 trace로 점프 |
| Service Graph | span의 SpanKind로 서비스 토폴로지 그래프 자동 생성 |
핵심: “메트릭에서 이상 발견 → exemplar로 느린 trace 클릭 → trace에서 에러 span 발견 → 그 trace_id 로그 조회”가 한 화면에서 끊김 없이 된다. 이게 3-pillar 관측의 완성형이다.
8. 알림(Alerting)
Grafana Alerting은 쿼리 결과가 조건을 위반하면 알림을 보낸다. (Grafana 8+ 통합 알림)
| 구성요소 | 역할 |
|---|---|
| Alert rule | 쿼리 + 조건 + 평가 주기 (예: p99 > 1s 가 5분 지속) |
| Contact point | 알림 전송처 (Slack, Email, PagerDuty, Webhook …) |
| Notification policy | 라벨 기반 라우팅 (팀·심각도별 분배) |
| Silence | 일시적 알림 음소거 (점검 중 등) |
# 예: API p99 지연시간 1초 초과 알림 (PromQL)
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket{job="api"}[5m])) by (le)
) > 1
상태는 Normal → Pending(조건 진입) → Firing(지속 확정)으로 전이한다. for(지속 시간)로 깜빡임(flapping)을 막는다.
9. 실전 셋업 (Docker Compose 예시)
services:
grafana:
image: grafana/grafana:latest
ports: ["3000:3000"]
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
volumes:
- ./provisioning:/etc/grafana/provisioning # 데이터소스·대시보드 자동등록
prometheus:
image: prom/prometheus:latest
volumes: [ "./prometheus.yml:/etc/prometheus/prometheus.yml" ]
tempo:
image: grafana/tempo:latest
command: [ "-config.file=/etc/tempo.yaml" ]
loki:
image: grafana/loki:latest
alloy: # OTLP 수신 → 위 백엔드로 라우팅
image: grafana/alloy:latest
ports: ["4317:4317","4318:4318"]
volumes: [ "./config.alloy:/etc/alloy/config.alloy" ]
# provisioning/datasources/ds.yaml — 데이터소스 코드로 등록
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
- name: Tempo
type: tempo
url: http://tempo:3200
- name: Loki
type: loki
url: http://loki:3100
10. 운영 베스트 프랙티스
- 대시보드는 코드로. JSON/Grafonnet/Terraform으로 버전관리. UI 수기 편집은 휘발성.
- 변수로 재사용성 확보. 서비스마다 대시보드 복제하지 말고
$service변수 하나로. - RED / USE 메서드. 서비스는 RED(Rate·Error·Duration), 리소스는 USE(Utilization·Saturation·Errors)로 패널 구성.
- 고카디널리티 라벨 주의. Prometheus/Loki 라벨에 user_id 같은 값 금지 — 시계열 폭발. (→ OTel 문서 참고)
- Exemplar·Derived fields 설정. 신호 간 점프가 관측의 핵심. 데이터소스에서 trace_id 연결을 꼭 켤 것.
- 알림은
for로 지속성 부여. 순간 스파이크에 알림 폭주(alert fatigue) 방지. - 대시보드 폴더·권한 분리. 팀별 폴더 + RBAC로 관리.
- OTLP는 Alloy/Collector 경유. 앱이 백엔드에 직접 붙지 말 것 — 백엔드 교체·버퍼링 용이.
11. Grafana OSS vs Cloud vs Enterprise
| 구분 | 내용 |
|---|---|
| Grafana OSS | 무료 오픈소스. 셀프호스팅. 대부분 기능 포함 |
| Grafana Cloud | 관리형 SaaS. LGTM 백엔드 + OTLP 게이트웨이 호스팅. 프리티어 존재 |
| Grafana Enterprise | 엔터프라이즈 데이터소스·RBAC·리포팅·SSO 등 추가 |
선택 가이드: 직접 LGTM을 굴릴 여력이 있으면 OSS 셀프호스팅, 운영 부담을 덜고 싶으면 Cloud. 어느 쪽이든 앱은 표준 OTLP로 보내므로 나중에 갈아타기 쉽다.
12. 용어 사전 & 링크
| 용어 | 뜻 |
|---|---|
| Data Source | Grafana가 질의하는 백엔드 연결 |
| LGTM | Loki·Grafana·Tempo·Mimir 오픈소스 관측 스택 |
| Alloy | Grafana의 OTel Collector 배포판(수집 에이전트) |
| PromQL / LogQL / TraceQL | 메트릭/로그/트레이스 질의 언어 |
| Exemplar | 메트릭 데이터점에 붙은 대표 trace_id 링크 |
| Derived field | 로그에서 trace_id를 추출해 트레이스로 링크하는 설정 |
| RED 메서드 | Rate·Error·Duration — 서비스 황금 지표 |
| Provisioning | 데이터소스·대시보드를 코드/파일로 자동 등록 |
참고 링크
- Grafana 문서: grafana.com/docs/grafana
- LGTM / Alloy: grafana.com/docs/alloy
- Tempo(TraceQL): grafana.com/docs/tempo
- 선행 학습: Learn → Monitoring → OpenTelemetry · Langfuse