Commit 89d463d8 authored by Piotr Skorupa's avatar Piotr Skorupa

Add fixture guard spec for SQL metric queries

This commit adds a guard spec that compares SQL metric queries to a
fixture file in order to catch any arbitrary changes to the queries.

The fixture file can be regenerated using a rake task.

Timestamps are freezed for and a stable set of Devise omniauth providers
is used to make queries that rely on them deterministic and not change
every time the fixture file is regenerated.
parent 888a0346
......@@ -26,4 +26,65 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c
end
end
end
# The fixture for this spec is generated automatically by
# RAILS_ENV=test bin/rake gitlab:usage_data:generate_sql_metrics_fixture
#
# Do not edit it manually!
describe 'guard SQL queries against arbitrary changes' do
# These metrics have SQL queries that rely on particular record IDs in
# the database, or are otherwise unreliable.
let(:ignored_metric_key_paths) do
%w(
counts.alert_bot_incident_issues
counts.issues_created_gitlab_alerts
counts.issues_created_manually_from_alerts
counts.service_desk_issues
counts_monthly.aggregated_metrics.xmau_plan
counts_monthly.aggregated_metrics.xmau_project_management
counts_monthly.aggregated_metrics.users_work_items
counts_weekly.aggregated_metrics.xmau_plan
counts_weekly.aggregated_metrics.xmau_project_management
counts_weekly.aggregated_metrics.users_work_items
topology.duration_s
usage_activity_by_stage_monthly.plan.service_desk_issues
usage_activity_by_stage.plan.service_desk_issues
uuid
).freeze
end
let(:stored_queries_fixture) do
fixture_file('lib/gitlab/usage/sql_metrics_queries.json')
end
let(:stored_queries_hash) do
Gitlab::Json.parse(stored_queries_fixture).with_indifferent_access
end
before do
stub_usage_data_connections
stub_object_store_settings
stub_prometheus_queries
remove_ignored_metrics!(stored_queries_hash)
allow(License).to receive(:current).and_return(nil)
end
it 'does not change SQL metric queries' do
report = Timecop.freeze(2021, 1, 1) do
described_class.for(output: :metrics_queries).with_indifferent_access
end
remove_ignored_metrics!(report)
expect(report).to eq(stored_queries_hash)
end
def remove_ignored_metrics!(hash)
ignored_metric_key_paths.each do |key_path|
*keys, last_key = key_path.split('.')
keys.inject(hash, :fetch)[last_key] = nil
end
end
end
end
......@@ -50,7 +50,7 @@ module Gitlab
def alt_usage_data(value = nil, fallback: FALLBACK, &block)
if block_given?
{ alt_usage_data_block: block.to_s }
{ alt_usage_data_block: "non-SQL usage data block" }
else
{ alt_usage_data_value: value }
end
......@@ -58,9 +58,9 @@ module Gitlab
def redis_usage_data(counter = nil, &block)
if block_given?
{ redis_usage_data_block: block.to_s }
{ redis_usage_data_block: "non-SQL usage data block" }
elsif counter.present?
{ redis_usage_data_counter: counter }
{ redis_usage_data_counter: counter.to_s }
end
end
......@@ -74,6 +74,11 @@ module Gitlab
def epics_deepest_relationship_level
{ epics_deepest_relationship_level: 0 }
end
# Do not include Devise omniauth providers for consistency between local and CI-run specs
def auth_providers
AuthenticationEvent::STATIC_PROVIDERS
end
end
end
end
......@@ -51,6 +51,15 @@ namespace :gitlab do
File.write(Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH, banner + YAML.dump(all_includes).gsub(/ *$/m, ''))
end
desc 'GitLab | UsageDataMetrics | Generate raw SQL metrics queries fixture for RSpec'
task generate_sql_metrics_fixture: :environment do
queries = Timecop.freeze(2021, 1, 1) do
Gitlab::Usage::ServicePingReport.for(output: :metrics_queries)
end
File.write('spec/fixtures/lib/gitlab/usage/sql_metrics_queries.json', Gitlab::Json.pretty_generate(queries))
end
def ci_template_includes_hash(source, template_directory = nil)
Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_templates("lib/gitlab/ci/templates/#{template_directory}").map do |template|
expanded_template_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.expand_template_name("#{template_directory}/#{template}")
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -34,14 +34,14 @@ RSpec.describe Gitlab::UsageDataQueries do
describe '.redis_usage_data' do
subject(:redis_usage_data) { described_class.redis_usage_data { 42 } }
it 'returns a class for redis_usage_data with a counter call' do
it 'returns a stringified class for redis_usage_data with a counter call' do
expect(described_class.redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter))
.to eq(redis_usage_data_counter: Gitlab::UsageDataCounters::WikiPageCounter)
.to eq(redis_usage_data_counter: "Gitlab::UsageDataCounters::WikiPageCounter")
end
it 'returns a stringified block for redis_usage_data with a block' do
it 'returns a placeholder string for redis_usage_data with a block' do
is_expected.to include(:redis_usage_data_block)
expect(redis_usage_data[:redis_usage_data_block]).to start_with('#<Proc:')
expect(redis_usage_data[:redis_usage_data_block]).to eq('non-SQL usage data block')
end
end
......@@ -53,8 +53,8 @@ RSpec.describe Gitlab::UsageDataQueries do
.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:')
it 'returns a placeholder string for alt_usage_data with a block' do
expect(alt_usage_data[:alt_usage_data_block]).to eq('non-SQL usage data block')
end
end
......
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