appsignal 3.11.0 → 3.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +115 -0
  3. data/Rakefile +1 -1
  4. data/lib/appsignal/cli/diagnose.rb +1 -1
  5. data/lib/appsignal/config.rb +150 -32
  6. data/lib/appsignal/demo.rb +1 -6
  7. data/lib/appsignal/helpers/instrumentation.rb +2 -2
  8. data/lib/appsignal/integrations/grape.rb +7 -0
  9. data/lib/appsignal/integrations/hanami.rb +8 -43
  10. data/lib/appsignal/integrations/padrino.rb +8 -73
  11. data/lib/appsignal/integrations/railtie.rb +35 -13
  12. data/lib/appsignal/integrations/sinatra.rb +8 -19
  13. data/lib/appsignal/loaders/grape.rb +13 -0
  14. data/lib/appsignal/loaders/hanami.rb +40 -0
  15. data/lib/appsignal/loaders/padrino.rb +68 -0
  16. data/lib/appsignal/loaders/sinatra.rb +24 -0
  17. data/lib/appsignal/loaders.rb +92 -0
  18. data/lib/appsignal/rack/abstract_middleware.rb +2 -1
  19. data/lib/appsignal/rack/event_handler.rb +5 -5
  20. data/lib/appsignal/rack.rb +6 -0
  21. data/lib/appsignal/version.rb +1 -1
  22. data/lib/appsignal.rb +163 -9
  23. data/spec/lib/appsignal/cli/demo_spec.rb +0 -1
  24. data/spec/lib/appsignal/cli/diagnose/paths_spec.rb +1 -1
  25. data/spec/lib/appsignal/cli/diagnose_spec.rb +0 -1
  26. data/spec/lib/appsignal/config_spec.rb +153 -1
  27. data/spec/lib/appsignal/demo_spec.rb +1 -2
  28. data/spec/lib/appsignal/environment_spec.rb +4 -2
  29. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +3 -6
  30. data/spec/lib/appsignal/hooks/activejob_spec.rb +3 -3
  31. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +4 -7
  32. data/spec/lib/appsignal/hooks/excon_spec.rb +3 -6
  33. data/spec/lib/appsignal/hooks/gvl_spec.rb +2 -2
  34. data/spec/lib/appsignal/hooks/http_spec.rb +1 -3
  35. data/spec/lib/appsignal/hooks/net_http_spec.rb +1 -1
  36. data/spec/lib/appsignal/hooks/redis_client_spec.rb +5 -8
  37. data/spec/lib/appsignal/hooks/redis_spec.rb +3 -6
  38. data/spec/lib/appsignal/hooks/resque_spec.rb +1 -1
  39. data/spec/lib/appsignal/hooks/sequel_spec.rb +3 -5
  40. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +1 -1
  41. data/spec/lib/appsignal/hooks/webmachine_spec.rb +1 -1
  42. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +2 -2
  43. data/spec/lib/appsignal/integrations/grape_spec.rb +36 -0
  44. data/spec/lib/appsignal/integrations/hanami_spec.rb +9 -178
  45. data/spec/lib/appsignal/integrations/http_spec.rb +1 -5
  46. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +4 -2
  47. data/spec/lib/appsignal/integrations/net_http_spec.rb +1 -1
  48. data/spec/lib/appsignal/integrations/object_spec.rb +1 -3
  49. data/spec/lib/appsignal/integrations/padrino_spec.rb +8 -330
  50. data/spec/lib/appsignal/integrations/railtie_spec.rb +275 -191
  51. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +1 -1
  52. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +11 -9
  53. data/spec/lib/appsignal/integrations/sinatra_spec.rb +9 -104
  54. data/spec/lib/appsignal/loaders/grape_spec.rb +12 -0
  55. data/spec/lib/appsignal/loaders/hanami_spec.rb +95 -0
  56. data/spec/lib/appsignal/loaders/padrino_spec.rb +277 -0
  57. data/spec/lib/appsignal/loaders/sinatra_spec.rb +47 -0
  58. data/spec/lib/appsignal/loaders_spec.rb +137 -0
  59. data/spec/lib/appsignal/probes/sidekiq_spec.rb +1 -1
  60. data/spec/lib/appsignal/probes_spec.rb +6 -5
  61. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +3 -2
  62. data/spec/lib/appsignal/rack/event_handler_spec.rb +33 -0
  63. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +1 -1
  64. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +2 -35
  65. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +1 -1
  66. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +3 -3
  67. data/spec/lib/appsignal/span_spec.rb +1 -3
  68. data/spec/lib/appsignal/transaction_spec.rb +61 -70
  69. data/spec/lib/appsignal_spec.rb +284 -26
  70. data/spec/lib/puma/appsignal_spec.rb +0 -3
  71. data/spec/spec_helper.rb +5 -4
  72. data/spec/support/helpers/config_helpers.rb +2 -1
  73. data/spec/support/helpers/loader_helper.rb +21 -0
  74. data/spec/support/matchers/transaction.rb +3 -2
  75. data/spec/support/stubs/appsignal/loaders/loader_stub.rb +7 -0
  76. data/spec/support/testing.rb +46 -0
  77. metadata +15 -2
@@ -408,13 +408,14 @@ describe Appsignal::Probes do
408
408
  end
409
409
 
410
410
  context "logger" do
411
- let(:log_stream) { std_stream }
412
- let(:log) { log_contents(log_stream) }
411
+ before { start_agent }
413
412
 
414
- around { |example| use_logger_with(log_stream) { example.run } }
415
413
  it "logs a deprecation message" do
416
- silence { collection.register :my_probe, lambda {} }
417
- expect(log).to contains_log :warn,
414
+ logs =
415
+ capture_logs do
416
+ silence { collection.register :my_probe, lambda {} }
417
+ end
418
+ expect(logs).to contains_log :warn,
418
419
  "The method 'Appsignal::Probes.probes.register' is deprecated. " \
419
420
  "Use 'Appsignal::Probes.register' instead."
420
421
  end
@@ -12,7 +12,7 @@ describe Appsignal::Rack::AbstractMiddleware do
12
12
  let(:options) { {} }
13
13
  let(:middleware) { described_class.new(app, options) }
14
14
 
15
- before(:context) { start_agent }
15
+ before { start_agent }
16
16
  around { |example| keep_transactions { example.run } }
17
17
 
18
18
  def make_request
@@ -400,11 +400,12 @@ describe Appsignal::Rack::AbstractMiddleware do
400
400
  expect(response_events).to eq(1)
401
401
  end
402
402
 
403
- context "when response body is already a BodyWrapper subclass" do
403
+ context "when the response body is already instrumented" do
404
404
  let(:body) { Appsignal::Rack::BodyWrapper.wrap(["hello!"], transaction) }
405
405
  let(:app) { DummyApp.new { [200, {}, body] } }
406
406
 
407
407
  it "doesn't wrap the body again" do
408
+ env[Appsignal::Rack::APPSIGNAL_RESPONSE_INSTRUMENTED] = true
408
409
  _status, _headers, body = make_request
409
410
  expect(body).to eq(body)
410
411
 
@@ -40,6 +40,14 @@ describe Appsignal::Rack::EventHandler do
40
40
  expect(Appsignal::Transaction.current).to eq(transaction)
41
41
  end
42
42
 
43
+ context "when not active" do
44
+ it "does not create a new transaction" do
45
+ allow(Appsignal).to receive(:active?).and_return(false)
46
+
47
+ expect { on_start }.to_not(change { created_transactions.length })
48
+ end
49
+ end
50
+
43
51
  context "when the handler is nested in another EventHandler" do
44
52
  it "does not create a new transaction in the nested EventHandler" do
45
53
  on_start
@@ -131,6 +139,17 @@ describe Appsignal::Rack::EventHandler do
131
139
  expect(last_transaction).to have_error("ExampleStandardError", "the error")
132
140
  end
133
141
 
142
+ context "when not active" do
143
+ it "does not report the transaction" do
144
+ allow(Appsignal).to receive(:active?).and_return(false)
145
+
146
+ on_start
147
+ on_error(ExampleStandardError.new("the error"))
148
+
149
+ expect(last_transaction).to_not have_error
150
+ end
151
+ end
152
+
134
153
  context "when the handler is nested in another EventHandler" do
135
154
  it "does not report the error on the transaction" do
136
155
  on_start
@@ -175,6 +194,20 @@ describe Appsignal::Rack::EventHandler do
175
194
  expect(last_transaction).to_not be_completed
176
195
  end
177
196
 
197
+ context "when not active" do
198
+ it "doesn't do anything" do
199
+ allow(Appsignal).to receive(:active?).and_return(false)
200
+
201
+ request.env[Appsignal::Rack::APPSIGNAL_TRANSACTION] = http_request_transaction
202
+ on_finish
203
+
204
+ expect(last_transaction).to_not have_action
205
+ expect(last_transaction).to_not include_events
206
+ expect(last_transaction).to include("sample_data" => {})
207
+ expect(last_transaction).to_not be_completed
208
+ end
209
+ end
210
+
178
211
  it "sets params on the transaction" do
179
212
  on_start
180
213
  on_finish
@@ -46,7 +46,7 @@ describe "Appsignal::Rack::GenericInstrumentation" do
46
46
  let(:env) { Rack::MockRequest.env_for("/some/path") }
47
47
  let(:middleware) { Appsignal::Rack::GenericInstrumentation.new(app, {}) }
48
48
 
49
- before(:context) { start_agent }
49
+ before { start_agent }
50
50
  around { |example| keep_transactions { example.run } }
51
51
 
52
52
  def make_request(env)
@@ -1,38 +1,5 @@
1
1
  if DependencyHelper.grape_present?
2
- require "appsignal/integrations/grape"
3
-
4
- context "Appsignal::Grape::Middleware constant" do
5
- let(:err_stream) { std_stream }
6
- let(:stderr) { err_stream.read }
7
-
8
- it "returns the Rack::GrapeMiddleware constant calling the Grape::Middleware constant" do
9
- silence { expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware) }
10
- end
11
-
12
- it "prints a deprecation warning to STDERR" do
13
- capture_std_streams(std_stream, err_stream) do
14
- expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware)
15
- end
16
-
17
- expect(stderr).to include(
18
- "appsignal WARNING: The constant Appsignal::Grape::Middleware has been deprecated."
19
- )
20
- end
21
-
22
- it "logs a warning" do
23
- logs =
24
- capture_logs do
25
- silence do
26
- expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware)
27
- end
28
- end
29
-
30
- expect(logs).to contains_log(
31
- :warn,
32
- "The constant Appsignal::Grape::Middleware has been deprecated."
33
- )
34
- end
35
- end
2
+ require "appsignal/rack/grape_middleware"
36
3
 
37
4
  describe Appsignal::Rack::GrapeMiddleware do
38
5
  let(:app) do
@@ -52,7 +19,7 @@ if DependencyHelper.grape_present?
52
19
  end
53
20
  let(:middleware) { Appsignal::Rack::GrapeMiddleware.new(api_endpoint) }
54
21
  let(:transaction) { http_request_transaction }
55
- before(:context) { start_agent }
22
+ before { start_agent }
56
23
  around do |example|
57
24
  GrapeExample = Module.new
58
25
  GrapeExample.send(:const_set, :Api, app)
@@ -12,7 +12,7 @@ if DependencyHelper.hanami2_present?
12
12
  end
13
13
  let(:middleware) { Appsignal::Rack::HanamiMiddleware.new(app, {}) }
14
14
 
15
- before(:context) { start_agent }
15
+ before { start_agent }
16
16
  around { |example| keep_transactions { example.run } }
17
17
 
18
18
  def make_request(env)
@@ -1,5 +1,5 @@
1
1
  if DependencyHelper.sinatra_present?
2
- require "appsignal/integrations/sinatra"
2
+ require "appsignal/rack/sinatra_instrumentation"
3
3
 
4
4
  module SinatraRequestHelpers
5
5
  def make_request
@@ -21,7 +21,7 @@ if DependencyHelper.sinatra_present?
21
21
  end
22
22
  let(:middleware) { Appsignal::Rack::SinatraInstrumentation.new(app) }
23
23
 
24
- before(:context) { start_agent }
24
+ before { start_agent }
25
25
  around do |example|
26
26
  keep_transactions { example.run }
27
27
  end
@@ -54,7 +54,7 @@ if DependencyHelper.sinatra_present?
54
54
  let(:options) { {} }
55
55
  let(:middleware) { Appsignal::Rack::SinatraBaseInstrumentation.new(app, options) }
56
56
 
57
- before(:context) { start_agent }
57
+ before { start_agent }
58
58
  around do |example|
59
59
  keep_transactions { example.run }
60
60
  end
@@ -1,9 +1,7 @@
1
1
  require "appsignal/span"
2
2
 
3
3
  describe Appsignal::Span do
4
- before :context do
5
- start_agent
6
- end
4
+ before { start_agent }
7
5
 
8
6
  let(:namespace) { "web" }
9
7
  let(:root) { Appsignal::Span.new(namespace) }
@@ -1,10 +1,12 @@
1
1
  describe Appsignal::Transaction do
2
2
  let(:time) { Time.at(fixed_time) }
3
3
 
4
- before { Timecop.freeze(time) }
4
+ before do
5
+ start_agent
6
+ Timecop.freeze(time)
7
+ end
5
8
  after { Timecop.return }
6
9
  around do |example|
7
- start_agent
8
10
  keep_transactions do
9
11
  example.run
10
12
  end
@@ -1497,54 +1499,53 @@ describe Appsignal::Transaction do
1497
1499
  describe "#set_error" do
1498
1500
  let(:transaction) { new_transaction }
1499
1501
  let(:env) { http_request_env_with_data }
1500
- let(:error) do
1501
- e = ExampleStandardError.new("test message")
1502
- allow(e).to receive(:backtrace).and_return(["line 1"])
1503
- e
1504
- end
1502
+ let(:error) { ExampleStandardError.new("test message") }
1505
1503
 
1506
- it "should also respond to add_exception for backwards compatibility" do
1504
+ it "responds to add_exception for backwards compatibility" do
1507
1505
  expect(transaction).to respond_to(:add_exception)
1508
1506
  end
1509
1507
 
1510
- it "should not add the error if appsignal is not active" do
1508
+ it "does not add the error if not active" do
1511
1509
  allow(Appsignal).to receive(:active?).and_return(false)
1512
- expect(transaction.ext).to_not receive(:set_error)
1513
1510
 
1514
1511
  transaction.set_error(error)
1512
+
1513
+ expect(transaction).to_not have_error
1515
1514
  end
1516
1515
 
1517
- context "when error is not an error" do
1516
+ context "when error argument is not an error" do
1518
1517
  let(:error) { Object.new }
1519
1518
 
1520
1519
  it "does not add the error" do
1521
- expect(Appsignal.internal_logger).to receive(:error).with(
1520
+ logs = capture_logs { transaction.set_error(error) }
1521
+
1522
+ expect(transaction).to_not have_error
1523
+ expect(logs).to contains_log(
1524
+ :error,
1522
1525
  "Appsignal::Transaction#set_error: Cannot set error. " \
1523
1526
  "The given value is not an exception: #{error.inspect}"
1524
1527
  )
1525
- expect(transaction.ext).to_not receive(:set_error)
1526
-
1527
- transaction.set_error(error)
1528
1528
  end
1529
1529
  end
1530
1530
 
1531
1531
  context "for a http request" do
1532
- it "should set an error in the extension" do
1533
- expect(transaction.ext).to receive(:set_error).with(
1532
+ it "sets an error on the transaction" do
1533
+ allow(error).to receive(:backtrace).and_return(["line 1"])
1534
+ transaction.set_error(error)
1535
+
1536
+ expect(transaction).to have_error(
1534
1537
  "ExampleStandardError",
1535
1538
  "test message",
1536
- Appsignal::Utils::Data.generate(["line 1"])
1539
+ ["line 1"]
1537
1540
  )
1538
-
1539
- transaction.set_error(error)
1540
1541
  end
1541
1542
  end
1542
1543
 
1543
1544
  context "when the error has no causes" do
1544
- it "should not send the causes information as sample data" do
1545
- expect(transaction.ext).to_not receive(:set_sample_data)
1546
-
1545
+ it "does not set the causes information as sample data" do
1547
1546
  transaction.set_error(error)
1547
+
1548
+ expect(transaction).to_not include_error_causes
1548
1549
  end
1549
1550
  end
1550
1551
 
@@ -1560,31 +1561,25 @@ describe Appsignal::Transaction do
1560
1561
  end
1561
1562
 
1562
1563
  it "sends the causes information as sample data" do
1563
- expect(transaction.ext).to receive(:set_error).with(
1564
+ transaction.set_error(error)
1565
+
1566
+ expect(transaction).to have_error(
1564
1567
  "ExampleStandardError",
1565
1568
  "test message",
1566
- Appsignal::Utils::Data.generate(["line 1"])
1569
+ ["line 1"]
1567
1570
  )
1568
-
1569
- expect(transaction.ext).to receive(:set_sample_data).with(
1570
- "error_causes",
1571
- Appsignal::Utils::Data.generate(
1572
- [
1573
- {
1574
- :name => "RuntimeError",
1575
- :message => "cause message"
1576
- },
1577
- {
1578
- :name => "StandardError",
1579
- :message => "cause message 2"
1580
- }
1581
- ]
1582
- )
1571
+ expect(transaction).to include_error_causes(
1572
+ [
1573
+ {
1574
+ "name" => "RuntimeError",
1575
+ "message" => "cause message"
1576
+ },
1577
+ {
1578
+ "name" => "StandardError",
1579
+ "message" => "cause message 2"
1580
+ }
1581
+ ]
1583
1582
  )
1584
-
1585
- expect(Appsignal.internal_logger).to_not receive(:debug)
1586
-
1587
- transaction.set_error(error)
1588
1583
  end
1589
1584
  end
1590
1585
 
@@ -1603,33 +1598,29 @@ describe Appsignal::Transaction do
1603
1598
  end
1604
1599
 
1605
1600
  it "sends only the first causes as sample data" do
1606
- expect(transaction.ext).to receive(:set_error).with(
1607
- "ExampleStandardError",
1608
- "wrapper error 10",
1609
- Appsignal::Utils::Data.generate(["line 1"])
1610
- )
1611
-
1612
- expected_error_causes = Array.new(10) do |i|
1613
- {
1614
- :name => "ExampleStandardError",
1615
- :message => "wrapper error #{9 - i}"
1616
- }
1617
- end
1601
+ expected_error_causes =
1602
+ Array.new(10) do |i|
1603
+ {
1604
+ "name" => "ExampleStandardError",
1605
+ "message" => "wrapper error #{9 - i}"
1606
+ }
1607
+ end
1608
+ expected_error_causes.last["is_root_cause"] = false
1618
1609
 
1619
- expected_error_causes.last[:is_root_cause] = false
1610
+ logs = capture_logs { transaction.set_error(error) }
1620
1611
 
1621
- expect(transaction.ext).to receive(:set_sample_data).with(
1622
- "error_causes",
1623
- Appsignal::Utils::Data.generate(expected_error_causes)
1612
+ expect(transaction).to have_error(
1613
+ "ExampleStandardError",
1614
+ "wrapper error 10",
1615
+ ["line 1"]
1624
1616
  )
1625
-
1626
- expect(Appsignal.internal_logger).to receive(:debug).with(
1617
+ expect(transaction).to include_error_causes(expected_error_causes)
1618
+ expect(logs).to contains_log(
1619
+ :debug,
1627
1620
  "Appsignal::Transaction#set_error: Error has more " \
1628
1621
  "than 10 error causes. Only the first 10 " \
1629
1622
  "will be reported."
1630
1623
  )
1631
-
1632
- transaction.set_error(error)
1633
1624
  end
1634
1625
  end
1635
1626
 
@@ -1641,18 +1632,18 @@ describe Appsignal::Transaction do
1641
1632
  e
1642
1633
  end
1643
1634
 
1644
- it "should not raise an error" do
1635
+ it "does not raise an error" do
1645
1636
  transaction.set_error(error)
1646
1637
  end
1647
1638
 
1648
- it "should set an error in the extension" do
1649
- expect(transaction.ext).to receive(:set_error).with(
1639
+ it "sets an error on the transaction without an error message" do
1640
+ transaction.set_error(error)
1641
+
1642
+ expect(transaction).to have_error(
1650
1643
  "ExampleStandardError",
1651
1644
  "",
1652
- Appsignal::Utils::Data.generate(["line 1"])
1645
+ ["line 1"]
1653
1646
  )
1654
-
1655
- transaction.set_error(error)
1656
1647
  end
1657
1648
  end
1658
1649
  end