airbrake-ruby 4.2.5-java → 4.3.0-java
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/lib/airbrake-ruby.rb +1 -3
- data/lib/airbrake-ruby/benchmark.rb +29 -4
- data/lib/airbrake-ruby/config.rb +1 -1
- data/lib/airbrake-ruby/loggable.rb +1 -1
- data/lib/airbrake-ruby/monotonic_time.rb +1 -1
- data/lib/airbrake-ruby/notice_notifier.rb +8 -8
- data/lib/airbrake-ruby/performance_breakdown.rb +2 -2
- data/lib/airbrake-ruby/timed_trace.rb +58 -0
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/benchmark_spec.rb +27 -1
- data/spec/timed_trace_spec.rb +125 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c197583dc778ab7035f99942ce99f49fff9f9a5a
|
4
|
+
data.tar.gz: d8d9046a0acee6834eb604769ed39d696c2c2325
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 293bc6a216b3032ee31b449831bb936b58774fef7b184118094230e10af63490baf962995c01faaea15692836a85cc08ddc9799e12988ddacc1a1b5194a6ffda
|
7
|
+
data.tar.gz: '098415b654116fce90700b9e4f7d540637c98d5712b321eb808c20c386a3100a3e63ba68ab6d514029831e84dab9585e66dc17cafcf271c916dc81ab3ebf6089'
|
data/lib/airbrake-ruby.rb
CHANGED
@@ -49,6 +49,7 @@ require 'airbrake-ruby/request'
|
|
49
49
|
require 'airbrake-ruby/performance_breakdown'
|
50
50
|
require 'airbrake-ruby/benchmark'
|
51
51
|
require 'airbrake-ruby/monotonic_time'
|
52
|
+
require 'airbrake-ruby/timed_trace'
|
52
53
|
|
53
54
|
# Airbrake is a thin wrapper around instances of the notifier classes (such as
|
54
55
|
# notice, performance & deploy notifiers). It creates a way to access them via a
|
@@ -77,9 +78,6 @@ module Airbrake
|
|
77
78
|
# special cases where we need to work around older implementations
|
78
79
|
JRUBY = (RUBY_ENGINE == 'jruby')
|
79
80
|
|
80
|
-
# @!macro see_public_api_method
|
81
|
-
# @see Airbrake.$0
|
82
|
-
|
83
81
|
class << self
|
84
82
|
# @since v4.2.3
|
85
83
|
# @api private
|
@@ -1,14 +1,39 @@
|
|
1
1
|
module Airbrake
|
2
2
|
# Benchmark benchmarks Ruby code.
|
3
3
|
#
|
4
|
-
# @since v4.
|
4
|
+
# @since v4.2.4
|
5
5
|
# @api private
|
6
|
-
|
6
|
+
class Benchmark
|
7
7
|
# Measures monotonic time for the given operation.
|
8
|
+
#
|
9
|
+
# @yieldreturn [void]
|
8
10
|
def self.measure
|
9
|
-
|
11
|
+
benchmark = new
|
12
|
+
|
10
13
|
yield
|
11
|
-
|
14
|
+
|
15
|
+
benchmark.stop
|
16
|
+
benchmark.duration
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Float]
|
20
|
+
attr_reader :duration
|
21
|
+
|
22
|
+
# @since v4.3.0
|
23
|
+
def initialize
|
24
|
+
@start = MonotonicTime.time_in_ms
|
25
|
+
@duration = 0.0
|
26
|
+
end
|
27
|
+
|
28
|
+
# Stops the benchmark and stores `duration`.
|
29
|
+
#
|
30
|
+
# @since v4.3.0
|
31
|
+
# @return [Boolean] true for the first invocation, false in all other cases
|
32
|
+
def stop
|
33
|
+
return false if @duration > 0.0
|
34
|
+
|
35
|
+
@duration = MonotonicTime.time_in_ms - @start
|
36
|
+
true
|
12
37
|
end
|
13
38
|
end
|
14
39
|
end
|
data/lib/airbrake-ruby/config.rb
CHANGED
@@ -31,27 +31,27 @@ module Airbrake
|
|
31
31
|
add_filter(Airbrake::Filters::ExceptionAttributesFilter.new)
|
32
32
|
end
|
33
33
|
|
34
|
-
# @
|
34
|
+
# @see Airbrake.notify
|
35
35
|
def notify(exception, params = {}, &block)
|
36
36
|
send_notice(exception, params, default_sender, &block)
|
37
37
|
end
|
38
38
|
|
39
|
-
# @
|
39
|
+
# @see Airbrake.notify_sync
|
40
40
|
def notify_sync(exception, params = {}, &block)
|
41
41
|
send_notice(exception, params, @sync_sender, &block).value
|
42
42
|
end
|
43
43
|
|
44
|
-
# @
|
44
|
+
# @see Airbrake.add_filte
|
45
45
|
def add_filter(filter = nil, &block)
|
46
46
|
@filter_chain.add_filter(block_given? ? block : filter)
|
47
47
|
end
|
48
48
|
|
49
|
-
# @
|
49
|
+
# @see Airbrake.delete_filter
|
50
50
|
def delete_filter(filter_class)
|
51
51
|
@filter_chain.delete_filter(filter_class)
|
52
52
|
end
|
53
53
|
|
54
|
-
# @
|
54
|
+
# @see Airbrake.build_notice
|
55
55
|
def build_notice(exception, params = {})
|
56
56
|
if @async_sender.closed?
|
57
57
|
raise Airbrake::Error,
|
@@ -66,17 +66,17 @@ module Airbrake
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
# @
|
69
|
+
# @see Airbrake.close
|
70
70
|
def close
|
71
71
|
@async_sender.close
|
72
72
|
end
|
73
73
|
|
74
|
-
# @
|
74
|
+
# @see Airbrake.configured?
|
75
75
|
def configured?
|
76
76
|
@config.valid?
|
77
77
|
end
|
78
78
|
|
79
|
-
# @
|
79
|
+
# @see Airbrake.merge_context
|
80
80
|
def merge_context(context)
|
81
81
|
@context.merge!(context)
|
82
82
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Airbrake
|
2
2
|
# PerformanceBreakdown holds data that shows how much time a request spent
|
3
|
-
# doing certaing subtasks such as (DB querying, view rendering, etc).
|
3
|
+
# doing certaing subtasks such as (DB querying, view rendering, etc).
|
4
4
|
#
|
5
5
|
# @see Airbrake.notify_breakdown
|
6
6
|
# @api public
|
7
|
-
# @since v4.
|
7
|
+
# @since v4.2.0
|
8
8
|
# rubocop:disable Metrics/BlockLength, Metrics/ParameterLists
|
9
9
|
PerformanceBreakdown = Struct.new(
|
10
10
|
:method, :route, :response_type, :groups, :start_time, :end_time
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# TimedTrace represents a chunk of code performance of which was measured and
|
3
|
+
# stored under a label. The chunk is called a "span".
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# timed_trace = TimedTrace.new
|
7
|
+
# timed_trace.span('http request') do
|
8
|
+
# http.get('example.com')
|
9
|
+
# end
|
10
|
+
# timed_trace.spans #=> { 'http request' => 0.123 }
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
# @since v4.3.0
|
14
|
+
class TimedTrace
|
15
|
+
# @param [String] label
|
16
|
+
# @return [Airbrake::TimedTrace]
|
17
|
+
def self.span(label, &block)
|
18
|
+
new.tap { |timed_trace| timed_trace.span(label, &block) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@spans = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] label
|
26
|
+
# @return [Boolean]
|
27
|
+
def span(label)
|
28
|
+
start_span(label)
|
29
|
+
yield
|
30
|
+
stop_span(label)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [String] label
|
34
|
+
# @return [Boolean]
|
35
|
+
def start_span(label)
|
36
|
+
return false if @spans.key?(label)
|
37
|
+
|
38
|
+
@spans[label] = Airbrake::Benchmark.new
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [String] label
|
43
|
+
# @return [Boolean]
|
44
|
+
def stop_span(label)
|
45
|
+
return false unless @spans.key?(label)
|
46
|
+
|
47
|
+
@spans[label].stop
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Hash<String=>Float>]
|
52
|
+
def spans
|
53
|
+
@spans.each_with_object({}) do |(label, benchmark), new_spans|
|
54
|
+
new_spans[label] = benchmark.duration
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spec/benchmark_spec.rb
CHANGED
@@ -1,7 +1,33 @@
|
|
1
1
|
RSpec.describe Airbrake::Benchmark do
|
2
2
|
describe ".measure" do
|
3
3
|
it "returns measured performance time" do
|
4
|
-
expect(
|
4
|
+
expect(described_class.measure { '10' * 10 }).to be_kind_of(Numeric)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#stop" do
|
9
|
+
before { subject }
|
10
|
+
|
11
|
+
context "when called one time" do
|
12
|
+
its(:stop) { is_expected.to eq(true) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when called twice or more" do
|
16
|
+
before { subject.stop }
|
17
|
+
|
18
|
+
its(:stop) { is_expected.to eq(false) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#duration" do
|
23
|
+
context "when #stop wasn't called yet" do
|
24
|
+
its(:duration) { is_expected.to be_zero }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when #stop was called" do
|
28
|
+
before { subject.stop }
|
29
|
+
|
30
|
+
its(:duration) { is_expected.to be > 0 }
|
5
31
|
end
|
6
32
|
end
|
7
33
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
RSpec.describe Airbrake::TimedTrace do
|
2
|
+
describe ".span" do
|
3
|
+
it "returns a timed trace" do
|
4
|
+
expect(described_class.span('operation') {}).to be_a(described_class)
|
5
|
+
end
|
6
|
+
|
7
|
+
it "returns a timed trace with a stopped span" do
|
8
|
+
timed_trace = described_class.span('operation') {}
|
9
|
+
expect(timed_trace.spans).to match('operation' => be > 0)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#span" do
|
14
|
+
it "captures a span" do
|
15
|
+
subject.span('operation') {}
|
16
|
+
expect(subject.spans).to match('operation' => be > 0)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#start_span" do
|
21
|
+
context "when called once" do
|
22
|
+
it "returns true" do
|
23
|
+
expect(subject.start_span('operation')).to eq(true)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when called multiple times" do
|
28
|
+
before { subject.start_span('operation') }
|
29
|
+
|
30
|
+
it "returns false" do
|
31
|
+
expect(subject.start_span('operation')).to eq(false)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when another span was started" do
|
36
|
+
before { subject.start_span('operation') }
|
37
|
+
|
38
|
+
it "returns true" do
|
39
|
+
expect(subject.start_span('another operation')).to eq(true)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when #spans was called" do
|
44
|
+
before { subject.start_span('operation') }
|
45
|
+
|
46
|
+
it "returns spans with zero values" do
|
47
|
+
expect(subject.spans).to eq('operation' => 0.0)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#stop_span" do
|
53
|
+
context "when #start_span wasn't invoked" do
|
54
|
+
it "returns false" do
|
55
|
+
expect(subject.stop_span('operation')).to eq(false)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when #start_span was invoked" do
|
60
|
+
before { subject.start_span('operation') }
|
61
|
+
|
62
|
+
it "returns true" do
|
63
|
+
expect(subject.stop_span('operation')).to eq(true)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when multiple spans were started" do
|
68
|
+
before do
|
69
|
+
subject.start_span('operation')
|
70
|
+
subject.start_span('another operation')
|
71
|
+
end
|
72
|
+
|
73
|
+
context "and when stopping in LIFO order" do
|
74
|
+
it "returns true for all spans" do
|
75
|
+
expect(subject.stop_span('another operation')).to eq(true)
|
76
|
+
expect(subject.stop_span('operation')).to eq(true)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "and when stopping in FIFO order" do
|
81
|
+
it "returns true for all spans" do
|
82
|
+
expect(subject.stop_span('operation')).to eq(true)
|
83
|
+
expect(subject.stop_span('another operation')).to eq(true)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#spans" do
|
90
|
+
context "when no spans were captured" do
|
91
|
+
it "returns an empty hash" do
|
92
|
+
expect(subject.spans).to eq({})
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "when a span was captured" do
|
97
|
+
before do
|
98
|
+
subject.start_span('operation')
|
99
|
+
subject.stop_span('operation')
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns a Hash with the corresponding span" do
|
103
|
+
subject.stop_span('operation')
|
104
|
+
expect(subject.spans).to match('operation' => be > 0)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "when multiple spans were captured" do
|
109
|
+
before do
|
110
|
+
subject.start_span('operation')
|
111
|
+
subject.stop_span('operation')
|
112
|
+
|
113
|
+
subject.start_span('another operation')
|
114
|
+
subject.stop_span('another operation')
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns a Hash with all spans" do
|
118
|
+
expect(subject.spans).to match(
|
119
|
+
'operation' => be > 0,
|
120
|
+
'another operation' => be > 0
|
121
|
+
)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airbrake-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Airbrake Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rbtree-jruby
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- lib/airbrake-ruby/sync_sender.rb
|
81
81
|
- lib/airbrake-ruby/tdigest.rb
|
82
82
|
- lib/airbrake-ruby/time_truncate.rb
|
83
|
+
- lib/airbrake-ruby/timed_trace.rb
|
83
84
|
- lib/airbrake-ruby/truncator.rb
|
84
85
|
- lib/airbrake-ruby/version.rb
|
85
86
|
- spec/airbrake_spec.rb
|
@@ -127,6 +128,7 @@ files:
|
|
127
128
|
- spec/sync_sender_spec.rb
|
128
129
|
- spec/tdigest_spec.rb
|
129
130
|
- spec/time_truncate_spec.rb
|
131
|
+
- spec/timed_trace_spec.rb
|
130
132
|
- spec/truncator_spec.rb
|
131
133
|
homepage: https://airbrake.io
|
132
134
|
licenses:
|
@@ -186,6 +188,7 @@ test_files:
|
|
186
188
|
- spec/performance_notifier_spec.rb
|
187
189
|
- spec/airbrake_spec.rb
|
188
190
|
- spec/nested_exception_spec.rb
|
191
|
+
- spec/timed_trace_spec.rb
|
189
192
|
- spec/filter_chain_spec.rb
|
190
193
|
- spec/response_spec.rb
|
191
194
|
- spec/file_cache.rb
|