appsignal 1.3.5 → 1.3.6.beta.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1df981364fb99fb2a476f560e03d4daa641ed611
4
- data.tar.gz: 2f0ce5ca8fbf1a6b71aba911969526bff71e25a7
3
+ metadata.gz: c006b3a5ff128b594596cc197d2f9c1b7a2c6a8e
4
+ data.tar.gz: caf8636d1ba933831cf582f65962d2c7155b62a9
5
5
  SHA512:
6
- metadata.gz: 089d7016d35c1bcde5db31d0030b7d35f8961f97f776121886d1d113ce775bdb0db77afea79b70cf64000ce141bb954af5c3a39c756fe4dbe9d8df8274c837c3
7
- data.tar.gz: 535b644066102b0deecd804aea5fc5bab859c59b659e51f29ffa34ffbc8d9ba5509636fd18d0f03da7637ce0c85233703d350c7d645f85a4716aaff532fa2e0b
6
+ metadata.gz: ddcb3f8151c062c01a029a595a7ca0d93cd93920bdeb1cf8cbc4f0922ab66fc291fba56fc3db3f2f121779a4bd3a186959da19ac1105a56fa251c6963e1c95ae
7
+ data.tar.gz: 5c79420049ae3cf242c426e1953c7a3286fa4630dd018703534b30502a2ec33aeb085ba5339e6caed01430c5629050eb571ffb9d533d69f483f4e6871fabebf5
@@ -1,8 +1,17 @@
1
+ # 1.3.6
2
+ * Support blocks arguments on method instrumentation
3
+ * Support `APPSIGNAL_APP_ENV` for Sinatra
4
+ * Minor improvements to installer
5
+ * More robust handing of non-writable log files
6
+ * Cleaner internal exception handling
7
+ * Support for mixed case keywords in sql lexing
8
+ * Support for inserting multiple rows in sql lexing
9
+
1
10
  # 1.3.5
2
11
 
3
- - Fix SSL certificate config in appsignal-agent. PR #151
4
- - Remove mounted_at Sinatra middleware option. Now detected by default. PR #146
5
- - Sinatra applications with middleware loading before AppSignal's middleware
12
+ * Fix SSL certificate config in appsignal-agent. PR #151
13
+ * Remove mounted_at Sinatra middleware option. Now detected by default. PR #146
14
+ * Sinatra applications with middleware loading before AppSignal's middleware
6
15
  would crash a request. Fixed in PR #156
7
16
 
8
17
  # 1.3.4
@@ -1,18 +1,18 @@
1
1
  ---
2
- version: f0c15da
2
+ version: 220a888
3
3
  triples:
4
4
  x86_64-linux:
5
- checksum: 2af2810c660b7b1ad38f5962db00a81965dcf0be07b101ff87f182d1699165b5
6
- download_url: https://appsignal-agent-releases.global.ssl.fastly.net/f0c15da/appsignal-x86_64-linux-all-static.tar.gz
5
+ checksum: 5e313156339389b339c289592327ac1c3d57999df93cd31ce9c69fa4ede1e38f
6
+ download_url: https://appsignal-agent-releases.global.ssl.fastly.net/220a888/appsignal-x86_64-linux-all-static.tar.gz
7
7
  i686-linux:
8
- checksum: a96f492f08bcccb0e66347fb0920b56d3d5c2958776469a241bf4357cfb4c1a0
9
- download_url: https://appsignal-agent-releases.global.ssl.fastly.net/f0c15da/appsignal-i686-linux-all-static.tar.gz
8
+ checksum: caeac8747e368bc122e56fdebd498b8c381a6d19d2b2dfaf01b648a6a973b28d
9
+ download_url: https://appsignal-agent-releases.global.ssl.fastly.net/220a888/appsignal-i686-linux-all-static.tar.gz
10
10
  x86-linux:
11
- checksum: a96f492f08bcccb0e66347fb0920b56d3d5c2958776469a241bf4357cfb4c1a0
12
- download_url: https://appsignal-agent-releases.global.ssl.fastly.net/f0c15da/appsignal-i686-linux-all-static.tar.gz
11
+ checksum: caeac8747e368bc122e56fdebd498b8c381a6d19d2b2dfaf01b648a6a973b28d
12
+ download_url: https://appsignal-agent-releases.global.ssl.fastly.net/220a888/appsignal-i686-linux-all-static.tar.gz
13
13
  x86_64-darwin:
14
- checksum: 0bbfdf50c06f1b3759ccac1a5b9bed8ebe42859144a045404ce258b3a2a93a4a
15
- download_url: https://appsignal-agent-releases.global.ssl.fastly.net/f0c15da/appsignal-x86_64-darwin-all-static.tar.gz
14
+ checksum: 949a325baf8b1a40978288082cf1689c22d48cdef6acbbc389d5613d670f6fb9
15
+ download_url: https://appsignal-agent-releases.global.ssl.fastly.net/220a888/appsignal-x86_64-darwin-all-static.tar.gz
16
16
  universal-darwin:
17
- checksum: 0bbfdf50c06f1b3759ccac1a5b9bed8ebe42859144a045404ce258b3a2a93a4a
18
- download_url: https://appsignal-agent-releases.global.ssl.fastly.net/f0c15da/appsignal-x86_64-darwin-all-static.tar.gz
17
+ checksum: 949a325baf8b1a40978288082cf1689c22d48cdef6acbbc389d5613d670f6fb9
18
+ download_url: https://appsignal-agent-releases.global.ssl.fastly.net/220a888/appsignal-x86_64-darwin-all-static.tar.gz
@@ -235,22 +235,26 @@ module Appsignal
235
235
  end
236
236
 
237
237
  def log_formatter
238
- proc do |severity, datetime, progname, msg|
239
- "[#{datetime.strftime('%Y-%m-%dT%H:%M:%S')} (process) ##{Process.pid}][#{severity}] #{msg}\n"
240
- end
238
+ proc do |severity, datetime, progname, msg|
239
+ "[#{datetime.strftime('%Y-%m-%dT%H:%M:%S')} (process) ##{Process.pid}][#{severity}] #{msg}\n"
240
+ end
241
241
  end
242
242
 
243
243
  def start_logger(path_arg=nil)
244
244
  path = Appsignal.config ? Appsignal.config.log_file_path : nil
245
- if path && !ENV['DYNO']
246
- @logger = Logger.new(path)
247
- @logger.formatter = log_formatter
248
- else
249
- @logger = Logger.new($stdout)
250
- @logger.formatter = lambda do |severity, datetime, progname, msg|
251
- "appsignal: #{msg}\n"
245
+ if path && !heroku?
246
+ begin
247
+ @logger = Logger.new(path)
248
+ @logger.formatter = log_formatter
249
+ rescue SystemCallError => error
250
+ start_stdout_logger
251
+ logger.warn "appsignal: Unable to start logger with log path '#{path}'."
252
+ logger.warn "appsignal: #{error}"
252
253
  end
254
+ else
255
+ start_stdout_logger
253
256
  end
257
+
254
258
  if config && config[:debug]
255
259
  @logger.level = Logger::DEBUG
256
260
  else
@@ -292,6 +296,19 @@ module Appsignal
292
296
  ensure
293
297
  Appsignal::Transaction.current.resume! if Appsignal::Transaction.current
294
298
  end
299
+
300
+ private
301
+
302
+ def start_stdout_logger
303
+ @logger = Logger.new($stdout)
304
+ @logger.formatter = lambda do |severity, datetime, progname, msg|
305
+ "appsignal: #{msg}\n"
306
+ end
307
+ end
308
+
309
+ def heroku?
310
+ ENV['DYNO']
311
+ end
295
312
  end
296
313
  end
297
314
 
@@ -93,11 +93,6 @@ module Appsignal
93
93
  puts
94
94
  puts " require 'appsignal/integrations/sinatra'"
95
95
  press_any_key
96
- puts "Configure subclass apps"
97
- puts " If your app is a subclass of Sinatra::Base you need to use this middleware:"
98
- puts
99
- puts " use Appsignal::Rack::SinatraInstrumentation"
100
- press_any_key
101
96
  done_notice
102
97
  end
103
98
 
@@ -136,6 +131,21 @@ module Appsignal
136
131
  done_notice
137
132
  end
138
133
 
134
+ def install_for_capistrano
135
+ capfile = File.join(Dir.pwd, 'Capfile')
136
+ return unless File.exist?(capfile)
137
+ return if File.read(capfile) =~ %r{require ['|"]appsignal/capistrano}
138
+
139
+ puts 'Installing for Capistrano'
140
+ print ' Adding AppSignal integration to Capfile'
141
+ File.open(capfile, 'a') do |f|
142
+ f.write "\nrequire 'appsignal/capistrano'\n"
143
+ end
144
+ periods
145
+ puts
146
+ puts
147
+ end
148
+
139
149
  def colorize(text, color)
140
150
  return text if Gem.win_platform?
141
151
  color_code = case color
@@ -187,16 +197,7 @@ module Appsignal
187
197
  end
188
198
 
189
199
  def configure(config, environments, name_overwritten)
190
- deploy_rb_file = File.join(Dir.pwd, 'config/deploy.rb')
191
- if File.exist?(deploy_rb_file) && (File.read(deploy_rb_file) =~ /require (\'|\").\/appsignal\/capistrano/).nil?
192
- print 'Adding AppSignal integration to deploy.rb'
193
- File.open(deploy_rb_file, 'a') do |f|
194
- f.write "\nrequire 'appsignal/capistrano'\n"
195
- end
196
- periods
197
- puts
198
- puts
199
- end
200
+ install_for_capistrano
200
201
 
201
202
  puts "How do you want to configure AppSignal?"
202
203
  puts " (1) a config file"
@@ -5,6 +5,7 @@ require 'socket'
5
5
 
6
6
  module Appsignal
7
7
  class Config
8
+ SYSTEM_TMP_DIR = '/tmp'
8
9
  DEFAULT_CONFIG = {
9
10
  :debug => false,
10
11
  :ignore_errors => [],
@@ -91,12 +92,19 @@ module Appsignal
91
92
  def log_file_path
92
93
  path = config_hash[:log_path] || root_path
93
94
  if path && File.writable?(path)
94
- File.join(File.realpath(path), 'appsignal.log')
95
+ return File.join(File.realpath(path), 'appsignal.log')
96
+ end
97
+
98
+ if File.writable? SYSTEM_TMP_DIR
99
+ $stdout.puts "appsignal: Unable to log to '#{path}'. Logging to "\
100
+ "'#{SYSTEM_TMP_DIR}' instead. Please check the "\
101
+ "permissions for the application's log directory."
102
+ File.join(SYSTEM_TMP_DIR, 'appsignal.log')
95
103
  else
96
- '/tmp/appsignal.log'
104
+ $stdout.puts "appsignal: Unable to log to '#{path}' or the "\
105
+ "'#{SYSTEM_TMP_DIR}' fallback. Please check the permissions "\
106
+ "for the application's (log) directory."
97
107
  end
98
- rescue Errno::ENOENT
99
- '/tmp/appsignal.log'
100
108
  end
101
109
 
102
110
  def valid?
@@ -46,7 +46,7 @@ module Appsignal
46
46
  else
47
47
  raise "#{f} does not have a format(payload) method"
48
48
  end
49
- rescue Exception => ex
49
+ rescue => ex
50
50
  formatter_classes.delete(name)
51
51
  formatters.delete(name)
52
52
  Appsignal.logger.debug("'#{ex.message}' when initializing #{name} event formatter")
@@ -2,24 +2,24 @@ class Object
2
2
  def self.appsignal_instrument_class_method(method_name, options = {})
3
3
  singleton_class.send \
4
4
  :alias_method, "appsignal_uninstrumented_#{method_name}", method_name
5
- singleton_class.send(:define_method, method_name) do |*args|
5
+ singleton_class.send(:define_method, method_name) do |*args, &block|
6
6
  name = options.fetch(:name) do
7
7
  "#{method_name}.class_method.#{appsignal_reverse_class_name}.other"
8
8
  end
9
9
  Appsignal.instrument name do
10
- send "appsignal_uninstrumented_#{method_name}", *args
10
+ send "appsignal_uninstrumented_#{method_name}", *args, &block
11
11
  end
12
12
  end
13
13
  end
14
14
 
15
15
  def self.appsignal_instrument_method(method_name, options = {})
16
16
  alias_method "appsignal_uninstrumented_#{method_name}", method_name
17
- define_method method_name do |*args|
17
+ define_method method_name do |*args, &block|
18
18
  name = options.fetch(:name) do
19
19
  "#{method_name}.#{appsignal_reverse_class_name}.other"
20
20
  end
21
21
  Appsignal.instrument name do
22
- send "appsignal_uninstrumented_#{method_name}", *args
22
+ send "appsignal_uninstrumented_#{method_name}", *args, &block
23
23
  end
24
24
  end
25
25
  end
@@ -6,7 +6,7 @@ Appsignal.logger.info("Loading Sinatra (#{Sinatra::VERSION}) integration")
6
6
  app_settings = ::Sinatra::Application.settings
7
7
  Appsignal.config = Appsignal::Config.new(
8
8
  app_settings.root || Dir.pwd,
9
- app_settings.environment
9
+ ENV.fetch('APPSIGNAL_APP_ENV'.freeze, app_settings.environment)
10
10
  )
11
11
 
12
12
  Appsignal.start_logger
@@ -25,7 +25,7 @@ module Appsignal::Integrations
25
25
  handle_exceptions_without_appsignal do
26
26
  begin
27
27
  yield
28
- rescue Exception => e
28
+ rescue => e
29
29
  Appsignal.set_error(e)
30
30
  raise e
31
31
  end
@@ -54,13 +54,15 @@ module Appsignal
54
54
  def each
55
55
  @stream.each { |c| yield(c) }
56
56
  rescue Exception => e
57
- @transaction.set_error(e); raise e
57
+ @transaction.set_error(e)
58
+ raise e
58
59
  end
59
60
 
60
61
  def close
61
62
  @stream.close if @stream.respond_to?(:close)
62
63
  rescue Exception => e
63
- @transaction.set_error(e); raise e
64
+ @transaction.set_error(e)
65
+ raise e
64
66
  ensure
65
67
  Appsignal::Transaction.complete_current!
66
68
  end
@@ -52,7 +52,7 @@ module Appsignal
52
52
 
53
53
  def complete_current!
54
54
  current.complete
55
- rescue Exception => e
55
+ rescue => e
56
56
  Appsignal.logger.error("Failed to complete transaction ##{current.transaction_id}. #{e.message}")
57
57
  ensure
58
58
  Thread.current[:appsignal_transaction] = nil
@@ -269,9 +269,9 @@ module Appsignal
269
269
  params =
270
270
  begin
271
271
  request.send options[:params_method]
272
- rescue Exception => ex
272
+ rescue => e
273
273
  # Getting params from the request has been know to fail.
274
- Appsignal.logger.debug "Exception while getting params: #{ex}"
274
+ Appsignal.logger.debug "Exception while getting params: #{e}"
275
275
  nil
276
276
  end
277
277
  return unless params
@@ -1,5 +1,5 @@
1
1
  require 'yaml'
2
2
 
3
3
  module Appsignal
4
- VERSION = '1.3.5'
4
+ VERSION = '1.3.6.beta.1'
5
5
  end
@@ -6,19 +6,13 @@ if capistrano2_present?
6
6
  describe "Capistrano 2 integration" do
7
7
  let(:out_stream) { StringIO.new }
8
8
  let(:config) { project_fixture_config }
9
-
10
- before do
11
- @original_stdout = $stdout
12
- $stdout = out_stream
13
- end
14
- after do
15
- $stdout = @original_stdout
16
- end
17
-
18
9
  before :all do
19
10
  @capistrano_config = Capistrano::Configuration.new
20
11
  Appsignal::Capistrano.tasks(@capistrano_config)
21
12
  end
13
+ around do |example|
14
+ capture_stdout(out_stream) { example.run }
15
+ end
22
16
 
23
17
  it "should have a deploy task" do
24
18
  @capistrano_config.find_task('appsignal:deploy').should_not be_nil
@@ -14,18 +14,11 @@ if capistrano3_present?
14
14
  @capistrano_config = Capistrano::Configuration.env
15
15
  @capistrano_config.set(:log_level, :error)
16
16
  @capistrano_config.set(:logger, logger)
17
- end
18
- before do
19
- @original_stdout = $stdout
20
- $stdout = out_stream
21
- @original_stderr = $stderr
22
- $stderr = out_stream
23
- end
24
- after do
25
- $stdout = @original_stdout
26
- $stderr = @original_stderr
27
17
  Rake::Task['appsignal:deploy'].reenable
28
18
  end
19
+ around do |example|
20
+ capture_std_streams(out_stream, out_stream) { example.run }
21
+ end
29
22
 
30
23
  it "should have a deploy task" do
31
24
  Rake::Task.task_defined?('appsignal:deploy').should be_true
@@ -13,15 +13,13 @@ describe Appsignal::CLI::Install do
13
13
 
14
14
  before do
15
15
  Dir.stub(:pwd => project_fixture_path)
16
- @original_stdout = $stdout
17
- $stdout = out_stream
18
16
  Appsignal::AuthCheck.stub(:new => auth_check)
19
17
  auth_check.stub(:perform => '200')
20
18
  cli.stub(:sleep)
21
19
  cli.stub(:press_any_key)
22
20
  end
23
- after do
24
- $stdout = @original_stdout
21
+ around do |example|
22
+ capture_stdout(out_stream) { example.run }
25
23
  end
26
24
 
27
25
  describe ".run" do
@@ -374,24 +372,50 @@ describe Appsignal::CLI::Install do
374
372
  end
375
373
  end
376
374
 
377
- context "when deploy.rb is present" do
378
- let(:config_dir) { File.join(tmp_dir, 'config') }
379
- let(:deploy_rb_file) { File.join(tmp_dir, 'config/deploy.rb') }
375
+ context "with capistrano" do
376
+ let(:capfile) { File.join(tmp_dir, 'Capfile') }
380
377
  before do
381
378
  Dir.stub(:pwd => tmp_dir)
382
- FileUtils.mkdir_p(config_dir)
383
- FileUtils.touch(deploy_rb_file)
379
+ FileUtils.mkdir_p(tmp_dir)
384
380
  cli.should_receive(:gets).once.and_return('2')
385
381
  end
386
382
  after do
387
- FileUtils.rm_rf(config_dir)
383
+ FileUtils.rm_rf(tmp_dir)
388
384
  end
389
385
 
390
- it "should add a require to deploy.rb" do
391
- cli.configure(config, [], false)
386
+ context "without Capfile" do
387
+ before { cli.configure(config, [], false) }
388
+
389
+ it "does nothing" do
390
+ expect(out_stream.string).to_not include 'Adding AppSignal integration to Capfile'
391
+ expect(File.exist?(capfile)).to be_false
392
+ end
393
+ end
392
394
 
393
- out_stream.string.should include 'Adding AppSignal integration to deploy.rb'
394
- File.read(deploy_rb_file).should include "require 'appsignal/capistrano'"
395
+ context "with Capfile" do
396
+ context "when already installed" do
397
+ before do
398
+ File.open(capfile, 'w') { |f| f.write("require 'appsignal/capistrano'") }
399
+ cli.configure(config, [], false)
400
+ end
401
+
402
+ it "does not add another require to Capfile" do
403
+ expect(out_stream.string).to_not include 'Adding AppSignal integration to Capfile'
404
+ expect(File.read(capfile).scan(/appsignal/).count).to eq(1)
405
+ end
406
+ end
407
+
408
+ context "when not installed" do
409
+ before do
410
+ FileUtils.touch(capfile)
411
+ cli.configure(config, [], false)
412
+ end
413
+
414
+ it "adds a require to Capfile" do
415
+ expect(out_stream.string).to include 'Adding AppSignal integration to Capfile'
416
+ expect(File.read(capfile)).to include "require 'appsignal/capistrano'"
417
+ end
418
+ end
395
419
  end
396
420
  end
397
421
  end
@@ -6,12 +6,10 @@ describe Appsignal::CLI::NotifyOfDeploy do
6
6
  let(:config) { Appsignal::Config.new(project_fixture_path, {}) }
7
7
  let(:marker_data) { {:revision => 'aaaaa', :user => 'thijs', :environment => 'production'} }
8
8
  before do
9
- @original_stdout = $stdout
10
- $stdout = out_stream
11
9
  config.stub(:active? => true)
12
10
  end
13
- after do
14
- $stdout = @original_stdout
11
+ around do |example|
12
+ capture_stdout(out_stream) { example.run }
15
13
  end
16
14
 
17
15
  describe ".run" do
@@ -4,13 +4,11 @@ describe Appsignal::CLI do
4
4
  let(:out_stream) { StringIO.new }
5
5
  let(:cli) { Appsignal::CLI }
6
6
  before do
7
- @original_stdout = $stdout
8
- $stdout = out_stream
9
7
  Dir.stub(:pwd => project_fixture_path)
10
8
  cli.options = {:environment => 'production'}
11
9
  end
12
- after do
13
- $stdout = @original_stdout
10
+ around do |example|
11
+ capture_stdout(out_stream) { example.run }
14
12
  end
15
13
 
16
14
  describe "#config" do
@@ -40,31 +40,145 @@ describe Appsignal::Config do
40
40
  })
41
41
  end
42
42
 
43
- context "if a log file path is set" do
44
- let(:config) { project_fixture_config('production', :log_path => '/tmp') }
43
+ describe "#log_file_path" do
44
+ let(:stdout) { StringIO.new }
45
+ let(:config) { project_fixture_config('production', :log_path => log_path) }
46
+ subject { config.log_file_path }
47
+ around do |example|
48
+ original_stdout = $stdout
49
+ $stdout = stdout
50
+ example.run
51
+ $stdout = original_stdout
52
+ end
53
+
54
+ context "when path is writable" do
55
+ let(:log_path) { File.join(tmp_dir, 'writable-path') }
56
+ before { FileUtils.mkdir_p(log_path, :mode => 0755) }
57
+ after { FileUtils.rm_rf(log_path) }
58
+
59
+ it "returns log file path" do
60
+ expect(subject).to eq File.join(log_path, 'appsignal.log')
61
+ end
62
+
63
+ it "prints no warning" do
64
+ subject
65
+ expect(stdout.string).to be_empty
66
+ end
67
+ end
45
68
 
46
- its(:log_file_path) { should end_with('/tmp/appsignal.log') }
69
+ shared_examples '#log_file_path: tmp path' do
70
+ let(:system_tmp_dir) { Appsignal::Config::SYSTEM_TMP_DIR }
71
+ before { FileUtils.mkdir_p(system_tmp_dir) }
72
+ after { FileUtils.rm_rf(system_tmp_dir) }
47
73
 
48
- context "if it is not writable" do
49
- before { FileUtils.mkdir_p('/tmp/not-writable', :mode => 0555) }
74
+ context "when the /tmp fallback path is writable" do
75
+ before { FileUtils.chmod(0777, system_tmp_dir) }
50
76
 
51
- let(:config) { project_fixture_config('production', :log_path => '/tmp/not-writable') }
77
+ it "returns returns the tmp location" do
78
+ expect(subject).to eq(File.join(system_tmp_dir, 'appsignal.log'))
79
+ end
52
80
 
53
- its(:log_file_path) { should eq '/tmp/appsignal.log' }
81
+ it "prints a warning" do
82
+ subject
83
+ expect(stdout.string).to include "appsignal: Unable to log to '#{log_path}'. "\
84
+ "Logging to '#{system_tmp_dir}' instead."
85
+ end
86
+ end
87
+
88
+ context "when the /tmp fallback path is not writable" do
89
+ before { FileUtils.chmod(0555, system_tmp_dir) }
90
+
91
+ it "returns nil" do
92
+ expect(subject).to be_nil
93
+ end
94
+
95
+ it "prints a warning" do
96
+ subject
97
+ expect(stdout.string).to include "appsignal: Unable to log to '#{log_path}' "\
98
+ "or the '#{system_tmp_dir}' fallback."
99
+ end
100
+ end
54
101
  end
55
102
 
56
- context "if it does not exist" do
57
- let(:config) { project_fixture_config('production', :log_path => '/non-existing') }
103
+ context "when path is nil" do
104
+ let(:log_path) { nil }
105
+
106
+ context "when root_path is nil" do
107
+ before { allow(config).to receive(:root_path).and_return(nil) }
58
108
 
59
- its(:log_file_path) { should eq '/tmp/appsignal.log' }
109
+ include_examples '#log_file_path: tmp path'
110
+ end
111
+
112
+ context "when root_path is set" do
113
+ it "returns returns the project log location" do
114
+ expect(subject).to eq File.join(config.root_path, 'appsignal.log')
115
+ end
116
+
117
+ it "prints no warning" do
118
+ subject
119
+ expect(stdout.string).to be_empty
120
+ end
121
+ end
122
+ end
123
+
124
+ context "when path does not exist" do
125
+ let(:log_path) { '/non-existing' }
126
+
127
+ include_examples '#log_file_path: tmp path'
128
+ end
129
+
130
+ context "when path is not writable" do
131
+ let(:log_path) { File.join(tmp_dir, 'not-writable-path') }
132
+ before { FileUtils.mkdir_p(log_path, :mode => 0555) }
133
+ after { FileUtils.rm_rf(log_path) }
134
+
135
+ include_examples '#log_file_path: tmp path'
60
136
  end
61
137
 
62
- context "if it is nil" do
63
- let(:config) { project_fixture_config('production', :log_path => nil) }
138
+ context "when path is a symlink" do
139
+ context "when linked path does not exist" do
140
+ let(:real_path) { File.join(tmp_dir, 'real-path') }
141
+ let(:log_path) { File.join(tmp_dir, 'symlink-path') }
142
+ before { File.symlink(real_path, log_path) }
143
+ after { FileUtils.rm(log_path) }
64
144
 
65
- before { config.stub(:root_path => nil) }
145
+ include_examples '#log_file_path: tmp path'
146
+ end
66
147
 
67
- its(:log_file_path) { should eq '/tmp/appsignal.log' }
148
+ context "when linked path exists" do
149
+ context "when linked path is not writable" do
150
+ let(:real_path) { File.join(tmp_dir, 'real-path') }
151
+ let(:log_path) { File.join(tmp_dir, 'symlink-path') }
152
+ before do
153
+ FileUtils.mkdir_p(real_path)
154
+ FileUtils.chmod(0444, real_path)
155
+ File.symlink(real_path, log_path)
156
+ end
157
+ after do
158
+ FileUtils.rm_rf(real_path)
159
+ FileUtils.rm(log_path)
160
+ end
161
+
162
+ include_examples '#log_file_path: tmp path'
163
+ end
164
+
165
+ context "when linked path is writable" do
166
+ let(:real_path) { File.join(tmp_dir, 'real-path') }
167
+ let(:log_path) { File.join(tmp_dir, 'symlink-path') }
168
+ before do
169
+ FileUtils.mkdir_p(real_path)
170
+ File.symlink(real_path, log_path)
171
+ end
172
+ after do
173
+ FileUtils.rm_rf(real_path)
174
+ FileUtils.rm(log_path)
175
+ end
176
+
177
+ it "returns real path of log path" do
178
+ expect(subject).to eq(File.join(real_path, 'appsignal.log'))
179
+ end
180
+ end
181
+ end
68
182
  end
69
183
  end
70
184
 
@@ -1,14 +1,11 @@
1
1
  if webmachine_present?
2
2
  describe Appsignal::Hooks::WebmachineHook do
3
3
  context "with webmachine" do
4
- before(:all) do
5
- Appsignal::Hooks::WebmachineHook.new.install
6
- end
4
+ let(:fsm) { Webmachine::Decision::FSM.new(double(:trace? => false), double, double) }
5
+ before(:all) { start_agent }
7
6
 
8
7
  its(:dependencies_present?) { should be_true }
9
8
 
10
- let(:fsm) { Webmachine::Decision::FSM.new(double(:trace? => false), double, double) }
11
-
12
9
  it "should include the run alias methods" do
13
10
  expect( fsm ).to respond_to(:run_with_appsignal)
14
11
  expect( fsm ).to respond_to(:run_without_appsignal)
@@ -92,6 +92,21 @@ describe Object do
92
92
  expect(instance.foo).to eq(1)
93
93
  end
94
94
  end
95
+
96
+ context "with a method given a block" do
97
+ let(:klass) do
98
+ Class.new do
99
+ def foo
100
+ yield
101
+ end
102
+ appsignal_instrument_method :foo
103
+ end
104
+ end
105
+
106
+ it "should yield the block" do
107
+ expect(instance.foo { 42 }).to eq(42)
108
+ end
109
+ end
95
110
  end
96
111
 
97
112
  context "when not active" do
@@ -194,6 +209,21 @@ describe Object do
194
209
  expect(klass.bar).to eq(2)
195
210
  end
196
211
  end
212
+
213
+ context "with a method given a block" do
214
+ let(:klass) do
215
+ Class.new do
216
+ def self.bar
217
+ yield
218
+ end
219
+ appsignal_instrument_class_method :bar
220
+ end
221
+ end
222
+
223
+ it "should yield the block" do
224
+ expect(klass.bar { 42 }).to eq(42)
225
+ end
226
+ end
197
227
  end
198
228
 
199
229
  context "when not active" do
@@ -3,16 +3,43 @@ if sinatra_present? && !padrino_present?
3
3
  require 'appsignal/integrations/sinatra'
4
4
 
5
5
  describe "Sinatra integration" do
6
- context "logger" do
6
+ context "Appsignal.logger" do
7
7
  subject { Appsignal.logger }
8
8
 
9
9
  it { should be_a Logger }
10
10
  end
11
11
 
12
- it "should have added the instrumentation middleware" do
13
- Sinatra::Base.middleware.to_a.should include(
14
- [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
15
- )
12
+ describe "middleware" do
13
+ it "adds the instrumentation middleware to Sinatra::Base" do
14
+ Sinatra::Base.middleware.to_a.should include(
15
+ [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
16
+ )
17
+ end
18
+ end
19
+
20
+ describe "environment" do
21
+ subject { Appsignal.config.env }
22
+
23
+ context "without APPSIGNAL_APP_ENV" do
24
+ before do
25
+ load File.expand_path('lib/appsignal/integrations/sinatra.rb', project_dir)
26
+ end
27
+
28
+ it "uses the app environment" do
29
+ expect(subject).to eq('test')
30
+ end
31
+ end
32
+
33
+ context "with APPSIGNAL_APP_ENV" do
34
+ before do
35
+ ENV['APPSIGNAL_APP_ENV'] = 'env-staging'
36
+ load File.expand_path('lib/appsignal/integrations/sinatra.rb', project_dir)
37
+ end
38
+
39
+ it "uses the environment variable" do
40
+ expect(subject).to eq('env-staging')
41
+ end
42
+ end
16
43
  end
17
44
  end
18
45
  end
@@ -3,17 +3,14 @@ if webmachine_present?
3
3
  require 'appsignal/integrations/webmachine'
4
4
 
5
5
  describe Appsignal::Integrations::WebmachinePlugin::FSM do
6
- before(:all) do
7
- Appsignal::Hooks::WebmachineHook.new.install
8
- end
9
6
  let(:request) do
10
7
  Webmachine::Request.new('GET', 'http://google.com:80/foo', {}, nil)
11
8
  end
12
9
  let(:resource) { double(:trace? => false, :handle_exception => true) }
13
10
  let(:response) { double }
14
11
  let(:transaction) { double(:set_action => true) }
15
-
16
12
  let(:fsm) { Webmachine::Decision::FSM.new(resource, request, response) }
13
+ before(:all) { start_agent }
17
14
 
18
15
  # Make sure the request responds to the method we need to get query params.
19
16
  describe "request" do
@@ -58,18 +55,15 @@ if webmachine_present?
58
55
  after { fsm.run }
59
56
  end
60
57
 
61
- describe "handle_exceptions_with_appsignal" do
62
- let(:error) { VerySpecificError.new('error') }
58
+ describe "#handle_exceptions_with_appsignal" do
59
+ let(:error) { VerySpecificError.new }
63
60
 
64
61
  it "should catch the error and send it to AppSignal" do
65
62
  expect( Appsignal ).to receive(:set_error).with(error)
66
63
  end
67
64
 
68
65
  after do
69
- begin
70
- fsm.send(:handle_exceptions) { raise error };
71
- rescue VerySpecificError
72
- end
66
+ fsm.send(:handle_exceptions) { raise error }
73
67
  end
74
68
  end
75
69
 
@@ -12,12 +12,8 @@ describe Appsignal::Marker do
12
12
  )
13
13
  }
14
14
  let(:out_stream) { StringIO.new }
15
- before do
16
- @original_stdout = $stdout
17
- $stdout = out_stream
18
- end
19
- after do
20
- $stdout = @original_stdout
15
+ around do |example|
16
+ capture_stdout(out_stream) { example.run }
21
17
  end
22
18
 
23
19
  context "transmit" do
@@ -120,10 +120,11 @@ describe Appsignal::Transaction do
120
120
 
121
121
  context "if a transaction is discarded" do
122
122
  it "should not complete the transaction" do
123
- Appsignal::Transaction.current.should_not_receive(:complete)
123
+ expect(Appsignal::Transaction.current.ext).to_not receive(:complete)
124
124
 
125
125
  Appsignal::Transaction.current.discard!
126
126
  expect(Appsignal::Transaction.current.discarded?).to be_true
127
+
127
128
  Appsignal::Transaction.complete_current!
128
129
 
129
130
  Thread.current[:appsignal_transaction].should be_nil
@@ -550,69 +550,124 @@ describe Appsignal do
550
550
 
551
551
  describe ".start_logger" do
552
552
  let(:out_stream) { StringIO.new }
553
- let(:log_path) { File.join(project_fixture_path, 'log') }
553
+ let(:log_path) { File.join(tmp_dir, 'log') }
554
554
  let(:log_file) { File.join(log_path, 'appsignal.log') }
555
555
 
556
556
  before do
557
- FileUtils.rm_f(log_file)
558
- @original_stdout = $stdout
559
- $stdout = out_stream
560
- Appsignal.logger.error('Log something')
557
+ FileUtils.mkdir_p(log_path)
558
+
559
+ Appsignal.logger.error('Log in memory')
561
560
  Appsignal.config = project_fixture_config(
562
561
  'production',
563
562
  :log_path => log_path
564
563
  )
565
564
  end
566
- after do
567
- $stdout = @original_stdout
565
+ around do |example|
566
+ capture_stdout(out_stream) { example.run }
568
567
  end
568
+ after { FileUtils.rm_rf(log_path) }
569
569
 
570
570
  context "when the log path is writable" do
571
- it "should log to file" do
571
+ context "when the log file is writable" do
572
+ let(:log_file_contents) { File.open(log_file).read }
573
+ before do
574
+ Appsignal.start_logger
575
+ Appsignal.logger.error('Log to file')
576
+ end
577
+
578
+ it "logs to file" do
579
+ expect(File.exist?(log_file)).to be_true
580
+ expect(log_file_contents).to include 'Log to file'
581
+ end
582
+
583
+ it "amends in memory log to log file" do
584
+ expect(log_file_contents).to include 'Log in memory'
585
+ end
586
+ end
587
+
588
+ context "when the log file is not writable" do
589
+ before do
590
+ FileUtils.touch log_file
591
+ FileUtils.chmod 0444, log_file
592
+
593
+ Appsignal.start_logger
594
+ Appsignal.logger.error('Log to not writable log file')
595
+ end
596
+
597
+ it "logs to stdout" do
598
+ expect(File.writable?(log_file)).to be_false
599
+ expect(out_stream.string).to include 'Log to not writable log file'
600
+ end
601
+
602
+ it "outputs a warning" do
603
+ output = out_stream.string
604
+ expect(output).to include "appsignal: Unable to start logger with "\
605
+ "log path '#{log_file}'."
606
+ expect(output).to include "appsignal: Permission denied"
607
+ end
608
+ end
609
+ end
610
+
611
+ context "when the log path is not writable" do
612
+ before do
613
+ FileUtils.chmod 0444, log_path
614
+
572
615
  Appsignal.start_logger
573
- Appsignal.logger.level.should eq Logger::INFO
574
- Appsignal.logger.error('Log to file')
575
- File.exist?(log_file).should be_true
576
- File.open(log_file).read.should include 'Log to file'
577
- File.open(log_file).read.should include 'Log something'
616
+ Appsignal.logger.error('Log to not writable log path')
617
+ end
618
+
619
+ it "logs to stdout" do
620
+ expect(File.writable?(log_path)).to be_false
621
+ expect(out_stream.string).to include 'Log to not writable log path'
622
+ end
623
+
624
+ it "amends in memory log to stdout" do
625
+ expect(out_stream.string).to include 'Log in memory'
578
626
  end
579
627
  end
580
628
 
581
- context "when we're on Heroku" do
629
+ context "when on Heroku" do
582
630
  before do
583
631
  ENV['DYNO'] = 'dyno1'
632
+ Appsignal.start_logger
633
+ Appsignal.logger.error('Log to stdout')
584
634
  end
585
635
  after { ENV.delete('DYNO') }
586
636
 
587
637
  it "should log to stdout" do
588
- Appsignal.start_logger
589
- Appsignal.logger.level.should eq Logger::INFO
590
- Appsignal.logger.error('Log to stdout')
591
638
  out_stream.string.should include 'appsignal: Log to stdout'
592
- out_stream.string.should include 'Log something'
593
639
  end
594
- end
595
640
 
596
- context "when there is no in memory log" do
597
- it "should not crash" do
598
- Appsignal.in_memory_log = nil
599
- Appsignal.start_logger
641
+ it "amends in memory log to stdout" do
642
+ expect(out_stream.string).to include 'Log in memory'
600
643
  end
601
644
  end
602
645
 
603
- context "when there is no config and debug is on" do
604
- it "should set the log level to info" do
605
- Appsignal.config = nil
606
- Appsignal.start_logger
607
- Appsignal.logger.level.should eq Logger::INFO
646
+ describe "#logger#level" do
647
+ subject { Appsignal.logger.level }
648
+
649
+ context "when there is no config" do
650
+ before do
651
+ Appsignal.config = nil
652
+ Appsignal.start_logger
653
+ end
654
+
655
+ it "sets the log level to info" do
656
+ expect(subject).to eq Logger::INFO
657
+ end
608
658
  end
609
- end
610
659
 
611
- context "when there is a config and debug is on" do
612
- it "should set the log level to debug" do
613
- Appsignal.config.config_hash[:debug] = true
614
- Appsignal.start_logger
615
- Appsignal.logger.level.should eq Logger::DEBUG
660
+ context "when there is a config" do
661
+ context "when log level is configured to debug" do
662
+ before do
663
+ Appsignal.config.config_hash[:debug] = true
664
+ Appsignal.start_logger
665
+ end
666
+
667
+ it "sets the log level to debug" do
668
+ expect(subject).to eq Logger::DEBUG
669
+ end
670
+ end
616
671
  end
617
672
  end
618
673
  end
@@ -1,4 +1,5 @@
1
1
  ENV['RAILS_ENV'] ||= 'test'
2
+ ENV['RACK_ENV'] ||= 'test'
2
3
  ENV['PADRINO_ENV'] ||= 'test'
3
4
 
4
5
  APPSIGNAL_SPEC_DIR = File.expand_path(File.dirname(__FILE__))
@@ -123,6 +124,7 @@ end
123
124
 
124
125
  RSpec.configure do |config|
125
126
  config.include DirectoryHelper
127
+ config.include StdStreamsHelper
126
128
  config.include ConfigHelpers
127
129
  config.include EnvHelpers
128
130
  config.include NotificationHelpers
@@ -132,10 +134,11 @@ RSpec.configure do |config|
132
134
  config.before :all do
133
135
  FileUtils.rm_rf(tmp_dir)
134
136
  FileUtils.mkdir_p(tmp_dir)
135
- end
136
137
 
137
- config.after do
138
- Thread.current[:appsignal_transaction] = nil
138
+ # Use modifiable SYSTEM_TMP_DIR
139
+ Appsignal::Config.send :remove_const, :SYSTEM_TMP_DIR
140
+ Appsignal::Config.send :const_set, :SYSTEM_TMP_DIR,
141
+ File.join(tmp_dir, 'system-tmp')
139
142
  end
140
143
 
141
144
  config.before do
@@ -148,6 +151,10 @@ RSpec.configure do |config|
148
151
  end
149
152
  end
150
153
 
154
+ config.after do
155
+ Thread.current[:appsignal_transaction] = nil
156
+ end
157
+
151
158
  config.after :all do
152
159
  ActiveSupport::Notifications.notifier.clear_subscribers
153
160
  FileUtils.rm_f(File.join(project_fixture_path, 'log/appsignal.log'))
@@ -0,0 +1,35 @@
1
+ module StdStreamsHelper
2
+ # Capture STDOUT in a variable
3
+ #
4
+ # Usage
5
+ #
6
+ # out_stream = StringIO.new
7
+ # capture_stdout(out_stream) { do_something }
8
+ def capture_stdout(stdout)
9
+ original_stdout = $stdout
10
+ $stdout = stdout
11
+
12
+ yield
13
+
14
+ $stdout = original_stdout
15
+ end
16
+
17
+ # Capture STDOUT and STDERR in variables
18
+ #
19
+ # Usage
20
+ #
21
+ # out_stream = StringIO.new
22
+ # err_stream = StringIO.new
23
+ # capture_std_streams(out_stream, err_stream) { do_something }
24
+ def capture_std_streams(stdout, stderr)
25
+ original_stdout = $stdout
26
+ $stdout = stdout
27
+ original_stderr = $stderr
28
+ $stderr = stderr
29
+
30
+ yield
31
+
32
+ $stdout = original_stdout
33
+ $stderr = original_stderr
34
+ end
35
+ end
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: 1.3.5
4
+ version: 1.3.6.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Beekman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-09-16 00:00:00.000000000 Z
12
+ date: 2016-09-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -285,6 +285,7 @@ files:
285
285
  - spec/support/helpers/directory_helper.rb
286
286
  - spec/support/helpers/env_helpers.rb
287
287
  - spec/support/helpers/notification_helpers.rb
288
+ - spec/support/helpers/std_streams_helper.rb
288
289
  - spec/support/helpers/time_helpers.rb
289
290
  - spec/support/helpers/transaction_helpers.rb
290
291
  - spec/support/helpers/very_specific_error.rb
@@ -313,12 +314,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
313
314
  version: '1.9'
314
315
  required_rubygems_version: !ruby/object:Gem::Requirement
315
316
  requirements:
316
- - - ">="
317
+ - - ">"
317
318
  - !ruby/object:Gem::Version
318
- version: '0'
319
+ version: 1.3.1
319
320
  requirements: []
320
321
  rubyforge_project:
321
- rubygems_version: 2.5.1
322
+ rubygems_version: 2.4.5
322
323
  signing_key:
323
324
  specification_version: 4
324
325
  summary: Logs performance and exception data from your app to appsignal.com
@@ -390,6 +391,7 @@ test_files:
390
391
  - spec/support/helpers/directory_helper.rb
391
392
  - spec/support/helpers/env_helpers.rb
392
393
  - spec/support/helpers/notification_helpers.rb
394
+ - spec/support/helpers/std_streams_helper.rb
393
395
  - spec/support/helpers/time_helpers.rb
394
396
  - spec/support/helpers/transaction_helpers.rb
395
397
  - spec/support/helpers/very_specific_error.rb
@@ -402,3 +404,4 @@ test_files:
402
404
  - spec/support/project_fixture/log/.gitkeep
403
405
  - spec/support/rails/my_app.rb
404
406
  - spec/support/stubs/delayed_job.rb
407
+ has_rdoc: