summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/metrics/exporter
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/metrics/exporter')
-rw-r--r--spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb74
-rw-r--r--spec/lib/gitlab/metrics/exporter/gc_request_middleware_spec.rb21
-rw-r--r--spec/lib/gitlab/metrics/exporter/health_checks_middleware_spec.rb52
-rw-r--r--spec/lib/gitlab/metrics/exporter/metrics_middleware_spec.rb39
-rw-r--r--spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb53
-rw-r--r--spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb6
6 files changed, 178 insertions, 67 deletions
diff --git a/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
index 9cd1ef4094e..c7afc02f0af 100644
--- a/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
+++ b/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
@@ -4,13 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::Exporter::BaseExporter do
let(:settings) { double('settings') }
- let(:exporter) { described_class.new(settings) }
- let(:log_filename) { File.join(Rails.root, 'log', 'sidekiq_exporter.log') }
-
- before do
- allow_any_instance_of(described_class).to receive(:log_filename).and_return(log_filename)
- allow_any_instance_of(described_class).to receive(:settings).and_return(settings)
- end
+ let(:log_enabled) { false }
+ let(:exporter) { described_class.new(settings, log_enabled: log_enabled, log_file: 'test_exporter.log') }
describe 'when exporter is enabled' do
before do
@@ -61,6 +56,38 @@ RSpec.describe Gitlab::Metrics::Exporter::BaseExporter do
exporter.start.join
end
+
+ context 'logging enabled' do
+ let(:log_enabled) { true }
+ let(:logger) { instance_double(WEBrick::Log) }
+
+ before do
+ allow(logger).to receive(:time_format=)
+ allow(logger).to receive(:info)
+ end
+
+ it 'configures a WEBrick logger with the given file' do
+ expect(WEBrick::Log).to receive(:new).with(end_with('test_exporter.log')).and_return(logger)
+
+ exporter
+ end
+
+ it 'logs any errors during startup' do
+ expect(::WEBrick::Log).to receive(:new).and_return(logger)
+ expect(::WEBrick::HTTPServer).to receive(:new).and_raise 'fail'
+ expect(logger).to receive(:error)
+
+ exporter.start
+ end
+ end
+
+ context 'logging disabled' do
+ it 'configures a WEBrick logger with the null device' do
+ expect(WEBrick::Log).to receive(:new).with(File::NULL).and_call_original
+
+ exporter
+ end
+ end
end
describe 'when thread is not alive' do
@@ -111,6 +138,18 @@ RSpec.describe Gitlab::Metrics::Exporter::BaseExporter do
describe 'request handling' do
using RSpec::Parameterized::TableSyntax
+ let(:fake_collector) do
+ Class.new do
+ def initialize(app, ...)
+ @app = app
+ end
+
+ def call(env)
+ @app.call(env)
+ end
+ end
+ end
+
where(:method_class, :path, :http_status) do
Net::HTTP::Get | '/metrics' | 200
Net::HTTP::Get | '/liveness' | 200
@@ -123,6 +162,8 @@ RSpec.describe Gitlab::Metrics::Exporter::BaseExporter do
allow(settings).to receive(:port).and_return(0)
allow(settings).to receive(:address).and_return('127.0.0.1')
+ stub_const('Gitlab::Metrics::Exporter::MetricsMiddleware', fake_collector)
+
# We want to wrap original method
# and run handling of requests
# in separate thread
@@ -134,8 +175,6 @@ RSpec.describe Gitlab::Metrics::Exporter::BaseExporter do
# is raised as we close listeners
end
end
-
- exporter.start.join
end
after do
@@ -146,12 +185,25 @@ RSpec.describe Gitlab::Metrics::Exporter::BaseExporter do
let(:config) { exporter.server.config }
let(:request) { method_class.new(path) }
- it 'responds with proper http_status' do
+ subject(:response) do
http = Net::HTTP.new(config[:BindAddress], config[:Port])
- response = http.request(request)
+ http.request(request)
+ end
+
+ it 'responds with proper http_status' do
+ exporter.start.join
expect(response.code).to eq(http_status.to_s)
end
+
+ it 'collects request metrics' do
+ expect_next_instance_of(fake_collector) do |instance|
+ expect(instance).to receive(:call).and_call_original
+ end
+
+ exporter.start.join
+ response
+ end
end
end
diff --git a/spec/lib/gitlab/metrics/exporter/gc_request_middleware_spec.rb b/spec/lib/gitlab/metrics/exporter/gc_request_middleware_spec.rb
new file mode 100644
index 00000000000..0c70a5de701
--- /dev/null
+++ b/spec/lib/gitlab/metrics/exporter/gc_request_middleware_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Metrics::Exporter::GcRequestMiddleware do
+ let(:app) { double(:app) }
+ let(:env) { {} }
+
+ subject(:middleware) { described_class.new(app) }
+
+ describe '#call' do
+ it 'runs a major GC after the next middleware is called' do
+ expect(app).to receive(:call).with(env).ordered.and_return([200, {}, []])
+ expect(GC).to receive(:start).ordered
+
+ response = middleware.call(env)
+
+ expect(response).to eq([200, {}, []])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/exporter/health_checks_middleware_spec.rb b/spec/lib/gitlab/metrics/exporter/health_checks_middleware_spec.rb
new file mode 100644
index 00000000000..9ee46a45e7a
--- /dev/null
+++ b/spec/lib/gitlab/metrics/exporter/health_checks_middleware_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Metrics::Exporter::HealthChecksMiddleware do
+ let(:app) { double(:app) }
+ let(:env) { { 'PATH_INFO' => path } }
+
+ let(:readiness_probe) { double(:readiness_probe) }
+ let(:liveness_probe) { double(:liveness_probe) }
+ let(:probe_result) { Gitlab::HealthChecks::Probes::Status.new(200, { status: 'ok' }) }
+
+ subject(:middleware) { described_class.new(app, readiness_probe, liveness_probe) }
+
+ describe '#call' do
+ context 'handling /readiness requests' do
+ let(:path) { '/readiness' }
+
+ it 'handles the request' do
+ expect(readiness_probe).to receive(:execute).and_return(probe_result)
+
+ response = middleware.call(env)
+
+ expect(response).to eq([200, { 'Content-Type' => 'application/json; charset=utf-8' }, ['{"status":"ok"}']])
+ end
+ end
+
+ context 'handling /liveness requests' do
+ let(:path) { '/liveness' }
+
+ it 'handles the request' do
+ expect(liveness_probe).to receive(:execute).and_return(probe_result)
+
+ response = middleware.call(env)
+
+ expect(response).to eq([200, { 'Content-Type' => 'application/json; charset=utf-8' }, ['{"status":"ok"}']])
+ end
+ end
+
+ context 'handling other requests' do
+ let(:path) { '/other_path' }
+
+ it 'forwards them to the next middleware' do
+ expect(app).to receive(:call).with(env).and_return([201, {}, []])
+
+ response = middleware.call(env)
+
+ expect(response).to eq([201, {}, []])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/exporter/metrics_middleware_spec.rb b/spec/lib/gitlab/metrics/exporter/metrics_middleware_spec.rb
new file mode 100644
index 00000000000..ac5721f5974
--- /dev/null
+++ b/spec/lib/gitlab/metrics/exporter/metrics_middleware_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Exporter::MetricsMiddleware do
+ let(:app) { double(:app) }
+ let(:pid) { 'fake_exporter' }
+ let(:env) { { 'PATH_INFO' => '/path', 'REQUEST_METHOD' => 'GET' } }
+
+ subject(:middleware) { described_class.new(app, pid) }
+
+ def metric(name, method, path, status)
+ metric = ::Prometheus::Client.registry.get(name)
+ return unless metric
+
+ values = metric.values.transform_keys { |k| k.slice(:method, :path, :pid, :code) }
+ values[{ method: method, path: path, pid: pid, code: status.to_s }]&.get
+ end
+
+ before do
+ expect(app).to receive(:call).with(env).and_return([200, {}, []])
+ end
+
+ describe '#call', :prometheus do
+ it 'records a total requests metric' do
+ response = middleware.call(env)
+
+ expect(response).to eq([200, {}, []])
+ expect(metric(:exporter_http_requests_total, 'get', '/path', 200)).to eq(1.0)
+ end
+
+ it 'records a request duration histogram' do
+ response = middleware.call(env)
+
+ expect(response).to eq([200, {}, []])
+ expect(metric(:exporter_http_request_duration_seconds, 'get', '/path', 200)).to be_a(Hash)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
deleted file mode 100644
index 75bc3ba9626..00000000000
--- a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Metrics::Exporter::SidekiqExporter do
- let(:exporter) { described_class.new(Settings.monitoring.sidekiq_exporter) }
-
- after do
- exporter.stop
- end
-
- context 'with valid config' do
- before do
- stub_config(
- monitoring: {
- sidekiq_exporter: {
- enabled: true,
- log_enabled: false,
- port: 0,
- address: '127.0.0.1'
- }
- }
- )
- end
-
- it 'does start thread' do
- expect(exporter.start).not_to be_nil
- end
-
- it 'does not enable logging by default' do
- expect(exporter.log_filename).to eq(File::NULL)
- end
- end
-
- context 'with logging enabled' do
- before do
- stub_config(
- monitoring: {
- sidekiq_exporter: {
- enabled: true,
- log_enabled: true,
- port: 0,
- address: '127.0.0.1'
- }
- }
- )
- end
-
- it 'returns a valid log filename' do
- expect(exporter.log_filename).to end_with('sidekiq_exporter.log')
- end
- end
-end
diff --git a/spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb
index 9deaecbf41b..0531bccf4b4 100644
--- a/spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb
+++ b/spec/lib/gitlab/metrics/exporter/web_exporter_spec.rb
@@ -24,14 +24,14 @@ RSpec.describe Gitlab::Metrics::Exporter::WebExporter do
exporter.stop
end
- context 'when running server' do
+ context 'when running server', :prometheus do
it 'readiness probe returns succesful status' do
expect(readiness_probe.http_status).to eq(200)
expect(readiness_probe.json).to include(status: 'ok')
expect(readiness_probe.json).to include('web_exporter' => [{ 'status': 'ok' }])
end
- it 'initializes request metrics', :prometheus do
+ it 'initializes request metrics' do
expect(Gitlab::Metrics::RailsSlis).to receive(:initialize_request_slis_if_needed!).and_call_original
http = Net::HTTP.new(exporter.server.config[:BindAddress], exporter.server.config[:Port])
@@ -42,7 +42,7 @@ RSpec.describe Gitlab::Metrics::Exporter::WebExporter do
end
describe '#mark_as_not_running!' do
- it 'readiness probe returns a failure status' do
+ it 'readiness probe returns a failure status', :prometheus do
exporter.mark_as_not_running!
expect(readiness_probe.http_status).to eq(503)