appsignal 2.11.0-java → 2.11.4-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/.rubocop.yml +2 -0
- data/.semaphore/semaphore.yml +197 -0
- data/CHANGELOG.md +19 -0
- data/README.md +16 -1
- data/Rakefile +20 -11
- data/build_matrix.yml +13 -0
- data/ext/agent.yml +17 -25
- data/ext/appsignal_extension.c +1 -1
- data/ext/base.rb +12 -9
- data/gemfiles/no_dependencies.gemfile +7 -0
- data/gemfiles/resque-2.gemfile +0 -1
- data/gemfiles/webmachine.gemfile +1 -0
- data/lib/appsignal/cli/diagnose/utils.rb +8 -11
- data/lib/appsignal/cli/install.rb +5 -8
- data/lib/appsignal/helpers/instrumentation.rb +32 -0
- data/lib/appsignal/hooks.rb +1 -0
- data/lib/appsignal/hooks/action_mailer.rb +22 -0
- data/lib/appsignal/hooks/active_support_notifications.rb +72 -0
- data/lib/appsignal/hooks/shoryuken.rb +43 -4
- data/lib/appsignal/integrations/object.rb +4 -34
- data/lib/appsignal/integrations/object_ruby_19.rb +37 -0
- data/lib/appsignal/integrations/object_ruby_modern.rb +64 -0
- data/lib/appsignal/system.rb +4 -0
- data/lib/appsignal/transaction.rb +30 -2
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/hooks/action_mailer_spec.rb +54 -0
- data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +35 -0
- data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +145 -0
- data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +69 -0
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +9 -137
- data/spec/lib/appsignal/hooks/resque_spec.rb +10 -2
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +151 -104
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +4 -2
- data/spec/lib/appsignal/integrations/object_19_spec.rb +266 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +29 -10
- data/spec/lib/appsignal/transaction_spec.rb +55 -0
- data/spec/lib/appsignal_spec.rb +30 -0
- data/spec/support/helpers/dependency_helper.rb +4 -0
- metadata +16 -3
@@ -60,7 +60,10 @@ describe Appsignal::Hooks::ResqueHook do
|
|
60
60
|
"error" => nil,
|
61
61
|
"namespace" => namespace,
|
62
62
|
"metadata" => {},
|
63
|
-
"sample_data" => {
|
63
|
+
"sample_data" => {
|
64
|
+
"breadcrumbs" => [],
|
65
|
+
"tags" => { "queue" => queue }
|
66
|
+
}
|
64
67
|
)
|
65
68
|
expect(transaction_hash["events"].map { |e| e["name"] })
|
66
69
|
.to eql(["perform.resque"])
|
@@ -84,7 +87,10 @@ describe Appsignal::Hooks::ResqueHook do
|
|
84
87
|
},
|
85
88
|
"namespace" => namespace,
|
86
89
|
"metadata" => {},
|
87
|
-
"sample_data" => {
|
90
|
+
"sample_data" => {
|
91
|
+
"breadcrumbs" => [],
|
92
|
+
"tags" => { "queue" => queue }
|
93
|
+
}
|
88
94
|
)
|
89
95
|
end
|
90
96
|
end
|
@@ -118,6 +124,7 @@ describe Appsignal::Hooks::ResqueHook do
|
|
118
124
|
"metadata" => {},
|
119
125
|
"sample_data" => {
|
120
126
|
"tags" => { "queue" => queue },
|
127
|
+
"breadcrumbs" => [],
|
121
128
|
"params" => [
|
122
129
|
"foo",
|
123
130
|
{
|
@@ -174,6 +181,7 @@ describe Appsignal::Hooks::ResqueHook do
|
|
174
181
|
"namespace" => namespace,
|
175
182
|
"metadata" => {},
|
176
183
|
"sample_data" => {
|
184
|
+
"breadcrumbs" => [],
|
177
185
|
"tags" => { "queue" => queue }
|
178
186
|
# Params will be set by the ActiveJob integration
|
179
187
|
}
|
@@ -1,55 +1,73 @@
|
|
1
1
|
describe Appsignal::Hooks::ShoryukenMiddleware do
|
2
|
-
let(:current_transaction) { background_job_transaction }
|
3
|
-
|
4
2
|
class DemoShoryukenWorker
|
5
3
|
end
|
6
4
|
|
5
|
+
let(:time) { "2010-01-01 10:01:00UTC" }
|
7
6
|
let(:worker_instance) { DemoShoryukenWorker.new }
|
8
|
-
let(:queue) {
|
9
|
-
let(:sqs_msg) { double(:attributes => {}) }
|
7
|
+
let(:queue) { "some-funky-queue-name" }
|
8
|
+
let(:sqs_msg) { double(:message_id => "msg1", :attributes => {}) }
|
10
9
|
let(:body) { {} }
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
before(:context) { start_agent }
|
11
|
+
around { |example| keep_transactions { example.run } }
|
12
|
+
|
13
|
+
def perform_job(&block)
|
14
|
+
block ||= lambda {}
|
15
|
+
Timecop.freeze(Time.parse(time)) do
|
16
|
+
Appsignal::Hooks::ShoryukenMiddleware.new.call(
|
17
|
+
worker_instance,
|
18
|
+
queue,
|
19
|
+
sqs_msg,
|
20
|
+
body,
|
21
|
+
&block
|
22
|
+
)
|
23
|
+
end
|
15
24
|
end
|
16
25
|
|
17
26
|
context "with a performance call" do
|
18
|
-
let(:
|
27
|
+
let(:sent_timestamp) { Time.parse("1976-11-18 0:00:00UTC").to_i * 1000 }
|
19
28
|
let(:sqs_msg) do
|
20
|
-
double(:attributes => { "SentTimestamp" =>
|
29
|
+
double(:message_id => "msg1", :attributes => { "SentTimestamp" => sent_timestamp })
|
21
30
|
end
|
22
31
|
|
23
32
|
context "with complex argument" do
|
24
|
-
let(:body)
|
25
|
-
{
|
26
|
-
:foo => "Foo",
|
27
|
-
:bar => "Bar"
|
28
|
-
}
|
29
|
-
end
|
30
|
-
after do
|
31
|
-
Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
|
32
|
-
Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
|
33
|
-
# nothing
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
33
|
+
let(:body) { { :foo => "Foo", :bar => "Bar" } }
|
37
34
|
|
38
35
|
it "wraps the job in a transaction with the correct params" do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
},
|
51
|
-
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
36
|
+
allow_any_instance_of(Appsignal::Transaction).to receive(:set_queue_start).and_call_original
|
37
|
+
expect { perform_job }.to change { created_transactions.length }.by(1)
|
38
|
+
|
39
|
+
transaction = last_transaction
|
40
|
+
expect(transaction).to be_completed
|
41
|
+
transaction_hash = transaction.to_h
|
42
|
+
expect(transaction_hash).to include(
|
43
|
+
"action" => "DemoShoryukenWorker#perform",
|
44
|
+
"id" => kind_of(String), # AppSignal generated id
|
45
|
+
"namespace" => Appsignal::Transaction::BACKGROUND_JOB,
|
46
|
+
"error" => nil
|
52
47
|
)
|
48
|
+
expect(transaction_hash["events"].first).to include(
|
49
|
+
"allocation_count" => kind_of(Integer),
|
50
|
+
"body" => "",
|
51
|
+
"body_format" => Appsignal::EventFormatter::DEFAULT,
|
52
|
+
"child_allocation_count" => kind_of(Integer),
|
53
|
+
"child_duration" => kind_of(Float),
|
54
|
+
"child_gc_duration" => kind_of(Float),
|
55
|
+
"count" => 1,
|
56
|
+
"gc_duration" => kind_of(Float),
|
57
|
+
"start" => kind_of(Float),
|
58
|
+
"duration" => kind_of(Float),
|
59
|
+
"name" => "perform_job.shoryuken",
|
60
|
+
"title" => ""
|
61
|
+
)
|
62
|
+
expect(transaction_hash["sample_data"]).to include(
|
63
|
+
"params" => { "foo" => "Foo", "bar" => "Bar" },
|
64
|
+
"metadata" => {
|
65
|
+
"message_id" => "msg1",
|
66
|
+
"queue" => queue,
|
67
|
+
"SentTimestamp" => sent_timestamp
|
68
|
+
}
|
69
|
+
)
|
70
|
+
expect(transaction).to have_received(:set_queue_start).with(sent_timestamp)
|
53
71
|
end
|
54
72
|
|
55
73
|
context "with parameter filtering" do
|
@@ -57,21 +75,16 @@ describe Appsignal::Hooks::ShoryukenMiddleware do
|
|
57
75
|
Appsignal.config = project_fixture_config("production")
|
58
76
|
Appsignal.config[:filter_parameters] = ["foo"]
|
59
77
|
end
|
78
|
+
after do
|
79
|
+
Appsignal.config[:filter_parameters] = []
|
80
|
+
end
|
60
81
|
|
61
82
|
it "filters selected arguments" do
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
:queue => "some-funky-queue-name",
|
68
|
-
"SentTimestamp" => 217_123_200_000
|
69
|
-
},
|
70
|
-
:params => {
|
71
|
-
:foo => "[FILTERED]",
|
72
|
-
:bar => "Bar"
|
73
|
-
},
|
74
|
-
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
83
|
+
perform_job
|
84
|
+
|
85
|
+
transaction_hash = last_transaction.to_h
|
86
|
+
expect(transaction_hash["sample_data"]).to include(
|
87
|
+
"params" => { "foo" => "[FILTERED]", "bar" => "Bar" }
|
75
88
|
)
|
76
89
|
end
|
77
90
|
end
|
@@ -81,23 +94,12 @@ describe Appsignal::Hooks::ShoryukenMiddleware do
|
|
81
94
|
let(:body) { "foo bar" }
|
82
95
|
|
83
96
|
it "handles string arguments" do
|
84
|
-
|
85
|
-
"perform_job.shoryuken",
|
86
|
-
:class => "DemoShoryukenWorker",
|
87
|
-
:method => "perform",
|
88
|
-
:metadata => {
|
89
|
-
:queue => "some-funky-queue-name",
|
90
|
-
"SentTimestamp" => 217_123_200_000
|
91
|
-
},
|
92
|
-
:params => { :params => body },
|
93
|
-
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
94
|
-
)
|
97
|
+
perform_job
|
95
98
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
99
|
+
transaction_hash = last_transaction.to_h
|
100
|
+
expect(transaction_hash["sample_data"]).to include(
|
101
|
+
"params" => { "params" => body }
|
102
|
+
)
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
@@ -105,58 +107,103 @@ describe Appsignal::Hooks::ShoryukenMiddleware do
|
|
105
107
|
let(:body) { 1 }
|
106
108
|
|
107
109
|
it "handles primitive types as arguments" do
|
108
|
-
|
109
|
-
"perform_job.shoryuken",
|
110
|
-
:class => "DemoShoryukenWorker",
|
111
|
-
:method => "perform",
|
112
|
-
:metadata => {
|
113
|
-
:queue => "some-funky-queue-name",
|
114
|
-
"SentTimestamp" => 217_123_200_000
|
115
|
-
},
|
116
|
-
:params => { :params => body },
|
117
|
-
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
118
|
-
)
|
110
|
+
perform_job
|
119
111
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
112
|
+
transaction_hash = last_transaction.to_h
|
113
|
+
expect(transaction_hash["sample_data"]).to include(
|
114
|
+
"params" => { "params" => body }
|
115
|
+
)
|
125
116
|
end
|
126
117
|
end
|
127
118
|
end
|
128
119
|
|
129
120
|
context "with exception" do
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
121
|
+
it "sets the exception on the transaction" do
|
122
|
+
expect do
|
123
|
+
expect do
|
124
|
+
perform_job { raise ExampleException, "error message" }
|
125
|
+
end.to raise_error(ExampleException)
|
126
|
+
end.to change { created_transactions.length }.by(1)
|
127
|
+
|
128
|
+
transaction = last_transaction
|
129
|
+
expect(transaction).to be_completed
|
130
|
+
transaction_hash = transaction.to_h
|
131
|
+
expect(transaction_hash).to include(
|
132
|
+
"action" => "DemoShoryukenWorker#perform",
|
133
|
+
"id" => kind_of(String), # AppSignal generated id
|
134
|
+
"namespace" => Appsignal::Transaction::BACKGROUND_JOB,
|
135
|
+
"error" => {
|
136
|
+
"name" => "ExampleException",
|
137
|
+
"message" => "error message",
|
138
|
+
"backtrace" => kind_of(String)
|
139
|
+
}
|
135
140
|
)
|
136
141
|
end
|
142
|
+
end
|
137
143
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
144
|
+
context "with batched jobs" do
|
145
|
+
let(:sqs_msg) do
|
146
|
+
[
|
147
|
+
double(
|
148
|
+
:message_id => "msg2",
|
149
|
+
:attributes => { "SentTimestamp" => (Time.parse("1976-11-18 01:00:00UTC").to_i * 1000).to_s }
|
150
|
+
),
|
151
|
+
double(
|
152
|
+
:message_id => "msg1",
|
153
|
+
:attributes => { "SentTimestamp" => sent_timestamp.to_s }
|
154
|
+
)
|
155
|
+
]
|
146
156
|
end
|
147
|
-
|
148
|
-
|
149
|
-
|
157
|
+
let(:body) do
|
158
|
+
[
|
159
|
+
"foo bar",
|
160
|
+
{ :id => "123", :foo => "Foo", :bar => "Bar" }
|
161
|
+
]
|
150
162
|
end
|
163
|
+
let(:sent_timestamp) { Time.parse("1976-11-18 01:00:00UTC").to_i * 1000 }
|
151
164
|
|
152
|
-
|
165
|
+
it "creates a transaction for the batch" do
|
166
|
+
allow_any_instance_of(Appsignal::Transaction).to receive(:set_queue_start).and_call_original
|
153
167
|
expect do
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
168
|
+
perform_job {}
|
169
|
+
end.to change { created_transactions.length }.by(1)
|
170
|
+
|
171
|
+
transaction = last_transaction
|
172
|
+
expect(transaction).to be_completed
|
173
|
+
transaction_hash = transaction.to_h
|
174
|
+
expect(transaction_hash).to include(
|
175
|
+
"action" => "DemoShoryukenWorker#perform",
|
176
|
+
"id" => kind_of(String), # AppSignal generated id
|
177
|
+
"namespace" => Appsignal::Transaction::BACKGROUND_JOB,
|
178
|
+
"error" => nil
|
179
|
+
)
|
180
|
+
expect(transaction_hash["events"].first).to include(
|
181
|
+
"allocation_count" => kind_of(Integer),
|
182
|
+
"body" => "",
|
183
|
+
"body_format" => Appsignal::EventFormatter::DEFAULT,
|
184
|
+
"child_allocation_count" => kind_of(Integer),
|
185
|
+
"child_duration" => kind_of(Float),
|
186
|
+
"child_gc_duration" => kind_of(Float),
|
187
|
+
"count" => 1,
|
188
|
+
"gc_duration" => kind_of(Float),
|
189
|
+
"start" => kind_of(Float),
|
190
|
+
"duration" => kind_of(Float),
|
191
|
+
"name" => "perform_job.shoryuken",
|
192
|
+
"title" => ""
|
193
|
+
)
|
194
|
+
expect(transaction_hash["sample_data"]).to include(
|
195
|
+
"params" => {
|
196
|
+
"msg2" => "foo bar",
|
197
|
+
"msg1" => { "id" => "123", "foo" => "Foo", "bar" => "Bar" }
|
198
|
+
},
|
199
|
+
"metadata" => {
|
200
|
+
"batch" => true,
|
201
|
+
"queue" => "some-funky-queue-name",
|
202
|
+
"SentTimestamp" => sent_timestamp.to_s # Earliest/oldest timestamp from messages
|
203
|
+
}
|
204
|
+
)
|
205
|
+
# Queue time based on earliest/oldest timestamp from messages
|
206
|
+
expect(transaction).to have_received(:set_queue_start).with(sent_timestamp)
|
160
207
|
end
|
161
208
|
end
|
162
209
|
end
|
@@ -262,7 +262,8 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
|
|
262
262
|
"sample_data" => {
|
263
263
|
"environment" => {},
|
264
264
|
"params" => expected_args,
|
265
|
-
"tags" => {}
|
265
|
+
"tags" => {},
|
266
|
+
"breadcrumbs" => []
|
266
267
|
}
|
267
268
|
)
|
268
269
|
expect_transaction_to_have_sidekiq_event(transaction_hash)
|
@@ -290,7 +291,8 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
|
|
290
291
|
"sample_data" => {
|
291
292
|
"environment" => {},
|
292
293
|
"params" => expected_args,
|
293
|
-
"tags" => {}
|
294
|
+
"tags" => {},
|
295
|
+
"breadcrumbs" => []
|
294
296
|
}
|
295
297
|
)
|
296
298
|
# TODO: Not available in transaction.to_h yet.
|
@@ -0,0 +1,266 @@
|
|
1
|
+
require "appsignal/integrations/object"
|
2
|
+
|
3
|
+
def is_ruby_19
|
4
|
+
RUBY_VERSION < "2.0"
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Object do
|
8
|
+
describe "#instrument_method" do
|
9
|
+
context "with instance method" do
|
10
|
+
let(:klass) do
|
11
|
+
Class.new do
|
12
|
+
def foo(param1, options = {})
|
13
|
+
[param1, options]
|
14
|
+
end
|
15
|
+
appsignal_instrument_method :foo
|
16
|
+
end
|
17
|
+
end
|
18
|
+
let(:instance) { klass.new }
|
19
|
+
|
20
|
+
def call_with_arguments
|
21
|
+
instance.foo(
|
22
|
+
"abc",
|
23
|
+
:foo => "bar"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when active" do
|
28
|
+
let(:transaction) { http_request_transaction }
|
29
|
+
before do
|
30
|
+
Appsignal.config = project_fixture_config
|
31
|
+
expect(Appsignal::Transaction).to receive(:current).at_least(:once).and_return(transaction)
|
32
|
+
end
|
33
|
+
after { Appsignal.config = nil }
|
34
|
+
|
35
|
+
context "with anonymous class" do
|
36
|
+
it "instruments the method and calls it" do
|
37
|
+
expect(Appsignal.active?).to be_truthy
|
38
|
+
expect(transaction).to receive(:start_event)
|
39
|
+
expect(transaction).to receive(:finish_event).with \
|
40
|
+
"foo.AnonymousClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
|
41
|
+
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "with named class" do
|
46
|
+
before do
|
47
|
+
class NamedClass
|
48
|
+
def foo
|
49
|
+
1
|
50
|
+
end
|
51
|
+
appsignal_instrument_method :foo
|
52
|
+
end
|
53
|
+
end
|
54
|
+
after { Object.send(:remove_const, :NamedClass) }
|
55
|
+
let(:klass) { NamedClass }
|
56
|
+
|
57
|
+
it "instruments the method and calls it" do
|
58
|
+
expect(Appsignal.active?).to be_truthy
|
59
|
+
expect(transaction).to receive(:start_event)
|
60
|
+
expect(transaction).to receive(:finish_event).with \
|
61
|
+
"foo.NamedClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
|
62
|
+
expect(instance.foo).to eq(1)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with nested named class" do
|
67
|
+
before do
|
68
|
+
module MyModule
|
69
|
+
module NestedModule
|
70
|
+
class NamedClass
|
71
|
+
def bar
|
72
|
+
2
|
73
|
+
end
|
74
|
+
appsignal_instrument_method :bar
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
after { Object.send(:remove_const, :MyModule) }
|
80
|
+
let(:klass) { MyModule::NestedModule::NamedClass }
|
81
|
+
|
82
|
+
it "instruments the method and calls it" do
|
83
|
+
expect(Appsignal.active?).to be_truthy
|
84
|
+
expect(transaction).to receive(:start_event)
|
85
|
+
expect(transaction).to receive(:finish_event).with \
|
86
|
+
"bar.NamedClass.NestedModule.MyModule.other", nil, nil,
|
87
|
+
Appsignal::EventFormatter::DEFAULT
|
88
|
+
expect(instance.bar).to eq(2)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with custom name" do
|
93
|
+
let(:klass) do
|
94
|
+
Class.new do
|
95
|
+
def foo
|
96
|
+
1
|
97
|
+
end
|
98
|
+
appsignal_instrument_method :foo, :name => "my_method.group"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "instruments with custom name" do
|
103
|
+
expect(Appsignal.active?).to be_truthy
|
104
|
+
expect(transaction).to receive(:start_event)
|
105
|
+
expect(transaction).to receive(:finish_event).with \
|
106
|
+
"my_method.group", nil, nil, Appsignal::EventFormatter::DEFAULT
|
107
|
+
expect(instance.foo).to eq(1)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "with a method given a block" do
|
112
|
+
let(:klass) do
|
113
|
+
Class.new do
|
114
|
+
def foo
|
115
|
+
yield
|
116
|
+
end
|
117
|
+
appsignal_instrument_method :foo
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should yield the block" do
|
122
|
+
expect(instance.foo { 42 }).to eq(42)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "when not active" do
|
128
|
+
let(:transaction) { Appsignal::Transaction.current }
|
129
|
+
|
130
|
+
it "does not instrument, but still calls the method" do
|
131
|
+
expect(Appsignal.active?).to be_falsy
|
132
|
+
expect(transaction).to_not receive(:start_event)
|
133
|
+
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "with class method" do
|
139
|
+
let(:klass) do
|
140
|
+
Class.new do
|
141
|
+
def self.bar(param1, options = {})
|
142
|
+
[param1, options]
|
143
|
+
end
|
144
|
+
appsignal_instrument_class_method :bar
|
145
|
+
end
|
146
|
+
end
|
147
|
+
def call_with_arguments
|
148
|
+
klass.bar(
|
149
|
+
"abc",
|
150
|
+
:foo => "bar"
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
context "when active" do
|
155
|
+
let(:transaction) { http_request_transaction }
|
156
|
+
before do
|
157
|
+
Appsignal.config = project_fixture_config
|
158
|
+
expect(Appsignal::Transaction).to receive(:current).at_least(:once)
|
159
|
+
.and_return(transaction)
|
160
|
+
end
|
161
|
+
after { Appsignal.config = nil }
|
162
|
+
|
163
|
+
context "with anonymous class" do
|
164
|
+
it "instruments the method and calls it" do
|
165
|
+
expect(Appsignal.active?).to be_truthy
|
166
|
+
expect(transaction).to receive(:start_event)
|
167
|
+
expect(transaction).to receive(:finish_event).with \
|
168
|
+
"bar.class_method.AnonymousClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
|
169
|
+
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context "with named class" do
|
174
|
+
before do
|
175
|
+
class NamedClass
|
176
|
+
def self.bar
|
177
|
+
2
|
178
|
+
end
|
179
|
+
appsignal_instrument_class_method :bar
|
180
|
+
end
|
181
|
+
end
|
182
|
+
after { Object.send(:remove_const, :NamedClass) }
|
183
|
+
let(:klass) { NamedClass }
|
184
|
+
|
185
|
+
it "instruments the method and calls it" do
|
186
|
+
expect(Appsignal.active?).to be_truthy
|
187
|
+
expect(transaction).to receive(:start_event)
|
188
|
+
expect(transaction).to receive(:finish_event).with \
|
189
|
+
"bar.class_method.NamedClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
|
190
|
+
expect(klass.bar).to eq(2)
|
191
|
+
end
|
192
|
+
|
193
|
+
context "with nested named class" do
|
194
|
+
before do
|
195
|
+
module MyModule
|
196
|
+
module NestedModule
|
197
|
+
class NamedClass
|
198
|
+
def self.bar
|
199
|
+
2
|
200
|
+
end
|
201
|
+
appsignal_instrument_class_method :bar
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
after { Object.send(:remove_const, :MyModule) }
|
207
|
+
let(:klass) { MyModule::NestedModule::NamedClass }
|
208
|
+
|
209
|
+
it "instruments the method and calls it" do
|
210
|
+
expect(Appsignal.active?).to be_truthy
|
211
|
+
expect(transaction).to receive(:start_event)
|
212
|
+
expect(transaction).to receive(:finish_event).with \
|
213
|
+
"bar.class_method.NamedClass.NestedModule.MyModule.other", nil, nil,
|
214
|
+
Appsignal::EventFormatter::DEFAULT
|
215
|
+
expect(klass.bar).to eq(2)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "with custom name" do
|
221
|
+
let(:klass) do
|
222
|
+
Class.new do
|
223
|
+
def self.bar
|
224
|
+
2
|
225
|
+
end
|
226
|
+
appsignal_instrument_class_method :bar, :name => "my_method.group"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
it "instruments with custom name" do
|
231
|
+
expect(Appsignal.active?).to be_truthy
|
232
|
+
expect(transaction).to receive(:start_event)
|
233
|
+
expect(transaction).to receive(:finish_event).with \
|
234
|
+
"my_method.group", nil, nil, Appsignal::EventFormatter::DEFAULT
|
235
|
+
expect(klass.bar).to eq(2)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context "with a method given a block" do
|
240
|
+
let(:klass) do
|
241
|
+
Class.new do
|
242
|
+
def self.bar
|
243
|
+
yield
|
244
|
+
end
|
245
|
+
appsignal_instrument_class_method :bar
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should yield the block" do
|
250
|
+
expect(klass.bar { 42 }).to eq(42)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "when not active" do
|
256
|
+
let(:transaction) { Appsignal::Transaction.current }
|
257
|
+
|
258
|
+
it "does not instrument, but still call the method" do
|
259
|
+
expect(Appsignal.active?).to be_falsy
|
260
|
+
expect(transaction).to_not receive(:start_event)
|
261
|
+
expect(call_with_arguments).to eq(["abc", { :foo => "bar" }])
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|