Commit f4e2ff8d authored by Alper Akgun's avatar Alper Akgun

Merge branch '229918-issue_data_epics' into 'master'

Add UsageData for Issues added to Epics

See merge request gitlab-org/gitlab!44371
parents 9e1bb927 6fb3fca1
---
title: Added UsageData metrics for issues added/removed from Epics
merge_request: 44371
author:
type: added
...@@ -22,16 +22,30 @@ module EE ...@@ -22,16 +22,30 @@ module EE
def assign_epic(issue, epic) def assign_epic(issue, epic)
issue.confidential = true if !issue.persisted? && epic.confidential issue.confidential = true if !issue.persisted? && epic.confidential
had_epic = issue.epic.present?
link_params = { target_issuable: issue, skip_epic_dates_update: true } 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 end
def unassign_epic(issue) def unassign_epic(issue)
link = EpicIssue.find_by_issue_id(issue.id) link = EpicIssue.find_by_issue_id(issue.id)
return success unless link 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 end
def epic_param(issue) def epic_param(issue)
......
...@@ -18,7 +18,10 @@ module EE ...@@ -18,7 +18,10 @@ module EE
return unless epic_issue = original_entity.epic_issue return unless epic_issue = original_entity.epic_issue
return unless can?(current_user, :update_epic, epic_issue.epic.group) 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 original_entity.reset
end end
......
...@@ -76,10 +76,38 @@ RSpec.describe Issues::MoveService do ...@@ -76,10 +76,38 @@ RSpec.describe Issues::MoveService do
expect(new_issue.epic_issue).to eq(epic_issue) expect(new_issue.epic_issue).to eq(epic_issue)
end end
it 'ignores epic issue reference if user can not update the epic' do it 'tracks usage data for changed epic action' do
new_issue = move_service.execute(old_issue, new_project) 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 end
end end
......
...@@ -171,6 +171,20 @@ RSpec.describe Issues::UpdateService do ...@@ -171,6 +171,20 @@ RSpec.describe Issues::UpdateService do
group.add_maintainer(user) group.add_maintainer(user)
end 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 context 'when issue does not belong to an epic yet' do
it 'assigns an issue to the provided epic' do it 'assigns an issue to the provided epic' do
expect { update_issue(epic: epic) }.to change { issue.reload.epic }.from(nil).to(epic) expect { update_issue(epic: epic) }.to change { issue.reload.epic }.from(nil).to(epic)
...@@ -185,6 +199,12 @@ RSpec.describe Issues::UpdateService do ...@@ -185,6 +199,12 @@ RSpec.describe Issues::UpdateService do
subject subject
end 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 end
context 'when issue belongs to another epic' do context 'when issue belongs to another epic' do
...@@ -207,6 +227,12 @@ RSpec.describe Issues::UpdateService do ...@@ -207,6 +227,12 @@ RSpec.describe Issues::UpdateService do
subject subject
end 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 end
end end
...@@ -229,6 +255,12 @@ RSpec.describe Issues::UpdateService do ...@@ -229,6 +255,12 @@ RSpec.describe Issues::UpdateService do
it 'does not do anything' do it 'does not do anything' do
expect { subject }.not_to change { issue.reload.epic } expect { subject }.not_to change { issue.reload.epic }
end 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 end
context 'when issue belongs to an epic' do context 'when issue belongs to an epic' do
...@@ -246,6 +278,25 @@ RSpec.describe Issues::UpdateService do ...@@ -246,6 +278,25 @@ RSpec.describe Issues::UpdateService do
subject subject
end 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 end
end end
......
...@@ -34,6 +34,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do ...@@ -34,6 +34,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do
it 'raises an exception' do it 'raises an exception' do
expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError) expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end 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 end
context 'when user can add issues to the epic' do context 'when user can add issues to the epic' do
...@@ -59,6 +65,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do ...@@ -59,6 +65,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do
execute execute
end 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
context 'when epic param is also present' do context 'when epic param is also present' do
...@@ -99,6 +111,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do ...@@ -99,6 +111,12 @@ RSpec.shared_examples 'issue with epic_id parameter' do
expect(issue.reload).to be_persisted expect(issue.reload).to be_persisted
expect(issue.epic).to eq(epic) expect(issue.epic).to eq(epic)
end 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 end
end end
...@@ -24,6 +24,9 @@ module Gitlab ...@@ -24,6 +24,9 @@ module Gitlab
ISSUE_MARKED_AS_DUPLICATE = 'g_project_management_issue_marked_as_duplicate' ISSUE_MARKED_AS_DUPLICATE = 'g_project_management_issue_marked_as_duplicate'
ISSUE_LOCKED = 'g_project_management_issue_locked' ISSUE_LOCKED = 'g_project_management_issue_locked'
ISSUE_UNLOCKED = 'g_project_management_issue_unlocked' 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 class << self
def track_issue_created_action(author:, time: Time.zone.now) def track_issue_created_action(author:, time: Time.zone.now)
...@@ -102,6 +105,18 @@ module Gitlab ...@@ -102,6 +105,18 @@ module Gitlab
track_unique_action(ISSUE_UNLOCKED, author, time) track_unique_action(ISSUE_UNLOCKED, author, time)
end 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 private
def track_unique_action(action, author, time) def track_unique_action(action, author, time)
......
...@@ -267,3 +267,15 @@ ...@@ -267,3 +267,15 @@
category: issues_edit category: issues_edit
redis_slot: project_management redis_slot: project_management
aggregation: daily 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 ...@@ -202,6 +202,36 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end end
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 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_title_changed_action(author: user1)
described_class.track_issue_description_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