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

3 4 5
require 'spec_helper'

describe Gitlab::UsageData do
6
  let(:projects) { create_list(:project, 4) }
7
  let!(:board) { create(:board, project: projects[0]) }
8 9

  describe '#data' do
10 11
    before do
      create(:jira_service, project: projects[0])
12
      create(:jira_service, :without_properties_callback, project: projects[1])
13
      create(:jira_service, :jira_cloud_service, project: projects[2])
14 15
      create(:jira_service, :without_properties_callback, project: projects[3],
             properties: { url: 'https://mysite.atlassian.net' })
16 17 18 19
      create(:prometheus_service, project: projects[1])
      create(:service, project: projects[0], type: 'SlackSlashCommandsService', active: true)
      create(:service, project: projects[1], type: 'SlackService', active: true)
      create(:service, project: projects[2], type: 'SlackService', active: true)
L
Logan King 已提交
20 21
      create(:project_error_tracking_setting, project: projects[0])
      create(:project_error_tracking_setting, project: projects[1], enabled: false)
22 23 24 25 26
      create_list(:issue, 4, project: projects[0])
      create(:zoom_meeting, project: projects[0], issue: projects[0].issues[0], issue_status: :added)
      create_list(:zoom_meeting, 2, project: projects[0], issue: projects[0].issues[1], issue_status: :removed)
      create(:zoom_meeting, project: projects[0], issue: projects[0].issues[2], issue_status: :added)
      create_list(:zoom_meeting, 2, project: projects[0], issue: projects[0].issues[2], issue_status: :removed)
27 28 29 30 31

      # Enabled clusters
      gcp_cluster = create(:cluster_provider_gcp, :created).cluster
      create(:cluster_provider_aws, :created)
      create(:cluster_platform_kubernetes)
32
      create(:cluster, :group)
33 34 35

      # Disabled clusters
      create(:cluster, :disabled)
36 37
      create(:cluster, :group, :disabled)
      create(:cluster, :group, :disabled)
38 39

      # Applications
40 41
      create(:clusters_applications_helm, :installed, cluster: gcp_cluster)
      create(:clusters_applications_ingress, :installed, cluster: gcp_cluster)
J
João Cunha 已提交
42
      create(:clusters_applications_cert_manager, :installed, cluster: gcp_cluster)
43 44
      create(:clusters_applications_prometheus, :installed, cluster: gcp_cluster)
      create(:clusters_applications_runner, :installed, cluster: gcp_cluster)
45
      create(:clusters_applications_knative, :installed, cluster: gcp_cluster)
46
      create(:clusters_applications_elastic_stack, :installed, cluster: gcp_cluster)
47 48

      ProjectFeature.first.update_attribute('repository_access_level', 0)
49 50
    end

51
    subject { described_class.data }
52

53
    it 'gathers usage data', :aggregate_failures do
J
James Lopez 已提交
54
      expect(subject.keys).to include(*%i(
55 56 57
        active_user_count
        counts
        recorded_at
S
Sean McGivern 已提交
58
        edition
59
        version
60
        installation_type
61
        uuid
S
Sean McGivern 已提交
62
        hostname
63 64 65 66 67 68 69
        mattermost_enabled
        signup_enabled
        ldap_enabled
        gravatar_enabled
        omniauth_enabled
        reply_by_email_enabled
        container_registry_enabled
70
        dependency_proxy_enabled
71
        gitlab_shared_runners_enabled
72 73
        gitlab_pages
        git
74
        gitaly
75
        database
76
        avg_cycle_analytics
R
Ryan Cobb 已提交
77 78
        influxdb_metrics_enabled
        prometheus_metrics_enabled
79
      ))
80 81
    end

82
    it 'gathers usage counts' do
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
      smau_keys = %i(
        snippet_create
        snippet_update
        snippet_comment
        merge_request_comment
        merge_request_create
        commit_comment
        wiki_pages_create
        wiki_pages_update
        wiki_pages_delete
        web_ide_views
        web_ide_commits
        web_ide_merge_requests
        navbar_searches
        cycle_analytics_views
        productivity_analytics_views
        source_code_pushes
      )

102
      expected_keys = %i(
103
        assignee_lists
104 105
        boards
        ci_builds
106 107
        ci_internal_pipelines
        ci_external_pipelines
108 109
        ci_pipeline_config_auto_devops
        ci_pipeline_config_repository
110 111
        ci_runners
        ci_triggers
112
        ci_pipeline_schedules
113 114
        auto_devops_enabled
        auto_devops_disabled
115 116
        deploy_keys
        deployments
117 118
        successful_deployments
        failed_deployments
119
        environments
120 121
        clusters
        clusters_enabled
122 123
        project_clusters_enabled
        group_clusters_enabled
124
        clusters_disabled
125 126
        project_clusters_disabled
        group_clusters_disabled
127
        clusters_platforms_eks
128 129 130 131
        clusters_platforms_gke
        clusters_platforms_user
        clusters_applications_helm
        clusters_applications_ingress
A
Amit Rathi 已提交
132
        clusters_applications_cert_managers
133 134
        clusters_applications_prometheus
        clusters_applications_runner
135
        clusters_applications_knative
136
        clusters_applications_elastic_stack
137
        in_review_folder
138 139
        groups
        issues
140 141
        issues_with_associated_zoom_link
        issues_using_zoom_quick_actions
142
        keys
143
        label_lists
144 145 146
        labels
        lfs_objects
        merge_requests
147
        milestone_lists
148 149
        milestones
        notes
150
        pool_repositories
151
        projects
152
        projects_imported_from_github
153
        projects_jira_active
154 155
        projects_jira_server_active
        projects_jira_cloud_active
156 157
        projects_slack_notifications_active
        projects_slack_slash_active
158
        projects_prometheus_active
159
        projects_with_repositories_enabled
L
Logan King 已提交
160
        projects_with_error_tracking_enabled
161 162 163
        pages_domains
        protected_branches
        releases
164
        remote_mirrors
165
        snippets
166
        suggestions
167
        todos
R
Robert Speicher 已提交
168
        uploads
169
        web_hooks
170
      ).push(*smau_keys)
171 172 173 174

      count_data = subject[:counts]

      expect(count_data[:boards]).to eq(1)
175
      expect(count_data[:projects]).to eq(4)
176
      expect(count_data.values_at(*smau_keys)).to all(be_an(Integer))
177 178
      expect(count_data.keys).to include(*expected_keys)
      expect(expected_keys - count_data.keys).to be_empty
179
    end
180

181
    it 'gathers projects data correctly', :aggregate_failures do
182 183
      count_data = subject[:counts]

184
      expect(count_data[:projects]).to eq(4)
185
      expect(count_data[:projects_prometheus_active]).to eq(1)
186
      expect(count_data[:projects_jira_active]).to eq(4)
187
      expect(count_data[:projects_jira_server_active]).to eq(2)
188
      expect(count_data[:projects_jira_cloud_active]).to eq(2)
189 190
      expect(count_data[:projects_slack_notifications_active]).to eq(2)
      expect(count_data[:projects_slack_slash_active]).to eq(1)
191
      expect(count_data[:projects_with_repositories_enabled]).to eq(3)
L
Logan King 已提交
192
      expect(count_data[:projects_with_error_tracking_enabled]).to eq(1)
193 194
      expect(count_data[:issues_with_associated_zoom_link]).to eq(2)
      expect(count_data[:issues_using_zoom_quick_actions]).to eq(3)
195

196 197
      expect(count_data[:clusters_enabled]).to eq(4)
      expect(count_data[:project_clusters_enabled]).to eq(3)
198 199 200 201 202
      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)
203
      expect(count_data[:clusters_platforms_eks]).to eq(1)
204 205 206 207
      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)
A
Amit Rathi 已提交
208
      expect(count_data[:clusters_applications_cert_managers]).to eq(1)
209 210
      expect(count_data[:clusters_applications_prometheus]).to eq(1)
      expect(count_data[:clusters_applications_runner]).to eq(1)
211
      expect(count_data[:clusters_applications_knative]).to eq(1)
212
      expect(count_data[:clusters_applications_elastic_stack]).to eq(1)
213
    end
214 215 216 217 218 219 220

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

      expect { subject }.not_to raise_error
    end
221 222
  end

A
Alex Kalderimis 已提交
223 224 225 226 227 228 229 230
  describe '#usage_data_counters' do
    subject { described_class.usage_data_counters }

    it { is_expected.to all(respond_to :totals) }

    describe 'the results of calling #totals on all objects in the array' do
      subject { described_class.usage_data_counters.map(&:totals) }

231 232
      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))) }
A
Alex Kalderimis 已提交
233 234 235 236 237 238 239 240 241
    end

    it 'does not have any conflicts' do
      all_keys = subject.flat_map { |counter| counter.totals.keys }

      expect(all_keys.size).to eq all_keys.to_set.size
    end
  end

242 243 244
  describe '#features_usage_data_ce' do
    subject { described_class.features_usage_data_ce }

245
    it 'gathers feature usage data', :aggregate_failures do
246 247 248 249
      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?)
250
      expect(subject[:omniauth_enabled]).to eq(Gitlab::Auth.omniauth_enabled?)
251 252
      expect(subject[:reply_by_email_enabled]).to eq(Gitlab::IncomingEmail.enabled?)
      expect(subject[:container_registry_enabled]).to eq(Gitlab.config.registry.enabled)
253
      expect(subject[:dependency_proxy_enabled]).to eq(Gitlab.config.dependency_proxy.enabled)
254
      expect(subject[:gitlab_shared_runners_enabled]).to eq(Gitlab.config.gitlab_ci.shared_runners_enabled)
255 256 257 258 259 260
    end
  end

  describe '#components_usage_data' do
    subject { described_class.components_usage_data }

261
    it 'gathers components usage data', :aggregate_failures do
262 263 264 265 266
      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)
267 268 269 270
      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)
271 272 273
    end
  end

274
  describe '#license_usage_data' do
275
    subject { described_class.license_usage_data }
276

277
    it 'gathers license data', :aggregate_failures do
278
      expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
279
      expect(subject[:version]).to eq(Gitlab::VERSION)
280
      expect(subject[:installation_type]).to eq('gitlab-development-kit')
281 282 283 284
      expect(subject[:active_user_count]).to eq(User.active.count)
      expect(subject[:recorded_at]).to be_a(Time)
    end
  end
285 286 287 288 289 290 291 292 293 294

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

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

      expect(described_class.count(relation)).to eq(1)
    end

295 296 297 298 299 300
    it 'returns the count for count_by when provided' do
      allow(relation).to receive(:count).with(:creator_id).and_return(2)

      expect(described_class.count(relation, count_by: :creator_id)).to eq(2)
    end

301 302 303 304 305 306
    it 'returns the fallback value when counting fails' do
      allow(relation).to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))

      expect(described_class.count(relation, fallback: 15)).to eq(15)
    end
  end
307 308

  describe '#approximate_counts' do
309
    it 'gets approximate counts for selected models', :aggregate_failures do
310 311 312
      create(:label)

      expect(Gitlab::Database::Count).to receive(:approximate_counts)
313
                                           .with(described_class::APPROXIMATE_COUNT_MODELS).once.and_call_original
314 315 316 317 318 319 320

      counts = described_class.approximate_counts.values

      expect(counts.count).to eq(described_class::APPROXIMATE_COUNT_MODELS.count)
      expect(counts.any? { |count| count < 0 }).to be_falsey
    end

321
    it 'returns default values if counts can not be retrieved', :aggregate_failures do
322 323 324 325
      described_class::APPROXIMATE_COUNT_MODELS.map do |model|
        model.name.underscore.pluralize.to_sym
      end

326
      expect(Gitlab::Database::Count).to receive(:approximate_counts).and_return({})
327 328 329
      expect(described_class.approximate_counts.values.uniq).to eq([-1])
    end
  end
330
end