diff --git a/doc/development/internal_analytics/internal_event_instrumentation/quick_start.md b/doc/development/internal_analytics/internal_event_instrumentation/quick_start.md index 02a902d941d2f8e2b32eb250ca1562607c4118c8..1ee54cfe98c957989a2a1975c056a4db7df789e0 100644 --- a/doc/development/internal_analytics/internal_event_instrumentation/quick_start.md +++ b/doc/development/internal_analytics/internal_event_instrumentation/quick_start.md @@ -62,6 +62,16 @@ If a `project` but no `namespace` is provided, the `project.namespace` is used a In some cases you might want to specify the `category` manually or provide none at all. To do that, you can call the `InternalEvents.track_event` method directly instead of using the module. +In case when a feature is enabled through multiple namespaces and its required to track why the feature is enabled, it is +possible to pass an optional `feature_enabled_by_namespace_ids` parameter with an array of namespace ids. + +```ruby +Gitlab::InternalEvents.track_event( + ... + feature_enabled_by_namespace_ids: [namespace_one.id, namespace_two.id] +) +``` + #### Additional properties Additional properties can be passed when tracking events. They can be used to save additional data related to given event. It is possible to send a maximum of three additional properties with keys `label` (string), `property` (string) and `value`(numeric). diff --git a/lib/gitlab/internal_events.rb b/lib/gitlab/internal_events.rb index b50658f46da8ff7753afda62d842a2acaf10354b..7f509016af5f8b551185b0b78da01ad53491f5b7 100644 --- a/lib/gitlab/internal_events.rb +++ b/lib/gitlab/internal_events.rb @@ -118,12 +118,14 @@ def trigger_snowplow_event(event_name, category, additional_properties, kwargs) user = kwargs[:user] project = kwargs[:project] namespace = kwargs[:namespace] + feature_enabled_by_namespace_ids = kwargs[:feature_enabled_by_namespace_ids] standard_context = Tracking::StandardContext.new( project_id: project&.id, user_id: user&.id, namespace_id: namespace&.id, - plan_name: namespace&.actual_plan_name + plan_name: namespace&.actual_plan_name, + feature_enabled_by_namespace_ids: feature_enabled_by_namespace_ids ).to_context service_ping_context = Tracking::ServicePingContext.new( diff --git a/lib/gitlab/tracking/standard_context.rb b/lib/gitlab/tracking/standard_context.rb index 4c04fa7d5257e82719d87443cae32335763045ec..06264d0300713cb400b044eb48cf0dc4d5f12fb9 100644 --- a/lib/gitlab/tracking/standard_context.rb +++ b/lib/gitlab/tracking/standard_context.rb @@ -6,7 +6,9 @@ class StandardContext GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-9' GITLAB_RAILS_SOURCE = 'gitlab-rails' - def initialize(namespace_id: nil, plan_name: nil, project_id: nil, user_id: nil, **extra) + def initialize( + namespace_id: nil, plan_name: nil, project_id: nil, user_id: nil, + feature_enabled_by_namespace_ids: nil, **extra) check_argument_type(:namespace_id, namespace_id, [Integer]) check_argument_type(:plan_name, plan_name, [String]) check_argument_type(:project_id, project_id, [Integer]) @@ -17,6 +19,7 @@ def initialize(namespace_id: nil, plan_name: nil, project_id: nil, user_id: nil, @project_id = project_id @user_id = user_id @extra = extra + @feature_enabled_by_namespace_ids = feature_enabled_by_namespace_ids end def to_context @@ -41,7 +44,7 @@ def source private - attr_accessor :namespace_id, :project_id, :extra, :plan_name, :user_id + attr_accessor :namespace_id, :project_id, :extra, :plan_name, :user_id, :feature_enabled_by_namespace_ids def to_h { @@ -53,6 +56,7 @@ def to_h is_gitlab_team_member: gitlab_team_member?(user_id), namespace_id: namespace_id, project_id: project_id, + feature_enabled_by_namespace_ids: feature_enabled_by_namespace_ids, context_generated_at: Time.current } end diff --git a/spec/lib/gitlab/internal_events_spec.rb b/spec/lib/gitlab/internal_events_spec.rb index 26a1ebfb2fbe347937556e3c4ff62a2218dc9e27..cecf9ddff789b2bf8338343b8b03597aa1b99a0b 100644 --- a/spec/lib/gitlab/internal_events_spec.rb +++ b/spec/lib/gitlab/internal_events_spec.rb @@ -174,6 +174,29 @@ def validate_service_ping_context(service_ping_context) end end + context 'when feature_enabled_by_namespace_ids is passed' do + let(:feature_enabled_by_namespace_ids) { [1, 2, 3] } + + it 'is sent to Snowplow' do + described_class.track_event( + event_name, + user: user, + project: project, + feature_enabled_by_namespace_ids: feature_enabled_by_namespace_ids + ) + + expect(fake_snowplow).to have_received(:event) do |_, _, args| + contexts = args[:context]&.map(&:to_json) + + standard_context = contexts.find do |c| + c[:schema] == Gitlab::Tracking::StandardContext::GITLAB_STANDARD_SCHEMA_URL + end + + expect(standard_context[:data][:feature_enabled_by_namespace_ids]).to eq(feature_enabled_by_namespace_ids) + end + end + end + context 'when arguments are invalid' do let(:error_class) { described_class::InvalidPropertyTypeError } diff --git a/spec/support/shared_examples/controllers/internal_event_tracking_examples.rb b/spec/support/shared_examples/controllers/internal_event_tracking_examples.rb index e421611e0705f790efba35adbecd9e6af4e2d787..2f7d68676ad952b53d490ec0a3a5b2b3a60d2da3 100644 --- a/spec/support/shared_examples/controllers/internal_event_tracking_examples.rb +++ b/spec/support/shared_examples/controllers/internal_event_tracking_examples.rb @@ -35,6 +35,7 @@ expect(Gitlab::Tracking::StandardContext) .to have_received(:new) .with( + feature_enabled_by_namespace_ids: try(:feature_enabled_by_namespace_ids), project_id: project&.id, user_id: user&.id, namespace_id: namespace&.id,