Commit 1ca8c808 authored by James Lopez's avatar James Lopez

Merge branch '63888-snippets-usage-ping-for-create-smau' into 'master'

Resolve "Snippets Usage Ping for Create SMAU"

See merge request gitlab-org/gitlab-ce!30930
parents 8505049e 4a6f959a
...@@ -23,6 +23,7 @@ class CreateSnippetService < BaseService ...@@ -23,6 +23,7 @@ class CreateSnippetService < BaseService
if snippet.save if snippet.save
UserAgentDetailService.new(snippet, @request).create UserAgentDetailService.new(snippet, @request).create
Gitlab::UsageDataCounters::SnippetCounter.count(:create)
end end
snippet snippet
......
...@@ -9,5 +9,9 @@ module Notes ...@@ -9,5 +9,9 @@ module Notes
note.noteable.diffs.clear_cache note.noteable.diffs.clear_cache
end end
end end
def increment_usage_counter(note)
Gitlab::UsageDataCounters::NoteCounter.count(:create, note.noteable_type)
end
end end
end end
...@@ -41,6 +41,7 @@ module Notes ...@@ -41,6 +41,7 @@ module Notes
todo_service.new_note(note, current_user) todo_service.new_note(note, current_user)
clear_noteable_diffs_cache(note) clear_noteable_diffs_cache(note)
Suggestions::CreateService.new(note).execute Suggestions::CreateService.new(note).execute
increment_usage_counter(note)
end end
if quick_actions_service.commands_executed_count.to_i > 0 if quick_actions_service.commands_executed_count.to_i > 0
......
...@@ -25,6 +25,8 @@ class UpdateSnippetService < BaseService ...@@ -25,6 +25,8 @@ class UpdateSnippetService < BaseService
snippet.assign_attributes(params) snippet.assign_attributes(params)
spam_check(snippet, current_user) spam_check(snippet, current_user)
snippet.save snippet.save.tap do |succeeded|
Gitlab::UsageDataCounters::SnippetCounter.count(:update) if succeeded
end
end end
end end
---
title: Count snippet creation, update and comment events
merge_request: 30930
author:
type: added
...@@ -140,6 +140,8 @@ module Gitlab ...@@ -140,6 +140,8 @@ module Gitlab
[ [
Gitlab::UsageDataCounters::WikiPageCounter, Gitlab::UsageDataCounters::WikiPageCounter,
Gitlab::UsageDataCounters::WebIdeCounter, Gitlab::UsageDataCounters::WebIdeCounter,
Gitlab::UsageDataCounters::NoteCounter,
Gitlab::UsageDataCounters::SnippetCounter,
Gitlab::UsageDataCounters::SearchCounter Gitlab::UsageDataCounters::SearchCounter
] ]
end end
......
# frozen_string_literal: true
module Gitlab::UsageDataCounters
class BaseCounter
extend RedisCounter
UnknownEvent = Class.new(StandardError)
class << self
def redis_key(event)
Gitlab::Sentry.track_exception(UnknownEvent, extra: { event: event }) unless known_events.include?(event.to_s)
"USAGE_#{prefix}_#{event}".upcase
end
def count(event)
increment(redis_key event)
end
def read(event)
total_count(redis_key event)
end
def totals
known_events.map { |e| ["#{prefix}_#{e}".to_sym, read(e)] }.to_h
end
private
def known_events
self::KNOWN_EVENTS
end
def prefix
self::PREFIX
end
end
end
end
# frozen_string_literal: true
module Gitlab::UsageDataCounters
class NoteCounter < BaseCounter
KNOWN_EVENTS = %w[create].freeze
PREFIX = 'note'
COUNTABLE_TYPES = %w[Snippet].freeze
class << self
def redis_key(event, noteable_type)
"#{super(event)}_#{noteable_type}".upcase
end
def count(event, noteable_type)
return unless countable?(noteable_type)
increment(redis_key(event, noteable_type))
end
def read(event, noteable_type)
return 0 unless countable?(noteable_type)
total_count(redis_key(event, noteable_type))
end
def totals
{
snippet_comment: read(:create, 'Snippet')
}
end
private
def countable?(noteable_type)
COUNTABLE_TYPES.include?(noteable_type.to_s)
end
end
end
end
# frozen_string_literal: true
module Gitlab::UsageDataCounters
class SnippetCounter < BaseCounter
KNOWN_EVENTS = %w[create update].freeze
PREFIX = 'snippet'
end
end
# frozen_string_literal: true # frozen_string_literal: true
module Gitlab::UsageDataCounters module Gitlab::UsageDataCounters
class WikiPageCounter class WikiPageCounter < BaseCounter
extend RedisCounter KNOWN_EVENTS = %w[create update delete].freeze
PREFIX = 'wiki_pages'
KNOWN_EVENTS = %w[create update delete].map(&:freeze).freeze
UnknownEvent = Class.new(StandardError)
class << self
# Each event gets a unique Redis key
def redis_key(event)
raise UnknownEvent, event unless KNOWN_EVENTS.include?(event.to_s)
"USAGE_WIKI_PAGES_#{event}".upcase
end
def count(event)
increment(redis_key event)
end
def read(event)
total_count(redis_key event)
end
def totals
KNOWN_EVENTS.map { |e| ["wiki_pages_#{e}".to_sym, read(e)] }.to_h
end
end
end end
end end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::UsageDataCounters::NoteCounter, :clean_gitlab_redis_shared_state do
shared_examples 'a note usage counter' do |event, noteable_type|
describe ".count(#{event})" do
it "increments the Note #{event} counter by 1" do
expect do
described_class.count(event, noteable_type)
end.to change { described_class.read(event, noteable_type) }.by 1
end
end
describe ".read(#{event})" do
event_count = 5
it "returns the total number of #{event} events" do
event_count.times do
described_class.count(event, noteable_type)
end
expect(described_class.read(event, noteable_type)).to eq(event_count)
end
end
end
it_behaves_like 'a note usage counter', :create, 'Snippet'
describe '.totals' do
let(:combinations) do
[
[:create, 'Snippet', 3]
]
end
let(:expected_totals) do
{ snippet_comment: 3 }
end
before do
combinations.each do |event, noteable_type, n|
n.times do
described_class.count(event, noteable_type)
end
end
end
it 'can report all totals' do
expect(described_class.totals).to include(expected_totals)
end
end
describe 'unknown events or noteable_type' do
using RSpec::Parameterized::TableSyntax
let(:unknown_event_error) { Gitlab::UsageDataCounters::BaseCounter::UnknownEvent }
where(:event, :noteable_type, :expected_count, :should_raise) do
:create | 'Snippet' | 1 | false
:wibble | 'Snippet' | 0 | true
:create | 'Issue' | 0 | false
:wibble | 'Issue' | 0 | false
end
with_them do
it "handles event" do
if should_raise
expect { described_class.count(event, noteable_type) }.to raise_error(unknown_event_error)
else
described_class.count(event, noteable_type)
expect(described_class.read(event, noteable_type)).to eq(expected_count)
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::UsageDataCounters::SnippetCounter do
it_behaves_like 'a redis usage counter', 'Snippet', :create
it_behaves_like 'a redis usage counter', 'Snippet', :update
it_behaves_like 'a redis usage counter with totals', :snippet,
create: 3,
update: 2
end
...@@ -62,6 +62,9 @@ describe Gitlab::UsageData do ...@@ -62,6 +62,9 @@ describe Gitlab::UsageData do
)) ))
expect(subject).to include( expect(subject).to include(
snippet_create: a_kind_of(Integer),
snippet_update: a_kind_of(Integer),
snippet_comment: a_kind_of(Integer),
wiki_pages_create: a_kind_of(Integer), wiki_pages_create: a_kind_of(Integer),
wiki_pages_update: a_kind_of(Integer), wiki_pages_update: a_kind_of(Integer),
wiki_pages_delete: a_kind_of(Integer), wiki_pages_delete: a_kind_of(Integer),
......
...@@ -36,6 +36,22 @@ describe CreateSnippetService do ...@@ -36,6 +36,22 @@ describe CreateSnippetService do
end end
end end
describe 'usage counter' do
let(:counter) { Gitlab::UsageDataCounters::SnippetCounter }
it 'increments count' do
expect do
create_snippet(nil, @admin, @opts)
end.to change { counter.read(:create) }.by 1
end
it 'does not increment count if create fails' do
expect do
create_snippet(nil, @admin, {})
end.not_to change { counter.read(:create) }
end
end
def create_snippet(project, user, opts) def create_snippet(project, user, opts)
CreateSnippetService.new(project, user, opts).execute CreateSnippetService.new(project, user, opts).execute
end end
......
...@@ -365,5 +365,43 @@ describe Notes::CreateService do ...@@ -365,5 +365,43 @@ describe Notes::CreateService do
.and change { existing_note.updated_at } .and change { existing_note.updated_at }
end end
end end
describe "usage counter" do
let(:counter) { Gitlab::UsageDataCounters::NoteCounter }
context 'snippet note' do
let(:snippet) { create(:project_snippet, project: project) }
let(:opts) { { note: 'reply', noteable_type: 'Snippet', noteable_id: snippet.id, project: project } }
it 'increments usage counter' do
expect do
note = described_class.new(project, user, opts).execute
expect(note).to be_valid
end.to change { counter.read(:create, opts[:noteable_type]) }.by 1
end
it 'does not increment usage counter when creation fails' do
expect do
note = described_class.new(project, user, { note: '' }).execute
expect(note).to be_invalid
end.not_to change { counter.read(:create, opts[:noteable_type]) }
end
end
context 'issue note' do
let(:issue) { create(:issue, project: project) }
let(:opts) { { note: 'reply', noteable_type: 'Issue', noteable_id: issue.id, project: project } }
it 'does not increment usage counter' do
expect do
note = described_class.new(project, user, opts).execute
expect(note).to be_valid
end.not_to change { counter.read(:create, opts[:noteable_type]) }
end
end
end
end end
end end
...@@ -40,6 +40,23 @@ describe UpdateSnippetService do ...@@ -40,6 +40,23 @@ describe UpdateSnippetService do
end end
end end
describe 'usage counter' do
let(:counter) { Gitlab::UsageDataCounters::SnippetCounter }
let(:snippet) { create_snippet(nil, @user, @opts) }
it 'increments count' do
expect do
update_snippet(nil, @admin, snippet, @opts)
end.to change { counter.read(:update) }.by 1
end
it 'does not increment count if create fails' do
expect do
update_snippet(nil, @admin, snippet, { title: '' })
end.not_to change { counter.read(:update) }
end
end
def create_snippet(project, user, opts) def create_snippet(project, user, opts)
CreateSnippetService.new(project, user, opts).execute CreateSnippetService.new(project, user, opts).execute
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