Grafana는 ClickHouse의 관측성 데이터를 시각화하는 데 권장되는 도구입니다. 이는 Grafana용 공식 ClickHouse 플러그인을 통해 구현됩니다. 설치 지침은 여기에서 확인할 수 있습니다.
플러그인 V4에서는 새로운 쿼리 빌더 환경에서 로그와 트레이스를 핵심적으로 다룰 수 있습니다. 이를 통해 SRE가 SQL 쿼리를 직접 작성할 필요를 줄이고, SQL 기반 관측성을 더 간편하게 구현할 수 있어 이 새로운 패러다임의 발전을 앞당깁니다. 이를 위해 OpenTelemetry(OTel)를 플러그인의 중심에 배치했습니다. 앞으로 수년간 이것이 SQL 기반 관측성의 토대이자 데이터 수집 방식의 기반이 될 것이라고 보기 때문입니다.
OpenTelemetry 통합
Grafana에서 ClickHouse 데이터 소스를 구성할 때 플러그인에서 로그와 트레이스에 사용할 기본 데이터베이스와 테이블, 그리고 해당 테이블이 OTel 스키마를 따르는지 여부를 지정할 수 있습니다. 이를 통해 플러그인은 Grafana에서 로그와 트레이스를 올바르게 렌더링하는 데 필요한 컬럼을 반환할 수 있습니다. 기본 OTel 스키마를 변경해 자체 컬럼 이름을 사용하려는 경우 해당 이름을 지정할 수 있습니다. 시간(Timestamp), 로그 레벨(SeverityText), 메시지 본문(Body)과 같은 컬럼에 기본 OTel 컬럼 이름을 사용하면 별도 변경이 필요하지 않습니다.
로그를 올바르게 렌더링하려면 Logs 구성에 시간, 로그 레벨, 메시지 컬럼이 필요합니다.
Traces 구성은 약간 더 복잡합니다(전체 목록은 여기에서 확인할 수 있습니다). 여기서 필요한 컬럼은 전체 trace profile을 구성하는 후속 쿼리를 추상화할 수 있도록 하기 위한 것입니다. 이러한 쿼리는 데이터가 OTel과 유사한 방식으로 구조화되어 있다고 가정하므로, 표준 스키마에서 크게 벗어난 경우 이 기능을 활용하려면 뷰를 사용해야 합니다.

구성이 완료되면 Grafana Explore로 이동해 로그와 트레이스 검색을 시작할 수 있습니다.
로그
로그에 대한 Grafana 요구 사항을 충족하는 경우, 쿼리 빌더에서 Query Type: Log를 선택하고 Run Query를 클릭할 수 있습니다. 그러면 쿼리 빌더가 로그를 나열하는 쿼리를 생성하고, 예를 들어 다음과 같이 표시되도록 합니다.
SELECT Timestamp as timestamp, Body as body, SeverityText as level, TraceId as traceID FROM "default"."otel_logs" WHERE ( timestamp >= $__fromTime AND timestamp <= $__toTime ) ORDER BY timestamp DESC LIMIT 1000
쿼리 빌더를 사용하면 SQL을 직접 작성하지 않고도 쿼리를 손쉽게 수정할 수 있습니다. 키워드가 포함된 로그를 찾는 것을 비롯한 필터링 작업도 쿼리 빌더에서 수행할 수 있습니다. 더 복잡한 쿼리를 작성하려면 SQL Editor로 전환할 수 있습니다. 적절한 컬럼이 반환되고 Query Type으로 logs를 선택하면 결과가 로그로 렌더링됩니다. 로그 렌더링에 필요한 컬럼은 여기에 나와 있습니다.
로그에서 트레이스로
로그에 트레이스 ID가 포함되어 있으면 특정 로그 항목에서 해당 트레이스로 바로 이동할 수 있습니다.

트레이스
위의 로깅 방식과 마찬가지로, Grafana가 트레이스를 렌더링하는 데 필요한 컬럼이 갖춰져 있으면(예: OTel 스키마 사용) 쿼리 빌더가 필요한 쿼리를 자동으로 작성할 수 있습니다. Query Type: Traces를 선택하고 Run Query를 클릭하면 다음과 유사한 쿼리가 생성되어 실행됩니다(구성된 컬럼에 따라 달라질 수 있으며, 아래 예시는 OTel 사용을 가정합니다):
SELECT "TraceId" as traceID,
"ServiceName" as serviceName,
"SpanName" as operationName,
"Timestamp" as startTime,
multiply("Duration", 0.000001) as duration
FROM "default"."otel_traces"
WHERE ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )
AND ( ParentSpanId = '' )
AND ( Duration > 0 )
ORDER BY Timestamp DESC, Duration DESC LIMIT 1000이 쿼리는 Grafana에서 필요한 컬럼 이름을 반환하며, 아래와 같이 트레이스 테이블을 표시합니다. SQL을 작성하지 않고도 duration이나 다른 컬럼을 기준으로 필터링할 수 있습니다.

더 복잡한 쿼리를 작성하려는 사용자는 SQL Editor로 전환할 수 있습니다.
트레이스 세부 정보 보기
위와 같이 트레이스 ID는 클릭 가능한 링크로 표시됩니다. 트레이스 ID를 클릭하면 View Trace 링크를 통해 관련 스팬을 볼 수 있습니다. 그러면 필요한 구조로 스팬을 가져오기 위해 다음 쿼리(OTel 컬럼을 기준으로 함)를 실행하며, 결과는 워터폴 형태로 표시됩니다.
WITH '<trace_id>' AS trace_id,
(SELECT min(Start) FROM "default"."otel_traces_trace_id_ts"
WHERE TraceId = trace_id) AS trace_start,
(SELECT max(End) + 1 FROM "default"."otel_traces_trace_id_ts"
WHERE TraceId = trace_id) AS trace_end
SELECT "TraceId" AS traceID,
"SpanId" AS spanID,
"ParentSpanId" AS parentSpanID,
"ServiceName" AS serviceName,
"SpanName" AS operationName,
"Timestamp" AS startTime,
multiply("Duration", 0.000001) AS duration,
arrayMap(key -> map('key', key, 'value',"SpanAttributes"[key]),
mapKeys("SpanAttributes")) AS tags,
arrayMap(key -> map('key', key, 'value',"ResourceAttributes"[key]),
mapKeys("ResourceAttributes")) AS serviceTags
FROM "default"."otel_traces"
WHERE traceID = trace_id
AND startTime >= trace_start
AND startTime <= trace_end
LIMIT 1000
트레이스에서 로그로
로그에 트레이스 ID가 포함되어 있으면 트레이스에서 해당 로그로 이동할 수 있습니다. 로그를 보려면 트레이스 ID를 클릭한 다음 View Logs를 선택하세요. 그러면 기본 OTel 컬럼을 기준으로 다음 쿼리가 실행됩니다.
SELECT Timestamp AS "timestamp",
Body AS "body", SeverityText AS "level",
TraceId AS "traceID" FROM "default"."otel_logs"
WHERE ( traceID = '<trace_id>' )
ORDER BY timestamp ASC LIMIT 1000
대시보드
Grafana에서 ClickHouse 데이터 소스를 사용해 대시보드를 만들 수 있습니다. 자세한 내용은 Grafana 및 ClickHouse 데이터 소스 문서를 참고하는 것이 좋습니다. 특히 매크로 개념과 변수를 참고하십시오.
이 플러그인은 바로 사용할 수 있는 여러 대시보드를 제공하며, 여기에는 OTel 사양을 준수하는 로깅 및 트레이싱 데이터용 예시 대시보드인 "Simple ClickHouse OTel dashboarding"도 포함됩니다. 이 대시보드를 사용하려면 OTel의 기본 컬럼 이름 규칙을 따라야 하며, 데이터 소스 구성에서 설치할 수 있습니다.

아래에는 시각화를 만들 때 유용한 몇 가지 간단한 팁을 제공합니다.
시계열
통계와 함께 선 차트는 관측성 사용 사례에서 가장 흔히 사용되는 시각화 방식입니다. 쿼리가 time이라는 이름의 datetime과 숫자 컬럼을 반환하면 ClickHouse 플러그인은 자동으로 선 차트를 표시합니다. 예시:
SELECT
$__timeInterval(Timestamp) as time,
quantile(0.99)(Duration)/1000000 AS p99
FROM otel_traces
WHERE
$__timeFilter(Timestamp)
AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )
GROUP BY time
ORDER BY time ASC
LIMIT 100000
다중 선 차트
다음 조건을 충족하면 쿼리가 다중 선 차트로 자동 렌더링됩니다:
- 필드 1:
time별칭(alias)을 가진 datetime 필드 - 필드 2: 그룹화할 값. String이어야 합니다.
- 필드 3+: 메트릭 값
예시:
SELECT
$__timeInterval(Timestamp) as time,
ServiceName,
quantile(0.99)(Duration)/1000000 AS p99
FROM otel_traces
WHERE $__timeFilter(Timestamp)
AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )
GROUP BY ServiceName, time
ORDER BY time ASC
LIMIT 100000
Geo 데이터 시각화
이전 섹션에서는 IP 딕셔너리를 사용해 관측성 데이터를 Geo 좌표로 보강하는 방법을 살펴보았습니다. latitude 및 longitude 컬럼이 있다고 가정하면 geohashEncode 함수를 사용해 관측성 데이터를 시각화할 수 있습니다. 이렇게 하면 Grafana Geo Map 차트와 호환되는 geohash가 생성됩니다. 예시 쿼리와 시각화는 아래와 같습니다:
WITH coords AS
(
SELECT
Latitude,
Longitude,
geohashEncode(Longitude, Latitude, 4) AS hash
FROM otel_logs_v2
WHERE (Longitude != 0) AND (Latitude != 0)
)
SELECT
hash,
count() AS heat,
round(log10(heat), 2) AS adj_heat
FROM coords
GROUP BY hash