[Step 1] Update Gitlab::UsageDataCounters::TrackUniqueActions to track new actions
In !35580 (merged), the service module Gitlab::UsageDataCounters::TrackUniqueActions
was introduced to track events that later will be consumed by Usage Data.
Nevertheless, this service class is very tight to the Event
model to a point in which it validates that the action to track is a valid action defined in that model.
The actions we want to track are quite particular since we don't create a real Event
when the action is executed. Specifically, we want to track when a commit is performed:
- Through the web IDE
- Through the Single File Editor
- Through the Snippets editor
Therefore, we cannot fully rely on the Gitlab::UsageDataCounters::TrackUniqueActions
service class because we need a custom set of actions and a payload that is different from the existing behavior.
That's why I'd proposed to create a service class named like Gitlab::UsageDataCounters::TrackUniqueVirtualActions
that would extend the Gitlab::UsageDataCounters::TrackUniqueActions
module.
This new service could be something like:
module Gitlab
module UsageDataCounters
module TrackUniqueVirtualActions
VIRTUAL_ACTIONS = %i[edit_by_web_ide edit_by_sfe edit_by_snippet_editor]
class << self
def track_action(event_action:, author_id:, time: Time.zone.now)
return unless Gitlab::CurrentSettings.usage_ping_enabled
return unless Feature.enabled?(FEATURE_FLAG)
return unless valid_action?(event_action)
target_key = key(event_action, time)
Gitlab::Redis::HLL.add(key: target_key, value: author_id, expiry: KEY_EXPIRY_LENGTH)
end
def count_unique_events(event_action:, date_from:, date_to:)
keys = (date_from.to_date..date_to.to_date).map { |date| key(event_action, date) }
Gitlab::Redis::HLL.count(keys: keys)
end
private
def valid_action?(action)
VIRTUAL_ACTIONS.key?(action)
end
def key(event_action, date)
year_day = date.strftime('%G-%j')
"#{year_day}-{#{event_action}}"
end
end
end
end
end
This is a quick approach to what would we need to achieve. We would need to think more about the action names and whether it's the best way for reusing it with other events.
Basically, this way we can store unique events related to virtual actions, we just need to figure out the programming nuances.