summaryrefslogtreecommitdiff
path: root/lib/gitlab/usage_data_counters/track_unique_actions.rb
blob: 0df982572a48191481d275128bea27a1ba4bd58e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# frozen_string_literal: true

module Gitlab
  module UsageDataCounters
    module TrackUniqueActions
      KEY_EXPIRY_LENGTH = 29.days

      WIKI_ACTION = :wiki_action
      DESIGN_ACTION = :design_action
      PUSH_ACTION = :project_action

      ACTION_TRANSFORMATIONS = HashWithIndifferentAccess.new({
        wiki: {
          created: WIKI_ACTION,
          updated: WIKI_ACTION,
          destroyed: WIKI_ACTION
        },
        design: {
          created: DESIGN_ACTION,
          updated: DESIGN_ACTION,
          destroyed: DESIGN_ACTION
        },
        project: {
          pushed: PUSH_ACTION
        }
      }).freeze

      class << self
        def track_event(event_action:, event_target:, author_id:, time: Time.zone.now)
          return unless Gitlab::CurrentSettings.usage_ping_enabled
          return unless valid_target?(event_target)
          return unless valid_action?(event_action)

          transformed_target = transform_target(event_target)
          transformed_action = transform_action(event_action, transformed_target)
          target_key = key(transformed_action, time)

          Gitlab::Redis::HLL.add(key: target_key, value: author_id, expiry: KEY_EXPIRY_LENGTH)
        end

        def count_unique(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 transform_action(event_action, event_target)
          ACTION_TRANSFORMATIONS.dig(event_target, event_action) || event_action
        end

        def transform_target(event_target)
          Event::TARGET_TYPES.key(event_target)
        end

        def valid_target?(target)
          Event::TARGET_TYPES.value?(target)
        end

        def valid_action?(action)
          Event.actions.key?(action)
        end

        def key(event_action, date)
          year_day = date.strftime('%G-%j')
          "#{year_day}-{#{event_action}}"
        end
      end
    end
  end
end