quiz_api_client 4.1.0 → 4.2.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 +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
|