Prometheus HTTP API 및 PromQL

Prometheus HTTP API 및 PromQL (Prometheus HTTP API and PromQL)

ClickHouse는 TimeSeries 테이블 위에 Prometheus HTTP API를 구현해요. 하나의 핸들러가 remote write, remote read, 즉시 PromQL 쿼리, 범위 PromQL 쿼리를 모두 처리해요.

출처: 문서

본문

ClickHouse는 TimeSeries 테이블 위에 Prometheus HTTP API를 구현해요. 하나의 핸들러가 remote write, remote read, 즉시 PromQL 쿼리, 범위 PromQL 쿼리를 모두 서빙해요.

Prometheus 서버가 스크랩할 ClickHouse 자신의 메트릭을 노출하려면 Prometheus 메트릭 엔드포인트를 참고해요.

사전 준비 (Prerequisites)

설정 단계는 ClickHouse Cloud와 자체 관리 ClickHouse 사이에 차이가 있어요. 배포에 맞는 섹션을 따르세요.

ClickHouse Cloud

참고: ClickHouse Cloud의 PromQL 지원은 비공개 프리뷰(private preview) 상태예요. 비공개 프리뷰에 참여하는 서비스는 이미 enable_time_series_table 설정과 Prometheus API 엔드포인트가 구성되어 있어요. 다른 ClickHouse Cloud 서비스는 이 구성을 갖고 있지 않으며, 그런 서비스에서는 직접 이 기능을 활성화할 수 없어요. 다음 섹션의 SET enable_time_series_table 문과 http_handlers 구성은 자체 관리 배포에 적용돼요.

비공개 프리뷰에 참여하는 서비스에서는 TimeSeries 테이블 만들기로 계속 진행하세요. 서비스는 엔드포인트 표에 나열된 엔드포인트 경로를 서빙해요.

자체 관리: TimeSeries 설정 활성화

테이블을 만들고 접근하는 사용자에 대해 enable_time_series_table 설정을 활성화해요:

SET enable_time_series_table = 1;

HTTP API 요청의 경우 API 사용자의 프로필에서 enable_time_series_table을 활성화해요.

자체 관리: Prometheus API 엔드포인트 구성

기본 ClickHouse HTTP 포트에 하나의 접두사 라우팅 핸들러를 구성해요:

<http_handlers>
    <defaults/>
    <rule>
        <url_prefix>/prometheus/api/v1</url_prefix>
        <handler>
            <type>prometheus_api_v1</type>
        </handler>
    </rule>
</http_handlers>

<defaults/>/ping 같은 엔드포인트와 SQL 요청에 대한 내장 핸들러를 보존해요. 위 접두사는 다음 엔드포인트를 하나의 핸들러로 노출해요:

엔드포인트 용도
/prometheus/api/v1/write Prometheus remote write
/prometheus/api/v1/read Prometheus remote read
/prometheus/api/v1/query 즉시 PromQL 쿼리
/prometheus/api/v1/query_range 범위 PromQL 쿼리
/prometheus/api/v1/format_query PromQL 표현식 포맷팅
/prometheus/api/v1/series 시리즈 메타데이터
/prometheus/api/v1/metadata 메트릭 패밀리 메타데이터

예시는 핸들러에서 databasetable을 생략했어요. 각 요청은 table 쿼리 파라미터를 제공해야 해요(/format_query 제외 — 주어진 PromQL 표현식만 파싱하고 테이블이 필요 없어요). 또한 database를 제공하거나, prometheus.metrics 같은 정규화된 테이블 이름을 사용하거나, 데이터베이스를 생략해 default를 사용할 수 있어요. 이렇게 하면 하나의 핸들러가 여러 TimeSeries 테이블을 서빙할 수 있어요.

모든 요청에 하나의 고정 테이블을 사용하려면 핸들러에서 구성해요:

<handler>
    <type>prometheus_api_v1</type>
    <database>prometheus</database>
    <table>metrics</table>
</handler>

핸들러에 구성된 테이블은 요청 파라미터로 재정의할 수 없어요.

라우팅 및 핸들러 설정:

이름 기본값 설명
url_prefix 없음 구성된 접두사로 시작하는 모든 요청 경로와 일치하는 규칙 필터.
table 없음 TimeSeries 테이블의 이름. 생략하면 요청이 table 쿼리 파라미터를 제공해야 해요. 구성된 이름은 데이터베이스를 포함할 수 있어요.
database 없음 테이블을 담고 있는 데이터베이스. 요청이 쿼리 파라미터로 제공할 수 있어요. 생략하면 ClickHouse가 정규화된 table 값의 데이터베이스를 사용하거나 default로 폴백해요.

TimeSeries 테이블 만들기 (Create a TimeSeries table)

데이터베이스와 TimeSeries 테이블을 만들어요:

CREATE DATABASE prometheus;
CREATE TABLE prometheus.metrics ENGINE = TimeSeries;

remote write로 메트릭 인제스트 (Ingest metrics with remote write)

ClickHouse는 Prometheus remote-write 프로토콜을 지원해요. Prometheus가 핸들러에 쓰도록 구성해요:

remote_write:
  - url: https://clickhouse.example.com:8443/prometheus/api/v1/write?database=prometheus&table=metrics
    basic_auth:
      username: default
      password: <password>

Prometheus는 샘플을 prometheus.metrics 테이블로 보내요.

많은 동시 remote-write 요청의 데이터를 더 적은 파트로 배치하려면 URL에 async_insert 설정을 추가해 비동기 삽입을 활성화해요(또는 사용자 프로필에서 활성화):

remote_write:
  - url: https://clickhouse.example.com:8443/prometheus/api/v1/write?database=prometheus&table=metrics&async_insert=1

ClickHouse는 wait_for_async_insert 설정과 무관하게, 데이터가 TimeSeries 테이블의 모든 내부 테이블로 플러시된 후에만 비동기 remote-write 요청을 승인해요. remote-write 프로토콜은 승인된 쓰기를 내구성 있는 것으로 취급하기 때문이에요. 플러시가 실패하면 요청이 오류를 반환하고 Prometheus가 그것을 재시도해요.

PromQL로 쿼리 (Query with PromQL)

즉시 쿼리 엔드포인트를 사용해 특정 시점에 PromQL 표현식을 평가해요:

curl --user default:<password> --get \
  "https://clickhouse.example.com:8443/prometheus/api/v1/query" \
  --data-urlencode "query=rate(http_requests_total[5m])" \
  --data-urlencode "database=prometheus" \
  --data-urlencode "table=metrics"

범위 쿼리 엔드포인트를 사용해 시간 범위에 걸쳐 표현식을 평가해요:

curl --user default:<password> --get \
  "https://clickhouse.example.com:8443/prometheus/api/v1/query_range" \
  --data-urlencode "query=rate(http_requests_total[5m])" \
  --data-urlencode "start=2026-08-15T12:00:00Z" \
  --data-urlencode "end=2026-08-15T13:00:00Z" \
  --data-urlencode "step=60s" \
  --data-urlencode "database=prometheus" \
  --data-urlencode "table=metrics"

쿼리 엔드포인트는 폼 본문의 파라미터도 받아들여요. --get 없이 curl은 파라미터를 POSTapplication/x-www-form-urlencoded로 보내요:

curl --user default:<password> \
  "https://clickhouse.example.com:8443/prometheus/api/v1/query_range" \
  --data-urlencode "query=rate(http_requests_total[5m])" \
  --data-urlencode "start=2026-08-15T12:00:00Z" \
  --data-urlencode "end=2026-08-15T13:00:00Z" \
  --data-urlencode "step=60s" \
  --data-urlencode "database=prometheus" \
  --data-urlencode "table=metrics"

format-query 엔드포인트를 사용해 PromQL 표현식을 평가하지 않고 파싱하고 포맷해요:

curl --user default:<password> --get \
  "https://clickhouse.example.com:8443/prometheus/api/v1/format_query" \
  --data-urlencode "query=sum by(job)(http_requests_total{code=\"200\"})/2"

표현식은 파싱된 쿼리에서 직렬화되어 반환되는데, 공백이 정규화되고, 주석이 제거되고, 불필요한 괄호가 빠지고, 지속 시간이 초 단위 숫자로 변환돼요: sum by (job) (http_requests_total{code="200"}) / 2. 이 엔드포인트는 표현식을 평가하지 않으므로 databasetable 파라미터가 필요 없어요.

HTTP API, promql 방언, 테이블 함수에서 사용하는 함수 및 집계 연산자 목록은 지원되는 PromQL 기능을 참고해요.

Grafana

기본 URL이 /api/v1 앞에서 끝나는 Prometheus 데이터 소스를 구성해요:

apiVersion: 1
datasources:
  - name: ClickHouse Prometheus
    type: prometheus
    access: proxy
    url: https://clickhouse.example.com:8443/prometheus
    basicAuth: true
    basicAuthUser: default
    jsonData:
      httpMethod: POST
      customQueryParameters: database=prometheus&table=metrics
    secureJsonData:
      basicAuthPassword: <password>

Grafana는 이 기본 URL에 /api/v1/query 또는 /api/v1/query_range를 추가하고 각 요청에 customQueryParameters를 더해요.

httpMethod: POST로 Grafana는 쿼리 파라미터를 요청 본문에 보내요. ClickHouse는 요청 본문과 URL 쿼리 문자열을 모두 읽으므로 customQueryParameters가 여전히 적용돼요. 긴 PromQL 표현식에는 POST를 사용하세요. URL에는 길이 제한이 있으니까요.

참고: 쿼리 엔드포인트 /api/v1/query, /api/v1/query_range, /api/v1/format_query와 메타데이터 엔드포인트 /api/v1/series, /api/v1/labels, /api/v1/label/<name>/values, /api/v1/metadata만 구현되어 있어요. /api/v1/series는 최소한 하나의 match[] 시리즈 셀렉터가 필요하고, 선택적 start, end, limit 파라미터를 지원하며, 각 셀렉터가 일치시킨 시리즈의 합집합을 반환해요. /api/v1/labels는 같은 파라미터를 받아들이며 match[]는 선택 사항이고, 일치한 시리즈(셀렉터가 없으면 모든 시리즈)의 정렬된 라벨 이름을 반환해요. /api/v1/label/<name>/values/api/v1/labels와 같은 파라미터를 받아들이고 한 라벨의 정렬된 값을 반환하며, <name>은 선택적으로 라벨 이름에 [a-zA-Z0-9_] 밖의 문자를 포함하는 경우 Prometheus U__... 이스케이프를 사용할 수 있어요. 이 엔드포인트들은 Grafana Prometheus 데이터 소스가 라벨 탐색, 템플릿 변수, 쿼리 빌더 자동 완성에 사용하는 것을 다룹니다.

SQL 진입점 (SQL entry points)

ClickHouse는 HTTP API, promql 방언, prometheusQueryprometheusQueryRange 테이블 함수에 대해 같은 PromQL 변환기를 사용해요.

clickhouse-client로 직접 PromQL을 실행해요:

clickhouse-client \
  --dialect promql \
  --promql_database prometheus \
  --promql_table metrics \
  --query 'rate(http_requests_total[5m])'

테이블 함수를 사용해 SQL 쿼리에 PromQL을 임베드해요:

SELECT *
FROM prometheusQuery(
    prometheus.metrics,
    'rate(http_requests_total[5m])',
    now()
);

메트릭 메타데이터 쿼리 (Query metric metadata)

/prometheus/api/v1/metadata 엔드포인트는 TimeSeries 테이블의 Metrics 대상 테이블에 저장된 메트릭 메타데이터(각 메트릭 패밀리의 타입, 도움말 텍스트, 단위)를 반환해요. URL 쿼리 문자열에서 다음 Prometheus 파라미터를 지원해요:

파라미터 설명
metric 이 메트릭 패밀리에 대한 메타데이터만 반환.
limit 반환되는 메트릭 패밀리 수를 제한. 음수 값은 제한 없음을 의미하고, 0은 메트릭 패밀리를 반환하지 않음.
limit_per_metric 각 메트릭 패밀리에 대해 반환되는 메타데이터 객체 수를 제한. 0과 음수 값은 제한 없음을 의미.

기본 Metrics 대상 테이블은 메트릭 패밀리 이름으로 정렬된 ReplacingMergeTree예요. 각 메트릭 패밀리에 대해 가장 최근에 쓰여진 메타데이터 항목을 유지해요. 패밀리당 여러 항목은 대상 테이블이 그것들을 저장하는 동안에만 반환돼요 — 파트가 병합되기 전 또는 테이블이 그것들을 보존하는 엔진으로 정의된 경우.

curl --user default:<password> --get \
  "https://clickhouse.example.com:8443/prometheus/api/v1/metadata" \
  --data-urlencode "metric=http_requests_total" \
  --data-urlencode "database=prometheus" \
  --data-urlencode "table=metrics"

remote read로 메트릭 읽기 (Read metrics with remote read)

ClickHouse는 /prometheus/api/v1/read에서 Prometheus remote-read 프로토콜을 지원해요.

같은 TimeSeries 테이블에서 읽도록 Prometheus 서버를 구성해요:

remote_read:
  - url: https://clickhouse.example.com:8443/prometheus/api/v1/read?database=prometheus&table=metrics
    basic_auth:
      username: default
      password: <password>

더 알아보기 (Learn more)