quiz_api_client 4.1.0 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +4 -0
- data/lib/quiz_api_client/config.rb +29 -8
- data/lib/quiz_api_client/http_client.rb +11 -40
- data/lib/quiz_api_client/http_request/failure.rb +65 -0
- data/lib/quiz_api_client/http_request/metrics.rb +67 -0
- data/lib/quiz_api_client/version.rb +1 -1
- data/lib/quiz_api_client.rb +2 -0
- data/quiz_api_client.gemspec +1 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9191c8a80cb0e2a654139c30e5e6ad3662e7589f6bf34a5b9f00b4517de22f99
|
4
|
+
data.tar.gz: 875e4bc7336dac500bbf699438ce9ad457680d6d3ce736b6aff3077efc495dfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf91a4c19851e9c1e4569f25be567ffae06bb91666da2d56cfc28fea0569cf55ce2706e18ebbb5ad38ce1ea9246eb348806f2fd05243250baa8573379ac9a843
|
7
|
+
data.tar.gz: aa366eff458ec1045bab8abae45d5a99bc374327a2d085a70fce32963e730b31d7a1f58ad5150f8978326b0b7608bb27c74b4a4ddde5e5bf3cbd25717ed463ff
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,13 @@ project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
|
7
7
|
[TOC]
|
8
8
|
|
9
|
+
#TODO: Enter the date
|
10
|
+
## 4.2.0 ()
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
* Internal refactor of request error handling
|
14
|
+
* Added `metric_handler` and `metrics_namespace` to work with InstStatsd gem
|
15
|
+
|
9
16
|
## 4.1.0 (2021-10-27)
|
10
17
|
|
11
18
|
### Breaking changes (potentially)
|
data/README.md
CHANGED
@@ -41,6 +41,10 @@ client = QuizApiClient::Client.new(
|
|
41
41
|
|
42
42
|
In order to set addition error information in your error handling system, you can set the `error_hander` property of the config. The list of valid values can be found in the `QuizApiClient::Config::ERROR_HANDLERS` constant.
|
43
43
|
|
44
|
+
### Metrics
|
45
|
+
|
46
|
+
HTTP Request metrics will now be provided if the `setup_metrics` method is called. The list of valid values can be found in the `QuizApiClient::Config::METRICS_HANDLERS` constant. The count and duration metrics will be provided under the namespace provided.
|
47
|
+
|
44
48
|
### Creation of Tokens
|
45
49
|
|
46
50
|
JWTs are created without hitting quiz_api and and they are validated on quiz_api. Tokens are created for a given scope, expiration, and an optional resource_id.
|
@@ -3,10 +3,13 @@ module QuizApiClient
|
|
3
3
|
DEFAULT_ALLOWABLE_RESPONSE_CODES = [401, 422].freeze
|
4
4
|
DEFAULT_PROTOCOL = 'https'.freeze
|
5
5
|
ERROR_HANDLERS = %i[sentry_raven].freeze
|
6
|
+
METRICS_HANDLERS = %i[inststatsd].freeze
|
6
7
|
|
7
8
|
class InvalidErrorHandler < StandardError; end
|
9
|
+
class InvalidMetricsHandler < StandardError; end
|
10
|
+
class InvalidMetricsNamespace < StandardError; end
|
8
11
|
|
9
|
-
attr_reader :error_handler
|
12
|
+
attr_reader :error_handler, :metrics_handler, :metrics_namespace
|
10
13
|
attr_writer :protocol, :allowable_response_codes
|
11
14
|
attr_accessor :consumer_key, :consumer_request_id, :host, :shared_secret
|
12
15
|
|
@@ -19,9 +22,17 @@ module QuizApiClient
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def error_handler=(handler)
|
22
|
-
|
25
|
+
validate_error_handler!(handler)
|
23
26
|
|
24
|
-
@error_handler = handler
|
27
|
+
@error_handler = handler.to_sym
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup_metrics(handler, namespace)
|
31
|
+
validate_metrics_handler!(handler)
|
32
|
+
validate_metrics_namespace!(namespace)
|
33
|
+
|
34
|
+
@metrics_handler = handler.to_sym
|
35
|
+
@metrics_namespace = namespace.to_s.strip
|
25
36
|
end
|
26
37
|
|
27
38
|
def allowable_response_codes
|
@@ -30,14 +41,24 @@ module QuizApiClient
|
|
30
41
|
|
31
42
|
private
|
32
43
|
|
33
|
-
def
|
44
|
+
def validate_error_handler!(handler)
|
34
45
|
return unless handler
|
46
|
+
return if ERROR_HANDLERS.include?(handler)
|
35
47
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
48
|
+
raise InvalidErrorHandler, "It must be one of the following: #{ERROR_HANDLERS.inspect}"
|
49
|
+
end
|
39
50
|
|
40
|
-
|
51
|
+
def validate_metrics_handler!(handler)
|
52
|
+
return unless handler
|
53
|
+
return if METRICS_HANDLERS.include?(handler)
|
54
|
+
|
55
|
+
raise InvalidMetricsHandler, "It must be one of the following: #{METRICS_HANDLERS.inspect}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_metrics_namespace!(namespace)
|
59
|
+
return unless namespace.nil? || namespace.to_s.strip == ''
|
60
|
+
|
61
|
+
raise InvalidMetricsNamespace, 'It must be present'
|
41
62
|
end
|
42
63
|
end
|
43
64
|
end
|
@@ -82,6 +82,7 @@ module QuizApiClient
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def make_request(method, url, request_options = {})
|
85
|
+
start_time = Time.now
|
85
86
|
resp = self.class.send(
|
86
87
|
method,
|
87
88
|
url,
|
@@ -91,6 +92,8 @@ module QuizApiClient
|
|
91
92
|
resp
|
92
93
|
rescue HTTParty::Error, Errno::ECONNREFUSED, Net::ReadTimeout => e
|
93
94
|
raise_error(method, url, current_error: e)
|
95
|
+
ensure
|
96
|
+
record_metrics(method, url, resp, start_time, Time.now)
|
94
97
|
end
|
95
98
|
|
96
99
|
def make_paginated_request(method, url, options)
|
@@ -146,50 +149,18 @@ module QuizApiClient
|
|
146
149
|
[url, options.merge(query: query)]
|
147
150
|
end
|
148
151
|
|
149
|
-
def
|
150
|
-
|
151
|
-
quiz_api_client: {
|
152
|
-
request: {
|
153
|
-
method: method,
|
154
|
-
url: url
|
155
|
-
}
|
156
|
-
}
|
157
|
-
}
|
158
|
-
|
159
|
-
if response
|
160
|
-
context[:quiz_api_client][:response] = {
|
161
|
-
body: response.body,
|
162
|
-
code: response.code
|
163
|
-
}
|
164
|
-
end
|
165
|
-
|
166
|
-
context
|
167
|
-
end
|
168
|
-
|
169
|
-
def record_error_context(context)
|
170
|
-
case config.error_handler
|
171
|
-
when :sentry_raven
|
172
|
-
require 'sentry-raven'
|
173
|
-
Raven.extra_context(context)
|
174
|
-
end
|
175
|
-
end
|
152
|
+
def raise_error(method, url, response: nil, current_error: nil)
|
153
|
+
failure = QuizApiClient::HttpRequest::Failure.new(config)
|
176
154
|
|
177
|
-
|
178
|
-
if current_error && response
|
179
|
-
"#{current_error.message}: #{url} responded #{response.body} (#{response.code})"
|
180
|
-
elsif current_error
|
181
|
-
current_error.message
|
182
|
-
elsif response
|
183
|
-
"#{url} responded #{response.body} (#{response.code})"
|
184
|
-
end
|
155
|
+
failure.raise_error(method, url, response: response, current_error: current_error)
|
185
156
|
end
|
186
157
|
|
187
|
-
def
|
188
|
-
|
189
|
-
|
190
|
-
record_error_context(context)
|
158
|
+
def record_metrics(method, url, resp, start_time, end_time)
|
159
|
+
code = resp&.code || 0
|
160
|
+
metrics = QuizApiClient::HttpRequest::Metrics.new(config, method, url, code)
|
191
161
|
|
192
|
-
|
162
|
+
metrics.increment
|
163
|
+
metrics.duration(start_time, end_time)
|
193
164
|
end
|
194
165
|
|
195
166
|
def successful_response?(resp)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module QuizApiClient
|
2
|
+
module HttpRequest
|
3
|
+
class Failure
|
4
|
+
attr_reader :config
|
5
|
+
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
end
|
9
|
+
|
10
|
+
def raise_error(
|
11
|
+
method,
|
12
|
+
url,
|
13
|
+
response: nil,
|
14
|
+
current_error: nil,
|
15
|
+
error_class: QuizApiClient::HttpClient::RequestFailed
|
16
|
+
)
|
17
|
+
context = generate_error_context(method, url, response)
|
18
|
+
|
19
|
+
record_error_context(context)
|
20
|
+
|
21
|
+
raise error_class.new(context), error_message(current_error, url, response)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def generate_error_context(method, url, response = nil)
|
27
|
+
context = {
|
28
|
+
quiz_api_client: {
|
29
|
+
request: {
|
30
|
+
method: method,
|
31
|
+
url: url
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
if response
|
37
|
+
context[:quiz_api_client][:response] = {
|
38
|
+
body: response.body,
|
39
|
+
code: response.code
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
context
|
44
|
+
end
|
45
|
+
|
46
|
+
def record_error_context(context)
|
47
|
+
case config.error_handler
|
48
|
+
when :sentry_raven
|
49
|
+
require 'sentry-raven'
|
50
|
+
Raven.extra_context(context)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def error_message(current_error, url, response)
|
55
|
+
if current_error && response
|
56
|
+
"#{current_error.message}: #{url} responded #{response.body} (#{response.code})"
|
57
|
+
elsif current_error
|
58
|
+
current_error.message
|
59
|
+
elsif response
|
60
|
+
"#{url} responded #{response.body} (#{response.code})"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module QuizApiClient
|
2
|
+
module HttpRequest
|
3
|
+
class Metrics
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
attr_reader :config, :method, :url, :code
|
7
|
+
def_delegators :config, :metrics_handler, :metrics_namespace
|
8
|
+
|
9
|
+
def initialize(config, method, url, code)
|
10
|
+
@config = config
|
11
|
+
@method = method
|
12
|
+
@url = url
|
13
|
+
@code = code
|
14
|
+
end
|
15
|
+
|
16
|
+
def increment
|
17
|
+
return unless configured?
|
18
|
+
|
19
|
+
case metrics_handler
|
20
|
+
when :inststatsd
|
21
|
+
InstStatsd::Statsd.increment count_metric_name, tags: tags
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def duration(start_time, end_time)
|
26
|
+
return unless configured?
|
27
|
+
|
28
|
+
duration_ms = ((end_time - start_time) * 1_000).round
|
29
|
+
|
30
|
+
case metrics_handler
|
31
|
+
when :inststatsd
|
32
|
+
InstStatsd::Statsd.timing duration_metric_name, duration_ms, tags: tags
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def configured?
|
39
|
+
metrics_handler_present? && metrics_namespace_present?
|
40
|
+
end
|
41
|
+
|
42
|
+
def count_metric_name
|
43
|
+
"#{metrics_namespace}.quiz_api_client.request.count"
|
44
|
+
end
|
45
|
+
|
46
|
+
def duration_metric_name
|
47
|
+
"#{metrics_namespace}.quiz_api_client.request.duration_ms"
|
48
|
+
end
|
49
|
+
|
50
|
+
def metrics_handler_present?
|
51
|
+
!metrics_handler.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def metrics_namespace_present?
|
55
|
+
!metrics_namespace.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def tags
|
59
|
+
{
|
60
|
+
method: method,
|
61
|
+
status: code,
|
62
|
+
url: url
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/quiz_api_client.rb
CHANGED
@@ -101,6 +101,8 @@ require 'quiz_api_client/version'
|
|
101
101
|
require 'quiz_api_client/config'
|
102
102
|
require 'quiz_api_client/http_client'
|
103
103
|
require 'quiz_api_client/json_formatter'
|
104
|
+
require 'quiz_api_client/http_request/failure'
|
105
|
+
require 'quiz_api_client/http_request/metrics'
|
104
106
|
require 'quiz_api_client/services/jwt_service'
|
105
107
|
require 'quiz_api_client/services/base_api_service'
|
106
108
|
|
data/quiz_api_client.gemspec
CHANGED
@@ -48,6 +48,7 @@ Gem::Specification.new do |spec|
|
|
48
48
|
spec.add_dependency 'jwt', '~> 2.2'
|
49
49
|
spec.add_dependency 'link_header', '~> 0.0'
|
50
50
|
|
51
|
+
spec.add_development_dependency 'inst_statsd'
|
51
52
|
spec.add_development_dependency 'pact', '~> 1.41'
|
52
53
|
spec.add_development_dependency 'pact_broker-client', '~> 1.19'
|
53
54
|
spec.add_development_dependency 'rake', '~> 12.3'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quiz_api_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Wang
|
@@ -20,7 +20,7 @@ authors:
|
|
20
20
|
autorequire:
|
21
21
|
bindir: exe
|
22
22
|
cert_chain: []
|
23
|
-
date: 2021-
|
23
|
+
date: 2021-11-19 00:00:00.000000000 Z
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: httparty
|
@@ -64,6 +64,20 @@ dependencies:
|
|
64
64
|
- - "~>"
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: '0.0'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: inst_statsd
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
67
81
|
- !ruby/object:Gem::Dependency
|
68
82
|
name: pact
|
69
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -214,6 +228,8 @@ files:
|
|
214
228
|
- lib/quiz_api_client.rb
|
215
229
|
- lib/quiz_api_client/config.rb
|
216
230
|
- lib/quiz_api_client/http_client.rb
|
231
|
+
- lib/quiz_api_client/http_request/failure.rb
|
232
|
+
- lib/quiz_api_client/http_request/metrics.rb
|
217
233
|
- lib/quiz_api_client/json_formatter.rb
|
218
234
|
- lib/quiz_api_client/services/base_api_service.rb
|
219
235
|
- lib/quiz_api_client/services/interaction_types_service.rb
|