バリューストリームアナリティクス開発ガイド
バリューストリームアナリティクスは、ドメインオブジェクトに記録された2つの任意のイベント間の時間を計算し、その期間に関する集約された統計情報を提供します。
GitLabでValue Stream Analyticsを設定する方法については、アナリティクスのドキュメントをご覧ください。
ステージ
開発中、イシューやマージリクエストを、完成とみなされるまでさまざまな進行ステージに進めるイベントが発生します。 これらのステージは、Stage
モデルで表現することができます。
ステージ例:
- 名称:開発者
- 開始イベント:イシュー作成
- 終了イベント:コミットで最初に言及されたイシュー
- 親です:
Group: gitlab-org
イベント
イベントは、バリューストリーム分析機能の最小構成要素です。 ステージは2つのイベントで構成されます:
- スタート
- 終了
これらのイベントは、持続時間の計算において重要な役割を果たします。
フォーミュラduration = end_event_time - start_event_time
継続時間の計算を柔軟にするために、Event
はそれぞれ別のクラスとして実装されています。これらは、計算クエリで使用されるタイムスタンプ式を定義する役割を担っています。
Event
クラスの実装
実装が必要なメソッドがいくつかあります。StageEvent
の基本クラスには、その詳細が記述されています。 最も重要なメソッドは以下のとおりです:
object_type
timestamp_projection
object_type
メソッドは、計算のためにどのドメイン・オブジェクトをクエリするかを定義します。 現在、2つのモデルが認められています:
Issue
MergeRequest
持続時間の計算には、timestamp_projection
方式を使用します。
def timestamp_projection
# your timestamp expression comes here
end
# event will use the issue creation time in the duration calculation
def timestamp_projection
Issue.arel_table[:created_at]
end
COALESCE
)。例については、既存のイベントクラスを見てください。場合によっては、timestamp_projection
メソッドを定義するだけでは十分ではありません。計算クエリは、どのテーブルにタイムスタンプ式が含まれているかを知っている必要があります。各Event
クラスは、timestamp_projection
を動作させるために計算クエリを修正する責任を負います。 これは通常、追加のテーブルを結合することを意味します。
issue_metrics
テーブルを結合し、first_mentioned_in_commit_at
カラムをタイムスタンプ式として使用する例:
def object_type
Issue
end
def timestamp_projection
IssueMetrics.arel_table[:first_mentioned_in_commit_at]
end
def apply_query_customization(query)
# in this case the query attribute will be based on the Issue model: `Issue.where(...)`
query.joins(:metrics)
end
開始イベントと終了イベントの検証
開始と終了のイベントペアの中には、互いに「互換性」がないものがあります。 たとえば、以下のようなものです:
- “イシューが作成されました” から “マージリクエストが作成されました”: イベントクラスが異なるドメインモデルで定義されているため、
object_type
メソッドが異なります。 - 「イシューのクローズ」から「イシューの作成」へ:イシューをクローズするには、まずイシューを作成する必要があります。
- 「イシューがクローズされました」→「イシューがクローズされました」:期間は常に0です。
StageEvents
モジュールは、許可されたstart_event
とend_event
のペアリング(PAIRING_RULES
定数)を記述しています。 新しいイベントが追加された場合、このモジュールに登録する必要があります。 新しいイベントを追加するには。
-
ENUM_MAPPING
、一意の番号を持つエントリを追加します。Stage
モデルでは、enum
として使用されます。 -
PAIRING_RULES
ハッシュ内のイベントと互換性のあるイベントを定義します。
サポートされる開始/終了イベントの組み合わせ:
親
チームや組織は、ソフトウェアを構築する独自の方法を定義するかもしれません。 そのため、ステージはまったく異なるものになる可能性があります。各ステージでは、親オブジェクトを定義する必要があります。
現在サポートされているご両親
Project
Group
親子関係の仕組み
- ユーザーは価値のストリーム分析ページに移動します。
- ユーザーがグループを選択します。
- バックエンドは選択されたグループの定義されたステージをロードします。
- ステージへの追加や変更は、選択されたグループ内でのみ永続化されます。
デフォルトステージ
バリューストリーム分析の元の実装では、7つのステージが定義されています。 これらのステージは、各親で常に使用可能ですが、これらのステージを変更することはできません。 物事を効率化し、作成されるレコードの数を減らすために、デフォルトのステージはインメモリオブジェクトとして表現されます(永続化されません)。 ユーザーが初めてカスタムステージを作成すると、すべてのステージが永続化されます。 この動作は、バリューストリーム分析サービスオブジェクトに実装されています。 この理由は、後でステージを非表示にしたり順序付ける機能を追加したいためです。
データコレクター
DataCollector
は、データベースからデータがクエリされる中心点です。 クラスは常に1つのステージでオペレーションされ、以下のコンポーネントで構成されます:
-
BaseQueryBuilder
:- 最初のクエリの作成を担当。
-
Stage
、イベントやクエリのカスタマイズなど、特定のコンフィギュレーションを扱います。 - UIからのパラメータ:日付範囲。
-
Median
BaseQueryBuilder
からのクエリを使用して、ステージの期間中央値を計算します。 -
RecordsFetcher
BaseQueryBuilder
からのクエリと、可視性ルールを適用するための特定の クラスを使用して、ステージに関連するレコードを読み込みます。Finder
-
DataForDurationChart
: 散布図チャートの終了時間(終了イベントのタイムスタンプ)と計算された持続時間をロードします。
新しい計算やクエリについては、DataCollector
クラスの新しいメソッド呼び出しとして実装します。
データベースクエリ
データベースクエリの構造:
SELECT (customized by: Median or RecordsFetcher or DataForDurationChart)
FROM OBJECT_TYPE (Issue or MergeRequest)
INNER JOIN (several JOIN statements, depending on the events)
WHERE
(Filter by the PARENT model, example: filter Issues from Project A)
(Date range filter based on the OBJECT_TYPE.created_at)
(Check if the START_EVENT is earlier than END_EVENT, preventing negative duration)
Median
のSELECT
ステートメントの構造 :
SELECT (calculate median from START_EVENT_TIME-END_EVENT_TIME)
DataForDurationChart
のSELECT
ステートメントの構造 :
SELECT (START_EVENT_TIME-END_EVENT_TIME) as duration, END_EVENT.timestamp
ハイレベルの概要
- Rails コントローラ (
Analytics::CycleAnalytics
モジュール): 価値ストリーム分析は、analytics
ワークスペース内に実装された JSON エンドポイントを介してデータを公開します。ステージの設定も、(CRUD)JSON エンドポイントを実装します。 - サービス (
Analytics::CycleAnalytics
モジュール):Stage
関連のアクションはすべて、それぞれのサービスオブジェクトに委譲されます。 - モデル (
Analytics::CycleAnalytics
モジュール): モデルは、Stage
オブジェクトProjectStage
とGroupStage
を永続化するために使用されます。 - フィーチャー・クラス (
Gitlab::Analytics::CycleAnalytics
モジュール):- クエリを作成し、機能固有のビジネスロジックを定義します。
-
DataCollector
,Event
,StageEvents
, etc.
テスト
たくさんのイベントと可能な組み合わせがあるので、それぞれの組み合わせをテストするのは不可能です。Event
クラスを使ったテストケースを少なくともひとつ用意するのがルールです。
新しいEvent
を使用してステージのテストケースを記述することは、両方のイベントに対してデータを作成する必要があるため、困難な場合があります。 これを少し簡単にするために、各テストケースは、ステージがDataCollector
を通してテストされるdata_collector_spec.rb
に実装する必要があります。各テストケースは、以下のケースをカバーする複数のテストになります:
- 異なる両親:
Group
またはProject
- さまざまな計算:
Median
,RecordsFetcher
またはDataForDurationChart