Commit f9caa6a1 authored by Marc Shaw's avatar Marc Shaw

Merge branch 'mwaw/test_service_ping_queries_agains_values_351085' into 'master'

Build a test to compare service ping output with output of the values from SQL generated

See merge request gitlab-org/gitlab!81002
parents 0e697050 79147730
...@@ -41,9 +41,19 @@ module Gitlab ...@@ -41,9 +41,19 @@ module Gitlab
end end
def maximum_id(model, column = nil) def maximum_id(model, column = nil)
# no-op: shadowing super for performance reasons
end end
def minimum_id(model, column = nil) def minimum_id(model, column = nil)
# no-op: shadowing super for performance reasons
end
def alt_usage_data(value = nil, fallback: FALLBACK, &block)
if block_given?
{ alt_usage_data_block: block.to_s }
else
{ alt_usage_data_value: value }
end
end end
def redis_usage_data(counter = nil, &block) def redis_usage_data(counter = nil, &block)
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_caching do RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_caching do
include UsageDataHelpers
let(:usage_data) { { uuid: "1111", counts: { issue: 0 } } } let(:usage_data) { { uuid: "1111", counts: { issue: 0 } } }
context 'when feature merge_service_ping_instrumented_metrics enabled' do context 'when feature merge_service_ping_instrumented_metrics enabled' do
...@@ -121,4 +123,97 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c ...@@ -121,4 +123,97 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c
end end
end end
end end
context 'cross test values against queries' do
# TODO: fix failing metrics https://gitlab.com/gitlab-org/gitlab/-/issues/353559
let(:failing_todo_metrics) do
["counts.labels",
"counts.jira_imports_total_imported_issues_count",
"counts.in_product_marketing_email_create_0_sent",
"counts.in_product_marketing_email_create_0_cta_clicked",
"counts.in_product_marketing_email_create_1_sent",
"counts.in_product_marketing_email_create_1_cta_clicked",
"counts.in_product_marketing_email_create_2_sent",
"counts.in_product_marketing_email_create_2_cta_clicked",
"counts.in_product_marketing_email_verify_0_sent",
"counts.in_product_marketing_email_verify_0_cta_clicked",
"counts.in_product_marketing_email_verify_1_sent",
"counts.in_product_marketing_email_verify_1_cta_clicked",
"counts.in_product_marketing_email_verify_2_sent",
"counts.in_product_marketing_email_verify_2_cta_clicked",
"counts.in_product_marketing_email_trial_0_sent",
"counts.in_product_marketing_email_trial_0_cta_clicked",
"counts.in_product_marketing_email_trial_1_sent",
"counts.in_product_marketing_email_trial_1_cta_clicked",
"counts.in_product_marketing_email_trial_2_sent",
"counts.in_product_marketing_email_trial_2_cta_clicked",
"counts.in_product_marketing_email_team_0_sent",
"counts.in_product_marketing_email_team_0_cta_clicked",
"counts.in_product_marketing_email_team_1_sent",
"counts.in_product_marketing_email_team_1_cta_clicked",
"counts.in_product_marketing_email_team_2_sent",
"counts.in_product_marketing_email_team_2_cta_clicked",
"counts.in_product_marketing_email_experience_0_sent",
"counts.in_product_marketing_email_team_short_0_sent",
"counts.in_product_marketing_email_team_short_0_cta_clicked",
"counts.in_product_marketing_email_trial_short_0_sent",
"counts.in_product_marketing_email_trial_short_0_cta_clicked",
"counts.in_product_marketing_email_admin_verify_0_sent",
"counts.in_product_marketing_email_admin_verify_0_cta_clicked",
"counts.ldap_users",
"usage_activity_by_stage.create.projects_with_sectional_code_owner_rules",
"usage_activity_by_stage.monitor.clusters_integrations_prometheus",
"usage_activity_by_stage.monitor.projects_with_enabled_alert_integrations_histogram",
"usage_activity_by_stage_monthly.create.projects_with_sectional_code_owner_rules",
"usage_activity_by_stage_monthly.monitor.clusters_integrations_prometheus"]
end
def fetch_value_by_query(query)
# Because test cases are run inside a transaction, if any query raise and error all queries that follows
# it are automatically canceled by PostgreSQL, to avoid that problem, and to provide exhaustive information
# about every metric, queries are wrapped explicitly in sub transactions.
ApplicationRecord.transaction do
ApplicationRecord.connection.execute(query)&.first&.values&.first
end
rescue ActiveRecord::StatementInvalid => e
e.message
end
def build_payload_from_queries(payload, accumulator = [], key_path = [])
payload.each do |key, value|
if value.is_a?(Hash)
build_payload_from_queries(value, accumulator, key_path.dup << key)
elsif value.is_a?(String) && /SELECT .* FROM.*/ =~ value
accumulator << [key_path.dup << key, value, fetch_value_by_query(value)]
end
end
accumulator
end
before do
stub_usage_data_connections
stub_object_store_settings
stub_prometheus_queries
memoized_constatns = Gitlab::UsageData::CE_MEMOIZED_VALUES
memoized_constatns += Gitlab::UsageData::EE_MEMOIZED_VALUES if defined? Gitlab::UsageData::EE_MEMOIZED_VALUES
memoized_constatns.each { |v| Gitlab::UsageData.clear_memoization(v) }
stub_database_flavor_check('Cloud SQL for PostgreSQL')
end
let(:service_ping_payload) { described_class.for(output: :all_metrics_values) }
let(:metrics_queries_with_values) { build_payload_from_queries(described_class.for(output: :metrics_queries)) }
it 'generates queries that match collected data', :aggregate_failures do
message = "Expected %{query} result to match %{value} for %{key_path} metric"
metrics_queries_with_values.each do |key_path, query, value|
next if failing_todo_metrics.include?(key_path.join('.'))
expect(value).to(
eq(service_ping_payload.dig(*key_path)),
message % { query: query, value: (value || 'NULL'), key_path: key_path.join('.') }
)
end
end
end
end end
...@@ -45,6 +45,19 @@ RSpec.describe Gitlab::UsageDataQueries do ...@@ -45,6 +45,19 @@ RSpec.describe Gitlab::UsageDataQueries do
end end
end end
describe '.alt_usage_data' do
subject(:alt_usage_data) { described_class.alt_usage_data { 42 } }
it 'returns value when used with value' do
expect(described_class.alt_usage_data(1))
.to eq(alt_usage_data_value: 1)
end
it 'returns a stringified block for alt_usage_data with a block' do
expect(alt_usage_data[:alt_usage_data_block]).to start_with('#<Proc:')
end
end
describe '.sum' do describe '.sum' do
it 'returns the raw SQL' do it 'returns the raw SQL' do
expect(described_class.sum(Issue, :weight)).to eq('SELECT SUM("issues"."weight") FROM "issues"') expect(described_class.sum(Issue, :weight)).to eq('SELECT SUM("issues"."weight") FROM "issues"')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment