gcx 사용 통계 이해하기

gcx 사용 통계 이해하기 (Understand gcx usage statistics)

이 문서에서는 gcx가 Grafana Labs에 보고하는 제한된 사용 통계에 대해 알아봐요. 어떤 데이터가 수집되고, 보고서가 어떻게 전송되며, 비활성화(옵트아웃)하는 방법을 다룹니다.

출처: 문서

본문

gcx는 자신에 대한 제한된 사용 통계를 Grafana Labs에 보고해요. 이 데이터는 어떤 명령어와 플래그가 가장 많이 사용되는지, 명령어가 어디에서 실패하는지, 그리고 사람들이 존재하지 않는 어떤 명령어를 시도하는지 이해하는 데 사용되어 제품을 더 나아지게 해요.

통계는 명령어 경로와 플래그 이름을 포함한 사용의 *형태(shape)*만을 설명해요. 위치 인자(positional argument) 값, 자유 형식 플래그 값, 리소스 이름은 절대 전송되지 않으며, 설정한 플래그는 이름으로만 기록돼요. 종료 코드, 지속 시간, HTTP 상태와 같은 숫자 값은 명령어 실행 또는 프로토콜 동작을 설명해요. 배치나 리소스 규모의 원시 개수는 전송되지 않아요.

인자 값이 전혀 사용되는 유일한 곳은 api 명령어예요. 여기서 요청된 라우트와 데이터소스 플러그인 유형은 먼저 바이너리에 내장된 고정 어휘로 축소되므로, 알려진 비식별 이름만 전송될 수 있어요. 자세한 내용은 api 명령어를 참고하세요.

배치를 운영하는 리소스 명령어의 경우 작업의 크기는 숫자가 아니라 일곱 개의 고정 범주 중 하나로 전송돼요. 그 범주 중 0과 1 두 개는 각각 단일 값을 담으므로 그 두 크기는 정확하고, 더 큰 모든 범주는 범위예요. 배치 필드 읽는 방법을 참고하세요.

추가 필드는 플래그를 명명하는 대신 명령어가 어떻게 실행되었는지 설명해요: output_format은 알려진 형식의 고정 목록에서 사용된 출력 형식을 기록하고, dry_run은 작업이 dry-run 모드로 실행되었는지 기록하며, grafana_auth_method는 고정 어휘에서 Grafana 연결에 선택된 인증 범주를 기록하고 자격 증명 자체는 절대 기록하지 않아요. output_format은 --output에서 읽는데, 이는 --json을 전달해서 JSON을 렌더링한 명령어도 여전히 --output의 값으로 기록된다는 뜻이에요. 이 불일치는 의도된 동작이 아니라 알려진 버그예요. dry_run은 작업에서 파생되며 --dry-run 플래그가 없는 명령어에도 설정되고, grafana_auth_method는 실패 및 인증 필드에서 설명해요. 내보내진 사용 통계에는 서버 측 보강도 수행돼요. 자세한 내용은 서버 측 보강을 참고하세요.

참고 사용 통계 보고는 기본적으로 활성화되어 있어요. 보고를 끄는 방법은 아래 옵트아웃 섹션을 참고하세요.

텔레메트리 데이터와 식별자 (Telemetry data and identifiers)

유일한 식별자는 device_id 필드예요. 처음 사용할 때 생성되고 $XDG_STATE_HOME/gcx/device-id에 저장되는 무작위 UUID예요. 이는 사람이 아닌 gcx 설치를 식별해요. 하드웨어나 계정에서 파생되지 않은 무작위 값이에요.

어떤 데이터가 수집되는지 이해하기 (Understand which data is collected)

각 gcx 이벤트는 다음 속성을 담고 있어요:

필드 설명 예시
service 항상 gcx. 보고하는 제품을 식별해요. gcx
version gcx 버전. 0.4.1
os 운영 체제. linux, darwin, windows
arch CPU 아키텍처. amd64, arm64
device_id 텔레메트리 데이터와 식별자에서 설명한 설치별 무작위 ID. UUID
device_id_persisted 디바이스 ID를 디스크에서 읽었거나 디스크에 저장했는지 여부. false는 이 호출에 일회용(throwaway) ID가 사용되었음을 뜻해요. true
command 해석된 명령어 경로만. 인자는 전송되지 않아요. dashboards push
flags 설정한 플래그의 이름(정렬됨). 이 필드에는 플래그 값이 전송되지 않아요. dry-run,folder
provider 명령어가 속한 리소스 공급자. dashboards
outcome 호출이 어떻게 끝났는지: ok, runtime_error, canceled, 또는 help. (parse_error는 예약되어 있고 아직 전송되지 않아요 — 아래 참고.) ok
exit_code 프로세스 종료 코드. 0
error_kind 명령어가 실패했을 때의 대략적인 오류 범주: usage_error, auth_failure, partial_failure, version_incompatible, 또는 error. 오류 메시지는 절대 아니에요. 명령어가 실패하지 않았을 때는(취소 포함) 비어 있어요. auth_failure
duration_ms 총 호출 지속 시간(밀리초). 1234
is_tty gcx가 대화형 터미널에 연결되어 실행되었는지 여부. false
is_ci CI 환경이 감지되었는지 여부. true
ci_provider 알려진 이름의 고정 목록에서 감지된 CI 시스템. gcx는 잘 알려진 CI 환경 변수를 읽어 공급자를 감지하지만 그 값을 전송하지는 않아요. github_actions
is_agent AI 코딩 에이전트가 호출을 주도했는지 여부. true
agent 감지된 경우 에이전트 하네스(harness) 이름. claude-code
target_kind 대상 Grafana가 cloud인지 self-hosted인지. 유효한 Grafana 대상을 해석할 수 없으면 비어 있어요. 의도적으로 대략적이에요 — URL, 호스트 이름, 스택 슬러그는 절대 아니에요. cloud
output_format 명령어가 사용한 출력 형식. table, json

호출이 완료까지 실행된 배치 리소스 작업(gcx resources push, pull, delete, 또는 validate)일 때 다음 추가 필드가 설정돼요. 이들은 작업의 크기를 설명하며 무엇이 포함되었는지는 설명하지 않아요:

필드 설명 예시
batch_succeeded_bucket 작업의 성공한 부분 크기. 일곱 개의 고정 범주 중 하나. 21-100
batch_failed_bucket 실패한 부분 크기. 같은 일곱 범주에서. 0
batch_skipped_bucket 건너뛴 부분 크기. 같은 일곱 범주에서. 0
dry_run 작업이 dry-run 모드로 실행되었는지 여부. false가 아무것도 변경되지 않았다는 뜻은 아니에요: gcx resources pull은 읽기 전용이며 항상 false로 보고해요. command와 함께 해석해요. 플래그가 아닌 작업에서 파생돼요: gcx resources validate는 항상 true, pull은 항상 false를 보고하며, 둘 다 --dry-run 플래그가 없어요. false

일곱 범주는 정확히 0, 1, 2-5, 6-20, 21-100, 101-1000, 1001+이에요. 0과 1은 단일 범주이므로 그 두 크기는 정확히 복구되고, 더 큰 모든 범주는 범위라는 점을 기억하세요.

크기는 숫자가 아니라 의도적으로 범주로 전송돼요. 큰 배치의 정확한 개수는 설치별 device_id 및 수신 시 추가되는 네트워크 조직 이름과 상관되면 특정 조직의 리소스 인벤토리를 설명하게 돼요. 범주는 그 세부 정보 없이 gcx가 어떻게 사용되는지에 답하며, 두 단일 범주는 추론할 인벤토리가 없어요. 원시 숫자 개수 필드는 전송되지 않아요.

배치 필드 읽는 방법 (How to read the batch fields)

이 필드는 오해하기 쉬우므로 다음 제약이 계약의 일부예요:

  • 네 개 모두 함께 존재하거나, 모두 존재하지 않는다.
  • 0은 그 결과에 아무것도 계산되지 않았음을 뜻하며, 아무 일도 일어나지 않았다는 것과는 달라요. gcx resources validate gcx resources delete 0 0 0 0.
  • 크기는 작업을 설명하지 출력을 설명하지 않아요. --jq --json <fields> validate.
  • 중간에 중단된 작업은 아무것도 보고하지 않아요. gcx resources delete --on-error=abort.
  • 단위는 명령어에 따라 달라지므로, 명령어 간에 비교하거나 합산하면 안 돼요. gcx resources pull type.
  • batch_skipped_bucket은 명령어마다 의미가 다르며, 무엇을 측정하는지도 실행에 달려 있어요. gcx resources push gcx resources delete --dry-run 0 gcx resources validate gcx resources pull.
  • dry_run은 변형(변경) 플래그가 아니에요. gcx resources validate true gcx resources pull false dry_run command.
  • gcx resources get은 이 필드를 보고하지 않아요. pull.

취소된 호출 (Canceled invocations)

끝나기 전에 멈춘 호출은 exit_code: 5와 함께 outcome: canceled를 보고하고, 멈춤은 실패의 한 종류가 아니므로 error_kind는 존재하되 비어 있어요. 취소를 위해 특별히 수집되는 속성은 없으며, 실패 및 인증 필드의 실패 필드도 같은 이유로 취소에는 결코 붙지 않아요. 다른 모든 이벤트처럼 베스트 에포트(best-effort) 기준으로 전송돼요. 중단한 호출의 경우 보고서가 전송되기 전에 Ctrl-C를 두 번 누르면 프로세스가 즉시 끝나요. 다른 이유로 멈춘 호출은 다른 실행과 마찬가지로 보고서를 기다려요. 두 번째 Ctrl-C가 따라갈 인터럽트가 없으니까요.

이 값이 말해주지 않는 세 가지:

  • 항상 당신의 Ctrl-C는 아니에요. 5 canceled.
  • 중단된 모든 명령어가 보고하는 것은 아니에요. gcx dev serve ok exit_code: 0.
  • Ctrl-C만 포착돼요. gcx SIGINT SIGTERM SIGKILL SIGTERM canceled.

처음 실행하는 gcx 명령어가 중단하는 명령어라면, 그 호출이 보고하므로 일회성 공지가 인터럽트 후에 출력돼요. 공지가 먼저 오고 그 뒤에 내보내기가 시도되므로, 공지는 전달이 아니라 시도를 기록해요. 위처럼 보고서는 베스트 에포트이며 도착하지 않을 수도 있어요.

이것은 모든 결과 비율의 분모를 두 가지 방식으로 움직여요. 따라서 canceled가 처음 나타나는 버전을 가로질러서가 아니라 version 내에서 비율을 비교해야 해요:

  • 일부 호출이 아예 계산되기 시작해요. 5 ok ok.
  • 일부 호출이 레이블을 바꿔요. 5가 runtime_error error_kind: error, canceled error_kind(runtime_error error_kind: error).

실패 및 인증 필드 (Failure and authentication fields)

Grafana 연결에 대해 gcx는 oauth, token, basic, mtls, anonymous, unknown 같은 선택된 인증 범주를 기록하지만 자격 증명은 절대 기록하지 않아요. 실패한 일부 명령어에 대해 4xx/5xx HTTP 상태 또는 고정 Kubernetes 사유 범주도 기록할 수 있어요. 이 세부 정보는 부분 실패와 취소에 대해서는 생략돼요.

필드 설명 예시
http_status 실패한 요청의 HTTP 전송 상태. 항상 400–599. 응답 본문 안에 내장된 상태나 Kubernetes 상태 코드는 절대 아니에요. 403
k8s_reason 실패한 API 호출의 Kubernetes 상태 사유. 고정 어휘에서. 어휘 밖의 사유는 절대 그대로가 아니라 other로 전송돼요. NotFound
grafana_auth_method Grafana 연결에 선택된 인증 범주. oauth, token, basic, mtls, anonymous, unknown 중 정확히 하나. 원시 구성 값이나 자격 증명 자료는 절대 아니에요. token

k8s_reason 어휘는 정확히 Unauthorized, Forbidden, NotFound, AlreadyExists, Conflict, Gone, Invalid, BadRequest, MethodNotAllowed, NotAcceptable, RequestEntityTooLarge, UnsupportedMediaType, Expired, Timeout, ServerTimeout, TooManyRequests, InternalError, ServiceUnavailable, StorageReadError, 그리고 other 센티널이에요.

이 필드는 오해하기 쉬우므로 다음 제약이 계약의 일부예요:

  • http_status는 전송 상태이지 본문 상태가 아니에요. http_status error_kind auth_failure.
  • 실패 상태만 이동해요. 400 599.
  • 적용 범위는 부분적이므로, 부재가 아무것도 증명하지 않아요. http_status는 gcx api에서 http_status.
  • Kubernetes 실패는 상태가 아니라 사유를 보고해요. k8s_reason http_status http_status.
  • 두 실패 필드는 종료 코드 4와 5에서는 생략돼요.
  • grafana_auth_method는 Grafana 연결 인증만 설명해요. gcx config check anonymous unknown.
  • grafana_auth_method는 모든 결과에 존재해요. gcx login.

구문 분석 실패 필드 (Parse-failure fields)

호출이 구문 분석에 실패하면 다음 추가 필드가 설정돼요. 이들은 사용자가 기대하는 것과 존재하는 것의 차이를 이해할 수 있도록 시도된 것을 포착해요. 아직 채워지지 않아요: 구문 분석 실패는 현재 아무 이벤트도 보고하지 않으며(아무것도 보고하지 않는 호출 참고), 오늘날 outcome이 parse_error인 경우는 없어요.

필드 설명 예시
parse_error_kind 구문 분석 실패 종류: unknown_command, unknown_flag, 또는 invalid_args. unknown_command
parse_error_parent 실패 전에 도달한 가장 깊은 유효 명령어. dashboards
parse_error_token 첫 번째 알 수 없는 토큰. 명령어 이름처럼 보일 때만 전송돼요(짧고, 소문자며, 숫자 없고, URL·IP 주소·UUID가 아님). 그렇지 않으면 <redacted>로 대체돼요. serch
attempted_command 상위 명령어에 알 수 없는 토큰을 더한 것. 알 수 없는 토큰에서 잘려 이후 인자는 포함되지 않아요. dashboards serch
parse_error_flags 알 수 없는 플래그의 이름. 플래그 값은 전송되지 않아요. verbsoe
parse_error_nearest 가까운 것이 있으면 가장 가까운 실제 명령어 또는 플래그 이름. search
parse_error_distance 가장 가까운 실제 이름까지의 편집 거리, 또는 근접 일치가 없으면 -1. 2

api 명령어 (The api command)

gcx api 명령어는 사용자가 Grafana API에 임의의 요청을 보낼 수 있게 해주므로 독특해요. 유용한 사용 정보(어떤 엔드포인트와 메서드가 사용되는지)를 얻으려면 인자 값을 검사해야 해요. 이는 사용 텔레메트리의 일부로 인자 값을 보내지 않는다는 주장에 대한 예외예요. 민감하거나 식별 가능한 정보를 보내는 위험은 녹화되기 전에 인자 값을 바이너리에 내장된 고정 어휘로 필터링해서 줄여요. 필터링된 인자 값은 사용자가 api 명령어를 어떤 엔드포인트와 쿼리에 사용하는지 배우는 데만 사용되며, 미래에 새 gcx 명령어로 가치를 더할 수 있는 곳을 발견할 수 있도록 해요.

필드 설명 예시
api_method HTTP 메서드. 유효 동사의 고정 목록에서. POST
api_route 요청된 라우트. 알려진 Grafana API 라우트 템플릿의 내장 표와 대조. UID와 이름 같은 가변 세그먼트는 자리 표시자로 대체되고, 알려진 라우트와 일치하지 않는 경로는 other로 전송돼요. 원시 경로는 절대 전송되지 않으며, 쿼리 문자열은 일치 전에 버려져요. /api/dashboards/uid/{uid}
api_datasource_types 데이터소스 쿼리 요청에만: 요청 본문에 이름이 나온 데이터소스 플러그인 유형. 유형은 바이너리에 내장된 Grafana 게시 플러그인 ID의 고정 목록에 나타날 때만 전송돼요(핵심 데이터소스 유형 + Grafana가 카탈로그에서 게시하는 데이터소스 플러그인). 다른 모든 유형(타사 및 비공개 플러그인 포함)은 other로 전송돼요. 본문은 queries[].datasource.type 필드를 읽는 데만 사용되며, 그렇게 읽을 수 없는 쿼리 요청(누락, 과대, 또는 잘못된 형식)은 other로 전송돼요. 데이터소스 UID와 이름, 쿼리 텍스트, 시간 범위, 본문의 다른 모든 것은 절대 전송되지 않아요. grafana-postgresql-datasource

이 모든 것은 GCX_TELEMETRY=log로 어떤 호출에서든 검증할 수 있어요(전송될 내용 검사 참고).

아무것도 보고하지 않는 호출 (Invocations that report nothing)

어떤 호출은 이벤트를 절대 내보내지 않아요:

  • 셸 완성(completion)
  • gcx version
  • 구문 분석에 실패한 호출 parse_error_*

보고서가 전송되는 방식 (How the report is sent)

한 호출은 기껏해야 보고서 하나를 전송해요. gcx는 이벤트를 배치하지 않고, 나중 실행을 위해 대기열에 넣지 않으며, 명령어보다 오래 사는 백그라운드 프로세스를 시작하지 않아요.

속성 값
대상 https://stats.grafana.org/gcx-usage-report
메서드 이벤트를 JSON 객체로 하는 단일 POST
시도 한 번. 실패한 보고서는 재시도되지도 저장되지도 않아요.
타이밍 동기적. 명령어가 출력을 기록한 후 프로세스가 종료되기 전
시간 제한 DNS, TCP, TLS를 포함한 전체 교환에 1초

보고서는 동기적으로 전송되므로 호출이 종료되기 전에 최대 1초가 더 걸릴 수 있어요. 정상 조건에서는 비용이 훨씬 작고, 연결을 거부하거나 해석에 실패하는 엔드포인트는 실패가 즉각적이므로 거의 비용이 들지 않아요.

매 호출에서 전체 1초가 드는 경우가 하나 있어요: 패킷을 거부하는 대신 조용히 떨어뜨리는 네트워크예요. 일부 기업 방화벽이 이렇게 해요. 그런 방식으로 대상을 차단하면 각 gcx 호출이 종료되기 전에 1초 제한을 기다려요. 지연을 피하려면 주소를 차단하는 대신 GCX_TELEMETRY=disabled로 옵트아웃해요. 옵트아웃된 호출은 이벤트를 만들지 않고 연결도 열지 않아요.

보고서를 다른 곳으로 보내려면 GCX_TELEMETRY_ENDPOINT를 다른 URL로 설정해요. 이는 대상만 바꿔요. 옵트아웃이 아니며 값은 주어진 대로 사용돼요.

서버 측 보강 (Server-side enrichment)

보고서는 Grafana, Loki, Tempo, Mimir에서 사용 보고를 받는 것과 동일한 Grafana의 사용 통계 서비스가 수신해요. 수신 시 서비스는 연결에서 파생된 두 가지 정보를 추가해요:

  • 지리적 지역
  • 네트워크 조직 이름

연결 IP 주소는 사용 이벤트에 저장되지 않아요.

전송될 내용 검사 (Inspect what would be sent)

호출에 대해 gcx가 정확히 무엇을 보고하는지 보려면 GCX_TELEMETRY=log를 설정해요. 이벤트가 stderr로 출력되고 아무것도 전송되지 않아요:

GCX_TELEMETRY=log gcx dashboards list

옵트아웃 (Opt out)

사용 통계 보고를 세 가지 방법으로 제어할 수 있어요:

  1. GCX_TELEMETRY 환경 변수 enabled disabled log
export GCX_TELEMETRY=disabled
  1. DO_NOT_TRACK 환경 변수: 보고를 비활성화하려면 1 또는 true로 설정해요. 도구 간 DO_NOT_TRACK 규약을 따르는 방식이에요. GCX_TELEMETRY가 덮어써요.

  2. 구성 파일: gcx 구성 파일에 최상위 diagnostics 블록을 추가하고 telemetry를 enabled, disabled, 또는 log로 설정해요:

diagnostics:
  telemetry: disabled

옵트아웃하면 보고가 완전히 비활성화돼요. 이벤트가 만들어지지 않고 아무것도 전송되지 않아요.

일회성 공지 (The one-time notice)

gcx는 호출을 처음 보고할 때 stderr에 짧은 공지를 출력해요. 공지는 무엇이 수집되는지와 옵트아웃 방법을 밝혀요. 명령어의 자체 출력 후에 출력되므로 stdout의 결과 문서에 절대 섞이지 않아요.

공지는 텍스트 수정본(revision)마다 최대 한 번 표시돼요. gcx는 표시한 수정본을 $XDG_STATE_HOME/gcx/telemetry-notice-shown에 기록해요. 대부분 시스템에서 ~/.local/state/gcx/telemetry-notice-shown이에요. 공지를 다시 보려면 그 파일을 삭제해요. 텍스트가 실질적으로 바뀌면 수정본도 함께 바뀌고, 공지가 한 번 더 표시돼요 — 이미 gcx를 실행한 설치에도요.

두 가지 제한을 명확히 말할 가치가 있어요:

  • 공지는 대화형 터미널에만 출력돼요.
  • 첫 번째 보고서는 공지를 출력하는 것과 같은 호출이 전송해요.

더 알아보기 (Learn more)