summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb')
-rw-r--r--spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb187
1 files changed, 177 insertions, 10 deletions
diff --git a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
index 9d5c4bdf9e2..5870f9a8f68 100644
--- a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
+++ b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
@@ -36,6 +36,7 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
it 'tracks request count and duration' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
expect(described_class).to receive_message_chain(:http_request_duration_seconds, :observe).with({ method: 'get' }, a_positive_execution_time)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(labels: { feature_category: 'unknown', endpoint_id: 'unknown' }, success: true)
subject.call(env)
end
@@ -70,7 +71,7 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
expect(described_class).not_to receive(:http_health_requests_total)
expect(described_class)
.to receive_message_chain(:http_request_duration_seconds, :observe)
- .with({ method: 'get' }, a_positive_execution_time)
+ .with({ method: 'get' }, a_positive_execution_time)
subject.call(env)
end
@@ -82,9 +83,10 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
context '@app.call returns an error code' do
let(:status) { '500' }
- it 'tracks count but not duration' do
+ it 'tracks count but not duration or apdex' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '500', feature_category: 'unknown')
expect(described_class).not_to receive(:http_request_duration_seconds)
+ expect(Gitlab::Metrics::RailsSlis).not_to receive(:request_apdex)
subject.call(env)
end
@@ -104,20 +106,23 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
expect(described_class).to receive_message_chain(:rack_uncaught_errors_count, :increment)
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: 'undefined', feature_category: 'unknown')
expect(described_class.http_request_duration_seconds).not_to receive(:observe)
+ expect(Gitlab::Metrics::RailsSlis).not_to receive(:request_apdex)
expect { subject.call(env) }.to raise_error(StandardError)
end
end
- context 'feature category header' do
- context 'when a feature category context is present' do
+ context 'application context' do
+ context 'when a context is present' do
before do
- ::Gitlab::ApplicationContext.push(feature_category: 'issue_tracking')
+ ::Gitlab::ApplicationContext.push(feature_category: 'issue_tracking', caller_id: 'IssuesController#show')
end
- it 'adds the feature category to the labels for http_requests_total' do
+ it 'adds the feature category to the labels for required metrics' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'issue_tracking')
expect(described_class).not_to receive(:http_health_requests_total)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex)
+ .to receive(:increment).with(labels: { feature_category: 'issue_tracking', endpoint_id: 'IssuesController#show' }, success: true)
subject.call(env)
end
@@ -127,6 +132,7 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
expect(described_class).to receive_message_chain(:http_health_requests_total, :increment).with(method: 'get', status: '200')
expect(described_class).not_to receive(:http_requests_total)
+ expect(Gitlab::Metrics::RailsSlis).not_to receive(:request_apdex)
subject.call(env)
end
@@ -140,19 +146,180 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
it 'adds the feature category to the labels for http_requests_total' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: 'undefined', feature_category: 'issue_tracking')
+ expect(Gitlab::Metrics::RailsSlis).not_to receive(:request_apdex)
expect { subject.call(env) }.to raise_error(StandardError)
end
end
- context 'when the feature category context is not available' do
- it 'sets the feature category to unknown' do
+ context 'when the context is not available' do
+ it 'sets the required labels to unknown' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
expect(described_class).not_to receive(:http_health_requests_total)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(labels: { feature_category: 'unknown', endpoint_id: 'unknown' }, success: true)
subject.call(env)
end
end
+
+ context 'SLI satisfactory' do
+ where(:request_urgency_name, :duration, :success) do
+ [
+ [:high, 0.1, true],
+ [:high, 0.25, false],
+ [:high, 0.3, false],
+ [:medium, 0.3, true],
+ [:medium, 0.5, false],
+ [:medium, 0.6, false],
+ [:default, 0.6, true],
+ [:default, 1.0, false],
+ [:default, 1.2, false],
+ [:low, 4.5, true],
+ [:low, 5.0, false],
+ [:low, 6, false]
+ ]
+ end
+
+ with_them do
+ context 'Grape API handler having expected duration setup' do
+ let(:api_handler) do
+ request_urgency = request_urgency_name
+ Class.new(::API::Base) do
+ feature_category :hello_world, ['/projects/:id/archive']
+ urgency request_urgency, ['/projects/:id/archive']
+ end
+ end
+
+ let(:endpoint) do
+ route = double(:route, request_method: 'GET', path: '/:version/projects/:id/archive(.:format)')
+ double(:endpoint, route: route,
+ options: { for: api_handler, path: [":id/archive"] },
+ namespace: "/projects")
+ end
+
+ let(:env) { { 'api.endpoint' => endpoint, 'REQUEST_METHOD' => 'GET' } }
+
+ before do
+ ::Gitlab::ApplicationContext.push(feature_category: 'hello_world', caller_id: 'GET /projects/:id/archive')
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100 + duration)
+ end
+
+ it "captures SLI metrics" do
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'hello_world', endpoint_id: 'GET /projects/:id/archive' },
+ success: success
+ )
+ subject.call(env)
+ end
+ end
+
+ context 'Rails controller having expected duration setup' do
+ let(:controller) do
+ request_urgency = request_urgency_name
+ Class.new(ApplicationController) do
+ feature_category :hello_world, [:index, :show]
+ urgency request_urgency, [:index, :show]
+ end
+ end
+
+ let(:env) do
+ controller_instance = controller.new
+ controller_instance.action_name = :index
+ { 'action_controller.instance' => controller_instance, 'REQUEST_METHOD' => 'GET' }
+ end
+
+ before do
+ ::Gitlab::ApplicationContext.push(feature_category: 'hello_world', caller_id: 'AnonymousController#index')
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100 + duration)
+ end
+
+ it "captures SLI metrics" do
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'hello_world', endpoint_id: 'AnonymousController#index' },
+ success: success
+ )
+ subject.call(env)
+ end
+ end
+ end
+
+ context 'Grape API without expected duration' do
+ let(:endpoint) do
+ route = double(:route, request_method: 'GET', path: '/:version/projects/:id/archive(.:format)')
+ double(:endpoint, route: route,
+ options: { for: api_handler, path: [":id/archive"] },
+ namespace: "/projects")
+ end
+
+ let(:env) { { 'api.endpoint' => endpoint, 'REQUEST_METHOD' => 'GET' } }
+
+ let(:api_handler) { Class.new(::API::Base) }
+
+ it "falls back request's expectation to medium (1 second)" do
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100.9)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ success: true
+ )
+ subject.call(env)
+
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 101)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ success: false
+ )
+ subject.call(env)
+ end
+ end
+
+ context 'Rails controller without expected duration' do
+ let(:controller) { Class.new(ApplicationController) }
+
+ let(:env) do
+ controller_instance = controller.new
+ controller_instance.action_name = :index
+ { 'action_controller.instance' => controller_instance, 'REQUEST_METHOD' => 'GET' }
+ end
+
+ it "falls back request's expectation to medium (1 second)" do
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100.9)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ success: true
+ )
+ subject.call(env)
+
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 101)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ success: false
+ )
+ subject.call(env)
+ end
+ end
+
+ context 'An unknown request' do
+ let(:env) do
+ { 'REQUEST_METHOD' => 'GET' }
+ end
+
+ it "falls back request's expectation to medium (1 second)" do
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100.9)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ success: true
+ )
+ subject.call(env)
+
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 101)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
+ labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ success: false
+ )
+ subject.call(env)
+ end
+ end
+ end
end
describe '.initialize_metrics', :prometheus do
@@ -181,8 +348,8 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
end
it 'has every label in config/feature_categories.yml' do
- defaults = [described_class::FEATURE_CATEGORY_DEFAULT, 'not_owned']
- feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:strip) + defaults
+ defaults = [::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT, 'not_owned']
+ feature_categories = Gitlab::FeatureCategories.default.categories + defaults
expect(described_class::FEATURE_CATEGORIES_TO_INITIALIZE).to all(be_in(feature_categories))
end