usage_data_spec.rb 11.0 KB
Newer Older
1 2
# frozen_string_literal: true

3 4
require 'spec_helper'

5 6
describe Gitlab::UsageData, :aggregate_failures do
  include UsageDataHelpers
7

8 9 10
  before do
    allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
  end
11 12 13 14 15

  shared_examples "usage data execution" do
    describe '#data' do
      let!(:ud) { build(:usage_data) }

16
      before do
17
        allow(Gitlab::GrafanaEmbedUsageData).to receive(:issue_count).and_return(2)
18
      end
19

20
      subject { described_class.data }
21

22 23 24
      it 'gathers usage data' do
        expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS)
      end
25

26 27
      it 'gathers usage counts' do
        count_data = subject[:counts]
28

29 30 31 32 33 34
        expect(count_data[:boards]).to eq(1)
        expect(count_data[:projects]).to eq(4)
        expect(count_data.values_at(*UsageDataHelpers::SMAU_KEYS)).to all(be_an(Integer))
        expect(count_data.keys).to include(*UsageDataHelpers::COUNTS_KEYS)
        expect(UsageDataHelpers::COUNTS_KEYS - count_data.keys).to be_empty
      end
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
      it 'gathers projects data correctly' do
        count_data = subject[:counts]

        expect(count_data[:projects]).to eq(4)
        expect(count_data[:projects_asana_active]).to eq(0)
        expect(count_data[:projects_prometheus_active]).to eq(1)
        expect(count_data[:projects_jira_active]).to eq(4)
        expect(count_data[:projects_jira_server_active]).to eq(2)
        expect(count_data[:projects_jira_cloud_active]).to eq(2)
        expect(count_data[:projects_slack_notifications_active]).to eq(2)
        expect(count_data[:projects_slack_slash_active]).to eq(1)
        expect(count_data[:projects_slack_active]).to eq(2)
        expect(count_data[:projects_slack_slash_commands_active]).to eq(1)
        expect(count_data[:projects_custom_issue_tracker_active]).to eq(1)
        expect(count_data[:projects_mattermost_active]).to eq(0)
        expect(count_data[:projects_with_repositories_enabled]).to eq(3)
        expect(count_data[:projects_with_error_tracking_enabled]).to eq(1)
        expect(count_data[:projects_with_alerts_service_enabled]).to eq(1)
        expect(count_data[:issues_created_from_gitlab_error_tracking_ui]).to eq(1)
        expect(count_data[:issues_with_associated_zoom_link]).to eq(2)
        expect(count_data[:issues_using_zoom_quick_actions]).to eq(3)
        expect(count_data[:issues_with_embedded_grafana_charts_approx]).to eq(2)
        expect(count_data[:incident_issues]).to eq(4)

        expect(count_data[:clusters_enabled]).to eq(4)
        expect(count_data[:project_clusters_enabled]).to eq(3)
        expect(count_data[:group_clusters_enabled]).to eq(1)
        expect(count_data[:clusters_disabled]).to eq(3)
        expect(count_data[:project_clusters_disabled]).to eq(1)
        expect(count_data[:group_clusters_disabled]).to eq(2)
        expect(count_data[:group_clusters_enabled]).to eq(1)
        expect(count_data[:clusters_platforms_eks]).to eq(1)
        expect(count_data[:clusters_platforms_gke]).to eq(1)
        expect(count_data[:clusters_platforms_user]).to eq(1)
        expect(count_data[:clusters_applications_helm]).to eq(1)
        expect(count_data[:clusters_applications_ingress]).to eq(1)
        expect(count_data[:clusters_applications_cert_managers]).to eq(1)
        expect(count_data[:clusters_applications_crossplane]).to eq(1)
        expect(count_data[:clusters_applications_prometheus]).to eq(1)
        expect(count_data[:clusters_applications_runner]).to eq(1)
        expect(count_data[:clusters_applications_knative]).to eq(1)
        expect(count_data[:clusters_applications_elastic_stack]).to eq(1)
        expect(count_data[:grafana_integrated_projects]).to eq(2)
        expect(count_data[:clusters_applications_jupyter]).to eq(1)
      end
81

82 83 84
      it 'works when queries time out' do
        allow_any_instance_of(ActiveRecord::Relation)
          .to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
85

86
        expect { subject }.not_to raise_error
87
      end
88 89 90 91 92 93 94

      it 'jira usage works when queries time out' do
        allow_any_instance_of(ActiveRecord::Relation)
          .to receive(:find_in_batches).and_raise(ActiveRecord::StatementInvalid.new(''))

        expect { described_class.jira_usage }.not_to raise_error
      end
95
    end
96

97 98
    describe '#usage_data_counters' do
      subject { described_class.usage_data_counters }
99

100
      it { is_expected.to all(respond_to :totals) }
A
Alex Kalderimis 已提交
101

102 103
      describe 'the results of calling #totals on all objects in the array' do
        subject { described_class.usage_data_counters.map(&:totals) }
A
Alex Kalderimis 已提交
104

105 106 107
        it { is_expected.to all(be_a Hash) }
        it { is_expected.to all(have_attributes(keys: all(be_a Symbol), values: all(be_a Integer))) }
      end
A
Alex Kalderimis 已提交
108

109 110
      it 'does not have any conflicts' do
        all_keys = subject.flat_map { |counter| counter.totals.keys }
A
Alex Kalderimis 已提交
111

112
        expect(all_keys.size).to eq all_keys.to_set.size
113
      end
114
    end
A
Alex Kalderimis 已提交
115

116 117 118 119 120 121 122 123 124 125 126 127 128
    describe '#license_usage_data' do
      subject { described_class.license_usage_data }

      it 'gathers license data' do
        expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
        expect(subject[:version]).to eq(Gitlab::VERSION)
        expect(subject[:installation_type]).to eq('gitlab-development-kit')
        expect(subject[:active_user_count]).to eq(User.active.size)
        expect(subject[:recorded_at]).to be_a(Time)
      end
    end

    context 'when not relying on database records' do
129 130 131
      describe '#features_usage_data_ce' do
        subject { described_class.features_usage_data_ce }

132
        it 'gathers feature usage data' do
133 134 135 136 137 138 139 140 141 142 143 144
          expect(subject[:mattermost_enabled]).to eq(Gitlab.config.mattermost.enabled)
          expect(subject[:signup_enabled]).to eq(Gitlab::CurrentSettings.allow_signup?)
          expect(subject[:ldap_enabled]).to eq(Gitlab.config.ldap.enabled)
          expect(subject[:gravatar_enabled]).to eq(Gitlab::CurrentSettings.gravatar_enabled?)
          expect(subject[:omniauth_enabled]).to eq(Gitlab::Auth.omniauth_enabled?)
          expect(subject[:reply_by_email_enabled]).to eq(Gitlab::IncomingEmail.enabled?)
          expect(subject[:container_registry_enabled]).to eq(Gitlab.config.registry.enabled)
          expect(subject[:dependency_proxy_enabled]).to eq(Gitlab.config.dependency_proxy.enabled)
          expect(subject[:gitlab_shared_runners_enabled]).to eq(Gitlab.config.gitlab_ci.shared_runners_enabled)
          expect(subject[:web_ide_clientside_preview_enabled]).to eq(Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?)
        end
      end
A
Alex Kalderimis 已提交
145

146 147 148
      describe '#components_usage_data' do
        subject { described_class.components_usage_data }

149
        it 'gathers components usage data' do
150 151
          expect(Gitlab::UsageData).to receive(:app_server_type).and_return('server_type')
          expect(subject[:app_server][:type]).to eq('server_type')
152 153 154 155 156 157 158 159 160 161 162
          expect(subject[:gitlab_pages][:enabled]).to eq(Gitlab.config.pages.enabled)
          expect(subject[:gitlab_pages][:version]).to eq(Gitlab::Pages::VERSION)
          expect(subject[:git][:version]).to eq(Gitlab::Git.version)
          expect(subject[:database][:adapter]).to eq(Gitlab::Database.adapter_name)
          expect(subject[:database][:version]).to eq(Gitlab::Database.version)
          expect(subject[:gitaly][:version]).to be_present
          expect(subject[:gitaly][:servers]).to be >= 1
          expect(subject[:gitaly][:filesystems]).to be_an(Array)
          expect(subject[:gitaly][:filesystems].first).to be_a(String)
        end
      end
163

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
      describe '#app_server_type' do
        subject { described_class.app_server_type }

        it 'successfully identifies runtime and returns the identifier' do
          expect(Gitlab::Runtime).to receive(:identify).and_return(:runtime_identifier)

          is_expected.to eq('runtime_identifier')
        end

        context 'when runtime is not identified' do
          let(:exception) { Gitlab::Runtime::IdentificationError.new('exception message from runtime identify') }

          it 'logs the exception and returns unknown app server type' do
            expect(Gitlab::Runtime).to receive(:identify).and_raise(exception)

            expect(Gitlab::AppLogger).to receive(:error).with(exception.message)
            expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception)
            expect(subject).to eq('unknown_app_server_type')
          end
        end
      end

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
      describe '#cycle_analytics_usage_data' do
        subject { described_class.cycle_analytics_usage_data }

        it 'works when queries time out in new' do
          allow(Gitlab::CycleAnalytics::UsageData)
            .to receive(:new).and_raise(ActiveRecord::StatementInvalid.new(''))

          expect { subject }.not_to raise_error
        end

        it 'works when queries time out in to_json' do
          allow_any_instance_of(Gitlab::CycleAnalytics::UsageData)
            .to receive(:to_json).and_raise(ActiveRecord::StatementInvalid.new(''))

          expect { subject }.not_to raise_error
        end
      end

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
      describe '#ingress_modsecurity_usage' do
        subject { described_class.ingress_modsecurity_usage }

        it 'gathers variable data' do
          allow_any_instance_of(
            ::Clusters::Applications::IngressModsecurityUsageService
          ).to receive(:execute).and_return(
            {
              ingress_modsecurity_blocking: 1,
              ingress_modsecurity_disabled: 2
            }
          )

          expect(subject[:ingress_modsecurity_blocking]).to eq(1)
          expect(subject[:ingress_modsecurity_disabled]).to eq(2)
        end
      end
221

222 223
      describe '#count' do
        let(:relation) { double(:relation) }
224

225 226
        it 'returns the count when counting succeeds' do
          allow(relation).to receive(:count).and_return(1)
227

228 229
          expect(described_class.count(relation, batch: false)).to eq(1)
        end
230

231 232
        it 'returns the fallback value when counting fails' do
          allow(relation).to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
233

234 235 236
          expect(described_class.count(relation, fallback: 15, batch: false)).to eq(15)
        end
      end
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252

      describe '#distinct_count' do
        let(:relation) { double(:relation) }

        it 'returns the count when counting succeeds' do
          allow(relation).to receive(:distinct_count_by).and_return(1)

          expect(described_class.distinct_count(relation, batch: false)).to eq(1)
        end

        it 'returns the fallback value when counting fails' do
          allow(relation).to receive(:distinct_count_by).and_raise(ActiveRecord::StatementInvalid.new(''))

          expect(described_class.distinct_count(relation, fallback: 15, batch: false)).to eq(15)
        end
      end
253 254
    end
  end
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

  context 'when usage usage_ping_batch_counter is true' do
    before do
      stub_feature_flags(usage_ping_batch_counter: true)
    end

    it_behaves_like 'usage data execution'
  end

  context 'when usage usage_ping_batch_counter is false' do
    before do
      stub_feature_flags(usage_ping_batch_counter: false)
    end

    it_behaves_like 'usage data execution'
  end
271
end