Commit abf7ea97 authored by Kai Armstrong's avatar Kai Armstrong

Track api usage of the jetbrains plugin

This implements RedisHLL tracking for api requests made from the
JetBrains plugin. It also adds JetBrains to rubocop and inflections
so the proper cased vendor can be used in methods and files.

Changelog: added
parent 04de8586
......@@ -174,6 +174,7 @@ Naming/FileName:
- GitLab
- JavaScript
- VSCode
- JetBrains
# default ones:
- CLI
- DSL
......
......@@ -31,6 +31,7 @@ class GraphqlController < ApplicationController
before_action :authorize_access_api!
before_action :set_user_last_activity
before_action :track_vs_code_usage
before_action :track_jetbrains_usage
before_action :disable_query_limiting
before_action :limit_query_size
......@@ -137,6 +138,11 @@ class GraphqlController < ApplicationController
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
end
def track_jetbrains_usage
Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
end
def execute_multiplex
GitlabSchema.multiplex(multiplex_queries, context: context)
end
......
---
name: usage_data_i_code_review_user_jetbrains_api_request
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78713
rollout_issue_url:
milestone: '14.8'
type: development
group: group::code review
default_enabled: true
......@@ -39,6 +39,7 @@ Rails.autoloaders.each do |autoloader|
'hangouts_chat_http_override' => 'HangoutsChatHTTPOverride',
'chunked_io' => 'ChunkedIO',
'http_io' => 'HttpIO',
'jetbrains_plugin_activity_unique_counter' => 'JetBrainsPluginActivityUniqueCounter',
'json_formatter' => 'JSONFormatter',
'json_web_token' => 'JSONWebToken',
'as_json' => 'AsJSON',
......
......@@ -73,6 +73,7 @@
- 'i_code_review_post_merge_click_cherry_pick'
- 'i_code_review_post_merge_submit_revert_modal'
- 'i_code_review_post_merge_submit_cherry_pick_modal'
- 'i_code_review_user_jetbrains_api_request'
- name: code_review_category_monthly_active_users
operator: OR
source: redis
......@@ -144,3 +145,4 @@
time_frame: [7d, 28d]
events:
- 'i_code_review_user_vs_code_api_request'
- 'i_code_review_user_jetbrains_api_request'
---
key_path: redis_hll_counters.code_review.i_code_review_user_jetbrains_api_request_monthly
description: Count of unique users per month who use GitLab plugin for JetBrains
product_section: dev
product_stage: create
product_group: group::code review
product_category: editor_extension
value_type: number
status: active
milestone: "14.8"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78713
time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
options:
events:
- i_code_review_user_jetbrains_api_request
performance_indicator_type: []
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
---
key_path: redis_hll_counters.code_review.i_code_review_user_jetbrains_api_request_weekly
description: Count of unique users per month who use GitLab plugin for JetBrains
product_section: dev
product_stage: create
product_group: group::code review
product_category: editor_extension
value_type: number
status: active
milestone: "14.8"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78713
time_frame: 7d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
options:
events:
- i_code_review_user_jetbrains_api_request
performance_indicator_type: []
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
......@@ -76,6 +76,10 @@ module API
Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
end
after do
Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
end
# The locale is set to the current user's locale when `current_user` is loaded
after { Gitlab::I18n.use_default_locale }
......
# frozen_string_literal: true
module Gitlab
module UsageDataCounters
module JetBrainsPluginActivityUniqueCounter
JETBRAINS_API_REQUEST_ACTION = 'i_code_review_user_jetbrains_api_request'
JETBRAINS_USER_AGENT_REGEX = /\Agitlab-jetbrains-plugin/.freeze
class << self
def track_api_request_when_trackable(user_agent:, user:)
user_agent&.match?(JETBRAINS_USER_AGENT_REGEX) && track_unique_action_by_user(JETBRAINS_API_REQUEST_ACTION, user)
end
private
def track_unique_action_by_user(action, user)
return unless user
track_unique_action(action, user.id)
end
def track_unique_action(action, value)
Gitlab::UsageDataCounters::HLLRedisCounter.track_usage_event(action, value)
end
end
end
end
end
......@@ -127,6 +127,11 @@
redis_slot: code_review
category: code_review
aggregation: weekly
- name: i_code_review_user_jetbrains_api_request
redis_slot: code_review
category: code_review
aggregation: weekly
feature_flag: usage_data_i_code_review_user_jetbrains_api_request
- name: i_code_review_user_create_mr_from_issue
redis_slot: code_review
category: code_review
......
......@@ -51,7 +51,8 @@ module QA
"smtp" => "SMTP",
"otp" => "OTP",
"jira_api" => "JiraAPI",
"registry_tls" => "RegistryTLS"
"registry_tls" => "RegistryTLS",
"jetbrains" => "JetBrains"
)
loader.setup
......
......@@ -124,6 +124,16 @@ RSpec.describe GraphqlController do
post :execute
end
it 'calls the track jetbrains api when trackable method' do
agent = 'gitlab-jetbrains-plugin/0.0.1 intellij-idea/2021.2.4 java/11.0.13 mac-os-x/aarch64/12.1'
request.env['HTTP_USER_AGENT'] = agent
expect(Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter)
.to receive(:track_api_request_when_trackable).with(user_agent: agent, user: user)
post :execute
end
end
context 'when user uses an API token' do
......@@ -151,6 +161,16 @@ RSpec.describe GraphqlController do
subject
end
it 'calls the track jetbrains api when trackable method' do
agent = 'gitlab-jetbrains-plugin/0.0.1 intellij-idea/2021.2.4 java/11.0.13 mac-os-x/aarch64/12.1'
request.env['HTTP_USER_AGENT'] = agent
expect(Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter)
.to receive(:track_api_request_when_trackable).with(user_agent: agent, user: user)
subject
end
end
context 'when user is not logged in' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.shared_examples 'a tracked jetbrains unique action' do |event|
before do
stub_application_setting(usage_ping_enabled: true)
end
def count_unique(date_from:, date_to:)
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: action, start_date: date_from, end_date: date_to)
end
it 'tracks when the user agent is from jetbrains' do
aggregate_failures do
user_agent = { user_agent: 'gitlab-jetbrains-plugin/0.0.1 intellij-idea/2021.2.4 java/11.0.13 mac-os-x/aarch64/12.1' }
expect(track_action(user: user1, **user_agent)).to be_truthy
expect(track_action(user: user1, **user_agent)).to be_truthy
expect(track_action(user: user2, **user_agent)).to be_truthy
expect(count_unique(date_from: time - 1.week, date_to: time + 1.week)).to eq(2)
end
end
it 'does not track when the user agent is not from jetbrains' do
aggregate_failures do
user_agent = { user_agent: 'normal_user_agent' }
expect(track_action(user: user1, **user_agent)).to be_falsey
expect(track_action(user: user1, **user_agent)).to be_falsey
expect(track_action(user: user2, **user_agent)).to be_falsey
expect(count_unique(date_from: time - 1.week, date_to: time + 1.week)).to eq(0)
end
end
it 'does not track if user agent is not present' do
expect(track_action(user: nil, user_agent: nil)).to be_nil
end
it 'does not track if user is not present' do
user_agent = { user_agent: 'gitlab-jetbrains-plugin/0.0.1 intellij-idea/2021.2.4 java/11.0.13 mac-os-x/aarch64/12.1' }
expect(track_action(user: nil, **user_agent)).to be_nil
end
end
RSpec.describe Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter, :clean_gitlab_redis_shared_state do
let(:user1) { build(:user, id: 1) }
let(:user2) { build(:user, id: 2) }
let(:time) { Time.current }
context 'when tracking a jetbrains api request' do
it_behaves_like 'a tracked jetbrains unique action' do
let(:action) { described_class::JETBRAINS_API_REQUEST_ACTION }
def track_action(params)
described_class.track_api_request_when_trackable(**params)
end
end
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