appsignal 1.3.5 → 1.3.6.beta.1

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 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: