Record usage on snippet usage
Generalize wiki page counter for other page types to extend to.
This commit is contained in:
parent
8505049e1f
commit
4a6f959ab8
|
|
@ -23,6 +23,7 @@ class CreateSnippetService < BaseService
|
|||
|
||||
if snippet.save
|
||||
UserAgentDetailService.new(snippet, @request).create
|
||||
Gitlab::UsageDataCounters::SnippetCounter.count(:create)
|
||||
end
|
||||
|
||||
snippet
|
||||
|
|
|
|||
|
|
@ -9,5 +9,9 @@ module Notes
|
|||
note.noteable.diffs.clear_cache
|
||||
end
|
||||
end
|
||||
|
||||
def increment_usage_counter(note)
|
||||
Gitlab::UsageDataCounters::NoteCounter.count(:create, note.noteable_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ module Notes
|
|||
todo_service.new_note(note, current_user)
|
||||
clear_noteable_diffs_cache(note)
|
||||
Suggestions::CreateService.new(note).execute
|
||||
increment_usage_counter(note)
|
||||
end
|
||||
|
||||
if quick_actions_service.commands_executed_count.to_i > 0
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ class UpdateSnippetService < BaseService
|
|||
snippet.assign_attributes(params)
|
||||
spam_check(snippet, current_user)
|
||||
|
||||
snippet.save
|
||||
snippet.save.tap do |succeeded|
|
||||
Gitlab::UsageDataCounters::SnippetCounter.count(:update) if succeeded
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Count snippet creation, update and comment events
|
||||
merge_request: 30930
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -140,6 +140,8 @@ module Gitlab
|
|||
[
|
||||
Gitlab::UsageDataCounters::WikiPageCounter,
|
||||
Gitlab::UsageDataCounters::WebIdeCounter,
|
||||
Gitlab::UsageDataCounters::NoteCounter,
|
||||
Gitlab::UsageDataCounters::SnippetCounter,
|
||||
Gitlab::UsageDataCounters::SearchCounter
|
||||
]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab::UsageDataCounters
|
||||
class SnippetCounter < BaseCounter
|
||||
KNOWN_EVENTS = %w[create update].freeze
|
||||
PREFIX = 'snippet'
|
||||
end
|
||||
end
|
||||
|
|
@ -1,32 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab::UsageDataCounters
|
||||
class WikiPageCounter
|
||||
extend RedisCounter
|
||||
|
||||
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
|
||||
class WikiPageCounter < BaseCounter
|
||||
KNOWN_EVENTS = %w[create update delete].freeze
|
||||
PREFIX = 'wiki_pages'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# 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
|
|||
))
|
||||
|
||||
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_update: a_kind_of(Integer),
|
||||
wiki_pages_delete: a_kind_of(Integer),
|
||||
|
|
|
|||
|
|
@ -36,6 +36,22 @@ describe CreateSnippetService do
|
|||
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)
|
||||
CreateSnippetService.new(project, user, opts).execute
|
||||
end
|
||||
|
|
|
|||
|
|
@ -365,5 +365,43 @@ describe Notes::CreateService do
|
|||
.and change { existing_note.updated_at }
|
||||
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
|
||||
|
|
|
|||
|
|
@ -40,6 +40,23 @@ describe UpdateSnippetService do
|
|||
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)
|
||||
CreateSnippetService.new(project, user, opts).execute
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue