diff options
Diffstat (limited to 'spec/lib/gitlab/usage/metrics')
11 files changed, 197 insertions, 70 deletions
diff --git a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb index 0fb3a69df05..8e02f4f562c 100644 --- a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb +++ b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb @@ -25,34 +25,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi end context 'aggregated_metrics_data' do - shared_examples 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature' do - before do - allow_next_instance_of(described_class) do |instance| - allow(instance).to receive(:aggregated_metrics).and_return(aggregated_metrics) - end - end - - context 'with disabled database_sourced_aggregated_metrics feature flag' do - before do - stub_feature_flags(database_sourced_aggregated_metrics: false) - end - - let(:aggregated_metrics) do - [ - aggregated_metric(name: "gmau_2", source: "database", time_frame: time_frame) - ] - end - - it 'skips database sourced metrics', :aggregate_failures do - results = {} - params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at } - - expect(sources::PostgresHll).not_to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3])) - expect(aggregated_metrics_data).to eq(results) - end - end - end - shared_examples 'aggregated_metrics_data' do context 'no aggregated metric is defined' do it 'returns empty hash' do @@ -237,7 +209,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi let(:time_frame) { ['all'] } it_behaves_like 'database_sourced_aggregated_metrics' - it_behaves_like 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature' context 'redis sourced aggregated metrics' do let(:aggregated_metrics) { [aggregated_metric(name: 'gmau_1', time_frame: time_frame)] } @@ -278,7 +249,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi it_behaves_like 'database_sourced_aggregated_metrics' it_behaves_like 'redis_sourced_aggregated_metrics' - it_behaves_like 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature' end describe '.aggregated_metrics_monthly_data' do @@ -289,7 +259,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi it_behaves_like 'database_sourced_aggregated_metrics' it_behaves_like 'redis_sourced_aggregated_metrics' - it_behaves_like 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature' end end end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb index 52c1ccdcd47..6f03c5a9ae3 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb @@ -5,5 +5,8 @@ require 'spec_helper' RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountBoardsMetric do let_it_be(:board) { create(:board) } - it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1 + let(:expected_value) { 1 } + let(:expected_query) { 'SELECT COUNT("boards"."id") FROM "boards"' } + + it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' } end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb index c3b59904f41..183aa03dd8a 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb @@ -5,5 +5,8 @@ require 'spec_helper' RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountIssuesMetric do let_it_be(:issue) { create(:issue) } - it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1 + let(:expected_value) { 1 } + let(:expected_query) { 'SELECT COUNT("issues"."id") FROM "issues"' } + + it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' } end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb index 9f4686ab6cd..3fb4c3a4e3f 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb @@ -8,10 +8,18 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersCreatingIssue let_it_be(:old_issue) { create(:issue, author: author, created_at: 2.months.ago) } context 'with all time frame' do - it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1 + let(:expected_value) { 1 } + let(:expected_query) { 'SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"' } + + it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' } end context 'for 28d time frame' do - it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'database' }, 1 + let(:expected_value) { 1 } + let(:start) { 30.days.ago.to_s(:db) } + let(:finish) { 2.days.ago.to_s(:db) } + let(:expected_query) { "SELECT COUNT(DISTINCT \"issues\".\"author_id\") FROM \"issues\" WHERE \"issues\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'" } + + it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d' } end end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb deleted file mode 100644 index 7adba825a13..00000000000 --- a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQuickActionMetric, :clean_gitlab_redis_shared_state do - before do - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago) - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago) - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.weeks.ago) - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago) - end - - it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'redis_hll' }, 2 - it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', data_source: 'redis_hll' }, 1 -end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb index 83e07200025..95e159a5bf7 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb @@ -3,5 +3,7 @@ require 'spec_helper' RSpec.describe Gitlab::Usage::Metrics::Instrumentations::HostnameMetric do - it_behaves_like 'a correct instrumented metric value', { time_frame: 'none', data_source: 'ruby' }, Gitlab.config.gitlab.host + let(:expected_value) { Gitlab.config.gitlab.host } + + it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' } end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb new file mode 100644 index 00000000000..347a2c779cb --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::RedisHLLMetric, :clean_gitlab_redis_shared_state do + before do + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.weeks.ago) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago) + end + + context 'for 28d' do + let(:expected_value) { 2 } + + it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', options: { events: ['i_quickactions_approve'] } } + end + + context 'for 7d' do + let(:expected_value) { 1 } + + it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', options: { events: ['i_quickactions_approve'] } } + end + + it 'raise exception if events options is not present' do + expect { described_class.new(time_frame: '28d') }.to raise_error(ArgumentError) + end +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb index 212dd3dc851..33e7e85611d 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb @@ -3,5 +3,7 @@ require 'spec_helper' RSpec.describe Gitlab::Usage::Metrics::Instrumentations::UuidMetric do - it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' }, Gitlab::CurrentSettings.uuid + let(:expected_value) { Gitlab::CurrentSettings.uuid } + + it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' } end diff --git a/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb b/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb new file mode 100644 index 00000000000..6955fbcaf5a --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::NameSuggestion do + describe '#for' do + shared_examples 'name suggestion' do + it 'return correct name' do + expect(described_class.for(operation, relation: relation, column: column)).to match name_suggestion + end + end + + context 'for count with nil column' do + it_behaves_like 'name suggestion' do + let(:operation) { :count } + let(:relation) { Board } + let(:column) { nil } + let(:name_suggestion) { /count_boards/ } + end + end + + context 'for count with column :id' do + it_behaves_like 'name suggestion' do + let(:operation) { :count } + let(:relation) { Board } + let(:column) { :id } + let(:name_suggestion) { /count_boards/ } + end + end + + context 'for count distinct with column defined metrics' do + it_behaves_like 'name suggestion' do + let(:operation) { :distinct_count } + let(:relation) { ZoomMeeting } + let(:column) { :issue_id } + let(:name_suggestion) { /count_distinct_issue_id_from_zoom_meetings/ } + end + end + + context 'joined relations' do + context 'counted attribute comes from source relation' do + it_behaves_like 'name suggestion' do + # corresponding metric is collected with count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: issue_minimum_id, finish: issue_maximum_id) + let(:operation) { :count } + let(:relation) { Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot) } + let(:column) { nil } + let(:name_suggestion) { /count_<adjective describing\: '\(issues\.author_id != \d+\)'>_issues_<with>_alert_management_alerts/ } + end + end + end + + context 'strips off time period constraint' do + it_behaves_like 'name suggestion' do + # corresponding metric is collected with distinct_count(::Clusters::Cluster.aws_installed.enabled.where(time_period), :user_id) + let(:operation) { :distinct_count } + let(:relation) { ::Clusters::Cluster.aws_installed.enabled.where(created_at: 30.days.ago..2.days.ago ) } + let(:column) { :user_id } + let(:constraints) { /<adjective describing\: '\(clusters.provider_type = \d+ AND \(cluster_providers_aws\.status IN \(\d+\)\) AND clusters\.enabled = TRUE\)'>/ } + let(:name_suggestion) { /count_distinct_user_id_from_#{constraints}_clusters_<with>_#{constraints}_cluster_providers_aws/ } + end + end + + context 'for sum metrics' do + it_behaves_like 'name suggestion' do + # corresponding metric is collected with sum(JiraImportState.finished, :imported_issues_count) + let(:key_path) { 'counts.jira_imports_total_imported_issues_count' } + let(:operation) { :sum } + let(:relation) { JiraImportState.finished } + let(:column) { :imported_issues_count} + let(:name_suggestion) { /sum_imported_issues_count_from_<adjective describing\: '\(jira_imports\.status = \d+\)'>_jira_imports/ } + end + end + + context 'for redis metrics' do + it_behaves_like 'name suggestion' do + # corresponding metric is collected with redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) } + let(:operation) { :redis } + let(:column) { nil } + let(:relation) { nil } + let(:name_suggestion) { /<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>/ } + end + end + + context 'for alt_usage_data metrics' do + it_behaves_like 'name suggestion' do + # corresponding metric is collected with alt_usage_data(fallback: nil) { operating_system } + let(:operation) { :alt } + let(:column) { nil } + let(:relation) { nil } + let(:name_suggestion) { /<please fill metric name>/ } + end + end + end +end diff --git a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb index 34b073b4729..b4ab9d4861b 100644 --- a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb +++ b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb @@ -33,24 +33,6 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do end context 'joined relations' do - context 'counted attribute comes from joined relation' do - it_behaves_like 'name suggestion' do - # corresponding metric is collected with: - # distinct_count( - # ::Clusters::Applications::Ingress.modsecurity_enabled.logging - # .joins(cluster: :deployments) - # .merge(::Clusters::Cluster.enabled) - # .merge(Deployment.success), - # ::Deployment.arel_table[:environment_id] - # ) - let(:key_path) { 'counts.ingress_modsecurity_logging' } - let(:name_suggestion) do - constrains = /'\(clusters_applications_ingress\.modsecurity_enabled = TRUE AND clusters_applications_ingress\.modsecurity_mode = \d+ AND clusters.enabled = TRUE AND deployments.status = \d+\)'/ - /count_distinct_environment_id_from_<adjective describing\: #{constrains}>_deployments_<with>_<adjective describing\: #{constrains}>_clusters_<having>_<adjective describing\: #{constrains}>_clusters_applications_ingress/ - end - end - end - context 'counted attribute comes from source relation' do it_behaves_like 'name suggestion' do # corresponding metric is collected with count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: issue_minimum_id, finish: issue_maximum_id) diff --git a/spec/lib/gitlab/usage/metrics/query_spec.rb b/spec/lib/gitlab/usage/metrics/query_spec.rb new file mode 100644 index 00000000000..60c8d044a64 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/query_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Query do + describe '.count' do + it 'returns the raw SQL' do + expect(described_class.for(:count, User)).to eq('SELECT COUNT("users"."id") FROM "users"') + end + + it 'does not mix a nil column with keyword arguments' do + expect(described_class.for(:count, User, nil)).to eq('SELECT COUNT("users"."id") FROM "users"') + end + end + + describe '.distinct_count' do + it 'returns the raw SQL' do + expect(described_class.for(:distinct_count, Issue, :author_id)).to eq('SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"') + end + + it 'does not mix a nil column with keyword arguments' do + expect(described_class.for(:distinct_count, Issue, nil)).to eq('SELECT COUNT(DISTINCT "issues"."id") FROM "issues"') + end + end + + describe '.sum' do + it 'returns the raw SQL' do + expect(described_class.for(:sum, Issue, :weight)).to eq('SELECT SUM("issues"."weight") FROM "issues"') + end + end + + describe 'estimate_batch_distinct_count' do + it 'returns the raw SQL' do + expect(described_class.for(:estimate_batch_distinct_count, Issue, :author_id)).to eq('SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"') + end + end + + describe '.histogram' do + it 'returns the histogram sql' do + expect(described_class.for(:histogram, AlertManagement::HttpIntegration.active, + :project_id, buckets: 1..2, bucket_size: 101)) + .to match(/^WITH "count_cte" AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}/) + end + end + + describe 'other' do + it 'raise ArgumentError error' do + expect { described_class.for(:other, nil) }.to raise_error(ArgumentError, 'other operation not supported') + end + end +end |