stripe 5.8.0 → 5.9.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 +3 -0
- data/README.md +26 -0
- data/VERSION +1 -1
- data/lib/stripe/instrumentation.rb +40 -0
- data/lib/stripe/stripe_client.rb +24 -4
- data/lib/stripe/version.rb +1 -1
- data/test/stripe/instrumentation_test.rb +61 -0
- data/test/stripe/stripe_client_test.rb +70 -0
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b59015578d0b75db3e8b02959010a9d3a7a3c4212823ad8b51790a869e32b92a
|
|
4
|
+
data.tar.gz: cc8dd57b285effb4814596431b8da59fe92d1a7e34a76d5dc738250a10673142
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6154e0332f7b4c7d66c2238d4474ce904c0faa129dea9a1e1d03668a03d8b03796c593ddb7f04a76082251e6d08520996a28bd2427d897cb1dd769dfc1c3f8aa
|
|
7
|
+
data.tar.gz: 3d4bf185574c11c8c867b1998e4f07f1bce7b4dcaab166d475a5e2406e0cf2275e6d9890bf0df7f94523d36cc58c577819edaa9d301ba96b0d722d4806cbcdac
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.9.0 - 2019-11-07
|
|
4
|
+
* [#870](https://github.com/stripe/stripe-ruby/pull/870) Add request instrumentation callback (see `README.md` for usage example)
|
|
5
|
+
|
|
3
6
|
## 5.8.0 - 2019-11-05
|
|
4
7
|
* [#879](https://github.com/stripe/stripe-ruby/pull/879) Add support for `Mandate`
|
|
5
8
|
* [#876](https://github.com/stripe/stripe-ruby/pull/876) Add additional per-request configuration documentation
|
data/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Stripe Ruby Library
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/rb/stripe)
|
|
3
4
|
[](https://travis-ci.org/stripe/stripe-ruby)
|
|
4
5
|
[](https://coveralls.io/github/stripe/stripe-ruby?branch=master)
|
|
5
6
|
|
|
@@ -221,6 +222,31 @@ There are a few options for enabling it:
|
|
|
221
222
|
Stripe.log_level = Stripe::LEVEL_INFO
|
|
222
223
|
```
|
|
223
224
|
|
|
225
|
+
### Instrumentation
|
|
226
|
+
|
|
227
|
+
The library has a hook for when a HTTP call is made which can be used for
|
|
228
|
+
monitoring. The callback receives a `RequestEvent` object with the following
|
|
229
|
+
data:
|
|
230
|
+
- HTTP method (`Symbol`)
|
|
231
|
+
- request path (`String`)
|
|
232
|
+
- HTTP response code (`Integer`) if available, or `nil` in case of a lower
|
|
233
|
+
level network error
|
|
234
|
+
- request duration in seconds (`Float`)
|
|
235
|
+
- the number of retries (`Integer`)
|
|
236
|
+
|
|
237
|
+
For example:
|
|
238
|
+
```ruby
|
|
239
|
+
Stripe::Instrumentation.subscribe(:request) do |request_event|
|
|
240
|
+
tags = {
|
|
241
|
+
method: request_event.method,
|
|
242
|
+
resource: request_event.path.split("/")[2],
|
|
243
|
+
code: request_event.http_status,
|
|
244
|
+
retries: request_event.num_retries
|
|
245
|
+
}
|
|
246
|
+
StatsD.distribution('stripe_request', request_event.duration, tags: tags)
|
|
247
|
+
end
|
|
248
|
+
```
|
|
249
|
+
|
|
224
250
|
### Writing a Plugin
|
|
225
251
|
|
|
226
252
|
If you're writing a plugin that uses the library, we'd appreciate it if you
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.9.0
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stripe
|
|
4
|
+
class Instrumentation
|
|
5
|
+
class RequestEvent
|
|
6
|
+
attr_reader :duration
|
|
7
|
+
attr_reader :http_status
|
|
8
|
+
attr_reader :method
|
|
9
|
+
attr_reader :num_retries
|
|
10
|
+
attr_reader :path
|
|
11
|
+
|
|
12
|
+
def initialize(duration:, http_status:, method:, num_retries:, path:)
|
|
13
|
+
@duration = duration
|
|
14
|
+
@http_status = http_status
|
|
15
|
+
@method = method
|
|
16
|
+
@num_retries = num_retries
|
|
17
|
+
@path = path
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.subscribe(topic, name = rand, &block)
|
|
23
|
+
subscribers[topic][name] = block
|
|
24
|
+
name
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.unsubscribe(topic, name)
|
|
28
|
+
subscribers[topic].delete(name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.notify(topic, event)
|
|
32
|
+
subscribers[topic].each_value { |subscriber| subscriber.call(event) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.subscribers
|
|
36
|
+
@subscribers ||= Hash.new { |hash, key| hash[key] = {} }
|
|
37
|
+
end
|
|
38
|
+
private_class_method :subscribers
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/stripe/stripe_client.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "stripe/instrumentation"
|
|
4
|
+
|
|
3
5
|
module Stripe
|
|
4
6
|
# StripeClient executes requests against the Stripe API and allows a user to
|
|
5
7
|
# recover both a resource a call returns as well as a response object that
|
|
@@ -452,15 +454,18 @@ module Stripe
|
|
|
452
454
|
request_start = Util.monotonic_time
|
|
453
455
|
log_request(context, num_retries)
|
|
454
456
|
resp = yield
|
|
457
|
+
request_duration = Util.monotonic_time - request_start
|
|
458
|
+
http_status = resp.code.to_i
|
|
455
459
|
context = context.dup_from_response_headers(resp)
|
|
456
460
|
|
|
457
|
-
handle_error_response(resp, context) if
|
|
461
|
+
handle_error_response(resp, context) if http_status >= 400
|
|
458
462
|
|
|
459
|
-
log_response(context, request_start,
|
|
463
|
+
log_response(context, request_start, http_status, resp.body)
|
|
464
|
+
notify_subscribers(request_duration, http_status, context,
|
|
465
|
+
num_retries)
|
|
460
466
|
|
|
461
467
|
if Stripe.enable_telemetry? && context.request_id
|
|
462
|
-
request_duration_ms =
|
|
463
|
-
((Util.monotonic_time - request_start) * 1000).to_int
|
|
468
|
+
request_duration_ms = (request_duration * 1000).to_i
|
|
464
469
|
@last_request_metrics =
|
|
465
470
|
StripeRequestMetrics.new(context.request_id, request_duration_ms)
|
|
466
471
|
end
|
|
@@ -472,14 +477,18 @@ module Stripe
|
|
|
472
477
|
# If we modify context we copy it into a new variable so as not to
|
|
473
478
|
# taint the original on a retry.
|
|
474
479
|
error_context = context
|
|
480
|
+
request_duration = Util.monotonic_time - request_start
|
|
481
|
+
http_status = nil
|
|
475
482
|
|
|
476
483
|
if e.is_a?(Stripe::StripeError)
|
|
477
484
|
error_context = context.dup_from_response_headers(e.http_headers)
|
|
485
|
+
http_status = resp.code.to_i
|
|
478
486
|
log_response(error_context, request_start,
|
|
479
487
|
e.http_status, e.http_body)
|
|
480
488
|
else
|
|
481
489
|
log_response_error(error_context, request_start, e)
|
|
482
490
|
end
|
|
491
|
+
notify_subscribers(request_duration, http_status, context, num_retries)
|
|
483
492
|
|
|
484
493
|
if self.class.should_retry?(e, method: method, num_retries: num_retries)
|
|
485
494
|
num_retries += 1
|
|
@@ -503,6 +512,17 @@ module Stripe
|
|
|
503
512
|
resp
|
|
504
513
|
end
|
|
505
514
|
|
|
515
|
+
private def notify_subscribers(duration, http_status, context, num_retries)
|
|
516
|
+
request_event = Instrumentation::RequestEvent.new(
|
|
517
|
+
duration: duration,
|
|
518
|
+
http_status: http_status,
|
|
519
|
+
method: context.method,
|
|
520
|
+
num_retries: num_retries,
|
|
521
|
+
path: context.path
|
|
522
|
+
)
|
|
523
|
+
Stripe::Instrumentation.notify(:request, request_event)
|
|
524
|
+
end
|
|
525
|
+
|
|
506
526
|
private def general_api_error(status, body)
|
|
507
527
|
APIError.new("Invalid response object from API: #{body.inspect} " \
|
|
508
528
|
"(HTTP response code was #{status})",
|
data/lib/stripe/version.rb
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
module Stripe
|
|
6
|
+
class InstrumentationTest < Test::Unit::TestCase
|
|
7
|
+
context ".notify" do
|
|
8
|
+
teardown do
|
|
9
|
+
Stripe::Instrumentation.send(:subscribers).clear
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
should "notify subscribers for the right topic" do
|
|
13
|
+
sub1_events = []
|
|
14
|
+
Stripe::Instrumentation.subscribe(:test1, :sub1) { |event| sub1_events << event }
|
|
15
|
+
sub2_events = []
|
|
16
|
+
Stripe::Instrumentation.subscribe(:test2, :sub2) { |event| sub2_events << event }
|
|
17
|
+
|
|
18
|
+
Stripe::Instrumentation.notify(:test1, "hello")
|
|
19
|
+
assert_equal(1, sub1_events.size)
|
|
20
|
+
assert_equal(0, sub2_events.size)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
should "notify multiple subscribers of the same topic" do
|
|
24
|
+
sub1_events = []
|
|
25
|
+
Stripe::Instrumentation.subscribe(:test, :sub1) { |event| sub1_events << event }
|
|
26
|
+
sub2_events = []
|
|
27
|
+
Stripe::Instrumentation.subscribe(:test, :sub2) { |event| sub2_events << event }
|
|
28
|
+
|
|
29
|
+
Stripe::Instrumentation.notify(:test, "hello")
|
|
30
|
+
assert_equal(1, sub1_events.size)
|
|
31
|
+
assert_equal(1, sub2_events.size)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
should "not notify a subscriber once it has unsubscribed" do
|
|
35
|
+
events = []
|
|
36
|
+
Stripe::Instrumentation.subscribe(:test, :sub) { |event| events << event }
|
|
37
|
+
|
|
38
|
+
Stripe::Instrumentation.notify(:test, "hello")
|
|
39
|
+
assert_equal(1, events.size)
|
|
40
|
+
|
|
41
|
+
Stripe::Instrumentation.unsubscribe(:test, :sub)
|
|
42
|
+
Stripe::Instrumentation.notify(:test, "hello")
|
|
43
|
+
assert_equal(1, events.size)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "RequestEvent" do
|
|
48
|
+
should "return a frozen object" do
|
|
49
|
+
event = Stripe::Instrumentation::RequestEvent.new(
|
|
50
|
+
duration: 0.1,
|
|
51
|
+
http_status: 200,
|
|
52
|
+
method: :get,
|
|
53
|
+
num_retries: 0,
|
|
54
|
+
path: "/v1/test"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
assert(event.frozen?)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1144,6 +1144,76 @@ module Stripe
|
|
|
1144
1144
|
assert(!trace_payload["last_request_metrics"]["request_duration_ms"].nil?)
|
|
1145
1145
|
end
|
|
1146
1146
|
end
|
|
1147
|
+
|
|
1148
|
+
context "instrumentation" do
|
|
1149
|
+
teardown do
|
|
1150
|
+
Stripe::Instrumentation.unsubscribe(:request, :test)
|
|
1151
|
+
end
|
|
1152
|
+
|
|
1153
|
+
should "notify a subscriber of a successful HTTP request" do
|
|
1154
|
+
events = []
|
|
1155
|
+
Stripe::Instrumentation.subscribe(:request, :test) { |event| events << event }
|
|
1156
|
+
|
|
1157
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges")
|
|
1158
|
+
.to_return(body: JSON.generate(object: "charge"))
|
|
1159
|
+
Stripe::Charge.list
|
|
1160
|
+
|
|
1161
|
+
assert_equal(1, events.size)
|
|
1162
|
+
event = events.first
|
|
1163
|
+
assert_equal(:get, event.method)
|
|
1164
|
+
assert_equal("/v1/charges", event.path)
|
|
1165
|
+
assert_equal(200, event.http_status)
|
|
1166
|
+
assert(event.duration.positive?)
|
|
1167
|
+
assert_equal(0, event.num_retries)
|
|
1168
|
+
end
|
|
1169
|
+
|
|
1170
|
+
should "notify a subscriber of a StripeError" do
|
|
1171
|
+
events = []
|
|
1172
|
+
Stripe::Instrumentation.subscribe(:request, :test) { |event| events << event }
|
|
1173
|
+
|
|
1174
|
+
error = {
|
|
1175
|
+
code: "code",
|
|
1176
|
+
message: "message",
|
|
1177
|
+
param: "param",
|
|
1178
|
+
type: "type",
|
|
1179
|
+
}
|
|
1180
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges")
|
|
1181
|
+
.to_return(
|
|
1182
|
+
body: JSON.generate(error: error),
|
|
1183
|
+
status: 500
|
|
1184
|
+
)
|
|
1185
|
+
assert_raises(Stripe::APIError) do
|
|
1186
|
+
Stripe::Charge.list
|
|
1187
|
+
end
|
|
1188
|
+
|
|
1189
|
+
assert_equal(1, events.size)
|
|
1190
|
+
event = events.first
|
|
1191
|
+
assert_equal(:get, event.method)
|
|
1192
|
+
assert_equal("/v1/charges", event.path)
|
|
1193
|
+
assert_equal(500, event.http_status)
|
|
1194
|
+
assert(event.duration.positive?)
|
|
1195
|
+
assert_equal(0, event.num_retries)
|
|
1196
|
+
end
|
|
1197
|
+
|
|
1198
|
+
should "notify a subscriber of a network error" do
|
|
1199
|
+
events = []
|
|
1200
|
+
Stripe::Instrumentation.subscribe(:request, :test) { |event| events << event }
|
|
1201
|
+
|
|
1202
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges")
|
|
1203
|
+
.to_raise(Net::OpenTimeout)
|
|
1204
|
+
assert_raises(Stripe::APIConnectionError) do
|
|
1205
|
+
Stripe::Charge.list
|
|
1206
|
+
end
|
|
1207
|
+
|
|
1208
|
+
assert_equal(1, events.size)
|
|
1209
|
+
event = events.first
|
|
1210
|
+
assert_equal(:get, event.method)
|
|
1211
|
+
assert_equal("/v1/charges", event.path)
|
|
1212
|
+
assert_nil(event.http_status)
|
|
1213
|
+
assert(event.duration.positive?)
|
|
1214
|
+
assert_equal(0, event.num_retries)
|
|
1215
|
+
end
|
|
1216
|
+
end
|
|
1147
1217
|
end
|
|
1148
1218
|
|
|
1149
1219
|
class SystemProfilerTest < Test::Unit::TestCase
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stripe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stripe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-11-
|
|
11
|
+
date: 2019-11-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Stripe is the easiest way to accept payments online. See https://stripe.com
|
|
14
14
|
for details.
|
|
@@ -49,6 +49,7 @@ files:
|
|
|
49
49
|
- lib/stripe/connection_manager.rb
|
|
50
50
|
- lib/stripe/error_object.rb
|
|
51
51
|
- lib/stripe/errors.rb
|
|
52
|
+
- lib/stripe/instrumentation.rb
|
|
52
53
|
- lib/stripe/list_object.rb
|
|
53
54
|
- lib/stripe/multipart_encoder.rb
|
|
54
55
|
- lib/stripe/oauth.rb
|
|
@@ -167,6 +168,7 @@ files:
|
|
|
167
168
|
- test/stripe/exchange_rate_test.rb
|
|
168
169
|
- test/stripe/file_link_test.rb
|
|
169
170
|
- test/stripe/file_test.rb
|
|
171
|
+
- test/stripe/instrumentation_test.rb
|
|
170
172
|
- test/stripe/invoice_item_test.rb
|
|
171
173
|
- test/stripe/invoice_line_item_test.rb
|
|
172
174
|
- test/stripe/invoice_test.rb
|
|
@@ -249,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
249
251
|
- !ruby/object:Gem::Version
|
|
250
252
|
version: '0'
|
|
251
253
|
requirements: []
|
|
252
|
-
rubygems_version: 3.0.
|
|
254
|
+
rubygems_version: 3.0.6
|
|
253
255
|
signing_key:
|
|
254
256
|
specification_version: 4
|
|
255
257
|
summary: Ruby bindings for the Stripe API
|
|
@@ -283,6 +285,7 @@ test_files:
|
|
|
283
285
|
- test/stripe/exchange_rate_test.rb
|
|
284
286
|
- test/stripe/file_link_test.rb
|
|
285
287
|
- test/stripe/file_test.rb
|
|
288
|
+
- test/stripe/instrumentation_test.rb
|
|
286
289
|
- test/stripe/invoice_item_test.rb
|
|
287
290
|
- test/stripe/invoice_line_item_test.rb
|
|
288
291
|
- test/stripe/invoice_test.rb
|