diff options
Diffstat (limited to 'spec/lib/gitlab/metrics')
-rw-r--r-- | spec/lib/gitlab/metrics/background_transaction_spec.rb | 6 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb | 6 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/dashboard/url_spec.rb | 32 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/method_call_spec.rb | 19 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/metric_spec.rb | 71 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/rack_middleware_spec.rb | 25 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb | 49 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb | 105 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb | 32 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb | 7 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/subscribers/action_view_spec.rb | 6 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/system_spec.rb | 117 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/transaction_spec.rb | 165 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/web_transaction_spec.rb | 144 |
15 files changed, 230 insertions, 556 deletions
diff --git a/spec/lib/gitlab/metrics/background_transaction_spec.rb b/spec/lib/gitlab/metrics/background_transaction_spec.rb index d87d2c839ad..84f405d7369 100644 --- a/spec/lib/gitlab/metrics/background_transaction_spec.rb +++ b/spec/lib/gitlab/metrics/background_transaction_spec.rb @@ -7,12 +7,6 @@ describe Gitlab::Metrics::BackgroundTransaction do subject { described_class.new(test_worker_class) } - describe '#action' do - it 'returns transaction action name' do - expect(subject.action).to eq('TestWorker#perform') - end - end - describe '#label' do it 'returns labels based on class name' do expect(subject.labels).to eq(controller: 'TestWorker', action: 'perform') diff --git a/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb index e41004bb57e..5d4bd4512e3 100644 --- a/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb @@ -9,9 +9,9 @@ describe Gitlab::Metrics::Dashboard::Stages::GrafanaFormatter do let_it_be(:project) { create(:project, namespace: namespace, name: 'bar') } describe '#transform!' do - let(:grafana_dashboard) { JSON.parse(fixture_file('grafana/simplified_dashboard_response.json'), symbolize_names: true) } - let(:datasource) { JSON.parse(fixture_file('grafana/datasource_response.json'), symbolize_names: true) } - let(:expected_dashboard) { JSON.parse(fixture_file('grafana/expected_grafana_embed.json'), symbolize_names: true) } + let(:grafana_dashboard) { Gitlab::Json.parse(fixture_file('grafana/simplified_dashboard_response.json'), symbolize_names: true) } + let(:datasource) { Gitlab::Json.parse(fixture_file('grafana/datasource_response.json'), symbolize_names: true) } + let(:expected_dashboard) { Gitlab::Json.parse(fixture_file('grafana/expected_grafana_embed.json'), symbolize_names: true) } subject(:dashboard) { described_class.new(project, {}, params).transform! } diff --git a/spec/lib/gitlab/metrics/dashboard/url_spec.rb b/spec/lib/gitlab/metrics/dashboard/url_spec.rb index 9ccd1c06d6b..75f9f99c8a6 100644 --- a/spec/lib/gitlab/metrics/dashboard/url_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/url_spec.rb @@ -3,17 +3,21 @@ require 'spec_helper' describe Gitlab::Metrics::Dashboard::Url do + include Gitlab::Routing.url_helpers + describe '#metrics_regex' do - let(:url) do - Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url( + let(:url_params) do + [ 'foo', 'bar', 1, - start: '2019-08-02T05:43:09.000Z', - dashboard: 'config/prometheus/common_metrics.yml', - group: 'awesome group', - anchor: 'title' - ) + { + start: '2019-08-02T05:43:09.000Z', + dashboard: 'config/prometheus/common_metrics.yml', + group: 'awesome group', + anchor: 'title' + } + ] end let(:expected_params) do @@ -29,12 +33,22 @@ describe Gitlab::Metrics::Dashboard::Url do subject { described_class.metrics_regex } - it_behaves_like 'regex which matches url when expected' + context 'for metrics route' do + let(:url) { metrics_namespace_project_environment_url(*url_params) } + + it_behaves_like 'regex which matches url when expected' + end + + context 'for metrics_dashboard route' do + let(:url) { metrics_dashboard_namespace_project_environment_url(*url_params) } + + it_behaves_like 'regex which matches url when expected' + end end describe '#grafana_regex' do let(:url) do - Gitlab::Routing.url_helpers.namespace_project_grafana_api_metrics_dashboard_url( + namespace_project_grafana_api_metrics_dashboard_url( 'foo', 'bar', start: '2019-08-02T05:43:09.000Z', diff --git a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb index a415b6407d5..0b820fdbde9 100644 --- a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb +++ b/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb @@ -53,7 +53,7 @@ describe Gitlab::Metrics::Exporter::SidekiqExporter do .with( class: described_class.to_s, message: 'Cannot start sidekiq_exporter', - exception: anything) + 'exception.message' => anything) exporter.start end diff --git a/spec/lib/gitlab/metrics/method_call_spec.rb b/spec/lib/gitlab/metrics/method_call_spec.rb index 3b5e04e2df5..229db67ec88 100644 --- a/spec/lib/gitlab/metrics/method_call_spec.rb +++ b/spec/lib/gitlab/metrics/method_call_spec.rb @@ -76,25 +76,6 @@ describe Gitlab::Metrics::MethodCall do end end - describe '#to_metric' do - it 'returns a Metric instance' do - expect(method_call).to receive(:real_time).and_return(4.0001).twice - expect(method_call).to receive(:cpu_time).and_return(3.0001) - - method_call.measure { 'foo' } - metric = method_call.to_metric - - expect(metric).to be_an_instance_of(Gitlab::Metrics::Metric) - expect(metric.series).to eq('rails_method_calls') - - expect(metric.values[:duration]).to eq(4000) - expect(metric.values[:cpu_duration]).to eq(3000) - expect(metric.values[:call_count]).to be_an(Integer) - - expect(metric.tags).to eq({ method: 'Foo#bar' }) - end - end - describe '#above_threshold?' do before do allow(Gitlab::Metrics).to receive(:method_call_threshold).and_return(100) diff --git a/spec/lib/gitlab/metrics/metric_spec.rb b/spec/lib/gitlab/metrics/metric_spec.rb deleted file mode 100644 index 611b59231ba..00000000000 --- a/spec/lib/gitlab/metrics/metric_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Gitlab::Metrics::Metric do - let(:metric) do - described_class.new('foo', { number: 10 }, { host: 'localtoast' }) - end - - describe '#series' do - subject { metric.series } - - it { is_expected.to eq('foo') } - end - - describe '#values' do - subject { metric.values } - - it { is_expected.to eq({ number: 10 }) } - end - - describe '#tags' do - subject { metric.tags } - - it { is_expected.to eq({ host: 'localtoast' }) } - end - - describe '#type' do - subject { metric.type } - - it { is_expected.to eq(:metric) } - end - - describe '#event?' do - it 'returns false for a regular metric' do - expect(metric.event?).to eq(false) - end - - it 'returns true for an event metric' do - expect(metric).to receive(:type).and_return(:event) - - expect(metric.event?).to eq(true) - end - end - - describe '#to_hash' do - it 'returns a Hash' do - expect(metric.to_hash).to be_an_instance_of(Hash) - end - - describe 'the returned Hash' do - let(:hash) { metric.to_hash } - - it 'includes the series' do - expect(hash[:series]).to eq('foo') - end - - it 'includes the tags' do - expect(hash[:tags]).to be_an_instance_of(Hash) - end - - it 'includes the values' do - expect(hash[:values]).to eq({ number: 10 }) - end - - it 'includes the timestamp' do - expect(hash[:timestamp]).to be_an(Integer) - end - end - end -end diff --git a/spec/lib/gitlab/metrics/rack_middleware_spec.rb b/spec/lib/gitlab/metrics/rack_middleware_spec.rb index 1c1681cc5ab..dd1dbf7a1f4 100644 --- a/spec/lib/gitlab/metrics/rack_middleware_spec.rb +++ b/spec/lib/gitlab/metrics/rack_middleware_spec.rb @@ -10,10 +10,6 @@ describe Gitlab::Metrics::RackMiddleware do let(:env) { { 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/foo' } } describe '#call' do - before do - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish) - end - it 'tracks a transaction' do expect(app).to receive(:call).with(env).and_return('yay') @@ -36,26 +32,5 @@ describe Gitlab::Metrics::RackMiddleware do it 'returns a Transaction' do expect(transaction).to be_an_instance_of(Gitlab::Metrics::WebTransaction) end - - it 'stores the request method and URI in the transaction as values' do - expect(transaction.values[:request_method]).to eq('GET') - expect(transaction.values[:request_uri]).to eq('/foo') - end - - context "when URI includes sensitive parameters" do - let(:env) do - { - 'REQUEST_METHOD' => 'GET', - 'REQUEST_URI' => '/foo?private_token=my-token', - 'PATH_INFO' => '/foo', - 'QUERY_STRING' => 'private_token=my_token', - 'action_dispatch.parameter_filter' => [:private_token] - } - end - - it 'stores the request URI with the sensitive parameters filtered' do - expect(transaction.values[:request_uri]).to eq('/foo?private_token=[FILTERED]') - end - end end end diff --git a/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb new file mode 100644 index 00000000000..fdf3b5bd045 --- /dev/null +++ b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Metrics::Samplers::DatabaseSampler do + subject { described_class.new(described_class::SAMPLING_INTERVAL_SECONDS) } + + describe '#sample' do + before do + described_class::METRIC_DESCRIPTIONS.each_key do |metric| + allow(subject.metrics[metric]).to receive(:set) + end + end + + context 'for ActiveRecord::Base' do + let(:labels) do + { + class: 'ActiveRecord::Base', + host: Gitlab::Database.config['host'], + port: Gitlab::Database.config['port'] + } + end + + context 'when the database is connected' do + it 'samples connection pool statistics' do + expect(subject.metrics[:size]).to receive(:set).with(labels, a_value >= 1) + expect(subject.metrics[:connections]).to receive(:set).with(labels, a_value >= 1) + expect(subject.metrics[:busy]).to receive(:set).with(labels, a_value >= 1) + expect(subject.metrics[:dead]).to receive(:set).with(labels, a_value >= 0) + expect(subject.metrics[:waiting]).to receive(:set).with(labels, a_value >= 0) + + subject.sample + end + end + + context 'when the database is not connected' do + before do + allow(ActiveRecord::Base).to receive(:connected?).and_return(false) + end + + it 'records no samples' do + expect(subject.metrics[:size]).not_to receive(:set).with(labels, anything) + + subject.sample + end + end + end + end +end diff --git a/spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb deleted file mode 100644 index 939c057c342..00000000000 --- a/spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Gitlab::Metrics::Samplers::InfluxSampler do - let(:sampler) { described_class.new(5) } - - describe '#start' do - it 'runs once and gathers a sample at a given interval' do - expect(sampler).to receive(:sleep).with(a_kind_of(Numeric)).twice - expect(sampler).to receive(:sample).once - expect(sampler).to receive(:running).and_return(true, false) - - sampler.start.join - end - end - - describe '#sample' do - it 'samples various statistics' do - expect(sampler).to receive(:sample_memory_usage) - expect(sampler).to receive(:sample_file_descriptors) - expect(sampler).to receive(:flush) - - sampler.sample - end - end - - describe '#flush' do - it 'schedules the metrics using Sidekiq' do - expect(Gitlab::Metrics).to receive(:submit_metrics) - .with([an_instance_of(Hash)]) - - sampler.sample_memory_usage - sampler.flush - end - end - - describe '#sample_memory_usage' do - it 'adds a metric containing the memory usage' do - expect(Gitlab::Metrics::System).to receive(:memory_usage) - .and_return(9000) - - expect(sampler).to receive(:add_metric) - .with(/memory_usage/, value: 9000) - .and_call_original - - sampler.sample_memory_usage - end - end - - describe '#sample_file_descriptors' do - it 'adds a metric containing the amount of open file descriptors' do - expect(Gitlab::Metrics::System).to receive(:file_descriptor_count) - .and_return(4) - - expect(sampler).to receive(:add_metric) - .with(/file_descriptors/, value: 4) - .and_call_original - - sampler.sample_file_descriptors - end - end - - describe '#add_metric' do - it 'prefixes the series name for a Rails process' do - expect(Gitlab::Runtime).to receive(:sidekiq?).and_return(false) - - expect(Gitlab::Metrics::Metric).to receive(:new) - .with('rails_cats', { value: 10 }, {}) - .and_call_original - - sampler.add_metric('cats', value: 10) - end - - it 'prefixes the series name for a Sidekiq process' do - expect(Gitlab::Runtime).to receive(:sidekiq?).and_return(true) - - expect(Gitlab::Metrics::Metric).to receive(:new) - .with('sidekiq_cats', { value: 10 }, {}) - .and_call_original - - sampler.add_metric('cats', value: 10) - end - end - - describe '#sleep_interval' do - it 'returns a Numeric' do - expect(sampler.sleep_interval).to be_a_kind_of(Numeric) - end - - # Testing random behaviour is very hard, so treat this test as a basic smoke - # test instead of a very accurate behaviour/unit test. - it 'does not return the same interval twice in a row' do - last = nil - - 100.times do - interval = sampler.sleep_interval - - expect(interval).not_to eq(last) - - last = interval - end - end - end -end diff --git a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb index 8c4071a7ed1..ead650a27f0 100644 --- a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb +++ b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb @@ -19,24 +19,38 @@ describe Gitlab::Metrics::Samplers::RubySampler do end describe '#sample' do - it 'samples various statistics' do - expect(Gitlab::Metrics::System).to receive(:cpu_time) - expect(Gitlab::Metrics::System).to receive(:file_descriptor_count) - expect(Gitlab::Metrics::System).to receive(:memory_usage) - expect(Gitlab::Metrics::System).to receive(:max_open_file_descriptors) - expect(sampler).to receive(:sample_gc) + it 'adds a metric containing the process resident memory bytes' do + expect(Gitlab::Metrics::System).to receive(:memory_usage_rss).and_return(9000) + + expect(sampler.metrics[:process_resident_memory_bytes]).to receive(:set).with({}, 9000) sampler.sample end - it 'adds a metric containing the process resident memory bytes' do - expect(Gitlab::Metrics::System).to receive(:memory_usage).and_return(9000) + it 'adds a metric containing the process unique and proportional memory bytes' do + expect(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).and_return(uss: 9000, pss: 10_000) - expect(sampler.metrics[:process_resident_memory_bytes]).to receive(:set).with({}, 9000) + expect(sampler.metrics[:process_unique_memory_bytes]).to receive(:set).with({}, 9000) + expect(sampler.metrics[:process_proportional_memory_bytes]).to receive(:set).with({}, 10_000) sampler.sample end + context 'when USS+PSS sampling is disabled via environment' do + before do + stub_env('enable_memory_uss_pss', "0") + end + + it 'does not sample USS or PSS' do + expect(Gitlab::Metrics::System).not_to receive(:memory_usage_uss_pss) + + expect(sampler.metrics[:process_unique_memory_bytes]).not_to receive(:set) + expect(sampler.metrics[:process_proportional_memory_bytes]).not_to receive(:set) + + sampler.sample + end + end + it 'adds a metric containing the amount of open file descriptors' do expect(Gitlab::Metrics::System).to receive(:file_descriptor_count) .and_return(4) diff --git a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb index bb95d5ab2ad..67336cf83e6 100644 --- a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb +++ b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb @@ -17,8 +17,6 @@ describe Gitlab::Metrics::SidekiqMiddleware do expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:set) .with(:sidekiq_queue_duration, instance_of(Float)) - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish) - middleware.call(worker, message, :test) { nil } end @@ -32,8 +30,6 @@ describe Gitlab::Metrics::SidekiqMiddleware do expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:set) .with(:sidekiq_queue_duration, instance_of(Float)) - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish) - middleware.call(worker, {}, :test) { nil } end @@ -46,9 +42,6 @@ describe Gitlab::Metrics::SidekiqMiddleware do expect_any_instance_of(Gitlab::Metrics::Transaction) .to receive(:add_event).with(:sidekiq_exception) - expect_any_instance_of(Gitlab::Metrics::Transaction) - .to receive(:finish) - expect { middleware.call(worker, message, :test) } .to raise_error(RuntimeError) end diff --git a/spec/lib/gitlab/metrics/subscribers/action_view_spec.rb b/spec/lib/gitlab/metrics/subscribers/action_view_spec.rb index 25c0e7b695a..857e54d3432 100644 --- a/spec/lib/gitlab/metrics/subscribers/action_view_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/action_view_spec.rb @@ -21,15 +21,9 @@ describe Gitlab::Metrics::Subscribers::ActionView do describe '#render_template' do it 'tracks rendering of a template' do - values = { duration: 2.1 } - tags = { view: 'app/views/x.html.haml' } - expect(transaction).to receive(:increment) .with(:view_duration, 2.1) - expect(transaction).to receive(:add_metric) - .with(described_class::SERIES, values, tags) - subscriber.render_template(event) end diff --git a/spec/lib/gitlab/metrics/system_spec.rb b/spec/lib/gitlab/metrics/system_spec.rb index a5aa80686fd..abb6a0096d6 100644 --- a/spec/lib/gitlab/metrics/system_spec.rb +++ b/spec/lib/gitlab/metrics/system_spec.rb @@ -3,33 +3,122 @@ require 'spec_helper' describe Gitlab::Metrics::System do - if File.exist?('/proc') - describe '.memory_usage' do - it "returns the process' memory usage in bytes" do - expect(described_class.memory_usage).to be > 0 + context 'when /proc files exist' do + # Fixtures pulled from: + # Linux carbon 5.3.0-7648-generic #41~1586789791~19.10~9593806-Ubuntu SMP Mon Apr 13 17:50:40 UTC x86_64 x86_64 x86_64 GNU/Linux + let(:proc_status) do + # most rows omitted for brevity + <<~SNIP + Name: less + VmHWM: 2468 kB + VmRSS: 2468 kB + RssAnon: 260 kB + SNIP + end + + let(:proc_smaps_rollup) do + # full snapshot + <<~SNIP + Rss: 2564 kB + Pss: 503 kB + Pss_Anon: 312 kB + Pss_File: 191 kB + Pss_Shmem: 0 kB + Shared_Clean: 2100 kB + Shared_Dirty: 0 kB + Private_Clean: 152 kB + Private_Dirty: 312 kB + Referenced: 2564 kB + Anonymous: 312 kB + LazyFree: 0 kB + AnonHugePages: 0 kB + ShmemPmdMapped: 0 kB + Shared_Hugetlb: 0 kB + Private_Hugetlb: 0 kB + Swap: 0 kB + SwapPss: 0 kB + Locked: 0 kB + SNIP + end + + let(:proc_limits) do + # full snapshot + <<~SNIP + Limit Soft Limit Hard Limit Units + Max cpu time unlimited unlimited seconds + Max file size unlimited unlimited bytes + Max data size unlimited unlimited bytes + Max stack size 8388608 unlimited bytes + Max core file size 0 unlimited bytes + Max resident set unlimited unlimited bytes + Max processes 126519 126519 processes + Max open files 1024 1048576 files + Max locked memory 67108864 67108864 bytes + Max address space unlimited unlimited bytes + Max file locks unlimited unlimited locks + Max pending signals 126519 126519 signals + Max msgqueue size 819200 819200 bytes + Max nice priority 0 0 + Max realtime priority 0 0 + Max realtime timeout unlimited unlimited us + SNIP + end + + describe '.memory_usage_rss' do + it "returns the process' resident set size (RSS) in bytes" do + mock_existing_proc_file('/proc/self/status', proc_status) + + expect(described_class.memory_usage_rss).to eq(2527232) end end describe '.file_descriptor_count' do it 'returns the amount of open file descriptors' do - expect(described_class.file_descriptor_count).to be > 0 + expect(Dir).to receive(:glob).and_return(['/some/path', '/some/other/path']) + + expect(described_class.file_descriptor_count).to eq(2) end end describe '.max_open_file_descriptors' do it 'returns the max allowed open file descriptors' do - expect(described_class.max_open_file_descriptors).to be > 0 + mock_existing_proc_file('/proc/self/limits', proc_limits) + + expect(described_class.max_open_file_descriptors).to eq(1024) + end + end + + describe '.memory_usage_uss_pss' do + it "returns the process' unique and porportional set size (USS/PSS) in bytes" do + mock_existing_proc_file('/proc/self/smaps_rollup', proc_smaps_rollup) + + # (Private_Clean (152 kB) + Private_Dirty (312 kB) + Private_Hugetlb (0 kB)) * 1024 + expect(described_class.memory_usage_uss_pss).to eq(uss: 475136, pss: 515072) end end - else - describe '.memory_usage' do - it 'returns 0.0' do - expect(described_class.memory_usage).to eq(0.0) + end + + context 'when /proc files do not exist' do + before do + mock_missing_proc_file + end + + describe '.memory_usage_rss' do + it 'returns 0' do + expect(described_class.memory_usage_rss).to eq(0) + end + end + + describe '.memory_usage_uss_pss' do + it "returns 0 for all components" do + expect(described_class.memory_usage_uss_pss).to eq(uss: 0, pss: 0) end end describe '.file_descriptor_count' do it 'returns 0' do + expect(Dir).to receive(:glob).and_return([]) + expect(described_class.file_descriptor_count).to eq(0) end end @@ -98,4 +187,12 @@ describe Gitlab::Metrics::System do expect(described_class.thread_cpu_duration(start_time)).to be_nil end end + + def mock_existing_proc_file(path, content) + allow(File).to receive(:foreach).with(path) { |_path, &block| content.each_line(&block) } + end + + def mock_missing_proc_file + allow(File).to receive(:foreach).and_raise(Errno::ENOENT) + end end diff --git a/spec/lib/gitlab/metrics/transaction_spec.rb b/spec/lib/gitlab/metrics/transaction_spec.rb index 08de2426c5a..cf46fa3e91c 100644 --- a/spec/lib/gitlab/metrics/transaction_spec.rb +++ b/spec/lib/gitlab/metrics/transaction_spec.rb @@ -4,7 +4,6 @@ require 'spec_helper' describe Gitlab::Metrics::Transaction do let(:transaction) { described_class.new } - let(:metric) { transaction.metrics[0] } let(:sensitive_tags) do { @@ -13,12 +12,6 @@ describe Gitlab::Metrics::Transaction do } end - shared_examples 'tag filter' do |sane_tags| - it 'filters potentially sensitive tags' do - expect(metric.tags).to eq(sane_tags) - end - end - describe '#duration' do it 'returns the duration of a transaction in seconds' do transaction.run { } @@ -61,25 +54,6 @@ describe Gitlab::Metrics::Transaction do end end - describe '#add_metric' do - it 'adds a metric to the transaction' do - transaction.add_metric('foo', value: 1) - - expect(metric.series).to eq('rails_foo') - expect(metric.tags).to eq({}) - expect(metric.values).to eq(value: 1) - end - - context 'with sensitive tags' do - before do - transaction - .add_metric('foo', { value: 1 }, **sensitive_tags.merge(sane: 'yes')) - end - - it_behaves_like 'tag filter', sane: 'yes' - end - end - describe '#method_call_for' do it 'returns a MethodCall' do method = transaction.method_call_for('Foo#bar', :Foo, '#bar') @@ -88,133 +62,23 @@ describe Gitlab::Metrics::Transaction do end end - describe '#increment' do - it 'increments a counter' do - transaction.increment(:time, 1) - transaction.increment(:time, 2) - - values = metric_values(time: 3) - - expect(transaction).to receive(:add_metric) - .with('transactions', values, {}) - - transaction.track_self - end - end - - describe '#set' do - it 'sets a value' do - transaction.set(:number, 10) - - values = metric_values(number: 10) - - expect(transaction).to receive(:add_metric) - .with('transactions', values, {}) - - transaction.track_self - end - end - - describe '#finish' do - it 'tracks the transaction details and submits them to Sidekiq' do - expect(transaction).to receive(:track_self) - expect(transaction).to receive(:submit) - - transaction.finish - end - end - - describe '#track_self' do - it 'adds a metric for the transaction itself' do - values = metric_values - - expect(transaction).to receive(:add_metric) - .with('transactions', values, {}) - - transaction.track_self - end - end - - describe '#submit' do - it 'submits the metrics to Sidekiq' do - transaction.track_self - - expect(Gitlab::Metrics).to receive(:submit_metrics) - .with([an_instance_of(Hash)]) - - transaction.submit - end - - it 'adds the action as a tag for every metric' do - allow(transaction) - .to receive(:labels) - .and_return(controller: 'Foo', action: 'bar') - - transaction.track_self - - hash = { - series: 'rails_transactions', - tags: { action: 'Foo#bar' }, - values: metric_values, - timestamp: a_kind_of(Integer) - } - - expect(Gitlab::Metrics).to receive(:submit_metrics) - .with([hash]) - - transaction.submit - end - - it 'does not add an action tag for events' do - allow(transaction) - .to receive(:labels) - .and_return(controller: 'Foo', action: 'bar') - - transaction.add_event(:meow) - - hash = { - series: 'events', - tags: { event: :meow }, - values: { count: 1 }, - timestamp: a_kind_of(Integer) - } - - expect(Gitlab::Metrics).to receive(:submit_metrics) - .with([hash]) - - transaction.submit - end - end - describe '#add_event' do - it 'adds a metric' do - transaction.add_event(:meow) + let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, increment: nil) } - expect(metric).to be_an_instance_of(Gitlab::Metrics::Metric) + before do + allow(described_class).to receive(:transaction_metric).and_return(prometheus_metric) end - it "does not prefix the metric's series name" do - transaction.add_event(:meow) - - expect(metric.series).to eq(described_class::EVENT_SERIES) - end - - it 'tracks a counter for every event' do - transaction.add_event(:meow) - - expect(metric.values).to eq(count: 1) - end + it 'adds a metric' do + expect(prometheus_metric).to receive(:increment) - it 'tracks the event name' do transaction.add_event(:meow) - - expect(metric.tags).to eq(event: :meow) end it 'allows tracking of custom tags' do - transaction.add_event(:bau, animal: 'dog') + expect(prometheus_metric).to receive(:increment).with(hash_including(animal: "dog")) - expect(metric.tags).to eq(event: :bau, animal: 'dog') + transaction.add_event(:bau, animal: 'dog') end context 'with sensitive tags' do @@ -222,16 +86,11 @@ describe Gitlab::Metrics::Transaction do transaction.add_event(:baubau, **sensitive_tags.merge(sane: 'yes')) end - it_behaves_like 'tag filter', event: :baubau, sane: 'yes' - end - end - - private + it 'filters tags' do + expect(prometheus_metric).not_to receive(:increment).with(hash_including(sensitive_tags)) - def metric_values(opts = {}) - { - duration: 0.0, - allocated_memory: a_kind_of(Numeric) - }.merge(opts) + transaction.add_event(:baubau, **sensitive_tags.merge(sane: 'yes')) + end + end end end diff --git a/spec/lib/gitlab/metrics/web_transaction_spec.rb b/spec/lib/gitlab/metrics/web_transaction_spec.rb index 21a762dbf25..47f1bd3bd10 100644 --- a/spec/lib/gitlab/metrics/web_transaction_spec.rb +++ b/spec/lib/gitlab/metrics/web_transaction_spec.rb @@ -5,6 +5,11 @@ require 'spec_helper' describe Gitlab::Metrics::WebTransaction do let(:env) { {} } let(:transaction) { described_class.new(env) } + let(:prometheus_metric) { double("prometheus metric") } + + before do + allow(described_class).to receive(:transaction_metric).and_return(prometheus_metric) + end describe '#duration' do it 'returns the duration of a transaction in seconds' do @@ -40,15 +45,6 @@ describe Gitlab::Metrics::WebTransaction do end end - describe '#add_metric' do - it 'adds a metric to the transaction' do - expect(Gitlab::Metrics::Metric).to receive(:new) - .with('rails_foo', { number: 10 }, {}) - - transaction.add_metric('foo', number: 10) - end - end - describe '#method_call_for' do it 'returns a MethodCall' do method = transaction.method_call_for('Foo#bar', :Foo, '#bar') @@ -59,101 +55,17 @@ describe Gitlab::Metrics::WebTransaction do describe '#increment' do it 'increments a counter' do - transaction.increment(:time, 1) - transaction.increment(:time, 2) - - values = { duration: 0.0, time: 3, allocated_memory: a_kind_of(Numeric) } + expect(prometheus_metric).to receive(:increment).with({}, 1) - expect(transaction).to receive(:add_metric) - .with('transactions', values, {}) - - transaction.track_self + transaction.increment(:time, 1) end end describe '#set' do it 'sets a value' do - transaction.set(:number, 10) - - values = { - duration: 0.0, - number: 10, - allocated_memory: a_kind_of(Numeric) - } - - expect(transaction).to receive(:add_metric) - .with('transactions', values, {}) - - transaction.track_self - end - end - - describe '#finish' do - it 'tracks the transaction details and submits them to Sidekiq' do - expect(transaction).to receive(:track_self) - expect(transaction).to receive(:submit) - - transaction.finish - end - end - - describe '#track_self' do - it 'adds a metric for the transaction itself' do - values = { - duration: transaction.duration, - allocated_memory: a_kind_of(Numeric) - } - - expect(transaction).to receive(:add_metric) - .with('transactions', values, {}) - - transaction.track_self - end - end - - describe '#submit' do - it 'submits the metrics to Sidekiq' do - transaction.track_self - - expect(Gitlab::Metrics).to receive(:submit_metrics) - .with([an_instance_of(Hash)]) - - transaction.submit - end + expect(prometheus_metric).to receive(:set).with({}, 10) - it 'adds the action as a tag for every metric' do - allow(transaction).to receive(:labels).and_return(controller: 'Foo', action: 'bar') - transaction.track_self - - hash = { - series: 'rails_transactions', - tags: { action: 'Foo#bar' }, - values: { duration: 0.0, allocated_memory: a_kind_of(Numeric) }, - timestamp: a_kind_of(Integer) - } - - expect(Gitlab::Metrics).to receive(:submit_metrics) - .with([hash]) - - transaction.submit - end - - it 'does not add an action tag for events' do - allow(transaction).to receive(:labels).and_return(controller: 'Foo', action: 'bar') - - transaction.add_event(:meow) - - hash = { - series: 'events', - tags: { event: :meow }, - values: { count: 1 }, - timestamp: a_kind_of(Integer) - } - - expect(Gitlab::Metrics).to receive(:submit_metrics) - .with([hash]) - - transaction.submit + transaction.set(:number, 10) end end @@ -167,7 +79,6 @@ describe Gitlab::Metrics::WebTransaction do end it 'provides labels with the method and path of the route in the grape endpoint' do expect(transaction.labels).to eq({ controller: 'Grape', action: 'GET /projects/:id/archive' }) - expect(transaction.action).to eq('Grape#GET /projects/:id/archive') end it 'does not provide labels if route infos are missing' do @@ -177,7 +88,6 @@ describe Gitlab::Metrics::WebTransaction do env['api.endpoint'] = endpoint expect(transaction.labels).to eq({}) - expect(transaction.action).to be_nil end end @@ -193,7 +103,6 @@ describe Gitlab::Metrics::WebTransaction do it 'tags a transaction with the name and action of a controller' do expect(transaction.labels).to eq({ controller: 'TestController', action: 'show' }) - expect(transaction.action).to eq('TestController#show') end context 'when the request content type is not :html' do @@ -201,7 +110,6 @@ describe Gitlab::Metrics::WebTransaction do it 'appends the mime type to the transaction action' do expect(transaction.labels).to eq({ controller: 'TestController', action: 'show.json' }) - expect(transaction.action).to eq('TestController#show.json') end end @@ -210,54 +118,26 @@ describe Gitlab::Metrics::WebTransaction do it 'does not append the MIME type to the transaction action' do expect(transaction.labels).to eq({ controller: 'TestController', action: 'show' }) - expect(transaction.action).to eq('TestController#show') end end end it 'returns no labels when no route information is present in env' do expect(transaction.labels).to eq({}) - expect(transaction.action).to eq(nil) end end describe '#add_event' do it 'adds a metric' do - transaction.add_event(:meow) + expect(prometheus_metric).to receive(:increment) - expect(transaction.metrics[0]).to be_an_instance_of(Gitlab::Metrics::Metric) - end - - it "does not prefix the metric's series name" do transaction.add_event(:meow) - - metric = transaction.metrics[0] - - expect(metric.series).to eq(described_class::EVENT_SERIES) - end - - it 'tracks a counter for every event' do - transaction.add_event(:meow) - - metric = transaction.metrics[0] - - expect(metric.values).to eq(count: 1) - end - - it 'tracks the event name' do - transaction.add_event(:meow) - - metric = transaction.metrics[0] - - expect(metric.tags).to eq(event: :meow) end it 'allows tracking of custom tags' do - transaction.add_event(:bau, animal: 'dog') - - metric = transaction.metrics[0] + expect(prometheus_metric).to receive(:increment).with(animal: "dog") - expect(metric.tags).to eq(event: :bau, animal: 'dog') + transaction.add_event(:bau, animal: 'dog') end end end |