appsignal 2.9.3 → 2.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,11 +22,13 @@ module Appsignal
22
22
  end
23
23
  end
24
24
 
25
- Appsignal::EventFormatter.register(
26
- "render_partial.action_view",
27
- Appsignal::EventFormatter::ActionView::RenderFormatter
28
- )
29
- Appsignal::EventFormatter.register(
30
- "render_template.action_view",
31
- Appsignal::EventFormatter::ActionView::RenderFormatter
32
- )
25
+ if defined?(Rails)
26
+ Appsignal::EventFormatter.register(
27
+ "render_partial.action_view",
28
+ Appsignal::EventFormatter::ActionView::RenderFormatter
29
+ )
30
+ Appsignal::EventFormatter.register(
31
+ "render_template.action_view",
32
+ Appsignal::EventFormatter::ActionView::RenderFormatter
33
+ )
34
+ end
@@ -27,6 +27,8 @@ module Appsignal
27
27
  end
28
28
  end
29
29
 
30
+ return unless defined?(::Puma::Cluster)
31
+ # For clustered mode with multiple workers
30
32
  ::Puma::Cluster.class_eval do
31
33
  alias stop_workers_without_appsignal stop_workers
32
34
 
@@ -49,7 +49,8 @@ module Appsignal
49
49
 
50
50
  ::Sidekiq::Queue.all.each do |queue|
51
51
  gauge "queue_length", queue.size, :queue => queue.name
52
- gauge "queue_latency", queue.latency, :queue => queue.name
52
+ # Convert latency from seconds to milliseconds
53
+ gauge "queue_latency", queue.latency * 1_000.0, :queue => queue.name
53
54
  end
54
55
  end
55
56
 
@@ -145,7 +145,8 @@ module Appsignal
145
145
  logger.debug("Gathering minutely metrics with '#{name}' probe")
146
146
  probe.call
147
147
  rescue => ex
148
- logger.error("Error in minutely probe '#{name}': #{ex}")
148
+ logger.error "Error in minutely probe '#{name}': #{ex}\n"
149
+ logger.debug ex.backtrace.join("\n")
149
150
  end
150
151
  end
151
152
  sleep(Appsignal::Minutely.wait_time)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "2.9.3".freeze
4
+ VERSION = "2.9.4".freeze
5
5
  end
@@ -1,43 +1,53 @@
1
- if DependencyHelper.rails_present?
2
- require "action_view"
1
+ describe Appsignal::EventFormatter::ActionView::RenderFormatter do
2
+ let(:klass) { Appsignal::EventFormatter::ActionView::RenderFormatter }
3
3
 
4
- describe Appsignal::EventFormatter::ActionView::RenderFormatter do
5
- before { allow(Rails.root).to receive(:to_s).and_return("/var/www/app/20130101") }
6
- let(:klass) { Appsignal::EventFormatter::ActionView::RenderFormatter }
7
- let(:formatter) { klass.new }
4
+ if DependencyHelper.rails_present?
5
+ require "action_view"
8
6
 
9
- it "should register render_partial.action_view and render_template.action_view" do
10
- expect(Appsignal::EventFormatter.registered?("render_partial.action_view", klass)).to be_truthy
11
- expect(Appsignal::EventFormatter.registered?("render_template.action_view", klass)).to be_truthy
12
- end
7
+ context "when in a Rails app" do
8
+ let(:formatter) { klass.new }
9
+ before { allow(Rails.root).to receive(:to_s).and_return("/var/www/app/20130101") }
10
+
11
+ it "registers render_partial.action_view and render_template.action_view" do
12
+ expect(Appsignal::EventFormatter.registered?("render_partial.action_view", klass)).to be_truthy
13
+ expect(Appsignal::EventFormatter.registered?("render_template.action_view", klass)).to be_truthy
14
+ end
13
15
 
14
- describe "#root_path" do
15
- subject { formatter.root_path }
16
+ describe "#root_path" do
17
+ subject { formatter.root_path }
16
18
 
17
- it "returns Rails root path" do
18
- is_expected.to eq "/var/www/app/20130101/"
19
+ it "returns Rails root path" do
20
+ is_expected.to eq "/var/www/app/20130101/"
21
+ end
19
22
  end
20
- end
21
23
 
22
- describe "#format" do
23
- subject { formatter.format(payload) }
24
+ describe "#format" do
25
+ subject { formatter.format(payload) }
24
26
 
25
- context "with an identifier" do
26
- let(:payload) { { :identifier => "/var/www/app/20130101/app/views/home/index/html.erb" } }
27
+ context "with an identifier" do
28
+ let(:payload) { { :identifier => "/var/www/app/20130101/app/views/home/index/html.erb" } }
27
29
 
28
- it { is_expected.to eq ["app/views/home/index/html.erb", nil] }
29
- end
30
+ it { is_expected.to eq ["app/views/home/index/html.erb", nil] }
31
+ end
30
32
 
31
- context "with a frozen identifier" do
32
- let(:payload) { { :identifier => "/var/www/app/20130101/app/views/home/index/html.erb".freeze } }
33
+ context "with a frozen identifier" do
34
+ let(:payload) { { :identifier => "/var/www/app/20130101/app/views/home/index/html.erb".freeze } }
33
35
 
34
- it { is_expected.to eq ["app/views/home/index/html.erb", nil] }
35
- end
36
+ it { is_expected.to eq ["app/views/home/index/html.erb", nil] }
37
+ end
36
38
 
37
- context "without an identifier" do
38
- let(:payload) { {} }
39
+ context "without an identifier" do
40
+ let(:payload) { {} }
39
41
 
40
- it { is_expected.to be_nil }
42
+ it { is_expected.to be_nil }
43
+ end
44
+ end
45
+ end
46
+ else
47
+ context "when not in a Rails app" do
48
+ it "does not register the event formatter" do
49
+ expect(Appsignal::EventFormatter.registered?("render_partial.action_view", klass)).to be_falsy
50
+ expect(Appsignal::EventFormatter.registered?("render_template.action_view", klass)).to be_falsy
41
51
  end
42
52
  end
43
53
  end
@@ -8,11 +8,6 @@ describe Appsignal::Hooks::PumaHook do
8
8
  def self.cli_config
9
9
  @cli_config ||= CliConfig.new
10
10
  end
11
-
12
- class Cluster
13
- def stop_workers
14
- end
15
- end
16
11
  end
17
12
 
18
13
  class CliConfig
@@ -31,23 +26,46 @@ describe Appsignal::Hooks::PumaHook do
31
26
  it { is_expected.to be_truthy }
32
27
  end
33
28
 
34
- context "when installed" do
35
- before do
36
- Appsignal::Hooks::PumaHook.new.install
29
+ describe "installation" do
30
+ context "when not clustered mode" do
31
+ it "does not add AppSignal stop behavior Puma::Cluster" do
32
+ expect(defined?(::Puma::Cluster)).to be_falsy
33
+ # Does not error on call
34
+ Appsignal::Hooks::PumaHook.new.install
35
+ end
36
+
37
+ it "adds the Puma minutely probe" do
38
+ probe = Appsignal::Minutely.probes[:puma]
39
+ expect(probe).to eql(Appsignal::Hooks::PumaProbe)
40
+ end
37
41
  end
38
42
 
39
- it "adds behavior to Unicorn::Worker#close" do
40
- cluster = Puma::Cluster.new
43
+ context "when in clustered mode" do
44
+ before do
45
+ class Puma
46
+ class Cluster
47
+ def stop_workers
48
+ @called = true
49
+ end
50
+ end
51
+ end
52
+ Appsignal::Hooks::PumaHook.new.install
53
+ end
54
+ after { Puma.send(:remove_const, :Cluster) }
41
55
 
42
- expect(Appsignal).to receive(:stop)
43
- expect(cluster).to receive(:stop_workers_without_appsignal)
56
+ it "adds behavior to Puma::Cluster.stop_workers" do
57
+ cluster = Puma::Cluster.new
44
58
 
45
- cluster.stop_workers
46
- end
59
+ expect(cluster.instance_variable_defined?(:@called)).to be_falsy
60
+ expect(Appsignal).to receive(:stop).and_call_original
61
+ cluster.stop_workers
62
+ expect(cluster.instance_variable_get(:@called)).to be(true)
63
+ end
47
64
 
48
- it "adds the Puma minutely probe" do
49
- probe = Appsignal::Minutely.probes[:puma]
50
- expect(probe).to eql(Appsignal::Hooks::PumaProbe)
65
+ it "adds the Puma minutely probe" do
66
+ probe = Appsignal::Minutely.probes[:puma]
67
+ expect(probe).to eql(Appsignal::Hooks::PumaProbe)
68
+ end
51
69
  end
52
70
  end
53
71
 
@@ -684,9 +684,9 @@ describe Appsignal::Hooks::SidekiqProbe do
684
684
  expect_gauge("job_count", 14, :status => :scheduled).twice
685
685
  expect_gauge("job_count", 15, :status => :enqueued).twice
686
686
  expect_gauge("queue_length", 10, :queue => "default").twice
687
- expect_gauge("queue_latency", 12, :queue => "default").twice
687
+ expect_gauge("queue_latency", 12_000, :queue => "default").twice
688
688
  expect_gauge("queue_length", 1, :queue => "critical").twice
689
- expect_gauge("queue_latency", 2, :queue => "critical").twice
689
+ expect_gauge("queue_latency", 2_000, :queue => "critical").twice
690
690
  # Call probe twice so we can calculate the delta for some gauge values
691
691
  probe.call
692
692
  probe.call
@@ -27,12 +27,9 @@ describe Appsignal::Minutely do
27
27
  end
28
28
 
29
29
  let(:log_stream) { StringIO.new }
30
- let(:log) do
31
- log_stream.rewind
32
- log_stream.read
33
- end
30
+ let(:log) { log_contents(log_stream) }
34
31
  before do
35
- Appsignal.logger = Logger.new(log_stream)
32
+ Appsignal.logger = test_logger(log_stream)
36
33
  # Speed up test time
37
34
  allow(Appsignal::Minutely).to receive(:wait_time).and_return(0.001)
38
35
  end
@@ -44,8 +41,8 @@ describe Appsignal::Minutely do
44
41
  Appsignal::Minutely.start
45
42
 
46
43
  wait_for("enough probe calls") { probe.calls >= 2 }
47
- expect(log).to include("Gathering minutely metrics with 1 probe")
48
- expect(log).to include("Gathering minutely metrics with 'my_probe' probe")
44
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 1 probe")
45
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 'my_probe' probe")
49
46
  end
50
47
  end
51
48
 
@@ -58,8 +55,8 @@ describe Appsignal::Minutely do
58
55
  Appsignal::Minutely.start
59
56
 
60
57
  wait_for("enough probe calls") { probe_instance.calls >= 2 }
61
- expect(log).to include("Gathering minutely metrics with 1 probe")
62
- expect(log).to include("Gathering minutely metrics with 'my_probe' probe")
58
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 1 probe")
59
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 'my_probe' probe")
63
60
  end
64
61
  end
65
62
 
@@ -71,8 +68,8 @@ describe Appsignal::Minutely do
71
68
  Appsignal::Minutely.start
72
69
 
73
70
  wait_for("enough probe calls") { calls >= 2 }
74
- expect(log).to include("Gathering minutely metrics with 1 probe")
75
- expect(log).to include("Gathering minutely metrics with 'my_probe' probe")
71
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 1 probe")
72
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 'my_probe' probe")
76
73
  end
77
74
  end
78
75
 
@@ -87,10 +84,12 @@ describe Appsignal::Minutely do
87
84
  wait_for("enough probe calls") { probe.calls >= 2 }
88
85
  wait_for("enough broken_probe calls") { broken_probe.calls >= 2 }
89
86
 
90
- expect(log).to include("Gathering minutely metrics with 2 probes")
91
- expect(log).to include("Gathering minutely metrics with 'my_probe' probe")
92
- expect(log).to include("Gathering minutely metrics with 'broken_probe' probe")
93
- expect(log).to include("Error in minutely probe 'broken_probe': oh no!")
87
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 2 probes")
88
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 'my_probe' probe")
89
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 'broken_probe' probe")
90
+ expect(log).to contains_log(:error, "Error in minutely probe 'broken_probe': oh no!")
91
+ gem_path = File.expand_path("../../../../", __FILE__) # Start of backtrace
92
+ expect(log).to contains_log(:debug, gem_path)
94
93
  end
95
94
  end
96
95
 
@@ -103,8 +102,8 @@ describe Appsignal::Minutely do
103
102
  end.to change { alive_thread_counter.call }.by(1)
104
103
 
105
104
  wait_for("enough probe calls") { probe.calls >= 2 }
106
- expect(log).to include("Gathering minutely metrics with 1 probe")
107
- expect(log).to include("Gathering minutely metrics with 'my_probe' probe")
105
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 1 probe")
106
+ expect(log).to contains_log(:debug, "Gathering minutely metrics with 'my_probe' probe")
108
107
  expect do
109
108
  # Fetch old thread
110
109
  thread = Appsignal::Minutely.class_variable_get(:@@thread)
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: 2.9.3
4
+ version: 2.9.4
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: 2019-03-29 00:00:00.000000000 Z
12
+ date: 2019-04-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack