InfoGrab DocsInfoGrab Docs

집계형 Value Stream Analytics

요약

이 페이지는 Value Stream Analytics(VSA)의 집계형 백엔드에 대한 고수준 개요를 제공합니다. 이 페이지는 향후 제품, 기능 및 기능성과 관련된 정보를 담고 있습니다. 집계형 백엔드는 GitLab 15.0부터 그룹 수준에서 기본으로 사용됩니다.

이 페이지는 Value Stream Analytics(VSA)의 집계형 백엔드에 대한 고수준 개요를 제공합니다.

이 페이지는 향후 제품, 기능 및 기능성과 관련된 정보를 담고 있습니다. 여기에 제시된 정보는 정보 제공 목적으로만 활용해야 합니다. 구매 또는 계획 목적으로 이 정보를 참고하지 마세요. 제품, 기능 또는 기능성의 개발, 릴리스 및 일정은 변경되거나 지연될 수 있으며, 전적으로 GitLab Inc.의 재량에 달려 있습니다.

현재 상태#

집계형 백엔드는 GitLab 15.0부터 그룹 수준에서 기본으로 사용됩니다.

도입 배경#

집계형 백엔드는 VSA 기능의 성능 한계를 해결하고 장기적인 성장을 위한 기반을 마련하는 것을 목표로 합니다.

기본 데이터베이스는 분석 워크로드를 위한 준비가 되어 있지 않습니다. 장시간 실행되는 쿼리는 애플리케이션의 안정성에 영향을 줄 수 있습니다. 대규모 그룹의 경우, 현재 구현(구 백엔드)은 속도가 느리고, 경우에 따라서는 구성된 구문 타임아웃(15초)으로 인해 로드되지 않기도 합니다.

구 백엔드의 데이터베이스 쿼리는 IssuableFinders 클래스를 통해 핵심 도메인 모델을 직접 사용합니다: (MergeRequestsFinderIssuesFinder). 날짜 범위 필터 변경 요청으로 인해 이 접근 방식은 성능 측면에서 더 이상 실행 가능하지 않게 되었습니다.

집계형 VSA 백엔드의 장점:

  • 더 단순한 데이터베이스 쿼리 (더 적은 JOIN).

  • 더 빠른 집계, 단일 테이블만 접근.

  • 첫 페이지 로드 시간 개선을 위한 추가 집계 도입 가능성.

  • 대규모 그룹(많은 하위 그룹, 프로젝트, 이슈 및 머지 리퀘스트 포함)에 대한 향상된 성능.

  • 데이터베이스 분해 준비 완료. VSA 관련 데이터베이스 테이블을 최소한의 개발 노력으로 별도의 데이터베이스에 둘 수 있음.

  • 데이터 내보내기에 유용할 수 있는 키셋 페이지네이션 준비 완료.

  • 더 복잡한 이벤트 정의 구현 가능성.

예를 들어, 시작 이벤트는 두 개의 타임스탬프 칼럼일 수 있으며, 시스템은 가장 이른 값을 사용합니다.

  • 예시: MIN(issues.created_at, issues.updated_at)

구성 예시#

[

](/19.1/development/value_stream_analytics/img/object_hierarchy_v14_10.png)

이 예시에서 Test Group(최상위 네임스페이스) 내에서 서로 다른 개발 워크플로를 사용하는 두 팀을 위해 두 개의 독립적인 value stream이 설정됩니다.

첫 번째 value stream은 Stage를 정의하기 위해 표준 타임스탬프 기반 이벤트를 사용합니다. 두 번째 value stream은 라벨 이벤트를 사용합니다.

예시의 각 value stream과 Stage 항목은 데이터베이스에 저장됩니다. Deployment Stage는 두 value stream 모두에 동일하므로, 두 Stage의 기본 stage_event_hash_id가 동일합니다. stage_event_hash_id는 백엔드가 수집하는 데이터의 양을 줄이고 데이터베이스 파티셔닝에서 중요한 역할을 합니다.

value stream과 Stage는 거의 변경되지 않을 것으로 예상됩니다. Stage(시작 및 종료 이벤트)가 변경되면 집계된 데이터가 오래됩니다. 이는 매일 발생하는 정기적인 집계에 의해 수정됩니다.

기능 가용성#

집계형 VSA 기능은 그룹 및 프로젝트 수준에서 사용할 수 있지만, 집계형 백엔드는 데이터 저장 및 데이터 연산 비용으로 인해 Premium 및 Ultimate 고객에게만 제공됩니다. 비정규화된 집계 데이터를 저장하려면 상당한 디스크 공간이 필요합니다.

집계형 Value Stream Analytics 아키텍처#

집계형 VSA 백엔드의 핵심 아이디어는 분리입니다: VSA 데이터베이스 테이블과 쿼리는 핵심 도메인 모델(Issue, MergeRequest)을 직접 사용하지 않습니다. 이를 통해 애플리케이션의 다른 부분과 독립적으로 VSA를 확장하고 최적화할 수 있습니다.

아키텍처는 두 가지 주요 메커니즘으로 구성됩니다:

  • 정기적인 데이터 수집 및 로딩 (백그라운드에서 발생).

  • 수집된 데이터 조회 (사용자에 의해 호출).

데이터 로딩#

VSA의 집계적 특성은 정기적인 데이터 로딩에서 비롯됩니다. 시스템은 핵심 도메인 모델을 쿼리하여 Stage 및 타임스탬프 데이터를 수집합니다. 이 데이터는 주기적으로 VSA 데이터베이스 테이블에 삽입됩니다.

Premium 또는 Ultimate 라이선스를 가진 각 최상위 네임스페이스에 대한 고수준 개요:

  • 그룹의 모든 Stage를 로드합니다.

  • 이슈 및 머지 리퀘스트 레코드를 반복합니다.

  • Stage 구성(시작 및 종료 이벤트 식별자)을 기반으로 타임스탬프 데이터를 수집합니다.

  • VSA 데이터베이스 테이블에 데이터를 INSERT 또는 UPDATE합니다.

데이터 로딩은 Analytics::CycleAnalytics::DataLoaderService 클래스 내에서 구현됩니다. 일부 그룹은 많은 데이터를 포함하므로, 기본 데이터베이스 과부하를 방지하기 위해 서비스는 배치로 작업을 수행하고 엄격한 애플리케이션 제한을 적용합니다:

  • 배치로 레코드 로드.

  • 배치로 레코드 삽입.

  • 한도에 도달하면 처리를 중단하고, 나중에 처리를 계속하기 위한 백그라운드 job을 예약.

  • 특정 지점부터 데이터 처리 계속.

데이터 로딩은 수동으로 수행됩니다. 기능이 준비되면, 서비스는 cron job을 통해 시스템에 의해 주기적으로 호출됩니다(이 부분은 아직 구현되지 않음).

레코드 반복#

배치 반복은 효율적인 IN 연산자로 구현됩니다. 백그라운드 job은 updated_atid 칼럼 순서로 그룹 계층 내의 모든 이슈 및 머지 리퀘스트 레코드를 스캔합니다. 이미 집계된 그룹의 경우, DataLoaderService는 특정 지점부터 집계를 계속하여 시간을 절약합니다.

타임스탬프 데이터 수집은 매 반복마다 발생합니다. DataLoaderService는 그룹 계층 내에서 어떤 Stage 이벤트가 구성되어 있는지 파악하고 필요한 타임스탬프를 선택하는 쿼리를 구성합니다. Stage 레코드는 어떤 이벤트가 구성되어 있는지 알고 있으며, 이벤트는 타임스탬프 칼럼을 선택하는 방법을 알고 있습니다.

수집된 Stage 이벤트 예시: merge request merged, merge request created, merge request closed

타임스탬프 로딩을 위해 생성된 SQL 쿼리:

SELECT
  -- the list of columns depends on the configured stages
  "merge_request_metrics"."merged_at",
  "merge_requests"."created_at",
  "merge_request_metrics"."latest_closed_at"
  FROM "merge_requests"
  LEFT OUTER JOIN "merge_request_metrics" ON "merge_request_metrics"."merge_request_id" = "merge_requests"."id"
  WHERE "merge_requests"."id" IN (1, 2, 3, 4) -- ids are coming from the batching query

merged_at 칼럼은 별도의 테이블(merge_request_metrics)에 위치합니다. Gitlab::Analytics::CycleAnalytics::StagEvents::MergeRequestMerged 클래스는 행 수에 영향을 주지 않고(LEFT JOIN 사용) 타임스탬프 데이터를 로딩하기 위한 스코프에 자신을 추가합니다. 이 동작은 include_in 메서드를 통해 각 StageEvent 클래스에 대해 구현됩니다.

데이터 수집 쿼리는 이벤트 수준에서 작동합니다. Stage에서 이벤트 타임스탬프를 추출하고 동일한 데이터를 여러 번 수집하지 않도록 보장합니다. 위에서 언급한 이벤트는 다음 Stage 구성에서 올 수 있습니다:

  • merge request created - merge request merged

  • merge request created - merge request closed

다른 조합도 가능하지만, 의미가 없는 조합은 방지합니다. 예를 들어:

  • merge request merged - merge request created

생성 시간은 항상 먼저 발생하므로, 이 Stage는 항상 음수 기간을 보고합니다.

데이터 범위#

데이터 수집은 최상위 그룹에서 시작하여 그룹 계층 내의 모든 이슈 및 머지 리퀘스트 레코드를 스캔하고 처리합니다. 즉, 그룹이 하위 그룹에 하나의 value stream만 있더라도, 이 그룹의 계층에 있는 모든 이슈 및 머지 리퀘스트의 데이터를 수집합니다. 이는 데이터 수집 메커니즘을 단순화하기 위한 것입니다. 또한, 데이터 조사에 따르면 대부분의 그룹 계층은 최상위 수준에서 Stage가 구성되어 있습니다.

데이터 수집 과정에서 수집된 타임스탬프 데이터는 행으로 변환됩니다. 구성된 각 Stage에 대해 시작 이벤트 타임스탬프가 있으면, 시스템은 하나의 이벤트 레코드를 삽입하거나 업데이트합니다. 이를 통해 모든 이슈 및 머지 리퀘스트를 합산하고 Stage 수를 곱하여 그룹당 삽입된 행의 상한을 결정할 수 있습니다.

데이터 일관성 문제#

데이터 수집의 비동기 특성으로 인해 데이터 일관성 문제가 발생할 수 있습니다. 이는 쿼리 성능을 크게 향상시키는 트레이드오프입니다. 분석 워크로드의 경우 데이터의 약간의 지연은 허용 가능하다고 생각합니다.

롤아웃 전에 가장 최근 백엔드 활동을 보여주는 VSA 페이지의 일부 지표를 구현할 계획입니다. 예를 들어, 마지막 데이터 수집 타임스탬프와 마지막 일관성 확인 타임스탬프를 보여주는 지표입니다.

데이터베이스 구조#

VSA는 다음 도메인 모델에 대한 데이터를 수집합니다: IssueMergeRequest. 집계된 데이터를 분리하기 위해 두 개의 추가 데이터베이스 테이블을 사용합니다:

  • analytics_cycle_analytics_issue_stage_events

  • analytics_cycle_analytics_merge_request_stage_events

두 테이블 모두 stage_event_hash_id로 해시 파티셔닝됩니다. 각 테이블은 32개의 파티션을 사용합니다. 이는 임의의 숫자이며 변경할 수 있습니다. 중요한 것은 파티션을 100 GB 미만으로 유지하는 것입니다(이는 기능에 충분한 여유를 제공합니다).

칼럼 설명
stage_event_hash_id 파티셔닝 키
merge_request_id 또는 issue_id 도메인 레코드(Issuable)에 대한 참조
group_id 그룹에 대한 참조(비정규화)
project_id 프로젝트에 대한 참조
milestone_id 도메인 레코드 테이블에서 복제된 데이터
author_id 도메인 레코드 테이블에서 복제된 데이터
state_id 도메인 레코드 테이블에서 복제된 데이터
start_event_timestamp Stage 구성에서 파생된 타임스탬프
end_event_timestamp Stage 구성에서 파생된 타임스탬프

데이터 분리 요구사항에 따라 테이블에는 외래 키가 없습니다. 일관성은 백그라운드 job에 의해 보장됩니다(최종적으로 일관성 유지).

데이터 조회#

기본 쿼리에는 항상 다음 필터가 포함됩니다:

  • stage_event_hash_id - 파티션 키

  • project_id 또는 group_id - 프로젝트 또는 그룹 쿼리 여부에 따라

  • end_event_timestamp - 날짜 범위 필터 (최근 30일)

예시: GitLab 프로젝트의 review Stage 기간 선택

SELECT end_event_timestamp - start_event_timestamp
FROM analytics_cycle_analytics_merge_request_stage_events
WHERE
stage_event_hash_id = 16 AND -- hits a specific partition
project_id = 278964 AND
end_event_timestamp > '2022-01-01' AND end_event_timestamp < '2022-01-30'

쿼리 생성#

쿼리 백엔드는 구 백엔드 구현이 사용하는 동일한 인터페이스 뒤에 숨겨져 있습니다. 덕분에 구 백엔드와 새 쿼리 백엔드 사이를 전환할 수 있습니다.

  • DataCollector: VSA 데이터 조회를 위한 진입점

BaseQueryBuilder: 기본 ActiveRecord 스코프를 제공합니다(필터가 여기에 적용됩니다).

  • average: 평균 집계.

  • median: 중앙값 집계.

  • count: 행 카운팅.

  • records: 이슈 또는 머지 리퀘스트 레코드 목록.

필터#

VSA는 기본 쿼리에 다양한 필터를 지원합니다. 대부분의 필터는 추가 JOIN이 필요하지 않습니다:

필터 이름 설명
milestone_title 백엔드가 이를 milestone_id 필터로 변환
author_username 백엔드가 이를 author_id 필터로 변환
project_ids 그룹 수준에서만 사용

예외: 이러한 필터는 다른 테이블에 적용되므로 JOIN합니다.

필터 이름 설명
label_name 배열 필터, label_links 테이블 사용
assignee_username 배열 필터, *_assignees 테이블 사용

데이터베이스를 완전히 분해하려면 필요한 ID 값이 VSA 데이터베이스 테이블에 복제되어야 합니다. 이 변경은 배열 칼럼을 사용하여 구현할 수 있습니다.

엔드포인트#

이 기능은 프론트엔드에 데이터를 전달하기 위해 비공개 JSON API를 사용합니다. 첫 페이지 로드 시 다음 요청들이 호출됩니다:

  • 초기 HTML 페이지 로드(대부분 비어 있음). 일부 구성 데이터는 data 속성을 통해 노출됩니다.

  • value_streams - 지정된 그룹에 사용 가능한 value stream을 로드합니다.

  • stages - 현재 선택된 value stream의 Stage를 로드합니다.

  • median - 각 Stage에 대해 중앙값 기간을 요청합니다.

  • count - 각 Stage에 대해 Stage의 항목 수를 요청합니다(이는 제한 카운트이며, 최대 1000행).

  • average_duration_chart - 기간 차트 데이터.

  • summary, time_summary - 최상위 집계, 대부분의 메트릭은 다른 API/finder를 사용하며 집계형 백엔드를 호출하지 않습니다.

특정 Stage를 선택하면 records 엔드포인트가 호출되어 특정 순서로 선택된 Stage에 대한 관련 레코드(페이지네이션)를 반환합니다.

데이터베이스 분해#

쿼리 로직을 메인 애플리케이션 코드에서 분리함으로써, 기능은 데이터베이스 분해를 위한 준비가 되어 있습니다. VSA에 별도의 데이터베이스 인스턴스가 필요하다고 결정하면, 집계 테이블을 이동하는 것은 적은 노력으로 수행할 수 있습니다.

기능의 성능을 더욱 향상시키기 위해 다른 데이터베이스 기술도 사용할 수 있습니다. 예를 들어 Timescale DB가 있습니다.

집계형 Value Stream Analytics

GitLab v19.1
원문 보기
요약

이 페이지는 Value Stream Analytics(VSA)의 집계형 백엔드에 대한 고수준 개요를 제공합니다. 이 페이지는 향후 제품, 기능 및 기능성과 관련된 정보를 담고 있습니다. 집계형 백엔드는 GitLab 15.0부터 그룹 수준에서 기본으로 사용됩니다.

이 페이지는 Value Stream Analytics(VSA)의 집계형 백엔드에 대한 고수준 개요를 제공합니다.

이 페이지는 향후 제품, 기능 및 기능성과 관련된 정보를 담고 있습니다. 여기에 제시된 정보는 정보 제공 목적으로만 활용해야 합니다. 구매 또는 계획 목적으로 이 정보를 참고하지 마세요. 제품, 기능 또는 기능성의 개발, 릴리스 및 일정은 변경되거나 지연될 수 있으며, 전적으로 GitLab Inc.의 재량에 달려 있습니다.

현재 상태#

집계형 백엔드는 GitLab 15.0부터 그룹 수준에서 기본으로 사용됩니다.

도입 배경#

집계형 백엔드는 VSA 기능의 성능 한계를 해결하고 장기적인 성장을 위한 기반을 마련하는 것을 목표로 합니다.

기본 데이터베이스는 분석 워크로드를 위한 준비가 되어 있지 않습니다. 장시간 실행되는 쿼리는 애플리케이션의 안정성에 영향을 줄 수 있습니다. 대규모 그룹의 경우, 현재 구현(구 백엔드)은 속도가 느리고, 경우에 따라서는 구성된 구문 타임아웃(15초)으로 인해 로드되지 않기도 합니다.

구 백엔드의 데이터베이스 쿼리는 IssuableFinders 클래스를 통해 핵심 도메인 모델을 직접 사용합니다: (MergeRequestsFinderIssuesFinder). 날짜 범위 필터 변경 요청으로 인해 이 접근 방식은 성능 측면에서 더 이상 실행 가능하지 않게 되었습니다.

집계형 VSA 백엔드의 장점:

  • 더 단순한 데이터베이스 쿼리 (더 적은 JOIN).

  • 더 빠른 집계, 단일 테이블만 접근.

  • 첫 페이지 로드 시간 개선을 위한 추가 집계 도입 가능성.

  • 대규모 그룹(많은 하위 그룹, 프로젝트, 이슈 및 머지 리퀘스트 포함)에 대한 향상된 성능.

  • 데이터베이스 분해 준비 완료. VSA 관련 데이터베이스 테이블을 최소한의 개발 노력으로 별도의 데이터베이스에 둘 수 있음.

  • 데이터 내보내기에 유용할 수 있는 키셋 페이지네이션 준비 완료.

  • 더 복잡한 이벤트 정의 구현 가능성.

예를 들어, 시작 이벤트는 두 개의 타임스탬프 칼럼일 수 있으며, 시스템은 가장 이른 값을 사용합니다.

  • 예시: MIN(issues.created_at, issues.updated_at)

구성 예시#

[

](/19.1/development/value_stream_analytics/img/object_hierarchy_v14_10.png)

이 예시에서 Test Group(최상위 네임스페이스) 내에서 서로 다른 개발 워크플로를 사용하는 두 팀을 위해 두 개의 독립적인 value stream이 설정됩니다.

첫 번째 value stream은 Stage를 정의하기 위해 표준 타임스탬프 기반 이벤트를 사용합니다. 두 번째 value stream은 라벨 이벤트를 사용합니다.

예시의 각 value stream과 Stage 항목은 데이터베이스에 저장됩니다. Deployment Stage는 두 value stream 모두에 동일하므로, 두 Stage의 기본 stage_event_hash_id가 동일합니다. stage_event_hash_id는 백엔드가 수집하는 데이터의 양을 줄이고 데이터베이스 파티셔닝에서 중요한 역할을 합니다.

value stream과 Stage는 거의 변경되지 않을 것으로 예상됩니다. Stage(시작 및 종료 이벤트)가 변경되면 집계된 데이터가 오래됩니다. 이는 매일 발생하는 정기적인 집계에 의해 수정됩니다.

기능 가용성#

집계형 VSA 기능은 그룹 및 프로젝트 수준에서 사용할 수 있지만, 집계형 백엔드는 데이터 저장 및 데이터 연산 비용으로 인해 Premium 및 Ultimate 고객에게만 제공됩니다. 비정규화된 집계 데이터를 저장하려면 상당한 디스크 공간이 필요합니다.

집계형 Value Stream Analytics 아키텍처#

집계형 VSA 백엔드의 핵심 아이디어는 분리입니다: VSA 데이터베이스 테이블과 쿼리는 핵심 도메인 모델(Issue, MergeRequest)을 직접 사용하지 않습니다. 이를 통해 애플리케이션의 다른 부분과 독립적으로 VSA를 확장하고 최적화할 수 있습니다.

아키텍처는 두 가지 주요 메커니즘으로 구성됩니다:

  • 정기적인 데이터 수집 및 로딩 (백그라운드에서 발생).

  • 수집된 데이터 조회 (사용자에 의해 호출).

데이터 로딩#

VSA의 집계적 특성은 정기적인 데이터 로딩에서 비롯됩니다. 시스템은 핵심 도메인 모델을 쿼리하여 Stage 및 타임스탬프 데이터를 수집합니다. 이 데이터는 주기적으로 VSA 데이터베이스 테이블에 삽입됩니다.

Premium 또는 Ultimate 라이선스를 가진 각 최상위 네임스페이스에 대한 고수준 개요:

  • 그룹의 모든 Stage를 로드합니다.

  • 이슈 및 머지 리퀘스트 레코드를 반복합니다.

  • Stage 구성(시작 및 종료 이벤트 식별자)을 기반으로 타임스탬프 데이터를 수집합니다.

  • VSA 데이터베이스 테이블에 데이터를 INSERT 또는 UPDATE합니다.

데이터 로딩은 Analytics::CycleAnalytics::DataLoaderService 클래스 내에서 구현됩니다. 일부 그룹은 많은 데이터를 포함하므로, 기본 데이터베이스 과부하를 방지하기 위해 서비스는 배치로 작업을 수행하고 엄격한 애플리케이션 제한을 적용합니다:

  • 배치로 레코드 로드.

  • 배치로 레코드 삽입.

  • 한도에 도달하면 처리를 중단하고, 나중에 처리를 계속하기 위한 백그라운드 job을 예약.

  • 특정 지점부터 데이터 처리 계속.

데이터 로딩은 수동으로 수행됩니다. 기능이 준비되면, 서비스는 cron job을 통해 시스템에 의해 주기적으로 호출됩니다(이 부분은 아직 구현되지 않음).

레코드 반복#

배치 반복은 효율적인 IN 연산자로 구현됩니다. 백그라운드 job은 updated_atid 칼럼 순서로 그룹 계층 내의 모든 이슈 및 머지 리퀘스트 레코드를 스캔합니다. 이미 집계된 그룹의 경우, DataLoaderService는 특정 지점부터 집계를 계속하여 시간을 절약합니다.

타임스탬프 데이터 수집은 매 반복마다 발생합니다. DataLoaderService는 그룹 계층 내에서 어떤 Stage 이벤트가 구성되어 있는지 파악하고 필요한 타임스탬프를 선택하는 쿼리를 구성합니다. Stage 레코드는 어떤 이벤트가 구성되어 있는지 알고 있으며, 이벤트는 타임스탬프 칼럼을 선택하는 방법을 알고 있습니다.

수집된 Stage 이벤트 예시: merge request merged, merge request created, merge request closed

타임스탬프 로딩을 위해 생성된 SQL 쿼리:

SELECT
  -- the list of columns depends on the configured stages
  "merge_request_metrics"."merged_at",
  "merge_requests"."created_at",
  "merge_request_metrics"."latest_closed_at"
  FROM "merge_requests"
  LEFT OUTER JOIN "merge_request_metrics" ON "merge_request_metrics"."merge_request_id" = "merge_requests"."id"
  WHERE "merge_requests"."id" IN (1, 2, 3, 4) -- ids are coming from the batching query

merged_at 칼럼은 별도의 테이블(merge_request_metrics)에 위치합니다. Gitlab::Analytics::CycleAnalytics::StagEvents::MergeRequestMerged 클래스는 행 수에 영향을 주지 않고(LEFT JOIN 사용) 타임스탬프 데이터를 로딩하기 위한 스코프에 자신을 추가합니다. 이 동작은 include_in 메서드를 통해 각 StageEvent 클래스에 대해 구현됩니다.

데이터 수집 쿼리는 이벤트 수준에서 작동합니다. Stage에서 이벤트 타임스탬프를 추출하고 동일한 데이터를 여러 번 수집하지 않도록 보장합니다. 위에서 언급한 이벤트는 다음 Stage 구성에서 올 수 있습니다:

  • merge request created - merge request merged

  • merge request created - merge request closed

다른 조합도 가능하지만, 의미가 없는 조합은 방지합니다. 예를 들어:

  • merge request merged - merge request created

생성 시간은 항상 먼저 발생하므로, 이 Stage는 항상 음수 기간을 보고합니다.

데이터 범위#

데이터 수집은 최상위 그룹에서 시작하여 그룹 계층 내의 모든 이슈 및 머지 리퀘스트 레코드를 스캔하고 처리합니다. 즉, 그룹이 하위 그룹에 하나의 value stream만 있더라도, 이 그룹의 계층에 있는 모든 이슈 및 머지 리퀘스트의 데이터를 수집합니다. 이는 데이터 수집 메커니즘을 단순화하기 위한 것입니다. 또한, 데이터 조사에 따르면 대부분의 그룹 계층은 최상위 수준에서 Stage가 구성되어 있습니다.

데이터 수집 과정에서 수집된 타임스탬프 데이터는 행으로 변환됩니다. 구성된 각 Stage에 대해 시작 이벤트 타임스탬프가 있으면, 시스템은 하나의 이벤트 레코드를 삽입하거나 업데이트합니다. 이를 통해 모든 이슈 및 머지 리퀘스트를 합산하고 Stage 수를 곱하여 그룹당 삽입된 행의 상한을 결정할 수 있습니다.

데이터 일관성 문제#

데이터 수집의 비동기 특성으로 인해 데이터 일관성 문제가 발생할 수 있습니다. 이는 쿼리 성능을 크게 향상시키는 트레이드오프입니다. 분석 워크로드의 경우 데이터의 약간의 지연은 허용 가능하다고 생각합니다.

롤아웃 전에 가장 최근 백엔드 활동을 보여주는 VSA 페이지의 일부 지표를 구현할 계획입니다. 예를 들어, 마지막 데이터 수집 타임스탬프와 마지막 일관성 확인 타임스탬프를 보여주는 지표입니다.

데이터베이스 구조#

VSA는 다음 도메인 모델에 대한 데이터를 수집합니다: IssueMergeRequest. 집계된 데이터를 분리하기 위해 두 개의 추가 데이터베이스 테이블을 사용합니다:

  • analytics_cycle_analytics_issue_stage_events

  • analytics_cycle_analytics_merge_request_stage_events

두 테이블 모두 stage_event_hash_id로 해시 파티셔닝됩니다. 각 테이블은 32개의 파티션을 사용합니다. 이는 임의의 숫자이며 변경할 수 있습니다. 중요한 것은 파티션을 100 GB 미만으로 유지하는 것입니다(이는 기능에 충분한 여유를 제공합니다).

칼럼 설명
stage_event_hash_id 파티셔닝 키
merge_request_id 또는 issue_id 도메인 레코드(Issuable)에 대한 참조
group_id 그룹에 대한 참조(비정규화)
project_id 프로젝트에 대한 참조
milestone_id 도메인 레코드 테이블에서 복제된 데이터
author_id 도메인 레코드 테이블에서 복제된 데이터
state_id 도메인 레코드 테이블에서 복제된 데이터
start_event_timestamp Stage 구성에서 파생된 타임스탬프
end_event_timestamp Stage 구성에서 파생된 타임스탬프

데이터 분리 요구사항에 따라 테이블에는 외래 키가 없습니다. 일관성은 백그라운드 job에 의해 보장됩니다(최종적으로 일관성 유지).

데이터 조회#

기본 쿼리에는 항상 다음 필터가 포함됩니다:

  • stage_event_hash_id - 파티션 키

  • project_id 또는 group_id - 프로젝트 또는 그룹 쿼리 여부에 따라

  • end_event_timestamp - 날짜 범위 필터 (최근 30일)

예시: GitLab 프로젝트의 review Stage 기간 선택

SELECT end_event_timestamp - start_event_timestamp
FROM analytics_cycle_analytics_merge_request_stage_events
WHERE
stage_event_hash_id = 16 AND -- hits a specific partition
project_id = 278964 AND
end_event_timestamp > '2022-01-01' AND end_event_timestamp < '2022-01-30'

쿼리 생성#

쿼리 백엔드는 구 백엔드 구현이 사용하는 동일한 인터페이스 뒤에 숨겨져 있습니다. 덕분에 구 백엔드와 새 쿼리 백엔드 사이를 전환할 수 있습니다.

  • DataCollector: VSA 데이터 조회를 위한 진입점

BaseQueryBuilder: 기본 ActiveRecord 스코프를 제공합니다(필터가 여기에 적용됩니다).

  • average: 평균 집계.

  • median: 중앙값 집계.

  • count: 행 카운팅.

  • records: 이슈 또는 머지 리퀘스트 레코드 목록.

필터#

VSA는 기본 쿼리에 다양한 필터를 지원합니다. 대부분의 필터는 추가 JOIN이 필요하지 않습니다:

필터 이름 설명
milestone_title 백엔드가 이를 milestone_id 필터로 변환
author_username 백엔드가 이를 author_id 필터로 변환
project_ids 그룹 수준에서만 사용

예외: 이러한 필터는 다른 테이블에 적용되므로 JOIN합니다.

필터 이름 설명
label_name 배열 필터, label_links 테이블 사용
assignee_username 배열 필터, *_assignees 테이블 사용

데이터베이스를 완전히 분해하려면 필요한 ID 값이 VSA 데이터베이스 테이블에 복제되어야 합니다. 이 변경은 배열 칼럼을 사용하여 구현할 수 있습니다.

엔드포인트#

이 기능은 프론트엔드에 데이터를 전달하기 위해 비공개 JSON API를 사용합니다. 첫 페이지 로드 시 다음 요청들이 호출됩니다:

  • 초기 HTML 페이지 로드(대부분 비어 있음). 일부 구성 데이터는 data 속성을 통해 노출됩니다.

  • value_streams - 지정된 그룹에 사용 가능한 value stream을 로드합니다.

  • stages - 현재 선택된 value stream의 Stage를 로드합니다.

  • median - 각 Stage에 대해 중앙값 기간을 요청합니다.

  • count - 각 Stage에 대해 Stage의 항목 수를 요청합니다(이는 제한 카운트이며, 최대 1000행).

  • average_duration_chart - 기간 차트 데이터.

  • summary, time_summary - 최상위 집계, 대부분의 메트릭은 다른 API/finder를 사용하며 집계형 백엔드를 호출하지 않습니다.

특정 Stage를 선택하면 records 엔드포인트가 호출되어 특정 순서로 선택된 Stage에 대한 관련 레코드(페이지네이션)를 반환합니다.

데이터베이스 분해#

쿼리 로직을 메인 애플리케이션 코드에서 분리함으로써, 기능은 데이터베이스 분해를 위한 준비가 되어 있습니다. VSA에 별도의 데이터베이스 인스턴스가 필요하다고 결정하면, 집계 테이블을 이동하는 것은 적은 노력으로 수행할 수 있습니다.

기능의 성능을 더욱 향상시키기 위해 다른 데이터베이스 기술도 사용할 수 있습니다. 예를 들어 Timescale DB가 있습니다.