Commit f1bfb5fd authored by Patrick Bajao's avatar Patrick Bajao

Track merge_requests_users usage data

To get the NSM for source code group, we need to track the number
of unique merge requests users. This will be used to determine
how much of MAUs in percentage are using merge requests.
parent fdb3fbba
---
title: Track merge_requests_users usage data
merge_request: 32562
author:
type: changed
...@@ -4,14 +4,15 @@ class AddIndexOnAuthorIdAndCreatedAtToEvents < ActiveRecord::Migration[6.0] ...@@ -4,14 +4,15 @@ class AddIndexOnAuthorIdAndCreatedAtToEvents < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
DOWNTIME = false DOWNTIME = false
INDEX_NAME = 'index_events_on_author_id_and_created_at'
disable_ddl_transaction! disable_ddl_transaction!
def up def up
add_concurrent_index :events, [:author_id, :created_at] add_concurrent_index :events, [:author_id, :created_at], name: INDEX_NAME
end end
def down def down
remove_concurrent_index :events, [:author_id, :created_at] remove_concurrent_index :events, INDEX_NAME
end end
end end
# frozen_string_literal: true
class AddMergeRequestPartialIndexToEvents < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
INDEX_NAME = 'index_events_on_author_id_and_created_at_merge_requests'
def up
add_concurrent_index(
:events,
[:author_id, :created_at],
name: INDEX_NAME,
where: "(target_type = 'MergeRequest')"
)
end
def down
remove_concurrent_index :events, INDEX_NAME
end
end
...@@ -9706,6 +9706,8 @@ CREATE INDEX index_events_on_action ON public.events USING btree (action); ...@@ -9706,6 +9706,8 @@ CREATE INDEX index_events_on_action ON public.events USING btree (action);
CREATE INDEX index_events_on_author_id_and_created_at ON public.events USING btree (author_id, created_at); CREATE INDEX index_events_on_author_id_and_created_at ON public.events USING btree (author_id, created_at);
CREATE INDEX index_events_on_author_id_and_created_at_merge_requests ON public.events USING btree (author_id, created_at) WHERE ((target_type)::text = 'MergeRequest'::text);
CREATE INDEX index_events_on_author_id_and_project_id ON public.events USING btree (author_id, project_id); CREATE INDEX index_events_on_author_id_and_project_id ON public.events USING btree (author_id, project_id);
CREATE INDEX index_events_on_group_id_partial ON public.events USING btree (group_id) WHERE (group_id IS NOT NULL); CREATE INDEX index_events_on_group_id_partial ON public.events USING btree (group_id) WHERE (group_id IS NOT NULL);
...@@ -14036,5 +14038,6 @@ COPY "schema_migrations" (version) FROM STDIN; ...@@ -14036,5 +14038,6 @@ COPY "schema_migrations" (version) FROM STDIN;
20200527151413 20200527151413
20200527152116 20200527152116
20200527152657 20200527152657
20200528123703
\. \.
...@@ -39,8 +39,8 @@ module EE ...@@ -39,8 +39,8 @@ module EE
override :uncached_data override :uncached_data
def uncached_data def uncached_data
time_period = { created_at: 28.days.ago..Time.current } usage_activity_by_stage_monthly = usage_activity_by_stage(:usage_activity_by_stage_monthly, default_time_period)
usage_activity_by_stage_monthly = usage_activity_by_stage(:usage_activity_by_stage_monthly, time_period)
super super
.merge(usage_activity_by_stage) .merge(usage_activity_by_stage)
.merge(usage_activity_by_stage_monthly) .merge(usage_activity_by_stage_monthly)
......
...@@ -32,6 +32,7 @@ module Gitlab ...@@ -32,6 +32,7 @@ module Gitlab
.merge(cycle_analytics_usage_data) .merge(cycle_analytics_usage_data)
.merge(object_store_usage_data) .merge(object_store_usage_data)
.merge(recording_ce_finish_data) .merge(recording_ce_finish_data)
.merge(merge_requests_usage_data(default_time_period))
end end
def to_json(force_refresh: false) def to_json(force_refresh: false)
...@@ -382,6 +383,27 @@ module Gitlab ...@@ -382,6 +383,27 @@ module Gitlab
{} # augmented in EE {} # augmented in EE
end end
# rubocop: disable CodeReuse/ActiveRecord
def merge_requests_usage_data(time_period)
query =
Event
.where(target_type: Event::TARGET_TYPES[:merge_request].to_s)
.where(time_period)
merge_request_users = distinct_count(
query,
:author_id,
batch_size: 5_000, # Based on query performance, this is the optimal batch size.
start: User.minimum(:id),
finish: User.maximum(:id)
)
{
merge_requests_users: merge_request_users
}
end
# rubocop: enable CodeReuse/ActiveRecord
def installation_type def installation_type
if Rails.env.production? if Rails.env.production?
Gitlab::INSTALLATION_TYPE Gitlab::INSTALLATION_TYPE
...@@ -389,6 +411,10 @@ module Gitlab ...@@ -389,6 +411,10 @@ module Gitlab
"gitlab-development-kit" "gitlab-development-kit"
end end
end end
def default_time_period
{ created_at: 28.days.ago..Time.current }
end
end end
end end
end end
......
...@@ -49,9 +49,9 @@ module Gitlab ...@@ -49,9 +49,9 @@ module Gitlab
FALLBACK FALLBACK
end end
def distinct_count(relation, column = nil, batch: true, start: nil, finish: nil) def distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
if batch && Feature.enabled?(:usage_ping_batch_counter, default_enabled: true) if batch && Feature.enabled?(:usage_ping_batch_counter, default_enabled: true)
Gitlab::Database::BatchCount.batch_distinct_count(relation, column, start: start, finish: finish) Gitlab::Database::BatchCount.batch_distinct_count(relation, column, batch_size: batch_size, start: start, finish: finish)
else else
relation.distinct_count_by(column) relation.distinct_count_by(column)
end end
......
...@@ -574,4 +574,27 @@ describe Gitlab::UsageData, :aggregate_failures do ...@@ -574,4 +574,27 @@ describe Gitlab::UsageData, :aggregate_failures do
it_behaves_like 'usage data execution' it_behaves_like 'usage data execution'
end end
describe '#merge_requests_usage_data' do
let(:time_period) { { created_at: 2.days.ago..Time.current } }
let(:merge_request) { create(:merge_request) }
let(:other_user) { create(:user) }
let(:another_user) { create(:user) }
before do
create(:event, target: merge_request, author: merge_request.author, created_at: 1.day.ago)
create(:event, target: merge_request, author: merge_request.author, created_at: 1.hour.ago)
create(:event, target: merge_request, author: merge_request.author, created_at: 3.days.ago)
create(:event, target: merge_request, author: other_user, created_at: 1.day.ago)
create(:event, target: merge_request, author: other_user, created_at: 1.hour.ago)
create(:event, target: merge_request, author: other_user, created_at: 3.days.ago)
create(:event, target: merge_request, author: another_user, created_at: 4.days.ago)
end
it 'returns the distinct count of users using merge requests (via events table) within the specified time period' do
expect(described_class.merge_requests_usage_data(time_period)).to eq(
merge_requests_users: 2
)
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment