Skip to content
Snippets Groups Projects
Commit 73207586 authored by Alexis Kalderimis's avatar Alexis Kalderimis :speech_balloon: Committed by Douwe Maan
Browse files

Count wiki page creation

This adds a counter to count page creation, which is reflected in the
usage-data we collect.

The number created is stored in Redis, avoiding DB access.
parent 66394bd1
No related branches found
No related tags found
No related merge requests found
Showing
with 270 additions and 16 deletions
Loading
Loading
@@ -8,6 +8,12 @@ module WikiPages
page_data = Gitlab::DataBuilder::WikiPage.build(page, current_user, action)
@project.execute_hooks(page_data, :wiki_page_hooks)
@project.execute_services(page_data, :wiki_page_hooks)
increment_usage(action)
end
# This method throws an error if the action is an unanticipated value.
def increment_usage(action)
Gitlab::UsageDataCounters::WikiPageCounter.count(action)
end
end
end
---
title: Count wiki creation, update and delete events
merge_request: 30864
author:
type: added
Loading
Loading
@@ -6,7 +6,9 @@ module Gitlab
 
class << self
def data(force_refresh: false)
Rails.cache.fetch('usage_data', force: force_refresh, expires_in: 2.weeks) { uncached_data }
Rails.cache.fetch('usage_data', force: force_refresh, expires_in: 2.weeks) do
uncached_data
end
end
 
def uncached_data
Loading
Loading
@@ -128,12 +130,15 @@ module Gitlab
}
end
 
# @return [Hash<Symbol, Integer>]
def usage_counters
{
web_ide_commits: Gitlab::UsageDataCounters::WebIdeCounter.total_commits_count,
web_ide_merge_requests: Gitlab::UsageDataCounters::WebIdeCounter.total_merge_requests_count,
web_ide_views: Gitlab::UsageDataCounters::WebIdeCounter.total_views_count
}
usage_data_counters.map(&:totals).reduce({}) { |a, b| a.merge(b) }
end
# @return [Array<#totals>] An array of objects that respond to `#totals`
def usage_data_counters
[Gitlab::UsageDataCounters::WikiPageCounter,
Gitlab::UsageDataCounters::WebIdeCounter]
end
 
def components_usage_data
Loading
Loading
Loading
Loading
@@ -33,6 +33,14 @@ module Gitlab
def total_views_count
total_count(VIEWS_COUNT_KEY)
end
def totals
{
web_ide_commits: total_commits_count,
web_ide_views: total_views_count,
web_ide_merge_requests: total_merge_requests_count
}
end
end
end
end
Loading
Loading
# 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
end
end
Loading
Loading
@@ -33,4 +33,24 @@ describe Gitlab::UsageDataCounters::WebIdeCounter, :clean_gitlab_redis_shared_st
 
it_behaves_like 'counter examples'
end
describe '.totals' do
commits = 5
merge_requests = 3
views = 2
before do
commits.times { described_class.increment_commits_count }
merge_requests.times { described_class.increment_merge_requests_count }
views.times { described_class.increment_views_count }
end
it 'can report all totals' do
expect(described_class.totals).to include(
web_ide_commits: commits,
web_ide_views: views,
web_ide_merge_requests: merge_requests
)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::UsageDataCounters::WikiPageCounter, :clean_gitlab_redis_shared_state do
shared_examples :wiki_page_event do |event|
describe ".count(#{event})" do
it "increments the wiki page #{event} counter by 1" do
expect do
described_class.count(event)
end.to change { described_class.read(event) }.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)
end
expect(described_class.read(event)).to eq(event_count)
end
end
end
include_examples :wiki_page_event, :create
include_examples :wiki_page_event, :update
include_examples :wiki_page_event, :delete
describe 'totals' do
creations = 5
edits = 3
deletions = 2
before do
creations.times do
described_class.count(:create)
end
edits.times do
described_class.count(:update)
end
deletions.times do
described_class.count(:delete)
end
end
it 'can report all totals' do
expect(described_class.totals).to include(
wiki_pages_update: edits,
wiki_pages_create: creations,
wiki_pages_delete: deletions
)
end
end
describe 'unknown events' do
error = described_class::UnknownEvent
it 'cannot increment' do
expect { described_class.count(:wibble) }.to raise_error error
end
it 'cannot read' do
expect { described_class.read(:wibble) }.to raise_error error
end
end
end
Loading
Loading
@@ -57,20 +57,18 @@ describe Gitlab::UsageData do
gitaly
database
avg_cycle_analytics
web_ide_views
web_ide_commits
web_ide_merge_requests
influxdb_metrics_enabled
prometheus_metrics_enabled
))
end
it 'calls expected usage data methods' do
expect(Gitlab::UsageDataCounters::WebIdeCounter).to receive(:total_commits_count)
expect(Gitlab::UsageDataCounters::WebIdeCounter).to receive(:total_merge_requests_count)
expect(Gitlab::UsageDataCounters::WebIdeCounter).to receive(:total_views_count)
 
subject
expect(subject).to include(
wiki_pages_create: a_kind_of(Integer),
wiki_pages_update: a_kind_of(Integer),
wiki_pages_delete: a_kind_of(Integer),
web_ide_views: a_kind_of(Integer),
web_ide_commits: a_kind_of(Integer),
web_ide_merge_requests: a_kind_of(Integer)
)
end
 
it "gathers usage counts" do
Loading
Loading
@@ -192,6 +190,28 @@ describe Gitlab::UsageData do
end
end
 
describe '#usage_data_counters' do
subject { described_class.usage_data_counters }
it { is_expected.to all(respond_to :totals) }
describe 'the results of calling #totals on all objects in the array' do
subject { described_class.usage_data_counters.map(&:totals) }
it do
is_expected
.to all(be_a Hash)
.and all(have_attributes(keys: all(be_a Symbol), values: all(be_a Integer)))
end
end
it 'does not have any conflicts' do
all_keys = subject.flat_map { |counter| counter.totals.keys }
expect(all_keys.size).to eq all_keys.to_set.size
end
end
describe '#features_usage_data_ce' do
subject { described_class.features_usage_data_ce }
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe WikiPages::BaseService do
let(:project) { double('project') }
let(:user) { double('user') }
subject(:service) { described_class.new(project, user, {}) }
describe '#increment_usage' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
error = counter::UnknownEvent
it 'raises an error on unknown events' do
expect { subject.send(:increment_usage, :bad_event) }.to raise_error error
end
context 'the event is valid' do
counter::KNOWN_EVENTS.each do |e|
it "updates the #{e} counter" do
expect { subject.send(:increment_usage, e) }.to change { counter.read(e) }
end
end
end
end
end
Loading
Loading
@@ -14,6 +14,10 @@ describe WikiPages::CreateService do
}
end
 
let(:bad_opts) do
{ title: '' }
end
subject(:service) { described_class.new(project, user, opts) }
 
before do
Loading
Loading
@@ -36,5 +40,26 @@ describe WikiPages::CreateService do
 
service.execute
end
it 'counts wiki page creation' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute }.to change { counter.read(:create) }.by 1
end
context 'when the options are bad' do
subject(:service) { described_class.new(project, user, bad_opts) }
it 'does not count a creation event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute }.not_to change { counter.read(:create) }
end
it 'reports the error' do
expect(service.execute).to be_invalid
.and have_attributes(errors: be_present)
end
end
end
end
Loading
Loading
@@ -20,5 +20,17 @@ describe WikiPages::DestroyService do
 
service.execute(page)
end
it 'increments the delete count' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute(page) }.to change { counter.read(:delete) }.by 1
end
it 'does not increment the delete count if the deletion failed' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute(nil) }.not_to change { counter.read(:delete) }
end
end
end
Loading
Loading
@@ -16,6 +16,10 @@ describe WikiPages::UpdateService do
}
end
 
let(:bad_opts) do
{ title: '' }
end
subject(:service) { described_class.new(project, user, opts) }
 
before do
Loading
Loading
@@ -39,5 +43,26 @@ describe WikiPages::UpdateService do
 
service.execute(page)
end
it 'counts edit events' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute page }.to change { counter.read(:update) }.by 1
end
context 'when the options are bad' do
subject(:service) { described_class.new(project, user, bad_opts) }
it 'does not count an edit event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute page }.not_to change { counter.read(:update) }
end
it 'reports the error' do
expect(service.execute page).to be_invalid
.and have_attributes(errors: be_present)
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment