airbrake-ruby 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +197 -43
- data/lib/airbrake-ruby/config.rb +43 -11
- data/lib/airbrake-ruby/deploy_notifier.rb +47 -0
- data/lib/airbrake-ruby/filter_chain.rb +32 -50
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +9 -1
- data/lib/airbrake-ruby/filters/sql_filter.rb +104 -0
- data/lib/airbrake-ruby/hash_keyable.rb +37 -0
- data/lib/airbrake-ruby/ignorable.rb +44 -0
- data/lib/airbrake-ruby/notice.rb +2 -22
- data/lib/airbrake-ruby/{notifier.rb → notice_notifier.rb} +66 -46
- data/lib/airbrake-ruby/performance_notifier.rb +161 -0
- data/lib/airbrake-ruby/stat.rb +56 -0
- data/lib/airbrake-ruby/tdigest.rb +393 -0
- data/lib/airbrake-ruby/time_truncate.rb +17 -0
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/airbrake_spec.rb +57 -13
- data/spec/async_sender_spec.rb +0 -2
- data/spec/backtrace_spec.rb +0 -2
- data/spec/code_hunk_spec.rb +0 -2
- data/spec/config/validator_spec.rb +0 -2
- data/spec/config_spec.rb +16 -4
- data/spec/deploy_notifier_spec.rb +41 -0
- data/spec/file_cache.rb +0 -2
- data/spec/filter_chain_spec.rb +1 -7
- data/spec/filters/context_filter_spec.rb +0 -2
- data/spec/filters/dependency_filter_spec.rb +0 -2
- data/spec/filters/exception_attributes_filter_spec.rb +0 -2
- data/spec/filters/gem_root_filter_spec.rb +0 -2
- data/spec/filters/git_last_checkout_filter_spec.rb +0 -2
- data/spec/filters/git_repository_filter.rb +0 -2
- data/spec/filters/git_revision_filter_spec.rb +0 -2
- data/spec/filters/keys_blacklist_spec.rb +0 -2
- data/spec/filters/keys_whitelist_spec.rb +0 -2
- data/spec/filters/root_directory_filter_spec.rb +0 -2
- data/spec/filters/sql_filter_spec.rb +219 -0
- data/spec/filters/system_exit_filter_spec.rb +0 -2
- data/spec/filters/thread_filter_spec.rb +0 -2
- data/spec/ignorable_spec.rb +14 -0
- data/spec/nested_exception_spec.rb +0 -2
- data/spec/{notifier_spec.rb → notice_notifier_spec.rb} +24 -114
- data/spec/{notifier_spec → notice_notifier_spec}/options_spec.rb +40 -39
- data/spec/notice_spec.rb +2 -4
- data/spec/performance_notifier_spec.rb +287 -0
- data/spec/promise_spec.rb +0 -2
- data/spec/response_spec.rb +0 -2
- data/spec/stat_spec.rb +35 -0
- data/spec/sync_sender_spec.rb +0 -2
- data/spec/tdigest_spec.rb +230 -0
- data/spec/time_truncate_spec.rb +13 -0
- data/spec/truncator_spec.rb +0 -2
- metadata +34 -15
- data/lib/airbrake-ruby/route_sender.rb +0 -175
- data/spec/route_sender_spec.rb +0 -130
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec.describe Airbrake::TimeTruncate do
|
2
|
+
describe "#utc_truncate_minutes" do
|
3
|
+
it "truncates time to the floor minute and returns an RFC3339 timestamp" do
|
4
|
+
time = Time.new(2018, 1, 1, 0, 0, 20, 0)
|
5
|
+
expect(subject.utc_truncate_minutes(time)).to eq('2018-01-01T00:00:00+00:00')
|
6
|
+
end
|
7
|
+
|
8
|
+
it "converts time with zone to UTC" do
|
9
|
+
time = Time.new(2018, 1, 1, 0, 0, 20, '-05:00')
|
10
|
+
expect(subject.utc_truncate_minutes(time)).to eq('2018-01-01T05:00:00+00:00')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/truncator_spec.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airbrake-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Airbrake Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rbtree3
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.5.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.5.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- lib/airbrake-ruby/code_hunk.rb
|
135
135
|
- lib/airbrake-ruby/config.rb
|
136
136
|
- lib/airbrake-ruby/config/validator.rb
|
137
|
+
- lib/airbrake-ruby/deploy_notifier.rb
|
137
138
|
- lib/airbrake-ruby/file_cache.rb
|
138
139
|
- lib/airbrake-ruby/filter_chain.rb
|
139
140
|
- lib/airbrake-ruby/filters/context_filter.rb
|
@@ -147,15 +148,21 @@ files:
|
|
147
148
|
- lib/airbrake-ruby/filters/keys_filter.rb
|
148
149
|
- lib/airbrake-ruby/filters/keys_whitelist.rb
|
149
150
|
- lib/airbrake-ruby/filters/root_directory_filter.rb
|
151
|
+
- lib/airbrake-ruby/filters/sql_filter.rb
|
150
152
|
- lib/airbrake-ruby/filters/system_exit_filter.rb
|
151
153
|
- lib/airbrake-ruby/filters/thread_filter.rb
|
154
|
+
- lib/airbrake-ruby/hash_keyable.rb
|
155
|
+
- lib/airbrake-ruby/ignorable.rb
|
152
156
|
- lib/airbrake-ruby/nested_exception.rb
|
153
157
|
- lib/airbrake-ruby/notice.rb
|
154
|
-
- lib/airbrake-ruby/
|
158
|
+
- lib/airbrake-ruby/notice_notifier.rb
|
159
|
+
- lib/airbrake-ruby/performance_notifier.rb
|
155
160
|
- lib/airbrake-ruby/promise.rb
|
156
161
|
- lib/airbrake-ruby/response.rb
|
157
|
-
- lib/airbrake-ruby/
|
162
|
+
- lib/airbrake-ruby/stat.rb
|
158
163
|
- lib/airbrake-ruby/sync_sender.rb
|
164
|
+
- lib/airbrake-ruby/tdigest.rb
|
165
|
+
- lib/airbrake-ruby/time_truncate.rb
|
159
166
|
- lib/airbrake-ruby/truncator.rb
|
160
167
|
- lib/airbrake-ruby/version.rb
|
161
168
|
- spec/airbrake_spec.rb
|
@@ -164,6 +171,7 @@ files:
|
|
164
171
|
- spec/code_hunk_spec.rb
|
165
172
|
- spec/config/validator_spec.rb
|
166
173
|
- spec/config_spec.rb
|
174
|
+
- spec/deploy_notifier_spec.rb
|
167
175
|
- spec/file_cache.rb
|
168
176
|
- spec/filter_chain_spec.rb
|
169
177
|
- spec/filters/context_filter_spec.rb
|
@@ -176,6 +184,7 @@ files:
|
|
176
184
|
- spec/filters/keys_blacklist_spec.rb
|
177
185
|
- spec/filters/keys_whitelist_spec.rb
|
178
186
|
- spec/filters/root_directory_filter_spec.rb
|
187
|
+
- spec/filters/sql_filter_spec.rb
|
179
188
|
- spec/filters/system_exit_filter_spec.rb
|
180
189
|
- spec/filters/thread_filter_spec.rb
|
181
190
|
- spec/fixtures/notroot.txt
|
@@ -185,15 +194,19 @@ files:
|
|
185
194
|
- spec/fixtures/project_root/short_file.rb
|
186
195
|
- spec/fixtures/project_root/vendor/bundle/ignored_file.rb
|
187
196
|
- spec/helpers.rb
|
197
|
+
- spec/ignorable_spec.rb
|
188
198
|
- spec/nested_exception_spec.rb
|
199
|
+
- spec/notice_notifier_spec.rb
|
200
|
+
- spec/notice_notifier_spec/options_spec.rb
|
189
201
|
- spec/notice_spec.rb
|
190
|
-
- spec/
|
191
|
-
- spec/notifier_spec/options_spec.rb
|
202
|
+
- spec/performance_notifier_spec.rb
|
192
203
|
- spec/promise_spec.rb
|
193
204
|
- spec/response_spec.rb
|
194
|
-
- spec/route_sender_spec.rb
|
195
205
|
- spec/spec_helper.rb
|
206
|
+
- spec/stat_spec.rb
|
196
207
|
- spec/sync_sender_spec.rb
|
208
|
+
- spec/tdigest_spec.rb
|
209
|
+
- spec/time_truncate_spec.rb
|
197
210
|
- spec/truncator_spec.rb
|
198
211
|
homepage: https://airbrake.io
|
199
212
|
licenses:
|
@@ -220,11 +233,11 @@ signing_key:
|
|
220
233
|
specification_version: 4
|
221
234
|
summary: Ruby notifier for https://airbrake.io
|
222
235
|
test_files:
|
223
|
-
- spec/route_sender_spec.rb
|
224
236
|
- spec/truncator_spec.rb
|
225
237
|
- spec/helpers.rb
|
226
238
|
- spec/filters/exception_attributes_filter_spec.rb
|
227
239
|
- spec/filters/root_directory_filter_spec.rb
|
240
|
+
- spec/filters/sql_filter_spec.rb
|
228
241
|
- spec/filters/keys_whitelist_spec.rb
|
229
242
|
- spec/filters/system_exit_filter_spec.rb
|
230
243
|
- spec/filters/thread_filter_spec.rb
|
@@ -238,13 +251,19 @@ test_files:
|
|
238
251
|
- spec/spec_helper.rb
|
239
252
|
- spec/notice_spec.rb
|
240
253
|
- spec/config_spec.rb
|
254
|
+
- spec/tdigest_spec.rb
|
241
255
|
- spec/async_sender_spec.rb
|
256
|
+
- spec/stat_spec.rb
|
242
257
|
- spec/backtrace_spec.rb
|
258
|
+
- spec/notice_notifier_spec.rb
|
259
|
+
- spec/time_truncate_spec.rb
|
243
260
|
- spec/promise_spec.rb
|
244
261
|
- spec/config/validator_spec.rb
|
245
262
|
- spec/sync_sender_spec.rb
|
263
|
+
- spec/ignorable_spec.rb
|
264
|
+
- spec/deploy_notifier_spec.rb
|
265
|
+
- spec/performance_notifier_spec.rb
|
246
266
|
- spec/airbrake_spec.rb
|
247
|
-
- spec/notifier_spec.rb
|
248
267
|
- spec/nested_exception_spec.rb
|
249
268
|
- spec/filter_chain_spec.rb
|
250
269
|
- spec/response_spec.rb
|
@@ -256,4 +275,4 @@ test_files:
|
|
256
275
|
- spec/fixtures/project_root/code.rb
|
257
276
|
- spec/fixtures/project_root/short_file.rb
|
258
277
|
- spec/fixtures/project_root/vendor/bundle/ignored_file.rb
|
259
|
-
- spec/
|
278
|
+
- spec/notice_notifier_spec/options_spec.rb
|
@@ -1,175 +0,0 @@
|
|
1
|
-
require 'tdigest'
|
2
|
-
require 'base64'
|
3
|
-
|
4
|
-
module Airbrake
|
5
|
-
# RouteSender aggregates information about requests and periodically sends
|
6
|
-
# collected data to Airbrake.
|
7
|
-
# @since v3.0.0
|
8
|
-
class RouteSender
|
9
|
-
# Monkey-patch https://github.com/castle/tdigest to pack with Big Endian
|
10
|
-
# (instead of Little Endian) since our backend wants it.
|
11
|
-
#
|
12
|
-
# @see https://github.com/castle/tdigest/blob/master/lib/tdigest/tdigest.rb
|
13
|
-
# @since v3.0.0
|
14
|
-
# @api private
|
15
|
-
module TDigestBigEndianness
|
16
|
-
refine TDigest::TDigest do
|
17
|
-
# rubocop:disable Metrics/AbcSize
|
18
|
-
def as_small_bytes
|
19
|
-
size = @centroids.size
|
20
|
-
output = [self.class::SMALL_ENCODING, compression, size]
|
21
|
-
x = 0
|
22
|
-
# delta encoding allows saving 4-bytes floats
|
23
|
-
mean_arr = @centroids.map do |_, c|
|
24
|
-
val = c.mean - x
|
25
|
-
x = c.mean
|
26
|
-
val
|
27
|
-
end
|
28
|
-
output += mean_arr
|
29
|
-
# Variable length encoding of numbers
|
30
|
-
c_arr = @centroids.each_with_object([]) do |(_, c), arr|
|
31
|
-
k = 0
|
32
|
-
n = c.n
|
33
|
-
while n < 0 || n > 0x7f
|
34
|
-
b = 0x80 | (0x7f & n)
|
35
|
-
arr << b
|
36
|
-
n = n >> 7
|
37
|
-
k += 1
|
38
|
-
raise 'Unreasonable large number' if k > 6
|
39
|
-
end
|
40
|
-
arr << n
|
41
|
-
end
|
42
|
-
output += c_arr
|
43
|
-
output.pack("NGNg#{size}C#{size}")
|
44
|
-
end
|
45
|
-
# rubocop:enable Metrics/AbcSize
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
using TDigestBigEndianness
|
50
|
-
|
51
|
-
# The key that represents a route.
|
52
|
-
RouteKey = Struct.new(:method, :route, :statusCode, :time)
|
53
|
-
|
54
|
-
# RouteStat holds data that describes a route's performance.
|
55
|
-
RouteStat = Struct.new(:count, :sum, :sumsq, :tdigest) do
|
56
|
-
# @param [Integer] count The number of requests
|
57
|
-
# @param [Float] sum The sum of request duration in milliseconds
|
58
|
-
# @param [Float] sumsq The squared sum of request duration in milliseconds
|
59
|
-
# @param [TDigest::TDigest] tdigest By default, the compression is 20
|
60
|
-
def initialize(
|
61
|
-
count: 0, sum: 0.0, sumsq: 0.0, tdigest: TDigest::TDigest.new(0.05)
|
62
|
-
)
|
63
|
-
super(count, sum, sumsq, tdigest)
|
64
|
-
end
|
65
|
-
|
66
|
-
# @return [Hash{String=>Object}] the route stat as a hash with compressed
|
67
|
-
# and serialized as binary base64 tdigest
|
68
|
-
def to_h
|
69
|
-
tdigest.compress!
|
70
|
-
{
|
71
|
-
'count' => count,
|
72
|
-
'sum' => sum,
|
73
|
-
'sumsq' => sumsq,
|
74
|
-
'tdigest' => Base64.strict_encode64(tdigest.as_small_bytes)
|
75
|
-
}
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# @param [Airbrake::Config] config
|
80
|
-
def initialize(config)
|
81
|
-
@config = config
|
82
|
-
@flush_period = config.route_stats_flush_period
|
83
|
-
@sender = SyncSender.new(config, :put)
|
84
|
-
@routes = {}
|
85
|
-
@thread = nil
|
86
|
-
@mutex = Mutex.new
|
87
|
-
end
|
88
|
-
|
89
|
-
# @macro see_public_api_method
|
90
|
-
# @param [Airbrake::Promise] promise
|
91
|
-
def notify_request(request_info, promise = Airbrake::Promise.new)
|
92
|
-
route = create_route_key(
|
93
|
-
request_info[:method],
|
94
|
-
request_info[:route],
|
95
|
-
request_info[:status_code],
|
96
|
-
utc_truncate_minutes(request_info[:start_time])
|
97
|
-
)
|
98
|
-
|
99
|
-
@mutex.synchronize do
|
100
|
-
@routes[route] ||= RouteStat.new
|
101
|
-
increment_stats(request_info, @routes[route])
|
102
|
-
|
103
|
-
if @flush_period > 0
|
104
|
-
schedule_flush(promise)
|
105
|
-
else
|
106
|
-
send(@routes, promise)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
promise
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
|
115
|
-
def create_route_key(method, route, status_code, tm)
|
116
|
-
# rubocop:disable Style/DateTime
|
117
|
-
time = DateTime.new(
|
118
|
-
tm.year, tm.month, tm.day, tm.hour, tm.min, 0, tm.zone || 0
|
119
|
-
)
|
120
|
-
# rubocop:enable Style/DateTime
|
121
|
-
RouteKey.new(method, route, status_code, time.rfc3339)
|
122
|
-
end
|
123
|
-
|
124
|
-
def increment_stats(request_info, stat)
|
125
|
-
stat.count += 1
|
126
|
-
|
127
|
-
end_time = request_info[:end_time] || Time.new
|
128
|
-
ms = (end_time - request_info[:start_time]) * 1000
|
129
|
-
|
130
|
-
stat.sum += ms
|
131
|
-
stat.sumsq += ms * ms
|
132
|
-
|
133
|
-
stat.tdigest.push(ms)
|
134
|
-
end
|
135
|
-
|
136
|
-
def schedule_flush(promise)
|
137
|
-
@thread ||= Thread.new do
|
138
|
-
sleep(@flush_period)
|
139
|
-
|
140
|
-
routes = nil
|
141
|
-
@mutex.synchronize do
|
142
|
-
routes = @routes
|
143
|
-
@routes = {}
|
144
|
-
@thread = nil
|
145
|
-
end
|
146
|
-
|
147
|
-
send(routes, promise)
|
148
|
-
end
|
149
|
-
|
150
|
-
# Setting a name is needed to test the timer.
|
151
|
-
# Ruby <=2.2 doesn't support Thread#name, so we have this check.
|
152
|
-
@thread.name = 'route-stat-thread' if @thread.respond_to?(:name)
|
153
|
-
end
|
154
|
-
|
155
|
-
def send(routes, promise)
|
156
|
-
if routes.none?
|
157
|
-
raise "#{self.class.name}##{__method__}: routes cannot be empty. Race?"
|
158
|
-
end
|
159
|
-
|
160
|
-
@config.logger.debug("#{LOG_LABEL} RouteStats#send: #{routes}")
|
161
|
-
|
162
|
-
@sender.send(
|
163
|
-
{ routes: routes.map { |k, v| k.to_h.merge(v.to_h) } },
|
164
|
-
promise,
|
165
|
-
URI.join(@config.host, "api/v5/projects/#{@config.project_id}/routes-stats")
|
166
|
-
)
|
167
|
-
end
|
168
|
-
|
169
|
-
def utc_truncate_minutes(time)
|
170
|
-
time_array = time.to_a
|
171
|
-
time_array[0] = 0
|
172
|
-
Time.utc(*time_array)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
data/spec/route_sender_spec.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Airbrake::RouteSender do
|
4
|
-
let(:endpoint) { 'https://api.airbrake.io/api/v5/projects/1/routes-stats' }
|
5
|
-
|
6
|
-
let(:config) do
|
7
|
-
Airbrake::Config.new(
|
8
|
-
project_id: 1,
|
9
|
-
project_key: 'banana',
|
10
|
-
route_stats_flush_period: 0.1
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
subject { described_class.new(config) }
|
15
|
-
|
16
|
-
describe "#notify_request" do
|
17
|
-
before do
|
18
|
-
stub_request(:put, endpoint).to_return(status: 200, body: '')
|
19
|
-
end
|
20
|
-
|
21
|
-
# Let the request finish.
|
22
|
-
after { sleep 0.2 }
|
23
|
-
|
24
|
-
it "rounds time to the floor minute" do
|
25
|
-
subject.notify_request(
|
26
|
-
method: 'GET',
|
27
|
-
route: '/foo',
|
28
|
-
status_code: 200,
|
29
|
-
start_time: Time.new(2018, 1, 1, 0, 0, 20, 0)
|
30
|
-
)
|
31
|
-
sleep 0.2
|
32
|
-
expect(
|
33
|
-
a_request(:put, endpoint).with(body: /"time":"2018-01-01T00:00:00\+00:00"/)
|
34
|
-
).to have_been_made
|
35
|
-
end
|
36
|
-
|
37
|
-
it "increments routes with the same key" do
|
38
|
-
subject.notify_request(
|
39
|
-
method: 'GET',
|
40
|
-
route: '/foo',
|
41
|
-
status_code: 200,
|
42
|
-
start_time: Time.new(2018, 1, 1, 0, 0, 20, 0)
|
43
|
-
)
|
44
|
-
subject.notify_request(
|
45
|
-
method: 'GET',
|
46
|
-
route: '/foo',
|
47
|
-
status_code: 200,
|
48
|
-
start_time: Time.new(2018, 1, 1, 0, 0, 50, 0)
|
49
|
-
)
|
50
|
-
sleep 0.2
|
51
|
-
expect(
|
52
|
-
a_request(:put, endpoint).with(body: /"count":2/)
|
53
|
-
).to have_been_made
|
54
|
-
end
|
55
|
-
|
56
|
-
it "groups routes by time" do
|
57
|
-
subject.notify_request(
|
58
|
-
method: 'GET',
|
59
|
-
route: '/foo',
|
60
|
-
status_code: 200,
|
61
|
-
start_time: Time.new(2018, 1, 1, 0, 0, 49, 0),
|
62
|
-
end_time: Time.new(2018, 1, 1, 0, 0, 50, 0)
|
63
|
-
)
|
64
|
-
subject.notify_request(
|
65
|
-
method: 'GET',
|
66
|
-
route: '/foo',
|
67
|
-
status_code: 200,
|
68
|
-
start_time: Time.new(2018, 1, 1, 0, 1, 49, 0),
|
69
|
-
end_time: Time.new(2018, 1, 1, 0, 1, 55, 0)
|
70
|
-
)
|
71
|
-
sleep 0.2
|
72
|
-
expect(
|
73
|
-
a_request(:put, endpoint).with(
|
74
|
-
body: %r|\A
|
75
|
-
{"routes":\[
|
76
|
-
{"method":"GET","route":"/foo","statusCode":200,
|
77
|
-
"time":"2018-01-01T00:00:00\+00:00","count":1,"sum":1000.0,
|
78
|
-
"sumsq":1000000.0,"tdigest":"AAAAAkA0AAAAAAAAAAAAAUR6AAAB"},
|
79
|
-
{"method":"GET","route":"/foo","statusCode":200,
|
80
|
-
"time":"2018-01-01T00:01:00\+00:00","count":1,"sum":6000.0,
|
81
|
-
"sumsq":36000000.0,"tdigest":"AAAAAkA0AAAAAAAAAAAAAUW7gAAB"}\]}
|
82
|
-
\z|x
|
83
|
-
)
|
84
|
-
).to have_been_made
|
85
|
-
end
|
86
|
-
|
87
|
-
it "groups routes by route key" do
|
88
|
-
subject.notify_request(
|
89
|
-
method: 'GET',
|
90
|
-
route: '/foo',
|
91
|
-
status_code: 200,
|
92
|
-
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
93
|
-
end_time: Time.new(2018, 1, 1, 0, 50, 0, 0)
|
94
|
-
)
|
95
|
-
subject.notify_request(
|
96
|
-
method: 'POST',
|
97
|
-
route: '/foo',
|
98
|
-
status_code: 200,
|
99
|
-
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
100
|
-
end_time: Time.new(2018, 1, 1, 0, 50, 0, 0)
|
101
|
-
)
|
102
|
-
sleep 0.2
|
103
|
-
expect(
|
104
|
-
a_request(:put, endpoint).with(
|
105
|
-
body: %r|\A
|
106
|
-
{"routes":\[
|
107
|
-
{"method":"GET","route":"/foo","statusCode":200,
|
108
|
-
"time":"2018-01-01T00:49:00\+00:00","count":1,"sum":60000.0,
|
109
|
-
"sumsq":3600000000.0,"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB"},
|
110
|
-
{"method":"POST","route":"/foo","statusCode":200,
|
111
|
-
"time":"2018-01-01T00:49:00\+00:00","count":1,"sum":60000.0,
|
112
|
-
"sumsq":3600000000.0,"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB"}\]}
|
113
|
-
\z|x
|
114
|
-
)
|
115
|
-
).to have_been_made
|
116
|
-
end
|
117
|
-
|
118
|
-
it "returns a promise" do
|
119
|
-
promise = subject.notify_request(
|
120
|
-
method: 'GET',
|
121
|
-
route: '/foo',
|
122
|
-
status_code: 200,
|
123
|
-
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0)
|
124
|
-
)
|
125
|
-
sleep 0.2
|
126
|
-
expect(promise).to be_an(Airbrake::Promise)
|
127
|
-
expect(promise.value).to eq('' => nil)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|