debian-mirror-gitlab/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
2023-06-20 00:43:36 +05:30

232 lines
7.2 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Metrics::Subscribers::ExternalHttp, :request_store, feature_category: :logging do
let(:transaction) { Gitlab::Metrics::WebTransaction.new({}) }
let(:subscriber) { described_class.new }
around do |example|
freeze_time { example.run }
end
let(:event_1) do
double(
:event,
payload: {
method: 'POST', code: "200", duration: 0.321,
scheme: 'https', host: 'gitlab.com', port: 443, path: '/api/v4/projects',
query: 'current=true'
},
time: Time.current
)
end
let(:event_2) do
double(
:event,
payload: {
method: 'GET', code: "301", duration: 0.12,
scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
query: 'current=true'
},
time: Time.current
)
end
let(:event_3) do
double(
:event,
payload: {
method: 'POST', duration: 5.3,
scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
query: 'current=true',
exception_object: Net::ReadTimeout.new
},
time: Time.current
)
end
describe '.detail_store' do
context 'when external HTTP detail store is empty' do
before do
Gitlab::SafeRequestStore[:peek_enabled] = true
end
it 'returns an empty array' do
expect(described_class.detail_store).to eql([])
end
end
context 'when the performance bar is not enabled' do
it 'returns an empty array' do
expect(described_class.detail_store).to eql([])
end
end
context 'when external HTTP detail store has some values' do
before do
Gitlab::SafeRequestStore[:peek_enabled] = true
Gitlab::SafeRequestStore[:external_http_detail_store] = [{
method: 'POST', code: "200", duration: 0.321
}]
end
it 'returns the external http detailed store' do
expect(described_class.detail_store).to eql([{ method: 'POST', code: "200", duration: 0.321 }])
end
end
end
describe '.payload' do
context 'when SafeRequestStore does not have any item from external HTTP' do
it 'returns an empty array' do
expect(described_class.payload).to eql(external_http_count: 0, external_http_duration_s: 0.0)
end
end
context 'when external HTTP recorded some values' do
before do
Gitlab::SafeRequestStore[:external_http_count] = 7
Gitlab::SafeRequestStore[:external_http_duration_s] = 1.2
end
it 'returns the external http detailed store' do
expect(described_class.payload).to eql(external_http_count: 7, external_http_duration_s: 1.2)
end
end
context 'with multiple requests' do
let(:slow_requests) do
[
{
method: 'POST',
host: 'gitlab.com',
port: 80,
path: '/api/v4/projects/2/issues',
duration_s: 5.3
},
{
method: 'POST',
host: 'gitlab.com',
port: 443,
path: '/api/v4/projects',
duration_s: 0.321
}
]
end
before do
stub_const("#{described_class}::MAX_SLOW_REQUESTS", 2)
stub_const("#{described_class}::THRESHOLD_SLOW_REQUEST_S", 0.01)
subscriber.request(event_1)
subscriber.request(event_2)
subscriber.request(event_3)
end
it 'returns a payload containing a limited set of slow requests' do
expect(described_class.payload).to eq(
external_http_count: 3,
external_http_duration_s: 5.741,
external_http_slow_requests: slow_requests
)
expect(described_class.top_slowest_requests).to eq(slow_requests)
expect(Gitlab::SafeRequestStore[:external_http_slow_requests].length).to eq(3)
end
end
end
describe '#request' do
before do
Gitlab::SafeRequestStore[:peek_enabled] = true
allow(subscriber).to receive(:current_transaction).and_return(transaction)
end
it 'tracks external HTTP request count' do
expect(transaction).to receive(:increment)
.with(:gitlab_external_http_total, 1, { code: "200", method: "POST" })
expect(transaction).to receive(:increment)
.with(:gitlab_external_http_total, 1, { code: "301", method: "GET" })
subscriber.request(event_1)
subscriber.request(event_2)
end
it 'tracks external HTTP duration' do
expect(transaction).to receive(:observe)
.with(:gitlab_external_http_duration_seconds, 0.321)
expect(transaction).to receive(:observe)
.with(:gitlab_external_http_duration_seconds, 0.12)
expect(transaction).to receive(:observe)
.with(:gitlab_external_http_duration_seconds, 5.3)
subscriber.request(event_1)
subscriber.request(event_2)
subscriber.request(event_3)
end
it 'tracks external HTTP exceptions' do
expect(transaction).to receive(:increment)
.with(:gitlab_external_http_total, 1, { code: 'undefined', method: "POST" })
expect(transaction).to receive(:increment)
.with(:gitlab_external_http_exception_total, 1)
subscriber.request(event_3)
end
it 'stores per-request counters' do
subscriber.request(event_1)
subscriber.request(event_2)
subscriber.request(event_3)
expect(Gitlab::SafeRequestStore[:external_http_count]).to eq(3)
expect(Gitlab::SafeRequestStore[:external_http_duration_s]).to eq(5.741) # 0.321 + 0.12 + 5.3
end
it 'stores a portion of events into the detail store' do
subscriber.request(event_1)
subscriber.request(event_2)
subscriber.request(event_3)
expect(Gitlab::SafeRequestStore[:external_http_detail_store].length).to eq(3)
expect(Gitlab::SafeRequestStore[:external_http_detail_store][0]).to match a_hash_including(
start: be_like_time(Time.current),
method: 'POST', code: "200", duration: 0.321,
scheme: 'https', host: 'gitlab.com', port: 443, path: '/api/v4/projects',
query: 'current=true', exception_object: nil,
backtrace: be_a(Array)
)
expect(Gitlab::SafeRequestStore[:external_http_detail_store][1]).to match a_hash_including(
start: be_like_time(Time.current),
method: 'GET', code: "301", duration: 0.12,
scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
query: 'current=true', exception_object: nil,
backtrace: be_a(Array)
)
expect(Gitlab::SafeRequestStore[:external_http_detail_store][2]).to match a_hash_including(
start: be_like_time(Time.current),
method: 'POST', duration: 5.3,
scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
query: 'current=true',
exception_object: be_a(Net::ReadTimeout),
backtrace: be_a(Array)
)
end
context 'when the performance bar is not enabled' do
before do
Gitlab::SafeRequestStore.delete(:peek_enabled)
end
it 'does not capture detail store' do
subscriber.request(event_1)
subscriber.request(event_2)
subscriber.request(event_3)
expect(Gitlab::SafeRequestStore[:external_http_detail_store]).to be(nil)
end
end
end
end