appsignal 0.8.15 → 0.9.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -2
  3. data/README.md +4 -0
  4. data/Rakefile +8 -0
  5. data/appsignal.gemspec +0 -1
  6. data/gemfiles/capistrano2.gemfile +5 -0
  7. data/gemfiles/capistrano3.gemfile +5 -0
  8. data/lib/appsignal.rb +10 -4
  9. data/lib/appsignal/agent.rb +5 -10
  10. data/lib/appsignal/capistrano.rb +8 -1
  11. data/lib/appsignal/config.rb +2 -1
  12. data/lib/appsignal/instrumentations/net_http.rb +15 -0
  13. data/lib/appsignal/integrations/capistrano/appsignal.cap +27 -0
  14. data/lib/appsignal/integrations/{capistrano.rb → capistrano/capistrano_2_tasks.rb} +2 -4
  15. data/lib/appsignal/integrations/capistrano/careful_logger.rb +1 -1
  16. data/lib/appsignal/integrations/delayed_job.rb +2 -4
  17. data/lib/appsignal/integrations/resque.rb +2 -4
  18. data/lib/appsignal/integrations/sidekiq.rb +2 -4
  19. data/lib/appsignal/marker.rb +1 -1
  20. data/lib/appsignal/rack/instrumentation.rb +1 -0
  21. data/lib/appsignal/rack/listener.rb +3 -4
  22. data/lib/appsignal/transaction.rb +16 -4
  23. data/lib/appsignal/version.rb +1 -1
  24. data/spec/lib/appsignal/agent_spec.rb +1 -23
  25. data/spec/lib/appsignal/config_spec.rb +2 -0
  26. data/spec/lib/appsignal/instrumentations/net_http_spec.rb +26 -0
  27. data/spec/lib/appsignal/integrations/capistrano2_spec.rb +178 -0
  28. data/spec/lib/appsignal/integrations/capistrano3_spec.rb +169 -0
  29. data/spec/lib/appsignal/integrations/resque_spec.rb +1 -1
  30. data/spec/lib/appsignal/marker_spec.rb +13 -10
  31. data/spec/lib/appsignal/transaction_spec.rb +34 -13
  32. data/spec/lib/appsignal_spec.rb +35 -0
  33. data/spec/lib/generators/appsignal/appsignal_generator_spec.rb +13 -14
  34. data/spec/spec_helper.rb +14 -0
  35. metadata +15 -21
  36. data/spec/lib/appsignal/integrations/capistrano_spec.rb +0 -151
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14c00518e40685c71256e3fb07a80568198e3660
4
- data.tar.gz: dc8a116a4c5541feb03e2df238554253e9284ab5
3
+ metadata.gz: 5027037bb3729ff0670c601fbe27fc5d84382ef4
4
+ data.tar.gz: 886a06cd1a10ca255c4b40d7f302a2e364e8f07e
5
5
  SHA512:
6
- metadata.gz: a2aa00e17ba12ffd245e83174e6c35e3bced66796fd42e2335cdb38b0099733f09847e769551140b940565e23eabccae7d20fd8361578f0c3e1f9b01ce1494f9
7
- data.tar.gz: ce94868b73e6867ebd738f285b2b596ea9b3fdf95cb844c9fd2a5d68c11c57370a34715bc7e6bfb78dfd7fd9b509489d07439afc1d46cbcc3842fe4cf4abe9ca
6
+ metadata.gz: db483be432d3e87ebfb4152806d17c0452e5d90e213f390a15a4c68df70fab1df9e002784e0d524180b047a8832f98f68e95bc76164e36cefebf14b765bdf1a6
7
+ data.tar.gz: e63378b1777d0681bce0bc304bb455dbc97722ebecc97f5be122945f6ebdb8d68f5ff819f98cdde8e8215ffc386d2a67bf553c590e86cfe3ca191e30051a7d53
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
- # 0.8.15
2
- * Exception logging in agent thread
1
+ # 0.9.0
2
+ * Add option to override Capistrano revision
3
+ * Expanded deploy message in Capistrano
4
+ * Refactor of usage of Thread.local
5
+ * Net::HTTP instrumentation
6
+ * Capistrano 3 support
3
7
 
4
8
  # 0.8.14
5
9
  * Few tweaks in logging
data/README.md CHANGED
@@ -59,6 +59,8 @@ end
59
59
  Run rake bundle or, or run bundle install for all Gemfiles:
60
60
 
61
61
  ```
62
+ bundle --gemfile gemfiles/capistrano2.gemfile
63
+ bundle --gemfile gemfiles/capistrano3.gemfile
62
64
  bundle --gemfile gemfiles/no_dependencies.gemfile
63
65
  bundle --gemfile gemfiles/rails-3.0.gemfile
64
66
  bundle --gemfile gemfiles/rails-3.1.gemfile
@@ -71,6 +73,8 @@ bundle --gemfile gemfiles/sinatra.gemfile
71
73
  To run the spec suite with a specific Gemfile:
72
74
 
73
75
  ```
76
+ BUNDLE_GEMFILE=gemfiles/capistrano2.gemfile bundle exec rspec
77
+ BUNDLE_GEMFILE=gemfiles/capistrano3.gemfile bundle exec rspec
74
78
  BUNDLE_GEMFILE=gemfiles/no_dependencies.gemfile bundle exec rspec
75
79
  BUNDLE_GEMFILE=gemfiles/rails-3.0.gemfile bundle exec rspec
76
80
  BUNDLE_GEMFILE=gemfiles/rails-3.1.gemfile bundle exec rspec
data/Rakefile CHANGED
@@ -59,6 +59,8 @@ task :publish do
59
59
  end
60
60
 
61
61
  task :bundle do
62
+ system 'bundle --gemfile gemfiles/capistrano2.gemfile'
63
+ system 'bundle --gemfile gemfiles/capistrano3.gemfile'
62
64
  system 'bundle --gemfile gemfiles/no_dependencies.gemfile'
63
65
  system 'bundle --gemfile gemfiles/rails-3.0.gemfile'
64
66
  system 'bundle --gemfile gemfiles/rails-3.1.gemfile'
@@ -69,6 +71,12 @@ task :bundle do
69
71
  end
70
72
 
71
73
  task :spec do
74
+ puts 'Running capistrano2'
75
+ system 'env BUNDLE_GEMFILE=gemfiles/capistrano2.gemfile bundle exec rspec'
76
+
77
+ puts 'Running capistrano3'
78
+ system 'env BUNDLE_GEMFILE=gemfiles/capistrano3.gemfile bundle exec rspec'
79
+
72
80
  puts 'Running no dependencies'
73
81
  system 'env BUNDLE_GEMFILE=gemfiles/no_dependencies.gemfile bundle exec rspec'
74
82
 
data/appsignal.gemspec CHANGED
@@ -30,7 +30,6 @@ Gem::Specification.new do |gem|
30
30
 
31
31
  gem.add_development_dependency 'rake'
32
32
  gem.add_development_dependency 'rspec'
33
- gem.add_development_dependency 'capistrano', '< 3.0'
34
33
  gem.add_development_dependency 'pry'
35
34
  gem.add_development_dependency 'timecop'
36
35
 
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'capistrano', '< 3.0'
4
+
5
+ gemspec :path => '../'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'capistrano', '>= 3.0'
4
+
5
+ gemspec :path => '../'
data/lib/appsignal.rb CHANGED
@@ -17,6 +17,10 @@ module Appsignal
17
17
  require 'appsignal/integrations/resque'
18
18
  end
19
19
 
20
+ def load_instrumentations
21
+ require 'appsignal/instrumentations/net_http' if config[:instrument_net_http]
22
+ end
23
+
20
24
  def extensions
21
25
  @extensions ||= []
22
26
  end
@@ -38,6 +42,7 @@ module Appsignal
38
42
  end
39
43
  logger.info("Starting appsignal-#{Appsignal::VERSION}")
40
44
  load_integrations
45
+ load_instrumentations
41
46
  initialize_extensions
42
47
  @agent = Appsignal::Agent.new
43
48
  at_exit { @agent.shutdown(true) }
@@ -74,10 +79,11 @@ module Appsignal
74
79
  end
75
80
 
76
81
  def add_exception(exception)
77
- return if !active? || Appsignal::Transaction.current.nil? || exception.nil?
78
- unless is_ignored_exception?(exception)
79
- Appsignal::Transaction.current.add_exception(exception)
80
- end
82
+ return if !active? ||
83
+ Appsignal::Transaction.current.nil? ||
84
+ exception.nil? ||
85
+ is_ignored_exception?(exception)
86
+ Appsignal::Transaction.current.add_exception(exception)
81
87
  end
82
88
 
83
89
  def tag_request(params={})
@@ -24,16 +24,11 @@ module Appsignal
24
24
  def start_thread
25
25
  Appsignal.logger.debug('Starting agent thread')
26
26
  @thread = Thread.new do
27
- begin
28
- sleep(rand(sleep_time))
29
- loop do
30
- send_queue if aggregator.has_transactions?
31
- Appsignal.logger.debug("Sleeping #{sleep_time}")
32
- sleep(sleep_time)
33
- end
34
- rescue Exception=>ex
35
- Appsignal.logger.error "#{ex.class} in agent thread: '#{ex.message}'"
36
- Appsignal.logger.error ex.backtrace.join('\n')
27
+ sleep(rand(sleep_time))
28
+ loop do
29
+ send_queue if aggregator.has_transactions?
30
+ Appsignal.logger.debug("Sleeping #{sleep_time}")
31
+ sleep(sleep_time)
37
32
  end
38
33
  end
39
34
  end
@@ -1,2 +1,9 @@
1
1
  require 'appsignal'
2
- require 'appsignal/integrations/capistrano'
2
+
3
+ if defined?(Capistrano::VERSION)
4
+ # Capistrano 3+
5
+ load File.expand_path('../integrations/capistrano/appsignal.cap', __FILE__)
6
+ else
7
+ # Capistrano 2
8
+ require 'appsignal/integrations/capistrano/capistrano_2_tasks'
9
+ end
@@ -10,7 +10,8 @@ module Appsignal
10
10
  :ignore_exceptions => [],
11
11
  :send_params => true,
12
12
  :endpoint => 'https://push.appsignal.com/1',
13
- :slow_request_threshold => 200
13
+ :slow_request_threshold => 200,
14
+ :instrument_net_http => true
14
15
  }.freeze
15
16
 
16
17
  attr_reader :root_path, :env, :initial_config, :config_hash
@@ -0,0 +1,15 @@
1
+ Net::HTTP.class_eval do
2
+ alias request_without_appsignal request
3
+
4
+ def request(request, body=nil, &block)
5
+ ActiveSupport::Notifications.instrument(
6
+ 'request.net_http',
7
+ :host => request['host'],
8
+ :scheme => use_ssl? ? 'https' : 'http',
9
+ :path => request.path,
10
+ :method => request.method
11
+ ) do
12
+ request_without_appsignal(request, body, &block)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ namespace :appsignal do
2
+ task :deploy do
3
+ env = fetch(:rails_env, fetch(:rack_env, 'production'))
4
+ user = ENV['USER'] || ENV['USERNAME']
5
+ revision = fetch(:appsignal_revision, fetch(:current_revision))
6
+ logger = fetch(:logger, Logger.new($stdout))
7
+
8
+ appsignal_config = Appsignal::Config.new(
9
+ ENV['PWD'],
10
+ env,
11
+ fetch(:appsignal_config, {}),
12
+ logger
13
+ )
14
+
15
+ if appsignal_config && appsignal_config.active?
16
+ marker_data = {
17
+ :revision => revision,
18
+ :user => user
19
+ }
20
+
21
+ marker = Appsignal::Marker.new(marker_data, appsignal_config, logger)
22
+ marker.transmit
23
+ end
24
+ end
25
+ end
26
+
27
+ after 'deploy:finished', 'appsignal:deploy'
@@ -1,5 +1,3 @@
1
- require 'capistrano'
2
-
3
1
  module Appsignal
4
2
  module Integrations
5
3
  class Capistrano
@@ -12,6 +10,7 @@ module Appsignal
12
10
  task :deploy do
13
11
  env = fetch(:rails_env, fetch(:rack_env, 'production'))
14
12
  user = ENV['USER'] || ENV['USERNAME']
13
+ revision = fetch(:appsignal_revision, fetch(:current_revision))
15
14
 
16
15
  appsignal_config = Appsignal::Config.new(
17
16
  ENV['PWD'],
@@ -22,8 +21,7 @@ module Appsignal
22
21
 
23
22
  if appsignal_config && appsignal_config.active?
24
23
  marker_data = {
25
- :revision => current_revision,
26
- :repository => repository,
24
+ :revision => revision,
27
25
  :user => user
28
26
  }
29
27
 
@@ -1,6 +1,6 @@
1
1
  module Appsignal
2
2
  module CarefulLogger
3
- # Because Capistrano's logger uses the term important
3
+ # Because Capistrano 2's logger uses the term important
4
4
  # instead of error.
5
5
  def carefully_log_error(message)
6
6
  if @logger.respond_to?(:important)
@@ -26,12 +26,10 @@ if defined?(::Delayed::Plugin)
26
26
  block.call(job)
27
27
  end
28
28
  rescue Exception => exception
29
- unless Appsignal.is_ignored_exception?(exception)
30
- Appsignal::Transaction.current.add_exception(exception)
31
- end
29
+ Appsignal.add_exception(exception)
32
30
  raise exception
33
31
  ensure
34
- Appsignal::Transaction.current.complete!
32
+ Appsignal::Transaction.complete_current!
35
33
  end
36
34
  end
37
35
  end
@@ -15,12 +15,10 @@ if defined?(::Resque)
15
15
  yield
16
16
  end
17
17
  rescue Exception => exception
18
- unless Appsignal.is_ignored_exception?(exception)
19
- Appsignal::Transaction.current.add_exception(exception)
20
- end
18
+ Appsignal.add_exception(exception)
21
19
  raise exception
22
20
  ensure
23
- Appsignal::Transaction.current.complete!
21
+ Appsignal::Transaction.complete_current!
24
22
  end
25
23
 
26
24
  end
@@ -17,12 +17,10 @@ if defined?(::Sidekiq)
17
17
  yield
18
18
  end
19
19
  rescue Exception => exception
20
- unless Appsignal.is_ignored_exception?(exception)
21
- Appsignal::Transaction.current.add_exception(exception)
22
- end
20
+ Appsignal.add_exception(exception)
23
21
  raise exception
24
22
  ensure
25
- Appsignal::Transaction.current.complete!
23
+ Appsignal::Transaction.complete_current!
26
24
  end
27
25
  end
28
26
  end
@@ -16,7 +16,7 @@ module Appsignal
16
16
  def transmit
17
17
  begin
18
18
  transmitter = Transmitter.new(ACTION, config)
19
- logger.info('Notifying Appsignal of deploy...')
19
+ logger.info("Notifying Appsignal of deploy with: revision: #{marker_data[:revision]}, user: #{marker_data[:user]}")
20
20
  result = transmitter.transmit(marker_data)
21
21
  if result == '200'
22
22
  logger.info('Appsignal has been notified of this deploy!')
@@ -2,6 +2,7 @@ module Appsignal
2
2
  module Rack
3
3
  class Instrumentation
4
4
  def initialize(app, options = {})
5
+ Appsignal.logger.debug 'Initializing Appsignal::Rack::Instrumentation'
5
6
  @app, @options = app, options
6
7
  end
7
8
 
@@ -2,6 +2,7 @@ module Appsignal
2
2
  module Rack
3
3
  class Listener
4
4
  def initialize(app, options = {})
5
+ Appsignal.logger.debug 'Initializing Appsignal::Rack::Listener'
5
6
  @app, @options = app, options
6
7
  end
7
8
 
@@ -17,12 +18,10 @@ module Appsignal
17
18
  Appsignal::Transaction.create(request_id(env), env)
18
19
  @app.call(env)
19
20
  rescue Exception => exception
20
- unless Appsignal.is_ignored_exception?(exception)
21
- Appsignal::Transaction.current.add_exception(exception)
22
- end
21
+ Appsignal.add_exception(exception)
23
22
  raise exception
24
23
  ensure
25
- Appsignal::Transaction.current.complete!
24
+ Appsignal::Transaction.complete_current!
26
25
  end
27
26
 
28
27
  def request_id(env)
@@ -11,20 +11,30 @@
11
11
  HTTP_CACHE_CONTROL HTTP_CONNECTION HTTP_USER_AGENT HTTP_FROM HTTP_NEGOTIATE
12
12
  HTTP_PRAGMA HTTP_REFERER HTTP_X_FORWARDED_FOR).freeze
13
13
 
14
- def self.create(key, env)
15
- Appsignal.logger.debug("Creating transaction: #{key}")
16
- Thread.current[:appsignal_transaction_id] = key
17
- Appsignal.transactions[key] = Appsignal::Transaction.new(key, env)
14
+ def self.create(request_id, env)
15
+ Appsignal.logger.debug("Creating transaction: #{request_id}")
16
+ Thread.current[:appsignal_transaction_id] = request_id
17
+ Appsignal::Transaction.new(request_id, env)
18
18
  end
19
19
 
20
20
  def self.current
21
21
  Appsignal.transactions[Thread.current[:appsignal_transaction_id]]
22
22
  end
23
23
 
24
+ def self.complete_current!
25
+ if current
26
+ current.complete!
27
+ Thread.current[:appsignal_transaction_id] = nil
28
+ else
29
+ Appsignal.logger.error('Trying to complete current, but no transaction present')
30
+ end
31
+ end
32
+
24
33
  attr_reader :request_id, :events, :process_action_event, :action, :exception,
25
34
  :env, :fullpath, :time, :tags, :kind, :queue_start
26
35
 
27
36
  def initialize(request_id, env)
37
+ Appsignal.transactions[request_id] = self
28
38
  @request_id = request_id
29
39
  @events = []
30
40
  @process_action_event = nil
@@ -128,6 +138,8 @@
128
138
  else
129
139
  Appsignal.logger.debug("Not processing transaction: #{@request_id}")
130
140
  end
141
+ ensure
142
+ Appsignal.transactions.delete(@request_id)
131
143
  end
132
144
 
133
145
  def set_background_queue_start
@@ -1,3 +1,3 @@
1
1
  module Appsignal
2
- VERSION = '0.8.15'
2
+ VERSION = '0.9.0.alpha.1'
3
3
  end
@@ -47,7 +47,7 @@ describe Appsignal::Agent do
47
47
  before do
48
48
  subject.stub(
49
49
  :aggregator => double(:has_transactions? => true),
50
- :sleep_time => 0.1
50
+ :sleep_time => 0.01
51
51
  )
52
52
  end
53
53
 
@@ -58,28 +58,6 @@ describe Appsignal::Agent do
58
58
  sleep 1
59
59
  end
60
60
  end
61
-
62
- context "when an exception occurs in the thread" do
63
- before do
64
- aggregator = double
65
- aggregator.stub(:has_transactions?).and_raise(
66
- RuntimeError.new('error')
67
- )
68
- subject.stub(
69
- :aggregator => aggregator,
70
- :sleep_time => 0.1
71
- )
72
- end
73
-
74
- it "should log the error" do
75
- Appsignal.logger.should_receive(:error).
76
- with("RuntimeError in agent thread: 'error'").
77
- once
78
-
79
- subject.start_thread
80
- sleep 1
81
- end
82
- end
83
61
  end
84
62
 
85
63
  describe "#restart_thread" do
@@ -17,6 +17,7 @@ describe Appsignal::Config do
17
17
  it "should merge with the default config and fill the config hash" do
18
18
  subject.config_hash.should == {
19
19
  :ignore_exceptions => [],
20
+ :instrument_net_http => true,
20
21
  :send_params => true,
21
22
  :endpoint => 'https://push.appsignal.com/1',
22
23
  :slow_request_threshold => 200,
@@ -123,6 +124,7 @@ describe Appsignal::Config do
123
124
  :push_api_key => 'push_api_key',
124
125
  :ignore_exceptions => [],
125
126
  :send_params => true,
127
+ :instrument_net_http => true,
126
128
  :endpoint => 'https://push.appsignal.com/1',
127
129
  :slow_request_threshold => 200,
128
130
  :active => true