diff options
Diffstat (limited to 'spec/lib/gitlab/usage_data')
-rw-r--r-- | spec/lib/gitlab/usage_data/topology_spec.rb | 110 |
1 files changed, 77 insertions, 33 deletions
diff --git a/spec/lib/gitlab/usage_data/topology_spec.rb b/spec/lib/gitlab/usage_data/topology_spec.rb index 7f4a25297e6..b8462e0290c 100644 --- a/spec/lib/gitlab/usage_data/topology_spec.rb +++ b/spec/lib/gitlab/usage_data/topology_spec.rb @@ -6,23 +6,23 @@ RSpec.describe Gitlab::UsageData::Topology do include UsageDataHelpers describe '#topology_usage_data' do - subject { described_class.new.topology_usage_data } + subject { topology.topology_usage_data } + + let(:topology) { described_class.new } + let(:prometheus_client) { Gitlab::PrometheusClient.new('http://localhost:9090') } + let(:fallback) { {} } before do # this pins down time shifts when benchmarking durations allow(Process).to receive(:clock_gettime).and_return(0) end - context 'when embedded Prometheus server is enabled' do - before do - expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(true) - expect(Gitlab::Prometheus::Internal).to receive(:uri).and_return('http://prom:9090') - end - + shared_examples 'query topology data from Prometheus' do context 'tracking node metrics' do it 'contains node level metrics for each instance' do - expect_prometheus_api_to( + expect_prometheus_client_to( receive_app_request_volume_query, + receive_query_apdex_ratio_query, receive_node_memory_query, receive_node_memory_utilization_query, receive_node_cpu_count_query, @@ -38,6 +38,7 @@ RSpec.describe Gitlab::UsageData::Topology do expect(subject[:topology]).to eq({ duration_s: 0, application_requests_per_hour: 36, + query_apdex_weekly_average: 0.996, failures: [], nodes: [ { @@ -105,8 +106,9 @@ RSpec.describe Gitlab::UsageData::Topology do context 'and some node memory metrics are missing' do it 'removes the respective entries and includes the failures' do - expect_prometheus_api_to( + expect_prometheus_client_to( receive_app_request_volume_query(result: []), + receive_query_apdex_ratio_query(result: []), receive_node_memory_query(result: []), receive_node_memory_utilization_query(result: []), receive_node_cpu_count_query, @@ -123,6 +125,7 @@ RSpec.describe Gitlab::UsageData::Topology do duration_s: 0, failures: [ { 'app_requests' => 'empty_result' }, + { 'query_apdex' => 'empty_result' }, { 'node_memory' => 'empty_result' }, { 'node_memory_utilization' => 'empty_result' }, { 'service_rss' => 'empty_result' }, @@ -243,8 +246,9 @@ RSpec.describe Gitlab::UsageData::Topology do end it 'normalizes equivalent instance values and maps them to the same node' do - expect_prometheus_api_to( + expect_prometheus_client_to( receive_app_request_volume_query(result: []), + receive_query_apdex_ratio_query(result: []), receive_node_memory_query(result: node_memory_response), receive_node_memory_utilization_query(result: node_memory_utilization_response), receive_node_cpu_count_query(result: []), @@ -261,6 +265,7 @@ RSpec.describe Gitlab::UsageData::Topology do duration_s: 0, failures: [ { 'app_requests' => 'empty_result' }, + { 'query_apdex' => 'empty_result' }, { 'node_cpus' => 'empty_result' }, { 'node_cpu_utilization' => 'empty_result' }, { 'service_uss' => 'empty_result' }, @@ -307,8 +312,9 @@ RSpec.describe Gitlab::UsageData::Topology do context 'and node metrics are missing but service metrics exist' do it 'still reports service metrics' do - expect_prometheus_api_to( + expect_prometheus_client_to( receive_app_request_volume_query(result: []), + receive_query_apdex_ratio_query(result: []), receive_node_memory_query(result: []), receive_node_memory_utilization_query(result: []), receive_node_cpu_count_query(result: []), @@ -325,6 +331,7 @@ RSpec.describe Gitlab::UsageData::Topology do duration_s: 0, failures: [ { 'app_requests' => 'empty_result' }, + { 'query_apdex' => 'empty_result' }, { 'node_memory' => 'empty_result' }, { 'node_memory_utilization' => 'empty_result' }, { 'node_cpus' => 'empty_result' }, @@ -380,8 +387,9 @@ RSpec.describe Gitlab::UsageData::Topology do end it 'filters out unknown service data and reports the unknown services as a failure' do - expect_prometheus_api_to( + expect_prometheus_client_to( receive_app_request_volume_query(result: []), + receive_query_apdex_ratio_query(result: []), receive_node_memory_query(result: []), receive_node_memory_utilization_query(result: []), receive_node_cpu_count_query(result: []), @@ -404,24 +412,25 @@ RSpec.describe Gitlab::UsageData::Topology do context 'and an error is raised when querying Prometheus' do context 'without timeout failures' do it 'returns empty result and executes subsequent queries as usual' do - expect_prometheus_api_to receive(:query) - .at_least(:once) - .and_raise(Gitlab::PrometheusClient::ConnectionError) + expect_prometheus_client_to( + receive(:query).at_least(:once).and_raise(Gitlab::PrometheusClient::UnexpectedResponseError) + ) expect(subject[:topology]).to eq({ duration_s: 0, failures: [ - { 'app_requests' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'node_memory' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'node_memory_utilization' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'node_cpus' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'node_cpu_utilization' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'node_uname_info' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'service_rss' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'service_uss' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'service_pss' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'service_process_count' => 'Gitlab::PrometheusClient::ConnectionError' }, - { 'service_workers' => 'Gitlab::PrometheusClient::ConnectionError' } + { 'app_requests' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'query_apdex' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'node_memory' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'node_memory_utilization' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'node_cpus' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'node_cpu_utilization' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'node_uname_info' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'service_rss' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'service_uss' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'service_pss' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'service_process_count' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }, + { 'service_workers' => 'Gitlab::PrometheusClient::UnexpectedResponseError' } ], nodes: [] }) @@ -435,13 +444,15 @@ RSpec.describe Gitlab::UsageData::Topology do with_them do it 'returns empty result and cancelled subsequent queries' do - expect_prometheus_api_to receive(:query) - .and_raise(exception) + expect_prometheus_client_to( + receive(:query).and_raise(exception) + ) expect(subject[:topology]).to eq({ duration_s: 0, failures: [ { 'app_requests' => exception.to_s }, + { 'query_apdex' => 'timeout_cancellation' }, { 'node_memory' => 'timeout_cancellation' }, { 'node_memory_utilization' => 'timeout_cancellation' }, { 'node_cpus' => 'timeout_cancellation' }, @@ -461,10 +472,8 @@ RSpec.describe Gitlab::UsageData::Topology do end end - context 'when embedded Prometheus server is disabled' do - it 'returns empty result with no failures' do - expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(false) - + shared_examples 'returns empty result with no failures' do + it do expect(subject[:topology]).to eq({ duration_s: 0, failures: [] @@ -472,9 +481,25 @@ RSpec.describe Gitlab::UsageData::Topology do end end + context 'can reach a ready Prometheus client' do + before do + expect(topology).to receive(:with_prometheus_client).and_yield(prometheus_client) + end + + it_behaves_like 'query topology data from Prometheus' + end + + context 'can not reach a ready Prometheus client' do + before do + expect(topology).to receive(:with_prometheus_client).and_return(fallback) + end + + it_behaves_like 'returns empty result with no failures' + end + context 'when top-level function raises error' do it 'returns empty result with generic failure' do - allow(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_raise(RuntimeError) + expect(topology).to receive(:with_prometheus_client).and_raise(RuntimeError) expect(subject[:topology]).to eq({ duration_s: 0, @@ -486,6 +511,14 @@ RSpec.describe Gitlab::UsageData::Topology do end end + def receive_ready_check_query(result: nil, raise_error: nil) + if raise_error.nil? + receive(:ready?).and_return(result.nil? ? true : result) + else + receive(:ready?).and_raise(raise_error) + end + end + def receive_app_request_volume_query(result: nil) receive(:query) .with(/gitlab_usage_ping:ops:rate/) @@ -497,6 +530,17 @@ RSpec.describe Gitlab::UsageData::Topology do ]) end + def receive_query_apdex_ratio_query(result: nil) + receive(:query) + .with(/gitlab_usage_ping:sql_duration_apdex:ratio_rate5m/) + .and_return(result || [ + { + 'metric' => {}, + 'value' => [1000, '0.996'] + } + ]) + end + def receive_node_memory_query(result: nil) receive(:query) .with(/node_memory_total_bytes/, an_instance_of(Hash)) |