lhc 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +37 -0
- data/.rubocop.localch.yml +325 -0
- data/.rubocop.yml +61 -0
- data/.ruby-version +1 -0
- data/Gemfile +13 -0
- data/Gemfile.activesupport4 +4 -0
- data/Gemfile.activesupport5 +4 -0
- data/Gemfile.activesupport6 +4 -0
- data/LICENSE +674 -0
- data/README.md +984 -0
- data/Rakefile +25 -0
- data/cider-ci.yml +6 -0
- data/cider-ci/bin/bundle +51 -0
- data/cider-ci/bin/ruby_install +8 -0
- data/cider-ci/bin/ruby_version +25 -0
- data/cider-ci/jobs/rspec-activesupport-4.yml +28 -0
- data/cider-ci/jobs/rspec-activesupport-5.yml +27 -0
- data/cider-ci/jobs/rspec-activesupport-6.yml +28 -0
- data/cider-ci/jobs/rubocop.yml +18 -0
- data/cider-ci/task_components/bundle.yml +22 -0
- data/cider-ci/task_components/rspec.yml +36 -0
- data/cider-ci/task_components/rubocop.yml +29 -0
- data/cider-ci/task_components/ruby.yml +15 -0
- data/friday.yml +3 -0
- data/lhc.gemspec +39 -0
- data/lib/core_ext/hash/deep_transform_values.rb +48 -0
- data/lib/lhc.rb +136 -0
- data/lib/lhc/concerns/lhc/basic_methods_concern.rb +42 -0
- data/lib/lhc/concerns/lhc/configuration_concern.rb +20 -0
- data/lib/lhc/concerns/lhc/fix_invalid_encoding_concern.rb +42 -0
- data/lib/lhc/concerns/lhc/formats_concern.rb +25 -0
- data/lib/lhc/concerns/lhc/request/user_agent_concern.rb +25 -0
- data/lib/lhc/config.rb +47 -0
- data/lib/lhc/endpoint.rb +119 -0
- data/lib/lhc/error.rb +80 -0
- data/lib/lhc/errors/client_error.rb +73 -0
- data/lib/lhc/errors/parser_error.rb +4 -0
- data/lib/lhc/errors/server_error.rb +28 -0
- data/lib/lhc/errors/timeout.rb +4 -0
- data/lib/lhc/errors/unknown_error.rb +4 -0
- data/lib/lhc/format.rb +18 -0
- data/lib/lhc/formats.rb +8 -0
- data/lib/lhc/formats/form.rb +45 -0
- data/lib/lhc/formats/json.rb +55 -0
- data/lib/lhc/formats/multipart.rb +45 -0
- data/lib/lhc/formats/plain.rb +42 -0
- data/lib/lhc/interceptor.rb +32 -0
- data/lib/lhc/interceptors.rb +26 -0
- data/lib/lhc/interceptors/auth.rb +98 -0
- data/lib/lhc/interceptors/caching.rb +127 -0
- data/lib/lhc/interceptors/default_timeout.rb +16 -0
- data/lib/lhc/interceptors/logging.rb +37 -0
- data/lib/lhc/interceptors/monitoring.rb +63 -0
- data/lib/lhc/interceptors/prometheus.rb +51 -0
- data/lib/lhc/interceptors/retry.rb +41 -0
- data/lib/lhc/interceptors/rollbar.rb +36 -0
- data/lib/lhc/interceptors/throttle.rb +81 -0
- data/lib/lhc/interceptors/zipkin.rb +110 -0
- data/lib/lhc/railtie.rb +10 -0
- data/lib/lhc/request.rb +157 -0
- data/lib/lhc/response.rb +60 -0
- data/lib/lhc/response/data.rb +28 -0
- data/lib/lhc/response/data/base.rb +22 -0
- data/lib/lhc/response/data/collection.rb +16 -0
- data/lib/lhc/response/data/item.rb +29 -0
- data/lib/lhc/rspec.rb +12 -0
- data/lib/lhc/test/cache_helper.rb +3 -0
- data/lib/lhc/version.rb +5 -0
- data/script/ci/build.sh +19 -0
- data/spec/basic_methods/delete_spec.rb +34 -0
- data/spec/basic_methods/get_spec.rb +49 -0
- data/spec/basic_methods/post_spec.rb +42 -0
- data/spec/basic_methods/put_spec.rb +48 -0
- data/spec/basic_methods/request_spec.rb +19 -0
- data/spec/basic_methods/request_without_rails_spec.rb +29 -0
- data/spec/config/endpoints_spec.rb +63 -0
- data/spec/config/placeholders_spec.rb +32 -0
- data/spec/core_ext/hash/deep_transform_values_spec.rb +24 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +8 -0
- data/spec/dummy/app/assets/config/manifest.js +3 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +7 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +4 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +5 -0
- data/spec/dummy/bin/rails +6 -0
- data/spec/dummy/bin/rake +6 -0
- data/spec/dummy/config.ru +6 -0
- data/spec/dummy/config/application.rb +16 -0
- data/spec/dummy/config/boot.rb +7 -0
- data/spec/dummy/config/environment.rb +7 -0
- data/spec/dummy/config/environments/development.rb +36 -0
- data/spec/dummy/config/environments/production.rb +77 -0
- data/spec/dummy/config/environments/test.rb +41 -0
- data/spec/dummy/config/initializers/assets.rb +10 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
- data/spec/dummy/config/initializers/inflections.rb +18 -0
- data/spec/dummy/config/initializers/mime_types.rb +6 -0
- data/spec/dummy/config/initializers/session_store.rb +5 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/endpoint/compile_spec.rb +35 -0
- data/spec/endpoint/match_spec.rb +41 -0
- data/spec/endpoint/placeholders_spec.rb +30 -0
- data/spec/endpoint/remove_interpolated_params_spec.rb +17 -0
- data/spec/endpoint/values_as_params_spec.rb +31 -0
- data/spec/error/dup_spec.rb +12 -0
- data/spec/error/find_spec.rb +57 -0
- data/spec/error/response_spec.rb +17 -0
- data/spec/error/timeout_spec.rb +14 -0
- data/spec/error/to_s_spec.rb +80 -0
- data/spec/formats/form_spec.rb +27 -0
- data/spec/formats/json_spec.rb +66 -0
- data/spec/formats/multipart_spec.rb +26 -0
- data/spec/formats/plain_spec.rb +29 -0
- data/spec/interceptors/after_request_spec.rb +20 -0
- data/spec/interceptors/after_response_spec.rb +39 -0
- data/spec/interceptors/auth/basic_auth_spec.rb +17 -0
- data/spec/interceptors/auth/bearer_spec.rb +19 -0
- data/spec/interceptors/auth/reauthentication_configuration_spec.rb +61 -0
- data/spec/interceptors/auth/reauthentication_spec.rb +44 -0
- data/spec/interceptors/before_request_spec.rb +21 -0
- data/spec/interceptors/before_response_spec.rb +20 -0
- data/spec/interceptors/caching/hydra_spec.rb +26 -0
- data/spec/interceptors/caching/main_spec.rb +73 -0
- data/spec/interceptors/caching/methods_spec.rb +42 -0
- data/spec/interceptors/caching/options_spec.rb +89 -0
- data/spec/interceptors/caching/parameters_spec.rb +24 -0
- data/spec/interceptors/caching/response_status_spec.rb +29 -0
- data/spec/interceptors/caching/to_cache_spec.rb +16 -0
- data/spec/interceptors/default_interceptors_spec.rb +15 -0
- data/spec/interceptors/default_timeout/main_spec.rb +34 -0
- data/spec/interceptors/define_spec.rb +29 -0
- data/spec/interceptors/dup_spec.rb +19 -0
- data/spec/interceptors/logging/main_spec.rb +37 -0
- data/spec/interceptors/monitoring/main_spec.rb +97 -0
- data/spec/interceptors/prometheus_spec.rb +54 -0
- data/spec/interceptors/response_competition_spec.rb +41 -0
- data/spec/interceptors/retry/main_spec.rb +73 -0
- data/spec/interceptors/return_response_spec.rb +38 -0
- data/spec/interceptors/rollbar/invalid_encoding_spec.rb +43 -0
- data/spec/interceptors/rollbar/main_spec.rb +57 -0
- data/spec/interceptors/throttle/main_spec.rb +106 -0
- data/spec/interceptors/throttle/reset_track_spec.rb +53 -0
- data/spec/interceptors/zipkin/distributed_tracing_spec.rb +135 -0
- data/spec/rails_helper.rb +6 -0
- data/spec/request/body_spec.rb +39 -0
- data/spec/request/encoding_spec.rb +37 -0
- data/spec/request/error_handling_spec.rb +88 -0
- data/spec/request/headers_spec.rb +12 -0
- data/spec/request/ignore_errors_spec.rb +73 -0
- data/spec/request/option_dup_spec.rb +13 -0
- data/spec/request/parallel_requests_spec.rb +59 -0
- data/spec/request/params_encoding_spec.rb +26 -0
- data/spec/request/request_without_rails_spec.rb +15 -0
- data/spec/request/url_patterns_spec.rb +54 -0
- data/spec/request/user_agent_spec.rb +26 -0
- data/spec/request/user_agent_without_rails_spec.rb +27 -0
- data/spec/response/body_spec.rb +16 -0
- data/spec/response/code_spec.rb +16 -0
- data/spec/response/data_accessor_spec.rb +29 -0
- data/spec/response/data_spec.rb +61 -0
- data/spec/response/effective_url_spec.rb +16 -0
- data/spec/response/headers_spec.rb +18 -0
- data/spec/response/options_spec.rb +18 -0
- data/spec/response/success_spec.rb +13 -0
- data/spec/response/time_spec.rb +21 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/fixtures/json/feedback.json +11 -0
- data/spec/support/fixtures/json/feedbacks.json +164 -0
- data/spec/support/fixtures/json/localina_content_ad.json +23 -0
- data/spec/support/load_json.rb +5 -0
- data/spec/support/reset_config.rb +7 -0
- data/spec/support/zipkin_mock.rb +113 -0
- data/spec/timeouts/no_signal_spec.rb +13 -0
- data/spec/timeouts/timings_spec.rb +55 -0
- metadata +534 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
# due to the fact that options passed into LHC get dup'ed
|
|
6
|
+
# we need a class where we can setup method expectations
|
|
7
|
+
# with `expect_any_instance`
|
|
8
|
+
class CacheMock
|
|
9
|
+
def fetch(*_); end
|
|
10
|
+
|
|
11
|
+
def write(*_); end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe LHC::Caching do
|
|
15
|
+
let(:default_cache) { LHC::Caching.cache }
|
|
16
|
+
|
|
17
|
+
before(:each) do
|
|
18
|
+
stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website')
|
|
19
|
+
LHC.config.interceptors = [LHC::Caching]
|
|
20
|
+
default_cache.clear
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'maps deprecated cache options' do
|
|
24
|
+
expected_options = { expires_in: 5.minutes, race_condition_ttl: 15.seconds }
|
|
25
|
+
expected_key = "LHC_CACHE(v1): key"
|
|
26
|
+
expect(default_cache).to receive(:write).with(expected_key, anything, expected_options)
|
|
27
|
+
expect(lambda {
|
|
28
|
+
LHC.get('http://local.ch', cache: true, cache_expires_in: 5.minutes, cache_key: 'key', cache_race_condition_ttl: 15.seconds)
|
|
29
|
+
}).to output(
|
|
30
|
+
/Cache options have changed! cache_expires_in, cache_key, cache_race_condition_ttl are deprecated and will be removed in future versions./
|
|
31
|
+
).to_stderr
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'does cache' do
|
|
35
|
+
expect(default_cache).to receive(:fetch)
|
|
36
|
+
expect(default_cache).to receive(:write)
|
|
37
|
+
LHC.get('http://local.ch', cache: true)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'does not cache' do
|
|
41
|
+
expect(default_cache).not_to receive(:fetch)
|
|
42
|
+
expect(default_cache).not_to receive(:write)
|
|
43
|
+
LHC.get('http://local.ch')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'options - directly via LHC.get' do
|
|
47
|
+
it 'uses the default cache' do
|
|
48
|
+
expect(default_cache).to receive(:fetch)
|
|
49
|
+
expect(default_cache).to receive(:write)
|
|
50
|
+
LHC.get('http://local.ch', cache: true)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'uses the provided cache' do
|
|
54
|
+
expect_any_instance_of(CacheMock).to receive(:fetch)
|
|
55
|
+
expect_any_instance_of(CacheMock).to receive(:write)
|
|
56
|
+
LHC.get('http://local.ch', cache: { use: CacheMock.new })
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'cache options are properly forwarded to the cache' do
|
|
60
|
+
cache_options = { expires_in: 5.minutes, race_condition_ttl: 15.seconds }
|
|
61
|
+
expect(default_cache).to receive(:write).with(anything, anything, cache_options)
|
|
62
|
+
LHC.get('http://local.ch', cache: cache_options)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'options - via endpoint configuration' do
|
|
67
|
+
it 'uses the default cache' do
|
|
68
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true)
|
|
69
|
+
expect(default_cache).to receive(:fetch)
|
|
70
|
+
expect(default_cache).to receive(:write)
|
|
71
|
+
LHC.get(:local)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'uses the provided cache' do
|
|
75
|
+
options = { cache: { use: CacheMock.new } }
|
|
76
|
+
LHC.config.endpoint(:local, 'http://local.ch', options)
|
|
77
|
+
expect_any_instance_of(CacheMock).to receive(:fetch)
|
|
78
|
+
expect_any_instance_of(CacheMock).to receive(:write)
|
|
79
|
+
LHC.get(:local)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'cache options are properly forwarded to the cache' do
|
|
83
|
+
cache_options = { expires_in: 5.minutes, race_condition_ttl: 15.seconds }
|
|
84
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: cache_options)
|
|
85
|
+
expect(default_cache).to receive(:write).with(anything, anything, cache_options)
|
|
86
|
+
LHC.get(:local)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Caching do
|
|
6
|
+
context 'parameters' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
LHC.config.interceptors = [LHC::Caching]
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'considers parameters when writing/reading from cache' do
|
|
13
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true)
|
|
14
|
+
stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website')
|
|
15
|
+
stub_request(:get, 'http://local.ch?location=zuerich').to_return(status: 200, body: 'The Website for Zuerich')
|
|
16
|
+
expect(
|
|
17
|
+
LHC.get(:local).body
|
|
18
|
+
).to eq 'The Website'
|
|
19
|
+
expect(
|
|
20
|
+
LHC.get(:local, params: { location: 'zuerich' }).body
|
|
21
|
+
).to eq 'The Website for Zuerich'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Caching do
|
|
6
|
+
before(:each) do
|
|
7
|
+
LHC.config.interceptors = [LHC::Caching]
|
|
8
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true)
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
# leverage the Typhoeus internal mock attribute in order to get Typhoeus evaluate the return_code
|
|
11
|
+
# lib/typhoeus/response/status.rb:48
|
|
12
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:mock).and_return(false)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let!(:stub) { stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website') }
|
|
16
|
+
|
|
17
|
+
it 'provides the correct response status for responses from cache' do
|
|
18
|
+
stub
|
|
19
|
+
# the real request provides the return_code
|
|
20
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:options)
|
|
21
|
+
.and_return(code: 200, status_message: '', body: 'The Website', headers: nil, return_code: :ok)
|
|
22
|
+
response = LHC.get(:local)
|
|
23
|
+
expect(response.success?).to eq true
|
|
24
|
+
# the cached response should get it from the cache
|
|
25
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:options).and_call_original
|
|
26
|
+
cached_response = LHC.get(:local)
|
|
27
|
+
expect(cached_response.success?).to eq true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Caching do
|
|
6
|
+
context 'to_cache' do
|
|
7
|
+
it 'returns a marshalable object to store in the cache' do
|
|
8
|
+
expect do
|
|
9
|
+
response = Typhoeus::Response.new(headers: { 'Accept' => 'application/json' })
|
|
10
|
+
Marshal.dump(
|
|
11
|
+
LHC::Caching.new(response).send(:to_cache, response)
|
|
12
|
+
)
|
|
13
|
+
end.not_to raise_error
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
context 'default interceptors' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
LHC.configure {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'alwayses return a list for default interceptors' do
|
|
12
|
+
expect(LHC.config.interceptors).to eq []
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::DefaultTimeout do
|
|
6
|
+
before(:each) do
|
|
7
|
+
LHC.config.interceptors = [LHC::DefaultTimeout]
|
|
8
|
+
LHC::DefaultTimeout.timeout = nil
|
|
9
|
+
LHC::DefaultTimeout.connecttimeout = nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:stub) { stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website') }
|
|
13
|
+
|
|
14
|
+
it 'applies default timeouts to all requests made' do
|
|
15
|
+
stub
|
|
16
|
+
expect_any_instance_of(Ethon::Easy).to receive(:http_request)
|
|
17
|
+
.with(anything, anything, hash_including(timeout: 15, connecttimeout: 2)).and_call_original
|
|
18
|
+
LHC.get('http://local.ch')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context 'with changed default timesouts' do
|
|
22
|
+
before(:each) do
|
|
23
|
+
LHC::DefaultTimeout.timeout = 10
|
|
24
|
+
LHC::DefaultTimeout.connecttimeout = 3
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'applies custom default timeouts to all requests made' do
|
|
28
|
+
stub
|
|
29
|
+
expect_any_instance_of(Ethon::Easy).to receive(:http_request)
|
|
30
|
+
.with(anything, anything, hash_including(timeout: 10, connecttimeout: 3)).and_call_original
|
|
31
|
+
LHC.get('http://local.ch')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class SomeInterceptor < LHC::Interceptor
|
|
9
|
+
end
|
|
10
|
+
class AnotherInterceptor < LHC::Interceptor
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'performs interceptor when they are set globally' do
|
|
15
|
+
LHC.configure { |c| c.interceptors = [SomeInterceptor] }
|
|
16
|
+
expect_any_instance_of(SomeInterceptor).to receive(:before_request)
|
|
17
|
+
stub_request(:get, 'http://local.ch')
|
|
18
|
+
LHC.get('http://local.ch')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'overrides interceptors on request level' do
|
|
22
|
+
LHC.configure { |c| c.interceptors = [SomeInterceptor] }
|
|
23
|
+
expect_any_instance_of(AnotherInterceptor).to receive(:before_request)
|
|
24
|
+
expect_any_instance_of(SomeInterceptor).not_to receive(:before_request)
|
|
25
|
+
stub_request(:get, 'http://local.ch')
|
|
26
|
+
LHC.get('http://local.ch', interceptors: [AnotherInterceptor])
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class SomeInterceptor < LHC::Interceptor
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'does not dup' do
|
|
13
|
+
options = { interceptors: [SomeInterceptor] }
|
|
14
|
+
expect(
|
|
15
|
+
options.deep_dup[:interceptors].include?(SomeInterceptor)
|
|
16
|
+
).to eq true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Logging do
|
|
6
|
+
let(:logger) { spy('logger') }
|
|
7
|
+
|
|
8
|
+
before(:each) do
|
|
9
|
+
LHC.config.interceptors = [LHC::Logging]
|
|
10
|
+
LHC::Logging.logger = logger
|
|
11
|
+
stub_request(:get, 'http://local.ch').to_return(status: 200)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'does log information before and after every request made with LHC' do
|
|
15
|
+
LHC.get('http://local.ch')
|
|
16
|
+
expect(logger).to have_received(:info).once.with(
|
|
17
|
+
%r{Before LHC request <\d+> GET http://local.ch at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Params={} Headers={.*?}}
|
|
18
|
+
)
|
|
19
|
+
expect(logger).to have_received(:info).once.with(
|
|
20
|
+
%r{After LHC response for request <\d+> GET http://local.ch at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Time=0ms URL=http://local.ch:80/}
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'source' do
|
|
25
|
+
let(:source) { '/Users/Sebastian/LHC/test.rb' }
|
|
26
|
+
|
|
27
|
+
it 'does log the source if provided as option' do
|
|
28
|
+
LHC.get('http://local.ch', source: source)
|
|
29
|
+
expect(logger).to have_received(:info).once.with(
|
|
30
|
+
%r{Before LHC request <\d+> GET http://local.ch at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Params={} Headers={.*?} \nCalled from #{source}}
|
|
31
|
+
)
|
|
32
|
+
expect(logger).to have_received(:info).once.with(
|
|
33
|
+
%r{After LHC response for request <\d+> GET http://local.ch at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Time=0ms URL=http://local.ch:80/ \nCalled from #{source}}
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Monitoring do
|
|
6
|
+
let(:stub) { stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website') }
|
|
7
|
+
let(:endpoint_configuration) { LHC.config.endpoint(:local, 'http://local.ch') }
|
|
8
|
+
|
|
9
|
+
module Statsd
|
|
10
|
+
def self.count(_path, _value); end
|
|
11
|
+
|
|
12
|
+
def self.timing(_path, _value); end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
before(:each) do
|
|
16
|
+
LHC.config.interceptors = [LHC::Monitoring]
|
|
17
|
+
LHC::Monitoring.statsd = Statsd
|
|
18
|
+
Rails.cache.clear
|
|
19
|
+
endpoint_configuration
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'does not report anything if no statsd is configured' do
|
|
23
|
+
stub
|
|
24
|
+
LHC.get(:local) # and also does not crash ;)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'statsd configured' do
|
|
28
|
+
it 'reports trial, response and timing by default ' do
|
|
29
|
+
stub
|
|
30
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
|
31
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
|
32
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
|
33
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.200', 1)
|
|
34
|
+
expect(Statsd).to receive(:timing).with('lhc.dummy.test.local_ch.get.time', anything)
|
|
35
|
+
LHC.get(:local)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'does not report timing when response failed' do
|
|
39
|
+
stub_request(:get, 'http://local.ch').to_return(status: 500)
|
|
40
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
|
41
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
|
42
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
|
43
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.500', 1)
|
|
44
|
+
expect(Statsd).not_to receive(:timing)
|
|
45
|
+
expect { LHC.get(:local) }.to raise_error LHC::ServerError
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'reports timeout instead of status code if response timed out' do
|
|
49
|
+
stub_request(:get, 'http://local.ch').to_timeout
|
|
50
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
|
51
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
|
52
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
|
53
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.timeout', 1)
|
|
54
|
+
expect(Statsd).not_to receive(:timing)
|
|
55
|
+
expect { LHC.get(:local) }.to raise_error LHC::Timeout
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'allows to set the stats key for request' do
|
|
59
|
+
stub
|
|
60
|
+
expect(Statsd).to receive(:count).with('defined_key.before_request', 1)
|
|
61
|
+
expect(Statsd).to receive(:count).with('defined_key.after_request', 1)
|
|
62
|
+
expect(Statsd).to receive(:count).with('defined_key.count', 1)
|
|
63
|
+
expect(Statsd).to receive(:count).with('defined_key.200', 1)
|
|
64
|
+
expect(Statsd).to receive(:timing).with('defined_key.time', anything)
|
|
65
|
+
LHC.get(:local, monitoring_key: 'defined_key')
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'without protocol' do
|
|
70
|
+
let(:endpoint_configuration) { LHC.config.endpoint(:local, 'local.ch') }
|
|
71
|
+
|
|
72
|
+
it 'reports trial, response and timing by default ' do
|
|
73
|
+
stub
|
|
74
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
|
75
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
|
76
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
|
77
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.200', 1)
|
|
78
|
+
expect(Statsd).to receive(:timing).with('lhc.dummy.test.local_ch.get.time', anything)
|
|
79
|
+
LHC.get(:local)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'with configured environment' do
|
|
84
|
+
before do
|
|
85
|
+
LHC::Monitoring.env = 'beta'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'uses the configured env' do
|
|
89
|
+
stub
|
|
90
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.beta.local_ch.get.before_request', 1)
|
|
91
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.beta.local_ch.get.after_request', 1)
|
|
92
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.beta.local_ch.get.count', 1)
|
|
93
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.beta.local_ch.get.200', 1)
|
|
94
|
+
LHC.get(:local)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
require 'prometheus/client'
|
|
5
|
+
|
|
6
|
+
describe LHC::Prometheus do
|
|
7
|
+
before(:each) do
|
|
8
|
+
LHC.config.interceptors = [LHC::Prometheus]
|
|
9
|
+
LHC::Prometheus.client = Prometheus::Client
|
|
10
|
+
LHC::Prometheus.namespace = 'test_app'
|
|
11
|
+
stub_request(:get, 'http://local.ch')
|
|
12
|
+
expect(Prometheus::Client).to receive(:registry).and_call_original.at_least(:once)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let(:client) { double("prometheus/client") }
|
|
16
|
+
|
|
17
|
+
context 'registering' do
|
|
18
|
+
it 'creates a counter and histogram registry in the prometheus client' do
|
|
19
|
+
expect(Prometheus::Client.registry).to receive(:counter).and_call_original.once
|
|
20
|
+
.with(:lhc_requests, 'Counter of all LHC requests.')
|
|
21
|
+
expect(Prometheus::Client.registry).to receive(:histogram).and_call_original.once
|
|
22
|
+
.with(:lhc_request_seconds, 'Request timings for all LHC requests in seconds.')
|
|
23
|
+
|
|
24
|
+
LHC.get('http://local.ch')
|
|
25
|
+
LHC.get('http://local.ch') # second request, registration should happen only once
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context 'logging' do
|
|
30
|
+
let(:requests_registry_double) { double('requests_registry_double') }
|
|
31
|
+
let(:times_registry_double) { double('times_registry_double') }
|
|
32
|
+
|
|
33
|
+
it 'logs monitoring information to the created registries' do
|
|
34
|
+
expect(Prometheus::Client.registry).to receive(:get).and_return(requests_registry_double).once
|
|
35
|
+
.with(:lhc_requests)
|
|
36
|
+
expect(Prometheus::Client.registry).to receive(:get).and_return(times_registry_double).once
|
|
37
|
+
.with(:lhc_request_seconds)
|
|
38
|
+
|
|
39
|
+
expect(requests_registry_double).to receive(:increment).once
|
|
40
|
+
.with(
|
|
41
|
+
code: 200,
|
|
42
|
+
success: true,
|
|
43
|
+
timeout: false,
|
|
44
|
+
app: 'test_app',
|
|
45
|
+
host: 'local.ch'
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
expect(times_registry_double).to receive(:observe).once
|
|
49
|
+
.with({ host: 'local.ch', app: 'test_app' }, 0)
|
|
50
|
+
|
|
51
|
+
LHC.get('http://local.ch')
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|