Commit d9438d1a authored by Mario de la Ossa's avatar Mario de la Ossa

Track monthly active users for QuickActions

Anonymously track how many unique users are using QuickActions
parent 4e1d6192
......@@ -164,6 +164,7 @@ module QuickActions
next unless definition
definition.execute(self, arg)
usage_ping_tracking(name, arg)
end
end
......@@ -178,6 +179,14 @@ module QuickActions
ext.references(type)
end
# rubocop: enable CodeReuse/ActiveRecord
def usage_ping_tracking(quick_action_name, arg)
Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter.track_unique_action(
quick_action_name,
args: arg&.strip,
user: current_user
)
end
end
end
......
---
title: Track monthly active users for QuickActions
merge_request: 52398
author:
type: added
---
name: usage_data_track_quickactions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52398
rollout_issue_url:
milestone: '13.9'
type: development
group: group::project management
default_enabled: false
This diff is collapsed.
# frozen_string_literal: true
module Gitlab
module UsageDataCounters
module QuickActionActivityUniqueCounter
class << self
# Tracks the quick action with name `name`.
# `args` is expected to be a single string, will be split internally when necessary.
def track_unique_action(name, args:, user:)
return unless Feature.enabled?(:usage_data_track_quickactions, default_enabled: :yaml)
return unless user
args ||= ''
name = prepare_name(name, args)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:"i_quickactions_#{name}", values: user.id)
end
private
def prepare_name(name, args)
case name
when 'assign'
event_name_for_assign(args)
when 'copy_metadata'
event_name_for_copy_metadata(args)
when 'remove_reviewer'
'unassign_reviewer'
when 'request_review', 'reviewer'
'assign_reviewer'
when 'spend'
event_name_for_spend(args)
when 'unassign'
event_name_for_unassign(args)
when 'unlabel', 'remove_label'
event_name_for_unlabel(args)
else
name
end
end
def event_name_for_assign(args)
args = args.split
if args.count == 1 && args.first == 'me'
'assign_self'
elsif args.count == 1
'assign_single'
else
'assign_multiple'
end
end
def event_name_for_copy_metadata(args)
if args.start_with?('#')
'copy_metadata_issue'
else
'copy_metadata_merge_request'
end
end
def event_name_for_spend(args)
if args.start_with?('-')
'spend_subtract'
else
'spend_add'
end
end
def event_name_for_unassign(args)
if args.present?
'unassign_specific'
else
'unassign_all'
end
end
def event_name_for_unlabel(args)
if args.present?
'unlabel_specific'
else
'unlabel_all'
end
end
end
end
end
end
......@@ -39,7 +39,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'snippets',
'code_review',
'terraform',
'ci_templates'
'ci_templates',
'quickactions'
)
end
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter, :clean_gitlab_redis_shared_state do
let(:user) { build(:user, id: 1) }
let(:note) { build(:note, author: user) }
let(:args) { nil }
shared_examples_for 'a tracked quick action unique event' do
specify do
expect { 3.times { subject } }
.to change {
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
event_names: action,
start_date: 2.weeks.ago,
end_date: 2.weeks.from_now
)
}
.by(1)
end
end
subject { described_class.track_unique_action(quickaction_name, args: args, user: user) }
describe '.track_unique_action' do
let(:quickaction_name) { 'approve' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_approve' }
end
end
context 'tracking assigns' do
let(:quickaction_name) { 'assign' }
context 'single assignee' do
let(:args) { '@one' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_assign_single' }
end
end
context 'multiple assignees' do
let(:args) { '@one @two' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_assign_multiple' }
end
end
context 'assigning "me"' do
let(:args) { 'me' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_assign_self' }
end
end
context 'assigning a reviewer' do
let(:quickaction_name) { 'assign_reviewer' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_assign_reviewer' }
end
end
context 'assigning a reviewer with request review alias' do
let(:quickaction_name) { 'request_review' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_assign_reviewer' }
end
end
end
context 'tracking copy_metadata' do
let(:quickaction_name) { 'copy_metadata' }
context 'for issues' do
let(:args) { '#123' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_copy_metadata_issue' }
end
end
context 'for merge requests' do
let(:args) { '!123' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_copy_metadata_merge_request' }
end
end
end
context 'tracking spend' do
let(:quickaction_name) { 'spend' }
context 'adding time' do
let(:args) { '1d' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_spend_add' }
end
end
context 'removing time' do
let(:args) { '-1d' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_spend_subtract' }
end
end
end
context 'tracking unassign' do
let(:quickaction_name) { 'unassign' }
context 'unassigning everyone' do
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_unassign_all' }
end
end
context 'unassigning specific users' do
let(:args) { '@hello' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_unassign_specific' }
end
end
end
context 'tracking unlabel' do
context 'called as unlabel' do
let(:quickaction_name) { 'unlabel' }
context 'removing all labels' do
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_unlabel_all' }
end
end
context 'removing specific labels' do
let(:args) { '~wow' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_unlabel_specific' }
end
end
end
context 'called as remove_label' do
let(:quickaction_name) { 'remove_label' }
it_behaves_like 'a tracked quick action unique event' do
let(:action) { 'i_quickactions_unlabel_all' }
end
end
end
end
......@@ -1793,6 +1793,24 @@ RSpec.describe QuickActions::InterpretService do
expect(text).to eq(" - list\n\ntest")
end
it 'tracks MAU for commands' do
content = "/shrug test\n/assign me\n/milestone %4"
expect(Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter)
.to receive(:track_unique_action)
.with('shrug', args: 'test', user: developer)
expect(Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter)
.to receive(:track_unique_action)
.with('assign', args: 'me', user: developer)
expect(Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter)
.to receive(:track_unique_action)
.with('milestone', args: '%4', user: developer)
service.execute(content, issue)
end
context '/create_merge_request command' do
let(:branch_name) { '1-feature' }
let(:content) { "/create_merge_request #{branch_name}" }
......
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