Commit 6fb3fca1 authored by Mario de la Ossa's avatar Mario de la Ossa

Add UsageData for Issues added to Epics

metrics for epic added/removed/changed in an issue
parent 1299d1a4
---
title: Added UsageData metrics for issues added/removed from Epics
merge_request: 44371
author:
type: added
......@@ -22,16 +22,30 @@ module EE
def assign_epic(issue, epic)
issue.confidential = true if !issue.persisted? && epic.confidential
had_epic = issue.epic.present?
link_params = { target_issuable: issue, skip_epic_dates_update: true }
EpicIssues::CreateService.new(epic, current_user, link_params).execute
EpicIssues::CreateService.new(epic, current_user, link_params).execute.tap do |result|
next unless result[:status] == :success
if had_epic
::Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_changed_epic_action(author: current_user)
else
::Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_added_to_epic_action(author: current_user)
end
end
end
def unassign_epic(issue)
link = EpicIssue.find_by_issue_id(issue.id)
return success unless link
EpicIssues::DestroyService.new(link, current_user).execute
EpicIssues::DestroyService.new(link, current_user).execute.tap do |result|
next unless result[:status] == :success
::Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_removed_from_epic_action(author: current_user)
end
end
def epic_param(issue)
......
......@@ -18,7 +18,10 @@ module EE
return unless epic_issue = original_entity.epic_issue
return unless can?(current_user, :update_epic, epic_issue.epic.group)
epic_issue.update(issue_id: new_entity.id)
updated = epic_issue.update(issue_id: new_entity.id)
::Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_changed_epic_action(author: current_user) if updated
original_entity.reset
end
......
......@@ -76,10 +76,38 @@ RSpec.describe Issues::MoveService do
expect(new_issue.epic_issue).to eq(epic_issue)
end
it 'ignores epic issue reference if user can not update the epic' do
new_issue = move_service.execute(old_issue, new_project)
it 'tracks usage data for changed epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_changed_epic_action).with(author: user)
epic_issue.epic.group.add_reporter(user)
move_service.execute(old_issue, new_project)
end
context 'user can not update the epic' do
it 'ignores epic issue reference' do
new_issue = move_service.execute(old_issue, new_project)
expect(new_issue.epic_issue).to be_nil
end
expect(new_issue.epic_issue).to be_nil
it 'does not send usage data for changed epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_changed_epic_action)
move_service.execute(old_issue, new_project)
end
end
context 'epic update fails' do
it 'does not send usage data for changed epic action' do
allow_next_instance_of(::EpicIssue) do |epic_issue|
allow(epic_issue).to receive(:update).and_return(false)
end
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_changed_epic_action)
move_service.execute(old_issue, new_project)
end
end
end
end
......
......@@ -171,6 +171,20 @@ RSpec.describe Issues::UpdateService do
group.add_maintainer(user)
end
context 'when EpicIssues::CreateService returns failure', :aggregate_failures do
it 'does not send usage data for added or changed epic action' do
link_sevice = double
expect(EpicIssues::CreateService).to receive(:new)
.with(epic, user, { target_issuable: issue, skip_epic_dates_update: true })
.and_return(link_sevice)
expect(link_sevice).to receive(:execute).and_return({ status: :failure })
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_added_to_epic_action)
subject
end
end
context 'when issue does not belong to an epic yet' do
it 'assigns an issue to the provided epic' do
expect { update_issue(epic: epic) }.to change { issue.reload.epic }.from(nil).to(epic)
......@@ -185,6 +199,12 @@ RSpec.describe Issues::UpdateService do
subject
end
it 'tracks usage data for added to epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_added_to_epic_action).with(author: user)
subject
end
end
context 'when issue belongs to another epic' do
......@@ -207,6 +227,12 @@ RSpec.describe Issues::UpdateService do
subject
end
it 'tracks usage data for changed epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_changed_epic_action).with(author: user)
subject
end
end
end
end
......@@ -229,6 +255,12 @@ RSpec.describe Issues::UpdateService do
it 'does not do anything' do
expect { subject }.not_to change { issue.reload.epic }
end
it 'does not send usage data for removed epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_removed_from_epic_action)
subject
end
end
context 'when issue belongs to an epic' do
......@@ -246,6 +278,25 @@ RSpec.describe Issues::UpdateService do
subject
end
it 'tracks usage data for removed from epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_removed_from_epic_action).with(author: user)
subject
end
context 'but EpicIssues::DestroyService returns failure', :aggregate_failures do
it 'does not send usage data for removed epic action' do
link_sevice = double
expect(EpicIssues::DestroyService).to receive(:new).with(EpicIssue.last, user)
.and_return(link_sevice)
expect(link_sevice).to receive(:execute).and_return({ status: :failure })
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_removed_from_epic_action)
subject
end
end
end
end
end
......
......@@ -34,6 +34,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do
it 'raises an exception' do
expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
it 'does not send usage data for added epic action', :aggregate_failures do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_added_epic_action)
expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
context 'when user can add issues to the epic' do
......@@ -59,6 +65,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do
execute
end
it 'tracks usage data for added to epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_added_to_epic_action).with(author: user)
execute
end
end
context 'when epic param is also present' do
......@@ -99,6 +111,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do
expect(issue.reload).to be_persisted
expect(issue.epic).to eq(epic)
end
it 'tracks usage data for added to epic action' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_added_to_epic_action).with(author: user)
execute
end
end
end
end
......@@ -24,6 +24,9 @@ module Gitlab
ISSUE_MARKED_AS_DUPLICATE = 'g_project_management_issue_marked_as_duplicate'
ISSUE_LOCKED = 'g_project_management_issue_locked'
ISSUE_UNLOCKED = 'g_project_management_issue_unlocked'
ISSUE_ADDED_TO_EPIC = 'g_project_management_issue_added_to_epic'
ISSUE_REMOVED_FROM_EPIC = 'g_project_management_issue_removed_from_epic'
ISSUE_CHANGED_EPIC = 'g_project_management_issue_changed_epic'
class << self
def track_issue_created_action(author:, time: Time.zone.now)
......@@ -102,6 +105,18 @@ module Gitlab
track_unique_action(ISSUE_UNLOCKED, author, time)
end
def track_issue_added_to_epic_action(author:, time: Time.zone.now)
track_unique_action(ISSUE_ADDED_TO_EPIC, author, time)
end
def track_issue_removed_from_epic_action(author:, time: Time.zone.now)
track_unique_action(ISSUE_REMOVED_FROM_EPIC, author, time)
end
def track_issue_changed_epic_action(author:, time: Time.zone.now)
track_unique_action(ISSUE_CHANGED_EPIC, author, time)
end
private
def track_unique_action(action, author, time)
......
......@@ -267,3 +267,15 @@
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_added_to_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_removed_from_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_changed_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
......@@ -202,6 +202,36 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
end
context 'for Issue added to epic actions' do
it_behaves_like 'tracks and counts action' do
let(:action) { described_class::ISSUE_ADDED_TO_EPIC}
def track_action(params)
described_class.track_issue_added_to_epic_action(**params)
end
end
end
context 'for Issue removed from epic actions' do
it_behaves_like 'tracks and counts action' do
let(:action) { described_class::ISSUE_REMOVED_FROM_EPIC}
def track_action(params)
described_class.track_issue_removed_from_epic_action(**params)
end
end
end
context 'for Issue changed epic actions' do
it_behaves_like 'tracks and counts action' do
let(:action) { described_class::ISSUE_CHANGED_EPIC}
def track_action(params)
described_class.track_issue_changed_epic_action(**params)
end
end
end
it 'can return the count of actions per user deduplicated', :aggregate_failures do
described_class.track_issue_title_changed_action(author: user1)
described_class.track_issue_description_changed_action(author: user1)
......
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