Commit 7082bf05 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch '39-count-unique-users-for-more-accurate-smau-reporting-create' into 'master'

Count unique users for more accurate SMAU reporting - Create

See merge request gitlab-org/gitlab!15686
parents 79b9bb18 0618e0b2
...@@ -5,6 +5,8 @@ module EE ...@@ -5,6 +5,8 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
include UsageStatistics
scope :ldap, -> { where(type: 'LDAPKey') } scope :ldap, -> { where(type: 'LDAPKey') }
end end
......
...@@ -13,6 +13,7 @@ module EE ...@@ -13,6 +13,7 @@ module EE
prepended do prepended do
include Elastic::ApplicationVersionedSearch include Elastic::ApplicationVersionedSearch
include DeprecatedApprovalsBeforeMerge include DeprecatedApprovalsBeforeMerge
include UsageStatistics
has_many :reviews, inverse_of: :merge_request has_many :reviews, inverse_of: :merge_request
has_many :approvals, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent has_many :approvals, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
......
...@@ -14,6 +14,7 @@ module EE ...@@ -14,6 +14,7 @@ module EE
scope :searchable, -> { where(system: false).includes(:noteable) } scope :searchable, -> { where(system: false).includes(:noteable) }
scope :by_humans, -> { user.joins(:author).merge(::User.humans) } scope :by_humans, -> { user.joins(:author).merge(::User.humans) }
scope :with_suggestions, -> { joins(:suggestions) }
after_commit :notify_after_create, on: :create after_commit :notify_after_create, on: :create
after_commit :notify_after_destroy, on: :destroy after_commit :notify_after_destroy, on: :destroy
......
...@@ -112,6 +112,9 @@ module EE ...@@ -112,6 +112,9 @@ module EE
scope :with_jira_dvcs_cloud, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: true)) } scope :with_jira_dvcs_cloud, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: true)) }
scope :with_jira_dvcs_server, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: false)) } scope :with_jira_dvcs_server, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: false)) }
scope :service_desk_enabled, -> { where(service_desk_enabled: true) } scope :service_desk_enabled, -> { where(service_desk_enabled: true) }
scope :github_imported, -> { where(import_type: 'github') }
scope :with_protected_branches, -> { joins(:protected_branches) }
scope :with_repositories_enabled, -> { joins(:project_feature).where(project_features: { repository_access_level: ::ProjectFeature::ENABLED }) }
scope :with_security_reports_stored, -> { where('EXISTS (?)', ::Vulnerabilities::Occurrence.scoped_project.select(1)) } scope :with_security_reports_stored, -> { where('EXISTS (?)', ::Vulnerabilities::Occurrence.scoped_project.select(1)) }
scope :with_security_reports, -> { where('EXISTS (?)', ::Ci::JobArtifact.security_reports.scoped_project.select(1)) } scope :with_security_reports, -> { where('EXISTS (?)', ::Ci::JobArtifact.security_reports.scoped_project.select(1)) }
......
...@@ -6,6 +6,7 @@ module EE ...@@ -6,6 +6,7 @@ module EE
prepended do prepended do
include Elastic::SnippetsSearch include Elastic::SnippetsSearch
include UsageStatistics
end end
end end
end end
...@@ -183,12 +183,29 @@ module EE ...@@ -183,12 +183,29 @@ module EE
def usage_activity_by_stage def usage_activity_by_stage
{ {
usage_activity_by_stage: { usage_activity_by_stage: {
create: usage_activity_by_stage_create,
manage: usage_activity_by_stage_manage, manage: usage_activity_by_stage_manage,
plan: usage_activity_by_stage_plan plan: usage_activity_by_stage_plan
} }
} }
end end
# Omitted because no user, creator or author associated: `lfs_objects`, `pool_repositories`, `web_hooks`
def usage_activity_by_stage_create
{
deploy_keys: ::DeployKey.distinct_count_by(:user_id),
keys: ::Key.regular_keys.distinct_count_by(:user_id),
merge_requests: ::MergeRequest.distinct_count_by(:author_id),
projects_enforcing_code_owner_approval: ::Project.requiring_code_owner_approval.distinct_count_by(:creator_id),
projects_imported_from_github: ::Project.github_imported.distinct_count_by(:creator_id),
projects_with_repositories_enabled: ::Project.with_repositories_enabled.distinct_count_by(:creator_id),
protected_branches: ::Project.with_protected_branches.distinct_count_by(:creator_id),
remote_mirrors: ::Project.with_remote_mirrors.distinct_count_by(:creator_id),
snippets: ::Snippet.distinct_count_by(:author_id),
suggestions: ::Note.with_suggestions.distinct_count_by(:author_id)
}
end
# Omitted because no user, creator or author associated: `campaigns_imported_from_github`, `ldap_group_links` # Omitted because no user, creator or author associated: `campaigns_imported_from_github`, `ldap_group_links`
def usage_activity_by_stage_manage def usage_activity_by_stage_manage
{ {
......
...@@ -81,5 +81,9 @@ FactoryBot.modify do ...@@ -81,5 +81,9 @@ FactoryBot.modify do
trait :service_desk_disabled do trait :service_desk_disabled do
service_desk_enabled nil service_desk_enabled nil
end end
trait :github_imported do
import_type 'github'
end
end end
end end
...@@ -88,6 +88,35 @@ describe Gitlab::UsageData do ...@@ -88,6 +88,35 @@ describe Gitlab::UsageData do
) )
end end
end end
context 'for create' do
it 'includes accurate usage_activity_by_stage data' do
user = create(:user)
project = create(:project, :repository_private, :requiring_code_owner_approval, :github_imported,
:test_repo, :remote_mirror, creator: user)
create(:deploy_key, user: user)
create(:key, user: user)
create(:merge_request, source_project: project)
create(:project, creator: user)
create(:protected_branch, project: project)
create(:remote_mirror, project: project)
create(:snippet, author: user)
create(:suggestion, note: create(:note, project: project))
expect(described_class.uncached_data[:usage_activity_by_stage][:create]).to eq(
deploy_keys: 1,
keys: 1,
merge_requests: 1,
projects_enforcing_code_owner_approval: 1,
projects_imported_from_github: 1,
projects_with_repositories_enabled: 1,
protected_branches: 1,
remote_mirrors: 1,
snippets: 1,
suggestions: 1
)
end
end
end end
end end
end end
...@@ -9,6 +9,18 @@ describe Note do ...@@ -9,6 +9,18 @@ describe Note do
it { is_expected.to belong_to(:review).inverse_of(:notes) } it { is_expected.to belong_to(:review).inverse_of(:notes) }
end end
describe 'scopes' do
describe '.with_suggestions' do
it 'returns the correct note' do
note_with_suggestion = create(:note, suggestions: [create(:suggestion)])
note_without_suggestion = create(:note)
expect(described_class.with_suggestions).to include(note_with_suggestion)
expect(described_class.with_suggestions).not_to include(note_without_suggestion)
end
end
end
describe 'callbacks' do describe 'callbacks' do
describe '#notify_after_create' do describe '#notify_after_create' do
it 'calls #after_note_created on the noteable' do it 'calls #after_note_created on the noteable' do
......
...@@ -112,6 +112,36 @@ describe Project do ...@@ -112,6 +112,36 @@ describe Project do
expect(described_class.with_jira_dvcs_server).not_to include(jira_dvcs_cloud_project) expect(described_class.with_jira_dvcs_server).not_to include(jira_dvcs_cloud_project)
end end
end end
describe '.github_imported' do
it 'returns the correct project' do
project_imported_from_github = create(:project, :github_imported)
project_not_imported_from_github = create(:project)
expect(described_class.github_imported).to include(project_imported_from_github)
expect(described_class.github_imported).not_to include(project_not_imported_from_github)
end
end
describe '.with_protected_branches' do
it 'returns the correct project' do
project_with_protected_branches = create(:project, protected_branches: [create(:protected_branch)])
project_without_protected_branches = create(:project)
expect(described_class.with_protected_branches).to include(project_with_protected_branches)
expect(described_class.with_protected_branches).not_to include(project_without_protected_branches)
end
end
describe '.with_repositories_enabled' do
it 'returns the correct project' do
project_with_repositories_enabled = create(:project, :repository_enabled)
project_with_repositories_disabled = create(:project, :repository_disabled)
expect(described_class.with_repositories_enabled).to include(project_with_repositories_enabled)
expect(described_class.with_repositories_enabled).not_to include(project_with_repositories_disabled)
end
end
end end
describe 'validations' do describe 'validations' do
......
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