Skip to content
Snippets Groups Projects
Commit 9b2e17ac authored by Tiago Botelho's avatar Tiago Botelho
Browse files

Adds WebIDE commits to UsagePing

Implements UsageCounters model to track feature usage counters
and makes easy to extend for future counters
parent d9241761
No related branches found
No related tags found
1 merge request!10495Merge Requests - Assignee
# frozen_string_literal: true
class UsageCounters < ActiveRecord::Base
RECORD_LIMIT = 1.freeze
BY = 1.freeze
BLACKLIST_ATTRIBUTES = %w(id created_at updated_at).freeze
validate :ensure_only_one, on: :create
default_value_for :web_ide_commits, 0
# This method supports concurrency so that several
# requests are able to increment the counter without
# us having inconsistent data
def increment_counters(attrs)
# We want to be able to use the service to increment
# both a single and multiple counters
attrs = Array(attrs)
attrs_with_by =
attrs.each_with_object({}) do |attr, hsh|
hsh[attr] = BY
end
self.class.update_counters(id, attrs_with_by)
end
# Every attribute in this table except the blacklisted
# attributes is a counter
def totals
attributes.except(*BLACKLIST_ATTRIBUTES).symbolize_keys
end
private
# We only want one UsageCounters per instance
def ensure_only_one
return unless UsageCounters.count >= RECORD_LIMIT
errors.add(:base, 'There can only be one usage counters record per instance')
end
end
---
title: Adds Web IDE commits to usage ping
merge_request: 22007
author:
type: added
# frozen_string_literal: true
class CreateUsageCounters < ActiveRecord::Migration
DOWNTIME = false
def change
create_table :usage_counters do |t|
t.integer :web_ide_commits
t.timestamps_with_timezone null: false
end
end
end
Loading
Loading
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
 
ActiveRecord::Schema.define(version: 20180917172041) do
ActiveRecord::Schema.define(version: 20180929102611) do
 
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Loading
Loading
@@ -2080,6 +2080,12 @@ ActiveRecord::Schema.define(version: 20180917172041) do
add_index "uploads", ["model_id", "model_type"], name: "index_uploads_on_model_id_and_model_type", using: :btree
add_index "uploads", ["uploader", "path"], name: "index_uploads_on_uploader_and_path", using: :btree
 
create_table "usage_counters", force: :cascade do |t|
t.integer "web_ide_commits"
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
end
create_table "user_agent_details", force: :cascade do |t|
t.string "user_agent", null: false
t.string "ip_address", null: false
Loading
Loading
Loading
Loading
@@ -108,6 +108,9 @@ module API
 
if result[:status] == :success
commit_detail = user_project.repository.commit(result[:result])
UsageCounters.first_or_create.increment_counters(:web_ide_commits) if find_user_from_warden
present commit_detail, with: Entities::CommitDetail
else
render_api_error!(result[:message], 400)
Loading
Loading
Loading
Loading
@@ -10,6 +10,7 @@ module Gitlab
.merge(features_usage_data)
.merge(components_usage_data)
.merge(cycle_analytics_usage_data)
.merge(usage_counters)
end
 
def to_json(force_refresh: false)
Loading
Loading
@@ -106,6 +107,10 @@ module Gitlab
}
end
 
def usage_counters
UsageCounters.first_or_create.totals
end
def components_usage_data
{
gitlab_pages: { enabled: Gitlab.config.pages.enabled, version: Gitlab::Pages::VERSION },
Loading
Loading
# frozen_string_literal: true
FactoryBot.define do
factory :usage_counters, class: 'UsageCounters' do
end
end
Loading
Loading
@@ -330,3 +330,6 @@ resource_label_events:
- merge_request
- epic
- label
usage_counters:
- project
- web_ide_commits
Loading
Loading
@@ -46,6 +46,7 @@ describe Gitlab::UsageData do
git
database
avg_cycle_analytics
web_ide_commits
))
end
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe UsageCounters do
let!(:usage_counters) { create(:usage_counters) }
describe 'maximum number of records' do
it 'allows for one single record to be created' do
expect do
described_class.create!
end.to raise_error(ActiveRecord::RecordInvalid, 'Validation failed: There can only be one usage counters record per instance')
end
end
describe '#totals' do
subject { usage_counters.totals }
it 'returns counters' do
is_expected.to include(web_ide_commits: 0)
end
end
describe '#increment_counters' do
it 'increments specified counters by 1' do
expect do
usage_counters.increment_counters(:web_ide_commits)
end.to change { usage_counters.reload.web_ide_commits }.from(0).to(1)
end
end
end
Loading
Loading
@@ -278,6 +278,12 @@ describe API::Commits do
}
end
 
it 'does not increment the usage counters using access token authentication' do
post api(url, user), valid_c_params
expect_any_instance_of(::UsageCounters).not_to receive(:increment_counters)
end
it 'a new file in project repo' do
post api(url, user), valid_c_params
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe Projects::UsageCountersIncrementService do
let(:project) { create(:usage_counters) }
subject(:service) { described_class.new(project) }
context '#execute' do
context 'when single attribute is passed' do
it 'increments attribute' do
expect do
service.execute(:web_ide_commits)
end.to change { project.usage_counters.reload.web_ide_commits }.from(0).to(1)
end
end
context 'when array is passed' do
it 'increments specified attributes' do
expect do
service.execute(%i(web_ide_commits))
end.to change { project.usage_counters.reload.web_ide_commits }.from(0).to(1)
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