diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb index 8e936782e5a60bd82548871f41660bf28c66e482..4f96cc5c89538de83dd44f51dacfde4c4254ab7e 100644 --- a/app/controllers/concerns/product_analytics_tracking.rb +++ b/app/controllers/concerns/product_analytics_tracking.rb @@ -29,7 +29,13 @@ def route_events_to(destinations, name, &block) track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll) if destinations.include?(:snowplow) && event_enabled?(name) - Gitlab::Tracking.event(self.class.to_s, name, namespace: tracking_namespace_source, user: current_user) + Gitlab::Tracking.event( + self.class.to_s, + name, + namespace: tracking_namespace_source, + user: current_user, + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context] + ) end end @@ -49,6 +55,7 @@ def route_custom_events_to(destinations, name, action, label, &block) user: current_user, property: name, label: label, + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context], **optional_arguments ) end diff --git a/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb b/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb index b79f2806fa65c35a30b8245b9271bf1fdf166c36..bfce13199b4633df82c1a41958a2172692a6d352 100644 --- a/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb +++ b/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb @@ -43,7 +43,7 @@ ['', 'dev', 'sec', 'ops'].each do |tab| it_behaves_like 'tracks usage event', 'i_analytics_dev_ops_adoption', tab - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, params: { tab: tab }, format: :html } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/ee/spec/controllers/ee/search_controller_spec.rb b/ee/spec/controllers/ee/search_controller_spec.rb index daa9dbd456b32d718658ce34b7c2bcad42b21423..acf34eb4eca9da8248944c9ab8465e152214b0ac 100644 --- a/ee/spec/controllers/ee/search_controller_spec.rb +++ b/ee/spec/controllers/ee/search_controller_spec.rb @@ -33,9 +33,12 @@ it 'emits all search events' do subject - expect_snowplow_event(category: category, action: 'i_search_total', namespace: namespace, user: user) - expect_snowplow_event(category: category, action: 'i_search_paid', namespace: namespace, user: user) - expect_snowplow_event(category: category, action: 'i_search_advanced', namespace: namespace, user: user) + expect_snowplow_event(category: category, action: 'i_search_total', namespace: namespace, user: user, + context: context('i_search_total')) + expect_snowplow_event(category: category, action: 'i_search_paid', namespace: namespace, user: user, + context: context('i_search_paid')) + expect_snowplow_event(category: category, action: 'i_search_advanced', namespace: namespace, user: user, + context: context('i_search_advanced')) end end @@ -398,4 +401,10 @@ def request end end end + + private + + def context(event) + [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json] + end end diff --git a/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb b/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb index a69224a1e97ff9a058efef81e0423efe656b91ec..8083129689068eed6d6aa07447cce9083608b703 100644 --- a/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb +++ b/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb @@ -59,8 +59,10 @@ end describe 'tracking events', :snowplow do + let(:event) { 'g_analytics_valuestream' } + it 'tracks redis hll event' do - expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with('g_analytics_valuestream', { values: anything }) + expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event, { values: anything }) get(:show, params: { group_id: group }) end @@ -68,11 +70,14 @@ it 'tracks snowplow event' do get(:show, params: { group_id: group }) + context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json + expect_snowplow_event( category: 'Groups::Analytics::CycleAnalyticsController', - action: 'g_analytics_valuestream', + action: event, namespace: group, - user: user + user: user, + context: [context] ) end end diff --git a/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb b/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb index 43796c72ca3ee4fdf76bc790f57a2157ffbcf1f0..1896547f2e6c2c1fdca26e311a18b362c71c6e0e 100644 --- a/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb +++ b/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb @@ -74,7 +74,7 @@ let(:target_id) { 'g_analytics_productivity' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, params: { group_id: group } } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb b/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb index ab6635b1ee8ca01f566e218bd2df271d38dae5e1..b03a40c5a3e6d9063d5d5991f545b638dee54af4 100644 --- a/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb +++ b/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb @@ -221,7 +221,7 @@ def create_push_event(author, project) let(:target_id) { 'g_analytics_contribution' } end - it_behaves_like 'Snowplow event tracking', overrides: { project: nil } do + it_behaves_like 'Snowplow event tracking with RedisHLL context', overrides: { project: nil } do let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } let(:category) { described_class.name } let(:action) { 'perform_analytics_usage_action' } diff --git a/ee/spec/controllers/groups/insights_controller_spec.rb b/ee/spec/controllers/groups/insights_controller_spec.rb index ca422c39e67352eb62c44ff579178105d75434bb..d707da29d8f79e94c0598d64b11b48de3638215d 100644 --- a/ee/spec/controllers/groups/insights_controller_spec.rb +++ b/ee/spec/controllers/groups/insights_controller_spec.rb @@ -138,7 +138,7 @@ let(:target_id) { 'g_analytics_insights' } end - it_behaves_like 'Snowplow event tracking', overrides: { project: nil } do + it_behaves_like 'Snowplow event tracking with RedisHLL context', overrides: { project: nil } do subject { get :show, params: params.merge(group_id: parent_group.to_param) } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/ee/spec/controllers/groups/issues_analytics_controller_spec.rb b/ee/spec/controllers/groups/issues_analytics_controller_spec.rb index 185711bee6dabf61ee627732964c5ff446ee105a..76d7eacf8c04dcae8590e2c6d703812a7be7fbea 100644 --- a/ee/spec/controllers/groups/issues_analytics_controller_spec.rb +++ b/ee/spec/controllers/groups/issues_analytics_controller_spec.rb @@ -34,7 +34,7 @@ let(:target_id) { 'g_analytics_issues' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, params: { group_id: group.to_param } } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb b/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb index f98b1cd99931014d4800ebd14b0e8ce10c579e58..a7f3f4661e1ee081fc7edf559b499318d5952ab9 100644 --- a/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb +++ b/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb @@ -27,7 +27,7 @@ let(:target_id) { 'p_analytics_issues' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, params: request_params, format: :html } let(:request_params) { { namespace_id: project.namespace, project_id: project1 } } diff --git a/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb b/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb index be1af9230636ceea046691f0be28c96fce6465c3..3e72f24cef1690598d882bbdec91051977c370a5 100644 --- a/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb +++ b/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb @@ -28,7 +28,7 @@ let(:target_id) { 'p_analytics_merge_request' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } let(:category) { described_class.name } let(:action) { 'perform_analytics_usage_action' } diff --git a/ee/spec/controllers/projects/insights_controller_spec.rb b/ee/spec/controllers/projects/insights_controller_spec.rb index a8a1b8eae7ecc9daaee6003f6182686bdddf8fca..f016a231e312dd7942bccb071cd3e2ce1eeaf3c0 100644 --- a/ee/spec/controllers/projects/insights_controller_spec.rb +++ b/ee/spec/controllers/projects/insights_controller_spec.rb @@ -107,7 +107,7 @@ let(:target_id) { 'p_analytics_insights' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, params: params, format: :html } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb b/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb index 1c4f402726b233803c7ddbedb3ad75046cd2d307..eb8b1aa4149d6d4e82ace3b6e9a4a8bfc0ad40d1 100644 --- a/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb +++ b/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb @@ -66,7 +66,7 @@ get :index, params: { namespace_id: project.namespace, project_id: project } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject(:get_index) { get :index, params: { namespace_id: project.namespace, project_id: project } } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb b/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb index 1858411c2a35486b3adb06cf447995706c0c90d1..80033d96c0d7c6f1f7ab7b930cf26b32636c1f7f 100644 --- a/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb +++ b/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb @@ -71,7 +71,7 @@ subject end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } let(:category) { described_class.name } let(:action) { 'perform_analytics_usage_action' } diff --git a/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb b/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb index 076018861d09df2a034e9ea4eef79029c863eca1..1bab44ffc769137e695c493d51b6264073f60fda 100644 --- a/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb +++ b/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb @@ -65,7 +65,7 @@ let(:target_id) { 'p_analytics_code_reviews' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :index, params: request_params, format: :html } let(:request_params) { { namespace_id: project.namespace, project_id: project } } diff --git a/lib/gitlab/tracking/service_ping_context.rb b/lib/gitlab/tracking/service_ping_context.rb new file mode 100644 index 0000000000000000000000000000000000000000..393cd647e7f9c44b2250b5b0d14dfe6f980d28f6 --- /dev/null +++ b/lib/gitlab/tracking/service_ping_context.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Gitlab + module Tracking + class ServicePingContext + SCHEMA_URL = 'iglu:com.gitlab/gitlab_service_ping/jsonschema/1-0-0' + ALLOWED_SOURCES = %i[redis_hll].freeze + + def initialize(data_source:, event:) + unless ALLOWED_SOURCES.include?(data_source) + raise ArgumentError, "#{data_source} is not acceptable data source for ServicePingContext" + end + + @payload = { + data_source: data_source, + event_name: event + } + end + + def to_context + SnowplowTracker::SelfDescribingJson.new(SCHEMA_URL, @payload) + end + end + end +end diff --git a/spec/controllers/admin/cohorts_controller_spec.rb b/spec/controllers/admin/cohorts_controller_spec.rb index 766073977c6d69c4b4892ffc5c5e2c9522db6dc5..50626a5da912cca6902b4a1a5f33a73d1e4062b7 100644 --- a/spec/controllers/admin/cohorts_controller_spec.rb +++ b/spec/controllers/admin/cohorts_controller_spec.rb @@ -14,7 +14,7 @@ let(:target_id) { 'i_analytics_cohorts' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :index } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb index 5d7a7e089aa8952e127edb088010ac371e2004f7..52a46b5e99ac4fad0d78ff2b421e01feac45d20e 100644 --- a/spec/controllers/admin/dev_ops_report_controller_spec.rb +++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb @@ -29,7 +29,7 @@ let(:request_params) { { tab: 'devops-score' } } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, format: :html } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/spec/controllers/admin/usage_trends_controller_spec.rb b/spec/controllers/admin/usage_trends_controller_spec.rb index 356f603bf57a0502042c539fba08c36a168cfef5..87cf8988b4e4b97f80e4aa37541a69bae56848ac 100644 --- a/spec/controllers/admin/usage_trends_controller_spec.rb +++ b/spec/controllers/admin/usage_trends_controller_spec.rb @@ -14,7 +14,7 @@ let(:target_id) { 'i_analytics_instance_statistics' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :index } let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } diff --git a/spec/controllers/concerns/product_analytics_tracking_spec.rb b/spec/controllers/concerns/product_analytics_tracking_spec.rb index 2e734d81ea003641309a690d51b41128b0eb5d25..f85b6806f301cd6851dad89a1554a0763235909a 100644 --- a/spec/controllers/concerns/product_analytics_tracking_spec.rb +++ b/spec/controllers/concerns/product_analytics_tracking_spec.rb @@ -55,11 +55,19 @@ def expect_tracking(user: self.user) expect(Gitlab::UsageDataCounters::HLLRedisCounter).to have_received(:track_event) .with('g_analytics_valuestream', values: instance_of(String)) + expect_snowplow_tracking(user) + end + + def expect_snowplow_tracking(user) + context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: 'g_analytics_valuestream') + .to_context.to_json + expect_snowplow_event( category: anything, action: 'g_analytics_valuestream', namespace: group, - user: user + user: user, + context: [context] ) end @@ -160,12 +168,7 @@ def expect_no_tracking get :show, params: { id: 2 } expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event) - expect_snowplow_event( - category: anything, - action: 'g_analytics_valuestream', - namespace: group, - user: nil - ) + expect_snowplow_tracking(nil) end end end diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb index f5dd8abd67b9fdc37a03b8acb54371f5e31078f9..034e6104f99a5df5b2e37e853842dc0e9621f9ac 100644 --- a/spec/controllers/projects/cycle_analytics_controller_spec.rb +++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb @@ -31,7 +31,7 @@ let(:target_id) { 'p_analytics_valuestream' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, params: request_params, format: :html } let(:request_params) { { namespace_id: project.namespace, project_id: project } } diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index 9227c7dd70a985beaf782265ad90c1ed8d0713e2..3dfc22927cfd49386fac11fa3d36c9d78c7499ec 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -90,7 +90,7 @@ let(:target_id) { 'p_analytics_repo' } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject do sign_in(user) get :charts, params: request_params, format: :html diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index b9acaf658926e7b7133bd270e6219e5d37db347b..6e2de0c4d57e58cdfb39f8a09422b485d4c2e230 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -859,7 +859,7 @@ def get_stage(name, params = {}) let(:target_id) { ['p_analytics_pipelines', tab[:event]] } end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :charts, params: request_params, format: :html } let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] } } diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb index 4131bd148dad211d3bd37e6b1332d65a526051cd..7ab66b04a6e537ff3bd0918c0d715cda787956e6 100644 --- a/spec/controllers/search_controller_spec.rb +++ b/spec/controllers/search_controller_spec.rb @@ -218,7 +218,7 @@ end end - it_behaves_like 'Snowplow event tracking' do + it_behaves_like 'Snowplow event tracking with RedisHLL context' do subject { get :show, params: { group_id: namespace.id, scope: 'blobs', search: 'term' } } let(:project) { nil } diff --git a/spec/lib/gitlab/tracking/service_ping_context_spec.rb b/spec/lib/gitlab/tracking/service_ping_context_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..d70dfaa4e0b51b2ce2ef15f182667bdbcb15781c --- /dev/null +++ b/spec/lib/gitlab/tracking/service_ping_context_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Tracking::ServicePingContext do + describe '#init' do + it 'does not accept unsupported data sources' do + expect { described_class.new(data_source: :random, event: 'event a') }.to raise_error(ArgumentError) + end + end + + describe '#to_context' do + let(:subject) { described_class.new(data_source: :redis_hll, event: 'sample_event') } + + it 'contains event_name' do + expect(subject.to_context.to_json.dig(:data, :event_name)).to eq('sample_event') + end + end +end diff --git a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb index 4af3c0cc6cc2e93ec3b517e1abfd5ab4c076320c..6749ebd471f1daff7b1325d4e062137e2f8bd503 100644 --- a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb +++ b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb @@ -32,7 +32,8 @@ user: try(:user), project: try(:project), label: try(:label), - property: try(:property) + property: try(:property), + context: try(:context) }.merge(overrides).compact.merge(extra) subject @@ -40,3 +41,12 @@ expect_snowplow_event(**params) end end + +RSpec.shared_examples 'Snowplow event tracking with RedisHLL context' do |overrides: {}| + it_behaves_like 'Snowplow event tracking', overrides: overrides do + let(:context) do + event = try(:property) || action + [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json] + end + end +end