diff options
Diffstat (limited to 'lib/gitlab/internal_events.rb')
-rw-r--r-- | lib/gitlab/internal_events.rb | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/lib/gitlab/internal_events.rb b/lib/gitlab/internal_events.rb index e2e4ea75dbf..eb2ba3449fb 100644 --- a/lib/gitlab/internal_events.rb +++ b/lib/gitlab/internal_events.rb @@ -4,30 +4,61 @@ module Gitlab module InternalEvents UnknownEventError = Class.new(StandardError) InvalidPropertyError = Class.new(StandardError) - InvalidMethodError = Class.new(StandardError) + InvalidPropertyTypeError = Class.new(StandardError) class << self include Gitlab::Tracking::Helpers + include Gitlab::Utils::StrongMemoize def track_event(event_name, send_snowplow_event: true, **kwargs) raise UnknownEventError, "Unknown event: #{event_name}" unless EventDefinitions.known_event?(event_name) + validate_property!(kwargs, :user, User) + validate_property!(kwargs, :namespace, Namespaces::UserNamespace, Group) + validate_property!(kwargs, :project, Project) + + project = kwargs[:project] + kwargs[:namespace] ||= project.namespace if project + increase_total_counter(event_name) + increase_weekly_total_counter(event_name) update_unique_counter(event_name, kwargs) trigger_snowplow_event(event_name, kwargs) if send_snowplow_event + + if Feature.enabled?(:internal_events_for_product_analytics) + send_application_instrumentation_event(event_name, kwargs) + end rescue StandardError => e - Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, event_name: event_name, kwargs: kwargs) + extra = {} + kwargs.each_key do |k| + extra[k] = kwargs[k].is_a?(::ApplicationRecord) ? kwargs[k].try(:id) : kwargs[k] + end + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, event_name: event_name, kwargs: extra) nil end private + def validate_property!(kwargs, property_name, *class_names) + return unless kwargs.has_key?(property_name) + return if kwargs[property_name].nil? + return if class_names.include?(kwargs[property_name].class) + + raise InvalidPropertyTypeError, "#{property_name} should be an instance of #{class_names.join(', ')}" + end + def increase_total_counter(event_name) redis_counter_key = Gitlab::Usage::Metrics::Instrumentations::TotalCountMetric.redis_key(event_name) Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) } end + def increase_weekly_total_counter(event_name) + redis_counter_key = + Gitlab::Usage::Metrics::Instrumentations::TotalCountMetric.redis_key(event_name, Date.today) + Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) } + end + def update_unique_counter(event_name, kwargs) unique_property = EventDefinitions.unique_property(event_name) return unless unique_property @@ -35,11 +66,9 @@ module Gitlab unique_method = :id unless kwargs.has_key?(unique_property) - raise InvalidPropertyError, "#{event_name} should be triggered with a named parameter '#{unique_property}'." - end - - unless kwargs[unique_property].respond_to?(unique_method) - raise InvalidMethodError, "'#{unique_property}' should have a '#{unique_method}' method." + message = "#{event_name} should be triggered with a named parameter '#{unique_property}'." + Gitlab::AppJsonLogger.warn(message: message) + return end unique_value = kwargs[unique_property].public_send(unique_method) # rubocop:disable GitlabSecurity/PublicSend @@ -75,6 +104,25 @@ module Gitlab Gitlab::ErrorTracking .track_and_raise_for_dev_exception(error, snowplow_category: category, snowplow_action: event_name) end + + def send_application_instrumentation_event(event_name, kwargs) + return if gitlab_sdk_client.nil? + + user = kwargs[:user] + + gitlab_sdk_client.identify(user&.id) + gitlab_sdk_client.track(event_name, { project_id: kwargs[:project]&.id, namespace_id: kwargs[:namespace]&.id }) + end + + def gitlab_sdk_client + app_id = ENV['GITLAB_ANALYTICS_ID'] + host = ENV['GITLAB_ANALYTICS_URL'] + + return unless app_id.present? && host.present? + + GitlabSDK::Client.new(app_id: app_id, host: host) + end + strong_memoize_attr :gitlab_sdk_client end end end |