쿼리
이 예제는 예약된 샘플 테이블 telemetry_quickstart의 가상 데이터를 사용합니다. API 동작을 확인할 뿐, 애플리케이션 계측이 완료되었다는 뜻은 아닙니다. 실제 애플리케이션에서는 작업 흐름에 맞는 테이블을 선택하고 실제 작업에서 이벤트를 보내세요.
API 쿼리를 사용하면 Telemetry 데이터에 대해 SQL을 실행할 수 있습니다.
포스트 https://api.telemetry.sh/query
헤더
| 이름 | 유형 | 설명 |
|---|---|---|
| 콘텐츠 유형 | 문자열 | 애플리케이션/json |
| 승인 | 문자열 | API 키(원본 키 또는 Bearer <key>) |
본문
| 이름 | 유형 | 필수 | 설명 |
|---|---|---|---|
| 쿼리 | 문자열 | 예 | 실행할 SQL 쿼리입니다. |
| 실시간 | 부울 | 아니요 | 기본값은 true입니다. 쿼리 서비스로 전달되었습니다. |
| JSON | 부울 | 아니요 | 기본값은 true입니다. 쿼리 서비스로 전달되었습니다. |
성공 응답, 200 OK
{
"status": "success",
"data": [
{
"city": "paris",
"average_price": 42.0
}
],
"key_order": ["city", "average_price"]
}
data에는 결과 행이 포함되어 있습니다. key_order는 쿼리 결과의 열 순서를 유지합니다.
cURL의 사용 예
이 cURL 요청은 telemetry_quickstart에서 도시별 평균 요금을 조회합니다.
QUERY=$(cat <<'SQL'
SELECT
city,
AVG(price) AS average_price
FROM
telemetry_quickstart
GROUP BY
city
LIMIT
10000;
SQL
)
curl -X POST https://api.telemetry.sh/query \
-H "Content-Type: application/json" \
-H "Authorization: $API_KEY" \
-d "$(jq -n --arg query "$QUERY" '{query: $query, realtime: true, json: true}')"
JavaScript SDK 사용
더 나은 개발자 경험을 위해 SDK를 사용하는 것이 좋습니다.
import telemetry from "telemetry-sh";
telemetry.init("YOUR_API_KEY");
const results =
await telemetry.query(`
SELECT
city,
AVG(price)
FROM
telemetry_quickstart
GROUP BY
city
`);
비동기 쿼리
작은 JSON 결과는 result의 data와 key_order로 직접 반환됩니다. 큰 JSON 결과와 Parquet 내보내기는 download_url을 사용합니다. 완료 응답에는 둘 중 하나만 있으면 됩니다. 직접 반환되는 결과에는 다운로드 URL이나 URL 만료 필드가 필요하지 않습니다. download_url_expired가 true이면 새 쿼리를 시작하세요. 만료 필드는 선택 사항입니다.
이는 전체 테이블을 내보내거나, 대규모 집계를 실행하거나, 결과를 JSON 또는 Parquet 파일로 다운로드하는 데 특히 유용합니다.
작동 원리
- 시작 —
POST/query/async에 대한 쿼리입니다. 서버는job_id및status_url를 반환합니다. - 설문조사 — 진행 상황을 확인하려면
GETstatus_url를 사용하세요. result에서 결과를 읽거나download_url에서 파일을 다운로드합니다.
API 참조
비동기 쿼리 시작
포스트 https://api.telemetry.sh/query/async
헤더
| 이름 | 유형 | 설명 |
|---|---|---|
| 콘텐츠 유형 | 문자열 | 애플리케이션/json |
| 승인 | 문자열 | API 키(원본 키 또는 Bearer <key>) |
본문
| 이름 | 유형 | 필수 | 설명 |
|---|---|---|---|
| 쿼리 | 문자열 | 예 | 실행할 SQL 쿼리입니다. |
| 실시간 | 부울 | 아니요 | 기본값은 true입니다. 쿼리 서비스로 전달되었습니다. |
| JSON | 부울 | 아니요 | 기본값은 true입니다. 쿼리 서비스로 전달되었습니다. |
| 형식 | 문자열 | 아니요 | 결과 형식: "json"(기본값) 또는 "parquet". |
응답(202 승인)
{
"status": "accepted",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"format": "json",
"status_url": "/query/async/550e8400-e29b-41d4-a716-446655440000"
}
폴링 쿼리 상태
GET https://api.telemetry.sh/query/async/{job_id}
헤더
| 이름 | 유형 | 설명 |
|---|---|---|
| 승인 | 문자열 | API 키(원본 키 또는 Bearer <key>) |
응답(200 OK)
직접 반환된 JSON 결과
{
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"query_status": "completed",
"format": "json",
"progress_pct": 100,
"result": {
"data": [{ "events": 7 }],
"key_order": ["events"]
}
}
다운로드 가능한 결과
{
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"query_status": "completed",
"format": "json",
"progress_pct": 100,
"message": "Query completed",
"created_at": "2025-02-24T12:00:00Z",
"completed_at": "2025-02-24T12:00:05Z",
"download_url": "https://storage.example.com/results/...",
"download_url_expires_in_seconds": 3600
}
format가 "json"인 경우 다운로드한 파일에는 쿼리 메타데이터와 result 아래의 표준 쿼리 결과 형태가 포함됩니다.
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"format": "json",
"result": {
"data": [
{
"city": "paris",
"average_price": 42.0
}
],
"key_order": ["city", "average_price"]
}
}
query_status 필드는 다음 중 하나입니다.
| 상태 | 설명 |
|---|---|
queued |
쿼리가 실행되기를 기다리고 있습니다. |
running |
쿼리가 현재 실행 중입니다. |
completed |
결과는 result 또는 download_url로 제공됩니다. |
failed |
쿼리가 실패했습니다. error 필드를 확인하세요. |
cancelled |
쿼리가 취소되었습니다. |
cURL을 사용한 비동기 쿼리
# 1. Start the async query
QUERY='SELECT * FROM telemetry_quickstart'
RESPONSE=$(curl --fail-with-body -sS --max-time 30 https://api.telemetry.sh/query/async \
-H "Content-Type: application/json" \
-H "Authorization: $API_KEY" \
-d "$(jq -n --arg query "$QUERY" '{query: $query, format: "json", realtime: true, json: true}')") || exit 1
STATUS_URL="https://api.telemetry.sh$(echo "$RESPONSE" | jq -r '.status_url')"
# 2. Poll for at most ten minutes
DEADLINE=$((SECONDS + 600))
while [ "$SECONDS" -lt "$DEADLINE" ]; do
STATUS=$(curl --fail-with-body -sS --max-time 30 -H "Authorization: $API_KEY" "$STATUS_URL") || exit 1
QUERY_STATUS=$(echo "$STATUS" | jq -r '.query_status')
if [ "$QUERY_STATUS" = "completed" ]; then
if echo "$STATUS" | jq -e '.download_url_expired == true' >/dev/null; then
echo "Result expired. Start a new query."
exit 1
elif echo "$STATUS" | jq -e '.result | type == "object"' >/dev/null; then
echo "$STATUS" | jq '{result: .result}' > results.json
else
DOWNLOAD_URL=$(echo "$STATUS" | jq -r '.download_url // empty')
if [ -z "$DOWNLOAD_URL" ]; then
echo "Completed response has neither a result nor an active download URL."
exit 1
fi
curl --fail-with-body -sS --max-time 300 -o results.json "$DOWNLOAD_URL" || exit 1
fi
# Both branches have the same result shape, including an empty data array.
jq '.result' results.json
exit 0
elif [ "$QUERY_STATUS" = "failed" ] || [ "$QUERY_STATUS" = "cancelled" ]; then
echo "Query $QUERY_STATUS: $(echo "$STATUS" | jq -r '.error // .message')"
exit 1
elif [ "$QUERY_STATUS" != "queued" ] && [ "$QUERY_STATUS" != "running" ]; then
echo "Unexpected query status: $QUERY_STATUS"
exit 1
fi
sleep 5
done
echo "Query polling timed out."
exit 1
예: 전체 테이블 내보내기
비동기 쿼리 API는 전체 테이블 내보내기에 이상적입니다. 비동기 쿼리에는 행 제한이 없으므로 모든 항목을 내보내고 결과를 단일 파일로 다운로드할 수 있습니다.
# Start the export as Parquet
QUERY='SELECT * FROM telemetry_quickstart'
RESPONSE=$(curl --fail-with-body -sS --max-time 30 https://api.telemetry.sh/query/async \
-H "Content-Type: application/json" \
-H "Authorization: $API_KEY" \
-d "$(jq -n --arg query "$QUERY" '{query: $query, format: "parquet", realtime: true, json: true}')") || exit 1
STATUS_URL="https://api.telemetry.sh$(echo "$RESPONSE" | jq -r '.status_url')"
# Poll for at most ten minutes
DEADLINE=$((SECONDS + 600))
while [ "$SECONDS" -lt "$DEADLINE" ]; do
STATUS=$(curl --fail-with-body -sS --max-time 30 -H "Authorization: $API_KEY" "$STATUS_URL") || exit 1
QUERY_STATUS=$(echo "$STATUS" | jq -r '.query_status')
if [ "$QUERY_STATUS" = "completed" ]; then
if echo "$STATUS" | jq -e '.download_url_expired == true' >/dev/null; then
echo "Result expired. Start a new export."
exit 1
fi
DOWNLOAD_URL=$(echo "$STATUS" | jq -r '.download_url // empty')
if [ -z "$DOWNLOAD_URL" ]; then
echo "Export completed, but no active download URL is available."
exit 1
fi
curl --fail-with-body -sS --max-time 300 -o telemetry_quickstart_export.parquet "$DOWNLOAD_URL" || exit 1
echo "Export complete: telemetry_quickstart_export.parquet"
exit 0
elif [ "$QUERY_STATUS" = "failed" ] || [ "$QUERY_STATUS" = "cancelled" ]; then
echo "Export $QUERY_STATUS: $(echo "$STATUS" | jq -r '.error // .message')"
exit 1
elif [ "$QUERY_STATUS" != "queued" ] && [ "$QUERY_STATUS" != "running" ]; then
echo "Unexpected query status: $QUERY_STATUS"
exit 1
fi
sleep 5
done
echo "Export polling timed out."
exit 1
SDK 경계
현재 JavaScript SDK의 query 메서드는 대화형 /query를 호출합니다.
끝점. /query/async를 시작하지 않고, status_url를 폴링하고, 실행합니다.
비동기 작업 시간 초과를 선택하거나 완료된 아티팩트를 다운로드하세요.
대규모 JSON 또는 Parquet의 경우 위의 HTTP 시작, 폴링 및 다운로드 흐름을 사용하세요.
수출. 애플리케이션 래퍼는 이 세 가지 작업을 캡슐화할 수 있지만
여전히 총 폴링 기한을 적용하고 failed에서 중지하고
이전 다운로드를 다시 시도하는 대신 새 내보내기로 download_url가 만료되었습니다.
무기한.
일반적인 오류
- JSON 본문이 유효하지 않은 경우
400 Bad Request query가 없거나 비어 있는 경우400 Bad Request- API 키가 없거나 잘못된 경우
401 Unauthorized 402 Payment Required페이월 확인으로 인해 계정이 차단된 경우- API 키가 게이트웨이 속도 제한을 초과하는 경우
429 Too Many Requests