summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/usage_data/topology_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/usage_data/topology_spec.rb')
-rw-r--r--spec/lib/gitlab/usage_data/topology_spec.rb110
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))