summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
blob: 2ab349a67d9bb878ab7b0c1adbb2318ab037bdb5 (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_shared_state do
  let(:entity1) { 'dfb9d2d2-f56c-4c77-8aeb-6cddc4a1f857' }
  let(:entity2) { '1dd9afb2-a3ee-4de1-8ae3-a405579c8584' }
  let(:entity3) { '34rfjuuy-ce56-sa35-ds34-dfer567dfrf2' }
  let(:entity4) { '8b9a2671-2abf-4bec-a682-22f6a8f7bf31' }

  let(:weekly_event) { 'g_analytics_contribution' }
  let(:daily_event) { 'g_search' }
  let(:different_aggregation) { 'different_aggregation' }

  let(:known_events) do
    [
      { name: "g_analytics_contribution", redis_slot: "analytics", category: "analytics", expiry: 84, aggregation: "weekly" },
      { name: "g_analytics_valuestream", redis_slot: "analytics", category: "analytics", expiry: 84, aggregation: "daily" },
      { name: "g_analytics_productivity", redis_slot: "analytics", category: "productivity", expiry: 84, aggregation: "weekly" },
      { name: "g_compliance_dashboard", redis_slot: "compliance", category: "compliance", aggregation: "weekly" },
      { name: "g_search", category: "global", aggregation: "daily" },
      { name: "different_aggregation", category: "global", aggregation: "monthly" }
    ].map(&:with_indifferent_access)
  end

  before do
    allow(described_class).to receive(:known_events).and_return(known_events)
  end

  around do |example|
    # We need to freeze to a reference time
    # because visits are grouped by the week number in the year
    # Without freezing the time, the test may behave inconsistently
    # depending on which day of the week test is run.
    # Monday 6th of June
    reference_time = Time.utc(2020, 6, 1)
    Timecop.freeze(reference_time) { example.run }
  end

  describe '.track_event' do
    it "raise error if metrics don't have same aggregation" do
      expect { described_class.track_event(entity1, different_aggregation, Date.current) } .to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownAggregation)
    end

    it 'raise error if metrics of unknown aggregation' do
      expect { described_class.track_event(entity1, 'unknown', Date.current) } .to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
    end
  end

  describe '.unique_events' do
    before do
      # events in current week, should not be counted as week is not complete
      described_class.track_event(entity1, weekly_event, Date.current)
      described_class.track_event(entity2, weekly_event, Date.current)

      # Events last week
      described_class.track_event(entity1, weekly_event, 2.days.ago)
      described_class.track_event(entity1, weekly_event, 2.days.ago)

      # Events 2 weeks ago
      described_class.track_event(entity1, weekly_event, 2.weeks.ago)

      # Events 4 weeks ago
      described_class.track_event(entity3, weekly_event, 4.weeks.ago)
      described_class.track_event(entity4, weekly_event, 29.days.ago)

      # events in current day should be counted in daily aggregation
      described_class.track_event(entity1, daily_event, Date.current)
      described_class.track_event(entity2, daily_event, Date.current)

      # Events last week
      described_class.track_event(entity1, daily_event, 2.days.ago)
      described_class.track_event(entity1, daily_event, 2.days.ago)

      # Events 2 weeks ago
      described_class.track_event(entity1, daily_event, 14.days.ago)

      # Events 4 weeks ago
      described_class.track_event(entity3, daily_event, 28.days.ago)
      described_class.track_event(entity4, daily_event, 29.days.ago)
    end

    it 'raise error if metrics are not in the same slot' do
      expect { described_class.unique_events(event_names: %w(g_analytics_contribution g_compliance_dashboard), start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should be in same slot')
    end

    it 'raise error if metrics are not in the same category' do
      expect { described_class.unique_events(event_names: %w(g_analytics_contribution g_analytics_productivity), start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should be in same category')
    end

    it "raise error if metrics don't have same aggregation" do
      expect { described_class.unique_events(event_names: %w(g_analytics_contribution g_analytics_valuestream), start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should have same aggregation level')
    end

    context 'when data for the last complete week' do
      it { expect(described_class.unique_events(event_names: weekly_event, start_date: 1.week.ago, end_date: Date.current)).to eq(1) }
    end

    context 'when data for the last 4 complete weeks' do
      it { expect(described_class.unique_events(event_names: weekly_event, start_date: 4.weeks.ago, end_date: Date.current)).to eq(2) }
    end

    context 'when data for the week 4 weeks ago' do
      it { expect(described_class.unique_events(event_names: weekly_event, start_date: 4.weeks.ago, end_date: 3.weeks.ago)).to eq(1) }
    end

    context 'when using daily aggregation' do
      it { expect(described_class.unique_events(event_names: daily_event, start_date: 7.days.ago, end_date: Date.current)).to eq(2) }
      it { expect(described_class.unique_events(event_names: daily_event, start_date: 28.days.ago, end_date: Date.current)).to eq(3) }
      it { expect(described_class.unique_events(event_names: daily_event, start_date: 28.days.ago, end_date: 21.days.ago)).to eq(1) }
    end
  end
end