appsignal 0.8.5 → 0.8.6.beta.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 +8 -8
- data/CHANGELOG.md +3 -0
- data/lib/appsignal.rb +2 -0
- data/lib/appsignal/agent.rb +6 -1
- data/lib/appsignal/integrations/resque.rb +44 -0
- data/lib/appsignal/pipe.rb +44 -0
- data/lib/appsignal/transaction.rb +6 -2
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/agent_spec.rb +20 -21
- data/spec/lib/appsignal/integrations/resque_spec.rb +78 -0
- data/spec/lib/appsignal/pipe_spec.rb +61 -0
- data/spec/lib/appsignal/transaction_spec.rb +15 -1
- data/spec/lib/appsignal_spec.rb +3 -1
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTFjZWJlMmZlZDk5YzFiZGZmN2E4ODZiYWNlNDM4ZWM0MGUzODBjMQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZDBlMDAxZjMwNDdiN2VlMjBiM2Y5ZTUxMjQ0ZjFhY2M0ZGQ2MWEwMg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NTM0NGE3Y2JlNTQ1NzI3YTQ3MzIwYjRmYTkxZmVmZWFiY2YxODMyYmNjMmYw
|
10
|
+
OTM1YmYzODQzMGJiNWNhZWQ0OTMyZTRkNDkwOWNjNTRkMjczNGNkYWNmMTY4
|
11
|
+
NWUyYjU4YWNkMzU1NjYwOGNiNjA1OGM5YmZjN2ViMzM4ODQyMTM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MzE1MDg5ODE2YjJmMDkzMGNjY2I0NTk1ODhhNzBkYzZjMzZkZmE2NzZmMGM1
|
14
|
+
NTgyZTZhNjk4MTZjOTA3NzU1NGI1MmMzMDBkMzUwNjIxOThjYTBkNjhhZTUy
|
15
|
+
YTA3NGE2OTAyN2FjYTcxNDgxZjRmMTA0MzhiODhkOWFlMTE1NzA=
|
data/CHANGELOG.md
CHANGED
data/lib/appsignal.rb
CHANGED
@@ -12,6 +12,7 @@ module Appsignal
|
|
12
12
|
require 'appsignal/integrations/passenger'
|
13
13
|
require 'appsignal/integrations/unicorn'
|
14
14
|
require 'appsignal/integrations/sidekiq'
|
15
|
+
require 'appsignal/integrations/resque'
|
15
16
|
end
|
16
17
|
|
17
18
|
def extensions
|
@@ -142,5 +143,6 @@ require 'appsignal/transaction'
|
|
142
143
|
require 'appsignal/transaction/formatter'
|
143
144
|
require 'appsignal/transaction/params_sanitizer'
|
144
145
|
require 'appsignal/transmitter'
|
146
|
+
require 'appsignal/pipe'
|
145
147
|
require 'appsignal/version'
|
146
148
|
require 'appsignal/integrations/rails'
|
data/lib/appsignal/agent.rb
CHANGED
@@ -25,6 +25,7 @@ module Appsignal
|
|
25
25
|
Appsignal.logger.debug('Starting agent thread')
|
26
26
|
@thread = Thread.new do
|
27
27
|
loop do
|
28
|
+
Appsignal.logger.debug aggregator.queue.inspect
|
28
29
|
send_queue if aggregator.has_transactions?
|
29
30
|
Appsignal.logger.debug("Sleeping #{sleep_time}")
|
30
31
|
sleep(sleep_time)
|
@@ -33,11 +34,15 @@ module Appsignal
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def restart_thread
|
37
|
+
stop_thread
|
38
|
+
start_thread
|
39
|
+
end
|
40
|
+
|
41
|
+
def stop_thread
|
36
42
|
if @thread && @thread.alive?
|
37
43
|
Appsignal.logger.debug 'Killing agent thread'
|
38
44
|
Thread.kill(@thread)
|
39
45
|
end
|
40
|
-
start_thread
|
41
46
|
end
|
42
47
|
|
43
48
|
def subscribe
|
@@ -0,0 +1,44 @@
|
|
1
|
+
if defined?(::Resque)
|
2
|
+
Appsignal.logger.info('Loading Resque integration')
|
3
|
+
|
4
|
+
module Appsignal
|
5
|
+
module Integrations
|
6
|
+
module ResquePlugin
|
7
|
+
|
8
|
+
def around_perform_resque_plugin(*args)
|
9
|
+
Appsignal::Transaction.create(SecureRandom.uuid, ENV.to_hash)
|
10
|
+
ActiveSupport::Notifications.instrument(
|
11
|
+
'perform_job.resque',
|
12
|
+
:class => self.to_s,
|
13
|
+
:method => 'perform'
|
14
|
+
) do
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
rescue Exception => exception
|
18
|
+
unless Appsignal.is_ignored_exception?(exception)
|
19
|
+
Appsignal::Transaction.current.add_exception(exception)
|
20
|
+
end
|
21
|
+
raise exception
|
22
|
+
ensure
|
23
|
+
Appsignal::Transaction.current.complete!
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Create a pipe for the workers to write to
|
31
|
+
Resque.before_first_fork do
|
32
|
+
Appsignal::Pipe.init
|
33
|
+
end
|
34
|
+
|
35
|
+
# In the fork, stop the normal agent startup
|
36
|
+
# and stop listening to the pipe (we'll only use it for writing)
|
37
|
+
Resque.after_fork do |job|
|
38
|
+
Appsignal.agent.stop_thread
|
39
|
+
Appsignal::Pipe.current.stop_listening!
|
40
|
+
end
|
41
|
+
|
42
|
+
# Extend the default job class with AppSignal instrumentation
|
43
|
+
Resque::Job.send(:extend, Appsignal::Integrations::ResquePlugin)
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Appsignal
|
2
|
+
class Pipe
|
3
|
+
attr_reader :reader, :writer, :listener
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
Appsignal.logger.debug "Initializing pipe in #{$$}"
|
7
|
+
@reader, @writer = IO.pipe
|
8
|
+
@listener = Thread.new do
|
9
|
+
loop do
|
10
|
+
Appsignal.agent.enqueue(Marshal::load(@reader))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
@listening = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(transaction)
|
17
|
+
Marshal::dump(transaction, @writer)
|
18
|
+
rescue IOError
|
19
|
+
Appsignal.logger.debug "Broken pipe in #{$$}"
|
20
|
+
Appsignal.agent.shutdown
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop_listening!
|
24
|
+
Thread.kill(@listener)
|
25
|
+
@reader.close unless @reader.closed?
|
26
|
+
@listening = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def listening?
|
30
|
+
!! @listening
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def init
|
35
|
+
Thread.current[:appsignal_pipe] = Appsignal::Pipe.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def current
|
39
|
+
Thread.current[:appsignal_pipe]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Appsignal
|
1
|
+
module Appsignal
|
2
2
|
class Transaction
|
3
3
|
# Based on what Rails uses + some variables we'd like to show
|
4
4
|
ENV_METHODS = %w(CONTENT_LENGTH AUTH_TYPE GATEWAY_INTERFACE
|
@@ -117,7 +117,11 @@ module Appsignal
|
|
117
117
|
Thread.current[:appsignal_transaction_id] = nil
|
118
118
|
current_transaction = Appsignal.transactions.delete(@request_id)
|
119
119
|
if process_action_event || exception?
|
120
|
-
Appsignal.
|
120
|
+
if Appsignal::Pipe.current
|
121
|
+
Appsignal::Pipe.current.write(self)
|
122
|
+
else
|
123
|
+
Appsignal.enqueue(current_transaction)
|
124
|
+
end
|
121
125
|
else
|
122
126
|
Appsignal.logger.debug("No process_action_event or exception: #{@request_id}")
|
123
127
|
end
|
data/lib/appsignal/version.rb
CHANGED
@@ -41,14 +41,24 @@ describe Appsignal::Agent do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
describe "#restart_thread" do
|
44
|
+
|
45
|
+
it "should stop thread" do
|
46
|
+
subject.should_receive(:stop_thread)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should start a thread" do
|
50
|
+
subject.should_receive(:start_thread)
|
51
|
+
end
|
52
|
+
|
53
|
+
after { subject.restart_thread }
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#stop_thread" do
|
44
57
|
context "if there is no thread" do
|
45
58
|
before { subject.thread = nil }
|
46
59
|
|
47
|
-
it "should
|
48
|
-
|
49
|
-
|
50
|
-
subject.thread.should be_a(Thread)
|
51
|
-
subject.thread.should be_alive
|
60
|
+
it "should not do anything" do
|
61
|
+
Thread.should_not_receive(:kill)
|
52
62
|
end
|
53
63
|
end
|
54
64
|
|
@@ -59,28 +69,17 @@ describe Appsignal::Agent do
|
|
59
69
|
end
|
60
70
|
|
61
71
|
it "should start a thread" do
|
62
|
-
|
63
|
-
|
64
|
-
subject.thread.should be_a(Thread)
|
65
|
-
subject.thread.should be_alive
|
72
|
+
Thread.should_not_receive(:kill)
|
66
73
|
end
|
67
74
|
end
|
68
75
|
|
69
76
|
context "if there is an active thread" do
|
70
|
-
it "should kill the current thread
|
71
|
-
|
72
|
-
previous_thread.should be_alive
|
73
|
-
|
74
|
-
subject.restart_thread
|
75
|
-
|
76
|
-
subject.thread.should be_a(Thread)
|
77
|
-
subject.thread.should be_alive
|
78
|
-
subject.thread.should_not == previous_thread
|
79
|
-
|
80
|
-
sleep 0.1 # We need to wait for the thread to exit
|
81
|
-
previous_thread.should_not be_alive
|
77
|
+
it "should kill the current thread " do
|
78
|
+
Thread.should_receive(:kill)
|
82
79
|
end
|
83
80
|
end
|
81
|
+
|
82
|
+
after { subject.stop_thread }
|
84
83
|
end
|
85
84
|
|
86
85
|
describe "#subscribe" do
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "ResquePlugin" do
|
4
|
+
let(:file) { File.expand_path('lib/appsignal/integrations/resque.rb') }
|
5
|
+
|
6
|
+
context "with resque" do
|
7
|
+
before do
|
8
|
+
module Resque
|
9
|
+
|
10
|
+
def self.before_first_fork
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.after_fork
|
14
|
+
end
|
15
|
+
|
16
|
+
class Job
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestError < StandardError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
load file
|
24
|
+
start_agent
|
25
|
+
end
|
26
|
+
|
27
|
+
describe :around_perform_resque_plugin do
|
28
|
+
let(:transaction) { Appsignal::Transaction.new(1, {}) }
|
29
|
+
let(:job) { Resque::Job }
|
30
|
+
let(:invoked_job) { nil }
|
31
|
+
before do
|
32
|
+
transaction.stub(:complete! => true)
|
33
|
+
Appsignal::Transaction.stub(:current => transaction)
|
34
|
+
end
|
35
|
+
|
36
|
+
context "without exception" do
|
37
|
+
it "should create a new transaction" do
|
38
|
+
Appsignal::Transaction.should_receive(:create).and_return(transaction)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should instrument with correct params" do
|
42
|
+
ActiveSupport::Notifications.should_receive(:instrument).with(
|
43
|
+
'perform_job.resque',
|
44
|
+
:class => 'Resque::Job',
|
45
|
+
:method => 'perform'
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should close the transaction" do
|
50
|
+
transaction.should_receive(:complete!)
|
51
|
+
end
|
52
|
+
|
53
|
+
after { job.around_perform_resque_plugin { invoked_job } }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with exception" do
|
57
|
+
it "should set the exception" do
|
58
|
+
transaction.should_receive(:add_exception)
|
59
|
+
end
|
60
|
+
|
61
|
+
after do
|
62
|
+
begin
|
63
|
+
job.around_perform_resque_plugin { raise(Resque::TestError.new('the roof')) }
|
64
|
+
rescue Resque::TestError
|
65
|
+
# Do nothing
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "without resque" do
|
73
|
+
before(:all) { Object.send(:remove_const, :Resque) }
|
74
|
+
|
75
|
+
specify { expect { ::Resque }.to raise_error(NameError) }
|
76
|
+
specify { expect { load file }.to_not raise_error }
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Appsignal::Pipe do
|
4
|
+
before :all do
|
5
|
+
Appsignal::Pipe.init
|
6
|
+
end
|
7
|
+
let(:agent) { double }
|
8
|
+
|
9
|
+
subject { Appsignal::Pipe.current }
|
10
|
+
|
11
|
+
its(:reader) { should be_instance_of(IO) }
|
12
|
+
its(:writer) { should be_instance_of(IO) }
|
13
|
+
its(:listener) { should be_instance_of(Thread) }
|
14
|
+
its(:listening?) { should be_true }
|
15
|
+
|
16
|
+
describe "#write" do
|
17
|
+
|
18
|
+
context "with a regular request" do
|
19
|
+
let(:transaction) { regular_transaction }
|
20
|
+
|
21
|
+
it "should dump" do
|
22
|
+
Marshal.should_receive(:dump)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when the pipe is closed" do
|
27
|
+
let(:transaction) { regular_transaction }
|
28
|
+
before { Appsignal.stub(:agent => agent) }
|
29
|
+
|
30
|
+
it "should shutdown" do
|
31
|
+
Appsignal::Pipe.current.writer.close
|
32
|
+
agent.should_receive(:shutdown)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
after { Appsignal::Pipe.current.write(transaction) }
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#stop_listening!" do
|
40
|
+
before do
|
41
|
+
subject.stop_listening!
|
42
|
+
sleep 0.1
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should have closed the reader" do
|
46
|
+
subject.reader.closed?.should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have killed the listener thread" do
|
50
|
+
subject.listener.alive?.should be_false
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not crash when called twice" do
|
54
|
+
expect { subject.stop_listening! }.not_to raise_error
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should know it's not listening anymore" do
|
58
|
+
subject.listening?.should be_false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -282,7 +282,10 @@ describe Appsignal::Transaction do
|
|
282
282
|
|
283
283
|
describe '#complete!' do
|
284
284
|
let(:event) { double(:event) }
|
285
|
-
before
|
285
|
+
before do
|
286
|
+
Appsignal::Pipe.stub(:current => nil)
|
287
|
+
transaction.set_process_action_event(notification_event)
|
288
|
+
end
|
286
289
|
|
287
290
|
it 'should remove transaction from the list' do
|
288
291
|
expect { transaction.complete! }.
|
@@ -326,6 +329,17 @@ describe Appsignal::Transaction do
|
|
326
329
|
Thread.current[:appsignal_transaction_id].should be_nil
|
327
330
|
end
|
328
331
|
end
|
332
|
+
|
333
|
+
context 'when using pipes' do
|
334
|
+
let(:pipe) { double }
|
335
|
+
before { Appsignal::Pipe.stub(:current => pipe) }
|
336
|
+
|
337
|
+
it "should send itself trough the pipe" do
|
338
|
+
pipe.should_receive(:write).with(transaction)
|
339
|
+
end
|
340
|
+
|
341
|
+
after { transaction.complete! }
|
342
|
+
end
|
329
343
|
end
|
330
344
|
|
331
345
|
describe "#set_background_queue_start" do
|
data/spec/lib/appsignal_spec.rb
CHANGED
@@ -252,8 +252,10 @@ describe Appsignal do
|
|
252
252
|
end
|
253
253
|
|
254
254
|
describe ".send_exception" do
|
255
|
+
before { Appsignal::Pipe.stub(:current => false) }
|
256
|
+
|
255
257
|
it "should send the exception to AppSignal" do
|
256
|
-
agent = double
|
258
|
+
agent = double(:shutdown => true)
|
257
259
|
Appsignal.stub(:agent).and_return(agent)
|
258
260
|
agent.should_receive(:send_queue)
|
259
261
|
agent.should_receive(:enqueue).with(kind_of(Appsignal::Transaction))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appsignal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6.beta.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Beekman
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2014-
|
15
|
+
date: 2014-02-14 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activesupport
|
@@ -169,10 +169,12 @@ files:
|
|
169
169
|
- lib/appsignal/integrations/delayed_job.rb
|
170
170
|
- lib/appsignal/integrations/passenger.rb
|
171
171
|
- lib/appsignal/integrations/rails.rb
|
172
|
+
- lib/appsignal/integrations/resque.rb
|
172
173
|
- lib/appsignal/integrations/sidekiq.rb
|
173
174
|
- lib/appsignal/integrations/sinatra.rb
|
174
175
|
- lib/appsignal/integrations/unicorn.rb
|
175
176
|
- lib/appsignal/marker.rb
|
177
|
+
- lib/appsignal/pipe.rb
|
176
178
|
- lib/appsignal/rack/instrumentation.rb
|
177
179
|
- lib/appsignal/rack/listener.rb
|
178
180
|
- lib/appsignal/transaction.rb
|
@@ -198,10 +200,12 @@ files:
|
|
198
200
|
- spec/lib/appsignal/integrations/delayed_job_spec.rb
|
199
201
|
- spec/lib/appsignal/integrations/passenger_spec.rb
|
200
202
|
- spec/lib/appsignal/integrations/rails_spec.rb
|
203
|
+
- spec/lib/appsignal/integrations/resque_spec.rb
|
201
204
|
- spec/lib/appsignal/integrations/sidekiq_spec.rb
|
202
205
|
- spec/lib/appsignal/integrations/sinatra_spec.rb
|
203
206
|
- spec/lib/appsignal/integrations/unicorn_spec.rb
|
204
207
|
- spec/lib/appsignal/marker_spec.rb
|
208
|
+
- spec/lib/appsignal/pipe_spec.rb
|
205
209
|
- spec/lib/appsignal/rack/instrumentation_spec.rb
|
206
210
|
- spec/lib/appsignal/rack/listener_spec.rb
|
207
211
|
- spec/lib/appsignal/transaction/formatter_spec.rb
|
@@ -237,9 +241,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
237
241
|
version: 1.9.3
|
238
242
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
239
243
|
requirements:
|
240
|
-
- - ! '
|
244
|
+
- - ! '>'
|
241
245
|
- !ruby/object:Gem::Version
|
242
|
-
version:
|
246
|
+
version: 1.3.1
|
243
247
|
requirements: []
|
244
248
|
rubyforge_project:
|
245
249
|
rubygems_version: 2.0.3
|
@@ -261,10 +265,12 @@ test_files:
|
|
261
265
|
- spec/lib/appsignal/integrations/delayed_job_spec.rb
|
262
266
|
- spec/lib/appsignal/integrations/passenger_spec.rb
|
263
267
|
- spec/lib/appsignal/integrations/rails_spec.rb
|
268
|
+
- spec/lib/appsignal/integrations/resque_spec.rb
|
264
269
|
- spec/lib/appsignal/integrations/sidekiq_spec.rb
|
265
270
|
- spec/lib/appsignal/integrations/sinatra_spec.rb
|
266
271
|
- spec/lib/appsignal/integrations/unicorn_spec.rb
|
267
272
|
- spec/lib/appsignal/marker_spec.rb
|
273
|
+
- spec/lib/appsignal/pipe_spec.rb
|
268
274
|
- spec/lib/appsignal/rack/instrumentation_spec.rb
|
269
275
|
- spec/lib/appsignal/rack/listener_spec.rb
|
270
276
|
- spec/lib/appsignal/transaction/formatter_spec.rb
|