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.
Files changed (195) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +37 -0
  3. data/.rubocop.localch.yml +325 -0
  4. data/.rubocop.yml +61 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +13 -0
  7. data/Gemfile.activesupport4 +4 -0
  8. data/Gemfile.activesupport5 +4 -0
  9. data/Gemfile.activesupport6 +4 -0
  10. data/LICENSE +674 -0
  11. data/README.md +984 -0
  12. data/Rakefile +25 -0
  13. data/cider-ci.yml +6 -0
  14. data/cider-ci/bin/bundle +51 -0
  15. data/cider-ci/bin/ruby_install +8 -0
  16. data/cider-ci/bin/ruby_version +25 -0
  17. data/cider-ci/jobs/rspec-activesupport-4.yml +28 -0
  18. data/cider-ci/jobs/rspec-activesupport-5.yml +27 -0
  19. data/cider-ci/jobs/rspec-activesupport-6.yml +28 -0
  20. data/cider-ci/jobs/rubocop.yml +18 -0
  21. data/cider-ci/task_components/bundle.yml +22 -0
  22. data/cider-ci/task_components/rspec.yml +36 -0
  23. data/cider-ci/task_components/rubocop.yml +29 -0
  24. data/cider-ci/task_components/ruby.yml +15 -0
  25. data/friday.yml +3 -0
  26. data/lhc.gemspec +39 -0
  27. data/lib/core_ext/hash/deep_transform_values.rb +48 -0
  28. data/lib/lhc.rb +136 -0
  29. data/lib/lhc/concerns/lhc/basic_methods_concern.rb +42 -0
  30. data/lib/lhc/concerns/lhc/configuration_concern.rb +20 -0
  31. data/lib/lhc/concerns/lhc/fix_invalid_encoding_concern.rb +42 -0
  32. data/lib/lhc/concerns/lhc/formats_concern.rb +25 -0
  33. data/lib/lhc/concerns/lhc/request/user_agent_concern.rb +25 -0
  34. data/lib/lhc/config.rb +47 -0
  35. data/lib/lhc/endpoint.rb +119 -0
  36. data/lib/lhc/error.rb +80 -0
  37. data/lib/lhc/errors/client_error.rb +73 -0
  38. data/lib/lhc/errors/parser_error.rb +4 -0
  39. data/lib/lhc/errors/server_error.rb +28 -0
  40. data/lib/lhc/errors/timeout.rb +4 -0
  41. data/lib/lhc/errors/unknown_error.rb +4 -0
  42. data/lib/lhc/format.rb +18 -0
  43. data/lib/lhc/formats.rb +8 -0
  44. data/lib/lhc/formats/form.rb +45 -0
  45. data/lib/lhc/formats/json.rb +55 -0
  46. data/lib/lhc/formats/multipart.rb +45 -0
  47. data/lib/lhc/formats/plain.rb +42 -0
  48. data/lib/lhc/interceptor.rb +32 -0
  49. data/lib/lhc/interceptors.rb +26 -0
  50. data/lib/lhc/interceptors/auth.rb +98 -0
  51. data/lib/lhc/interceptors/caching.rb +127 -0
  52. data/lib/lhc/interceptors/default_timeout.rb +16 -0
  53. data/lib/lhc/interceptors/logging.rb +37 -0
  54. data/lib/lhc/interceptors/monitoring.rb +63 -0
  55. data/lib/lhc/interceptors/prometheus.rb +51 -0
  56. data/lib/lhc/interceptors/retry.rb +41 -0
  57. data/lib/lhc/interceptors/rollbar.rb +36 -0
  58. data/lib/lhc/interceptors/throttle.rb +81 -0
  59. data/lib/lhc/interceptors/zipkin.rb +110 -0
  60. data/lib/lhc/railtie.rb +10 -0
  61. data/lib/lhc/request.rb +157 -0
  62. data/lib/lhc/response.rb +60 -0
  63. data/lib/lhc/response/data.rb +28 -0
  64. data/lib/lhc/response/data/base.rb +22 -0
  65. data/lib/lhc/response/data/collection.rb +16 -0
  66. data/lib/lhc/response/data/item.rb +29 -0
  67. data/lib/lhc/rspec.rb +12 -0
  68. data/lib/lhc/test/cache_helper.rb +3 -0
  69. data/lib/lhc/version.rb +5 -0
  70. data/script/ci/build.sh +19 -0
  71. data/spec/basic_methods/delete_spec.rb +34 -0
  72. data/spec/basic_methods/get_spec.rb +49 -0
  73. data/spec/basic_methods/post_spec.rb +42 -0
  74. data/spec/basic_methods/put_spec.rb +48 -0
  75. data/spec/basic_methods/request_spec.rb +19 -0
  76. data/spec/basic_methods/request_without_rails_spec.rb +29 -0
  77. data/spec/config/endpoints_spec.rb +63 -0
  78. data/spec/config/placeholders_spec.rb +32 -0
  79. data/spec/core_ext/hash/deep_transform_values_spec.rb +24 -0
  80. data/spec/dummy/README.rdoc +28 -0
  81. data/spec/dummy/Rakefile +8 -0
  82. data/spec/dummy/app/assets/config/manifest.js +3 -0
  83. data/spec/dummy/app/assets/images/.keep +0 -0
  84. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  85. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  86. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  87. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  88. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  89. data/spec/dummy/app/mailers/.keep +0 -0
  90. data/spec/dummy/app/models/.keep +0 -0
  91. data/spec/dummy/app/models/concerns/.keep +0 -0
  92. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  93. data/spec/dummy/bin/bundle +5 -0
  94. data/spec/dummy/bin/rails +6 -0
  95. data/spec/dummy/bin/rake +6 -0
  96. data/spec/dummy/config.ru +6 -0
  97. data/spec/dummy/config/application.rb +16 -0
  98. data/spec/dummy/config/boot.rb +7 -0
  99. data/spec/dummy/config/environment.rb +7 -0
  100. data/spec/dummy/config/environments/development.rb +36 -0
  101. data/spec/dummy/config/environments/production.rb +77 -0
  102. data/spec/dummy/config/environments/test.rb +41 -0
  103. data/spec/dummy/config/initializers/assets.rb +10 -0
  104. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  105. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  106. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  107. data/spec/dummy/config/initializers/inflections.rb +18 -0
  108. data/spec/dummy/config/initializers/mime_types.rb +6 -0
  109. data/spec/dummy/config/initializers/session_store.rb +5 -0
  110. data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
  111. data/spec/dummy/config/locales/en.yml +23 -0
  112. data/spec/dummy/config/routes.rb +58 -0
  113. data/spec/dummy/config/secrets.yml +22 -0
  114. data/spec/dummy/lib/assets/.keep +0 -0
  115. data/spec/dummy/log/.keep +0 -0
  116. data/spec/dummy/public/404.html +67 -0
  117. data/spec/dummy/public/422.html +67 -0
  118. data/spec/dummy/public/500.html +66 -0
  119. data/spec/dummy/public/favicon.ico +0 -0
  120. data/spec/endpoint/compile_spec.rb +35 -0
  121. data/spec/endpoint/match_spec.rb +41 -0
  122. data/spec/endpoint/placeholders_spec.rb +30 -0
  123. data/spec/endpoint/remove_interpolated_params_spec.rb +17 -0
  124. data/spec/endpoint/values_as_params_spec.rb +31 -0
  125. data/spec/error/dup_spec.rb +12 -0
  126. data/spec/error/find_spec.rb +57 -0
  127. data/spec/error/response_spec.rb +17 -0
  128. data/spec/error/timeout_spec.rb +14 -0
  129. data/spec/error/to_s_spec.rb +80 -0
  130. data/spec/formats/form_spec.rb +27 -0
  131. data/spec/formats/json_spec.rb +66 -0
  132. data/spec/formats/multipart_spec.rb +26 -0
  133. data/spec/formats/plain_spec.rb +29 -0
  134. data/spec/interceptors/after_request_spec.rb +20 -0
  135. data/spec/interceptors/after_response_spec.rb +39 -0
  136. data/spec/interceptors/auth/basic_auth_spec.rb +17 -0
  137. data/spec/interceptors/auth/bearer_spec.rb +19 -0
  138. data/spec/interceptors/auth/reauthentication_configuration_spec.rb +61 -0
  139. data/spec/interceptors/auth/reauthentication_spec.rb +44 -0
  140. data/spec/interceptors/before_request_spec.rb +21 -0
  141. data/spec/interceptors/before_response_spec.rb +20 -0
  142. data/spec/interceptors/caching/hydra_spec.rb +26 -0
  143. data/spec/interceptors/caching/main_spec.rb +73 -0
  144. data/spec/interceptors/caching/methods_spec.rb +42 -0
  145. data/spec/interceptors/caching/options_spec.rb +89 -0
  146. data/spec/interceptors/caching/parameters_spec.rb +24 -0
  147. data/spec/interceptors/caching/response_status_spec.rb +29 -0
  148. data/spec/interceptors/caching/to_cache_spec.rb +16 -0
  149. data/spec/interceptors/default_interceptors_spec.rb +15 -0
  150. data/spec/interceptors/default_timeout/main_spec.rb +34 -0
  151. data/spec/interceptors/define_spec.rb +29 -0
  152. data/spec/interceptors/dup_spec.rb +19 -0
  153. data/spec/interceptors/logging/main_spec.rb +37 -0
  154. data/spec/interceptors/monitoring/main_spec.rb +97 -0
  155. data/spec/interceptors/prometheus_spec.rb +54 -0
  156. data/spec/interceptors/response_competition_spec.rb +41 -0
  157. data/spec/interceptors/retry/main_spec.rb +73 -0
  158. data/spec/interceptors/return_response_spec.rb +38 -0
  159. data/spec/interceptors/rollbar/invalid_encoding_spec.rb +43 -0
  160. data/spec/interceptors/rollbar/main_spec.rb +57 -0
  161. data/spec/interceptors/throttle/main_spec.rb +106 -0
  162. data/spec/interceptors/throttle/reset_track_spec.rb +53 -0
  163. data/spec/interceptors/zipkin/distributed_tracing_spec.rb +135 -0
  164. data/spec/rails_helper.rb +6 -0
  165. data/spec/request/body_spec.rb +39 -0
  166. data/spec/request/encoding_spec.rb +37 -0
  167. data/spec/request/error_handling_spec.rb +88 -0
  168. data/spec/request/headers_spec.rb +12 -0
  169. data/spec/request/ignore_errors_spec.rb +73 -0
  170. data/spec/request/option_dup_spec.rb +13 -0
  171. data/spec/request/parallel_requests_spec.rb +59 -0
  172. data/spec/request/params_encoding_spec.rb +26 -0
  173. data/spec/request/request_without_rails_spec.rb +15 -0
  174. data/spec/request/url_patterns_spec.rb +54 -0
  175. data/spec/request/user_agent_spec.rb +26 -0
  176. data/spec/request/user_agent_without_rails_spec.rb +27 -0
  177. data/spec/response/body_spec.rb +16 -0
  178. data/spec/response/code_spec.rb +16 -0
  179. data/spec/response/data_accessor_spec.rb +29 -0
  180. data/spec/response/data_spec.rb +61 -0
  181. data/spec/response/effective_url_spec.rb +16 -0
  182. data/spec/response/headers_spec.rb +18 -0
  183. data/spec/response/options_spec.rb +18 -0
  184. data/spec/response/success_spec.rb +13 -0
  185. data/spec/response/time_spec.rb +21 -0
  186. data/spec/spec_helper.rb +8 -0
  187. data/spec/support/fixtures/json/feedback.json +11 -0
  188. data/spec/support/fixtures/json/feedbacks.json +164 -0
  189. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  190. data/spec/support/load_json.rb +5 -0
  191. data/spec/support/reset_config.rb +7 -0
  192. data/spec/support/zipkin_mock.rb +113 -0
  193. data/spec/timeouts/no_signal_spec.rb +13 -0
  194. data/spec/timeouts/timings_spec.rb +55 -0
  195. 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