Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
707bf4370d
commit
75389143b6
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: product_analytics_tracking
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46482
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285519
|
||||
milestone: '13.7'
|
||||
type: ops
|
||||
group: group::product analytics
|
||||
default_enabled: false
|
||||
|
|
@ -26,6 +26,7 @@ module Gitlab
|
|||
|
||||
def event(category, action, label: nil, property: nil, value: nil, context: nil)
|
||||
snowplow.event(category, action, label: label, property: property, value: value, context: context)
|
||||
product_analytics.event(category, action, label: label, property: property, value: value, context: context)
|
||||
end
|
||||
|
||||
def self_describing_event(schema_url, event_data_json, context: nil)
|
||||
|
|
@ -49,6 +50,10 @@ module Gitlab
|
|||
def snowplow
|
||||
@snowplow ||= Gitlab::Tracking::Destinations::Snowplow.new
|
||||
end
|
||||
|
||||
def product_analytics
|
||||
@product_analytics ||= Gitlab::Tracking::Destinations::ProductAnalytics.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Tracking
|
||||
module Destinations
|
||||
class ProductAnalytics < Base
|
||||
extend ::Gitlab::Utils::Override
|
||||
include ::Gitlab::Utils::StrongMemoize
|
||||
|
||||
override :event
|
||||
def event(category, action, label: nil, property: nil, value: nil, context: nil)
|
||||
return unless event_allowed?(category, action)
|
||||
return unless enabled?
|
||||
|
||||
tracker.track_struct_event(category, action, label, property, value, context, (Time.now.to_f * 1000).to_i)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def event_allowed?(category, action)
|
||||
category == 'epics' && action == 'promote'
|
||||
end
|
||||
|
||||
def enabled?
|
||||
Feature.enabled?(:product_analytics_tracking, type: :ops) &&
|
||||
Gitlab::CurrentSettings.usage_ping_enabled? &&
|
||||
Gitlab::CurrentSettings.self_monitoring_project_id.present?
|
||||
end
|
||||
|
||||
def tracker
|
||||
@tracker ||= SnowplowTracker::Tracker.new(
|
||||
SnowplowTracker::AsyncEmitter.new(::ProductAnalytics::Tracker::COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol),
|
||||
SnowplowTracker::Subject.new,
|
||||
Gitlab::Tracking::SNOWPLOW_NAMESPACE,
|
||||
Gitlab::CurrentSettings.self_monitoring_project_id.to_s
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -7,36 +7,5 @@ module ProductAnalytics
|
|||
|
||||
# The collector URL minus protocol and /i
|
||||
COLLECTOR_URL = Gitlab.config.gitlab.url.sub(/\Ahttps?\:\/\//, '') + '/-/collector'
|
||||
|
||||
class << self
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
def event(category, action, label: nil, property: nil, value: nil, context: nil)
|
||||
return unless enabled?
|
||||
|
||||
snowplow.track_struct_event(category, action, label, property, value, context, (Time.now.to_f * 1000).to_i)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enabled?
|
||||
Gitlab::CurrentSettings.usage_ping_enabled?
|
||||
end
|
||||
|
||||
def project_id
|
||||
Gitlab::CurrentSettings.self_monitoring_project_id
|
||||
end
|
||||
|
||||
def snowplow
|
||||
strong_memoize(:snowplow) do
|
||||
SnowplowTracker::Tracker.new(
|
||||
SnowplowTracker::AsyncEmitter.new(COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol),
|
||||
SnowplowTracker::Subject.new,
|
||||
Gitlab::Tracking::SNOWPLOW_NAMESPACE,
|
||||
project_id.to_s
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Tracking::Destinations::ProductAnalytics do
|
||||
let(:emitter) { SnowplowTracker::Emitter.new('localhost', buffer_size: 1) }
|
||||
let(:tracker) { SnowplowTracker::Tracker.new(emitter, SnowplowTracker::Subject.new, 'namespace', 'app_id') }
|
||||
|
||||
describe '#event' do
|
||||
shared_examples 'does not send an event' do
|
||||
it 'does not send an event' do
|
||||
expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_struct_event)
|
||||
|
||||
subject.event(allowed_category, allowed_action)
|
||||
end
|
||||
end
|
||||
|
||||
let(:allowed_category) { 'epics' }
|
||||
let(:allowed_action) { 'promote' }
|
||||
let(:self_monitoring_project) { create(:project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(product_analytics_tracking: true)
|
||||
stub_application_setting(self_monitoring_project_id: self_monitoring_project.id)
|
||||
stub_application_setting(usage_ping_enabled: true)
|
||||
end
|
||||
|
||||
context 'with allowed event' do
|
||||
it 'sends an event to Product Analytics snowplow collector' do
|
||||
expect(SnowplowTracker::AsyncEmitter)
|
||||
.to receive(:new)
|
||||
.with(ProductAnalytics::Tracker::COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol)
|
||||
.and_return(emitter)
|
||||
|
||||
expect(SnowplowTracker::Tracker)
|
||||
.to receive(:new)
|
||||
.with(emitter, an_instance_of(SnowplowTracker::Subject), Gitlab::Tracking::SNOWPLOW_NAMESPACE, self_monitoring_project.id.to_s)
|
||||
.and_return(tracker)
|
||||
|
||||
freeze_time do
|
||||
expect(tracker)
|
||||
.to receive(:track_struct_event)
|
||||
.with(allowed_category, allowed_action, 'label', 'property', 1.5, nil, (Time.now.to_f * 1000).to_i)
|
||||
|
||||
subject.event(allowed_category, allowed_action, label: 'label', property: 'property', value: 1.5)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non-allowed event' do
|
||||
it 'does not send an event' do
|
||||
expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_struct_event)
|
||||
|
||||
subject.event('category', 'action')
|
||||
subject.event(allowed_category, 'action')
|
||||
subject.event('category', allowed_action)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when self-monitoring project does not exist' do
|
||||
before do
|
||||
stub_application_setting(self_monitoring_project_id: nil)
|
||||
end
|
||||
|
||||
include_examples 'does not send an event'
|
||||
end
|
||||
|
||||
context 'when product_analytics_tracking FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(product_analytics_tracking: false)
|
||||
end
|
||||
|
||||
include_examples 'does not send an event'
|
||||
end
|
||||
|
||||
context 'when usage ping is disabled' do
|
||||
before do
|
||||
stub_application_setting(usage_ping_enabled: false)
|
||||
end
|
||||
|
||||
include_examples 'does not send an event'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -36,6 +36,11 @@ RSpec.describe Gitlab::Tracking do
|
|||
end
|
||||
|
||||
describe '.event' do
|
||||
before do
|
||||
allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow).to receive(:event)
|
||||
allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event)
|
||||
end
|
||||
|
||||
it 'delegates to snowplow destination' do
|
||||
expect_any_instance_of(Gitlab::Tracking::Destinations::Snowplow)
|
||||
.to receive(:event)
|
||||
|
|
@ -43,6 +48,14 @@ RSpec.describe Gitlab::Tracking do
|
|||
|
||||
described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5)
|
||||
end
|
||||
|
||||
it 'delegates to ProductAnalytics destination' do
|
||||
expect_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics)
|
||||
.to receive(:event)
|
||||
.with('category', 'action', label: 'label', property: 'property', value: 1.5, context: nil)
|
||||
|
||||
described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.self_describing_event' do
|
||||
|
|
|
|||
|
|
@ -5,53 +5,4 @@ require 'spec_helper'
|
|||
RSpec.describe ProductAnalytics::Tracker do
|
||||
it { expect(described_class::URL).to eq('http://localhost/-/sp.js') }
|
||||
it { expect(described_class::COLLECTOR_URL).to eq('localhost/-/collector') }
|
||||
|
||||
describe '.event' do
|
||||
after do
|
||||
described_class.clear_memoization(:snowplow)
|
||||
end
|
||||
|
||||
context 'when usage ping is enabled' do
|
||||
let(:tracker) { double }
|
||||
let(:project_id) { 1 }
|
||||
|
||||
before do
|
||||
stub_application_setting(usage_ping_enabled: true, self_monitoring_project_id: project_id)
|
||||
end
|
||||
|
||||
it 'sends an event to Product Analytics snowplow collector' do
|
||||
expect(SnowplowTracker::AsyncEmitter)
|
||||
.to receive(:new)
|
||||
.with(described_class::COLLECTOR_URL, { protocol: 'http' })
|
||||
.and_return('_emitter_')
|
||||
|
||||
expect(SnowplowTracker::Tracker)
|
||||
.to receive(:new)
|
||||
.with('_emitter_', an_instance_of(SnowplowTracker::Subject), 'gl', project_id.to_s)
|
||||
.and_return(tracker)
|
||||
|
||||
freeze_time do
|
||||
expect(tracker)
|
||||
.to receive(:track_struct_event)
|
||||
.with('category', 'action', '_label_', '_property_', '_value_', nil, (Time.current.to_f * 1000).to_i)
|
||||
|
||||
described_class.event('category', 'action', label: '_label_', property: '_property_',
|
||||
value: '_value_', context: nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when usage ping is disabled' do
|
||||
before do
|
||||
stub_application_setting(usage_ping_enabled: false)
|
||||
end
|
||||
|
||||
it 'does not send an event' do
|
||||
expect(SnowplowTracker::Tracker).not_to receive(:new)
|
||||
|
||||
described_class.event('category', 'action', label: '_label_', property: '_property_',
|
||||
value: '_value_', context: nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ RSpec.configure do |config|
|
|||
# WebMock is set up to allow requests to `localhost`
|
||||
host = 'localhost'
|
||||
|
||||
allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event)
|
||||
|
||||
allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow)
|
||||
.to receive(:emitter)
|
||||
.and_return(SnowplowTracker::Emitter.new(host, buffer_size: buffer_size))
|
||||
|
|
|
|||
Loading…
Reference in New Issue