stripe 5.14.0 → 5.15.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/Gemfile +4 -1
- data/README.md +48 -29
- data/VERSION +1 -1
- data/lib/stripe/instrumentation.rb +44 -2
- data/lib/stripe/stripe_client.rb +43 -10
- data/lib/stripe/version.rb +1 -1
- data/test/stripe/instrumentation_test.rb +16 -3
- data/test/stripe/stripe_client_test.rb +51 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b0ca3c982da5bfe967d889047eeadbc2a2ba7ef6807dc860639a844f706cf15
|
4
|
+
data.tar.gz: 450bc197cbfd02398b3103aa89a5447f28bf2dd0f74608f3f54953e48e7ba4fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84c4915401aaf4a8e546763a17f44395df5ed284e36e721c6ba8d04612bbe4af9cc3d6bdeb235aba10abb82f5b001039f48ff0077e4d7477aed2f165a9f616a3
|
7
|
+
data.tar.gz: e4b3cacde2e92739ad543c2287cb06aa5041d2daa29780c83b3c670f97bdd395be7c537dc880cb452402575112b1498e10417244aada07653aec0fa52e551389
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 5.15.0 - 2020-02-10
|
4
|
+
* [#902](https://github.com/stripe/stripe-ruby/pull/902) Add `request_begin` instrumentation callback
|
5
|
+
|
3
6
|
## 5.14.0 - 2020-01-14
|
4
7
|
* [#896](https://github.com/stripe/stripe-ruby/pull/896) Add support for `CreditNoteLineItem`
|
5
8
|
* [#894](https://github.com/stripe/stripe-ruby/pull/894) Clean up test output by capturing `$stderr` when we expect warnings
|
data/Gemfile
CHANGED
@@ -11,7 +11,10 @@ group :development do
|
|
11
11
|
gem "rake"
|
12
12
|
gem "shoulda-context"
|
13
13
|
gem "test-unit"
|
14
|
-
|
14
|
+
|
15
|
+
# Version doesn't matter that much, but this one contains some fixes for Ruby
|
16
|
+
# 2.7 warnings that add noise to the test suite.
|
17
|
+
gem "webmock", ">= 3.8.0"
|
15
18
|
|
16
19
|
# Rubocop changes pretty quickly: new cops get added and old cops change
|
17
20
|
# names or go into new namespaces. This is a library and we don't have
|
data/README.md
CHANGED
@@ -14,8 +14,6 @@ The library also provides other features. For example:
|
|
14
14
|
|
15
15
|
- Easy configuration path for fast setup and use.
|
16
16
|
- Helpers for pagination.
|
17
|
-
- Tracking of "fresh" values in API resources so that partial updates can be
|
18
|
-
executed.
|
19
17
|
- Built-in mechanisms for the serialization of parameters according to the
|
20
18
|
expectations of Stripe's API.
|
21
19
|
|
@@ -65,13 +63,11 @@ value:
|
|
65
63
|
require "stripe"
|
66
64
|
Stripe.api_key = "sk_test_..."
|
67
65
|
|
68
|
-
# list
|
69
|
-
Stripe::
|
66
|
+
# list customers
|
67
|
+
Stripe::Customer.list()
|
70
68
|
|
71
|
-
# retrieve single
|
72
|
-
Stripe::
|
73
|
-
"ch_18atAXCdGbJFKhCuBAa4532Z",
|
74
|
-
)
|
69
|
+
# retrieve single customer
|
70
|
+
Stripe::Customer.retrieve("cus_123456789")
|
75
71
|
```
|
76
72
|
|
77
73
|
### Per-request Configuration
|
@@ -83,7 +79,7 @@ per-request key and/or account:
|
|
83
79
|
```ruby
|
84
80
|
require "stripe"
|
85
81
|
|
86
|
-
Stripe::
|
82
|
+
Stripe::Customer.list(
|
87
83
|
{},
|
88
84
|
{
|
89
85
|
api_key: "sk_test_...",
|
@@ -92,8 +88,8 @@ Stripe::Charge.list(
|
|
92
88
|
}
|
93
89
|
)
|
94
90
|
|
95
|
-
Stripe::
|
96
|
-
"
|
91
|
+
Stripe::Customer.retrieve(
|
92
|
+
"cus_123456789",
|
97
93
|
{
|
98
94
|
api_key: "sk_test_...",
|
99
95
|
stripe_account: "acct_...",
|
@@ -101,9 +97,9 @@ Stripe::Charge.retrieve(
|
|
101
97
|
}
|
102
98
|
)
|
103
99
|
|
104
|
-
Stripe::
|
100
|
+
Stripe::Customer.retrieve(
|
105
101
|
{
|
106
|
-
id: "
|
102
|
+
id: "cus_123456789",
|
107
103
|
expand: %w(balance_transaction)
|
108
104
|
},
|
109
105
|
{
|
@@ -112,8 +108,8 @@ Stripe::Charge.retrieve(
|
|
112
108
|
}
|
113
109
|
)
|
114
110
|
|
115
|
-
Stripe::
|
116
|
-
"
|
111
|
+
Stripe::Customer.capture(
|
112
|
+
"cus_123456789",
|
117
113
|
{},
|
118
114
|
{
|
119
115
|
stripe_version: "2018-02-28",
|
@@ -123,6 +119,7 @@ Stripe::Charge.capture(
|
|
123
119
|
```
|
124
120
|
|
125
121
|
Keep in mind that there are different method signatures depending on the action:
|
122
|
+
|
126
123
|
- When operating on a collection (e.g. `.list`, `.create`) the method signature is
|
127
124
|
`method(params, opts)`.
|
128
125
|
- When operating on resource (e.g. `.capture`, `.update`) the method signature is
|
@@ -138,10 +135,8 @@ method:
|
|
138
135
|
|
139
136
|
```ruby
|
140
137
|
client = Stripe::StripeClient.new
|
141
|
-
|
142
|
-
Stripe::
|
143
|
-
"ch_18atAXCdGbJFKhCuBAa4532Z",
|
144
|
-
)
|
138
|
+
customer, resp = client.request do
|
139
|
+
Stripe::Customer.retrieve("cus_123456789",)
|
145
140
|
end
|
146
141
|
puts resp.request_id
|
147
142
|
```
|
@@ -224,19 +219,43 @@ There are a few options for enabling it:
|
|
224
219
|
|
225
220
|
### Instrumentation
|
226
221
|
|
227
|
-
The library has
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
-
|
222
|
+
The library has various hooks that user code can tie into by passing a block to
|
223
|
+
`Stripe::Instrumentation.subscribe` to be notified about specific events.
|
224
|
+
|
225
|
+
#### `request_begin`
|
226
|
+
|
227
|
+
Invoked when an HTTP request starts. Receives `RequestBeginEvent` with the
|
228
|
+
following properties:
|
229
|
+
|
230
|
+
- `method`: HTTP method. (`Symbol`)
|
231
|
+
- `num_retries`: The number of retries. (`Integer`)
|
232
|
+
- `user_data`: A hash on which users can set arbitrary data, and which will be
|
233
|
+
passed through to `request_end` invocations. This could be used, for example,
|
234
|
+
to assign unique IDs to each request, and it'd work even if many requests are
|
235
|
+
running in parallel. All subscribers share the same object for any particular
|
236
|
+
request, so they must be careful to use unique keys that will not conflict
|
237
|
+
with other subscribers. (`Hash`)
|
238
|
+
|
239
|
+
#### `request_end`
|
240
|
+
|
241
|
+
Invoked when an HTTP request finishes, regardless of whether it terminated with
|
242
|
+
a success or error. Receives `RequestEndEvent` with the following properties:
|
243
|
+
|
244
|
+
- `duration`: Request duration in seconds. (`Float`)
|
245
|
+
- `http_status`: HTTP response code (`Integer`) if available, or `nil` in case
|
246
|
+
of a lower level network error.
|
247
|
+
- `method`: HTTP method. (`Symbol`)
|
248
|
+
- `num_retries`: The number of retries. (`Integer`)
|
249
|
+
- `path`: Request path. (`String`)
|
250
|
+
- `user_data`: A hash on which users may have set arbitrary data in
|
251
|
+
`request_begin`. See above for more information. (`Hash`)
|
252
|
+
|
253
|
+
#### Example
|
236
254
|
|
237
255
|
For example:
|
256
|
+
|
238
257
|
```ruby
|
239
|
-
Stripe::Instrumentation.subscribe(:
|
258
|
+
Stripe::Instrumentation.subscribe(:request_end) do |request_event|
|
240
259
|
tags = {
|
241
260
|
method: request_event.method,
|
242
261
|
resource: request_event.path.split("/")[2],
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.
|
1
|
+
5.15.0
|
@@ -2,23 +2,65 @@
|
|
2
2
|
|
3
3
|
module Stripe
|
4
4
|
class Instrumentation
|
5
|
-
|
5
|
+
# Event emitted on `request_begin` callback.
|
6
|
+
class RequestBeginEvent
|
7
|
+
attr_reader :method
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
# Arbitrary user-provided data in the form of a Ruby hash that's passed
|
11
|
+
# from subscribers on `request_begin` to subscribers on `request_end`.
|
12
|
+
# `request_begin` subscribers can set keys which will then be available
|
13
|
+
# in `request_end`.
|
14
|
+
#
|
15
|
+
# Note that all subscribers of `request_begin` share the same object, so
|
16
|
+
# they must be careful to set unique keys so as to not conflict with data
|
17
|
+
# set by other subscribers.
|
18
|
+
attr_reader :user_data
|
19
|
+
|
20
|
+
def initialize(method:, path:, user_data:)
|
21
|
+
@method = method
|
22
|
+
@path = path
|
23
|
+
@user_data = user_data
|
24
|
+
freeze
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Event emitted on `request_end` callback.
|
29
|
+
class RequestEndEvent
|
6
30
|
attr_reader :duration
|
7
31
|
attr_reader :http_status
|
8
32
|
attr_reader :method
|
9
33
|
attr_reader :num_retries
|
10
34
|
attr_reader :path
|
11
35
|
|
12
|
-
|
36
|
+
# Arbitrary user-provided data in the form of a Ruby hash that's passed
|
37
|
+
# from subscribers on `request_begin` to subscribers on `request_end`.
|
38
|
+
# `request_begin` subscribers can set keys which will then be available
|
39
|
+
# in `request_end`.
|
40
|
+
attr_reader :user_data
|
41
|
+
|
42
|
+
def initialize(duration:, http_status:, method:, num_retries:, path:,
|
43
|
+
user_data: nil)
|
13
44
|
@duration = duration
|
14
45
|
@http_status = http_status
|
15
46
|
@method = method
|
16
47
|
@num_retries = num_retries
|
17
48
|
@path = path
|
49
|
+
@user_data = user_data
|
18
50
|
freeze
|
19
51
|
end
|
20
52
|
end
|
21
53
|
|
54
|
+
# This class was renamed for consistency. This alias is here for backwards
|
55
|
+
# compatibility.
|
56
|
+
RequestEvent = RequestEndEvent
|
57
|
+
|
58
|
+
# Returns true if there are a non-zero number of subscribers on the given
|
59
|
+
# topic, and false otherwise.
|
60
|
+
def self.any_subscribers?(topic)
|
61
|
+
!subscribers[topic].empty?
|
62
|
+
end
|
63
|
+
|
22
64
|
def self.subscribe(topic, name = rand, &block)
|
23
65
|
subscribers[topic][name] = block
|
24
66
|
name
|
data/lib/stripe/stripe_client.rb
CHANGED
@@ -450,19 +450,26 @@ module Stripe
|
|
450
450
|
|
451
451
|
private def execute_request_with_rescues(method, api_base, context)
|
452
452
|
num_retries = 0
|
453
|
+
|
453
454
|
begin
|
454
|
-
request_start =
|
455
|
+
request_start = nil
|
456
|
+
user_data = nil
|
457
|
+
|
455
458
|
log_request(context, num_retries)
|
459
|
+
user_data = notify_request_begin(context)
|
460
|
+
|
461
|
+
request_start = Util.monotonic_time
|
456
462
|
resp = yield
|
457
463
|
request_duration = Util.monotonic_time - request_start
|
464
|
+
|
458
465
|
http_status = resp.code.to_i
|
459
466
|
context = context.dup_from_response_headers(resp)
|
460
467
|
|
461
468
|
handle_error_response(resp, context) if http_status >= 400
|
462
469
|
|
463
470
|
log_response(context, request_start, http_status, resp.body)
|
464
|
-
|
465
|
-
num_retries)
|
471
|
+
notify_request_end(context, request_duration, http_status,
|
472
|
+
num_retries, user_data)
|
466
473
|
|
467
474
|
if Stripe.enable_telemetry? && context.request_id
|
468
475
|
request_duration_ms = (request_duration * 1000).to_i
|
@@ -477,8 +484,8 @@ module Stripe
|
|
477
484
|
# If we modify context we copy it into a new variable so as not to
|
478
485
|
# taint the original on a retry.
|
479
486
|
error_context = context
|
480
|
-
request_duration = Util.monotonic_time - request_start
|
481
487
|
http_status = nil
|
488
|
+
request_duration = Util.monotonic_time - request_start if request_start
|
482
489
|
|
483
490
|
if e.is_a?(Stripe::StripeError)
|
484
491
|
error_context = context.dup_from_response_headers(e.http_headers)
|
@@ -488,7 +495,8 @@ module Stripe
|
|
488
495
|
else
|
489
496
|
log_response_error(error_context, request_start, e)
|
490
497
|
end
|
491
|
-
|
498
|
+
notify_request_end(context, request_duration, http_status, num_retries,
|
499
|
+
user_data)
|
492
500
|
|
493
501
|
if self.class.should_retry?(e, method: method, num_retries: num_retries)
|
494
502
|
num_retries += 1
|
@@ -512,15 +520,39 @@ module Stripe
|
|
512
520
|
resp
|
513
521
|
end
|
514
522
|
|
515
|
-
private def
|
516
|
-
|
523
|
+
private def notify_request_begin(context)
|
524
|
+
return unless Instrumentation.any_subscribers?(:request_begin)
|
525
|
+
|
526
|
+
event = Instrumentation::RequestBeginEvent.new(
|
527
|
+
method: context.method,
|
528
|
+
path: context.path,
|
529
|
+
user_data: {}
|
530
|
+
)
|
531
|
+
Stripe::Instrumentation.notify(:request_begin, event)
|
532
|
+
|
533
|
+
# This field may be set in the `request_begin` callback. If so, we'll
|
534
|
+
# forward it onto `request_end`.
|
535
|
+
event.user_data
|
536
|
+
end
|
537
|
+
|
538
|
+
private def notify_request_end(context, duration, http_status, num_retries,
|
539
|
+
user_data)
|
540
|
+
return if !Instrumentation.any_subscribers?(:request_end) &&
|
541
|
+
!Instrumentation.any_subscribers?(:request)
|
542
|
+
|
543
|
+
event = Instrumentation::RequestEndEvent.new(
|
517
544
|
duration: duration,
|
518
545
|
http_status: http_status,
|
519
546
|
method: context.method,
|
520
547
|
num_retries: num_retries,
|
521
|
-
path: context.path
|
548
|
+
path: context.path,
|
549
|
+
user_data: user_data || {}
|
522
550
|
)
|
523
|
-
Stripe::Instrumentation.notify(:
|
551
|
+
Stripe::Instrumentation.notify(:request_end, event)
|
552
|
+
|
553
|
+
# The name before `request_begin` was also added. Provided for backwards
|
554
|
+
# compatibility.
|
555
|
+
Stripe::Instrumentation.notify(:request, event)
|
524
556
|
end
|
525
557
|
|
526
558
|
private def general_api_error(status, body)
|
@@ -772,8 +804,9 @@ module Stripe
|
|
772
804
|
end
|
773
805
|
|
774
806
|
private def log_response_error(context, request_start, error)
|
807
|
+
elapsed = request_start ? Util.monotonic_time - request_start : nil
|
775
808
|
Util.log_error("Request error",
|
776
|
-
elapsed:
|
809
|
+
elapsed: elapsed,
|
777
810
|
error_message: error.message,
|
778
811
|
idempotency_key: context.idempotency_key,
|
779
812
|
method: context.method,
|
data/lib/stripe/version.rb
CHANGED
@@ -44,14 +44,27 @@ module Stripe
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
context "
|
47
|
+
context "RequestEventBegin" do
|
48
48
|
should "return a frozen object" do
|
49
|
-
event = Stripe::Instrumentation::
|
49
|
+
event = Stripe::Instrumentation::RequestBeginEvent.new(
|
50
|
+
method: :get,
|
51
|
+
path: "/v1/test",
|
52
|
+
user_data: nil
|
53
|
+
)
|
54
|
+
|
55
|
+
assert(event.frozen?)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "RequestEventEnd" do
|
60
|
+
should "return a frozen object" do
|
61
|
+
event = Stripe::Instrumentation::RequestEndEvent.new(
|
50
62
|
duration: 0.1,
|
51
63
|
http_status: 200,
|
52
64
|
method: :get,
|
53
65
|
num_retries: 0,
|
54
|
-
path: "/v1/test"
|
66
|
+
path: "/v1/test",
|
67
|
+
user_data: nil
|
55
68
|
)
|
56
69
|
|
57
70
|
assert(event.frozen?)
|
@@ -1150,9 +1150,23 @@ module Stripe
|
|
1150
1150
|
Stripe::Instrumentation.unsubscribe(:request, :test)
|
1151
1151
|
end
|
1152
1152
|
|
1153
|
+
should "notify a subscribe on HTTP request start" do
|
1154
|
+
events = []
|
1155
|
+
Stripe::Instrumentation.subscribe(:request_end, :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
|
+
end
|
1166
|
+
|
1153
1167
|
should "notify a subscriber of a successful HTTP request" do
|
1154
1168
|
events = []
|
1155
|
-
Stripe::Instrumentation.subscribe(:
|
1169
|
+
Stripe::Instrumentation.subscribe(:request_end, :test) { |event| events << event }
|
1156
1170
|
|
1157
1171
|
stub_request(:get, "#{Stripe.api_base}/v1/charges")
|
1158
1172
|
.to_return(body: JSON.generate(object: "charge"))
|
@@ -1169,7 +1183,7 @@ module Stripe
|
|
1169
1183
|
|
1170
1184
|
should "notify a subscriber of a StripeError" do
|
1171
1185
|
events = []
|
1172
|
-
Stripe::Instrumentation.subscribe(:
|
1186
|
+
Stripe::Instrumentation.subscribe(:request_end, :test) { |event| events << event }
|
1173
1187
|
|
1174
1188
|
error = {
|
1175
1189
|
code: "code",
|
@@ -1197,7 +1211,7 @@ module Stripe
|
|
1197
1211
|
|
1198
1212
|
should "notify a subscriber of a network error" do
|
1199
1213
|
events = []
|
1200
|
-
Stripe::Instrumentation.subscribe(:
|
1214
|
+
Stripe::Instrumentation.subscribe(:request_end, :test) { |event| events << event }
|
1201
1215
|
|
1202
1216
|
stub_request(:get, "#{Stripe.api_base}/v1/charges")
|
1203
1217
|
.to_raise(Net::OpenTimeout)
|
@@ -1213,6 +1227,40 @@ module Stripe
|
|
1213
1227
|
assert(event.duration.positive?)
|
1214
1228
|
assert_equal(0, event.num_retries)
|
1215
1229
|
end
|
1230
|
+
|
1231
|
+
should "pass `user_data` from `request_begin` to `request_end`" do
|
1232
|
+
actual_user_data = nil
|
1233
|
+
|
1234
|
+
Stripe::Instrumentation.subscribe(:request_begin) do |event|
|
1235
|
+
event.user_data[:foo] = :bar
|
1236
|
+
end
|
1237
|
+
Stripe::Instrumentation.subscribe(:request_end) do |event|
|
1238
|
+
actual_user_data = event.user_data
|
1239
|
+
end
|
1240
|
+
|
1241
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges")
|
1242
|
+
.to_return(body: JSON.generate(object: "charge"))
|
1243
|
+
Stripe::Charge.list
|
1244
|
+
|
1245
|
+
assert_equal({ foo: :bar }, actual_user_data)
|
1246
|
+
end
|
1247
|
+
|
1248
|
+
should "provide backward compatibility on `request` topic" do
|
1249
|
+
events = []
|
1250
|
+
Stripe::Instrumentation.subscribe(:request, :test) { |event| events << event }
|
1251
|
+
|
1252
|
+
stub_request(:get, "#{Stripe.api_base}/v1/charges")
|
1253
|
+
.to_return(body: JSON.generate(object: "charge"))
|
1254
|
+
Stripe::Charge.list
|
1255
|
+
|
1256
|
+
assert_equal(1, events.size)
|
1257
|
+
event = events.first
|
1258
|
+
assert_equal(:get, event.method)
|
1259
|
+
assert_equal("/v1/charges", event.path)
|
1260
|
+
assert_equal(200, event.http_status)
|
1261
|
+
assert(event.duration.positive?)
|
1262
|
+
assert_equal(0, event.num_retries)
|
1263
|
+
end
|
1216
1264
|
end
|
1217
1265
|
end
|
1218
1266
|
|
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.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stripe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-02-10 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.
|