appsignal 3.10.0-java → 3.12.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +197 -0
  4. data/Gemfile +1 -0
  5. data/Rakefile +1 -1
  6. data/benchmark.rake +99 -42
  7. data/lib/appsignal/cli/demo.rb +0 -1
  8. data/lib/appsignal/cli/diagnose.rb +1 -1
  9. data/lib/appsignal/config.rb +204 -130
  10. data/lib/appsignal/demo.rb +16 -26
  11. data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
  12. data/lib/appsignal/event_formatter.rb +3 -2
  13. data/lib/appsignal/helpers/instrumentation.rb +331 -19
  14. data/lib/appsignal/hooks/action_cable.rb +21 -16
  15. data/lib/appsignal/hooks/active_job.rb +14 -8
  16. data/lib/appsignal/hooks/delayed_job.rb +1 -1
  17. data/lib/appsignal/hooks/shoryuken.rb +3 -63
  18. data/lib/appsignal/integrations/action_cable.rb +5 -7
  19. data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
  20. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
  21. data/lib/appsignal/integrations/data_mapper.rb +1 -0
  22. data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
  23. data/lib/appsignal/integrations/dry_monitor.rb +1 -0
  24. data/lib/appsignal/integrations/excon.rb +1 -0
  25. data/lib/appsignal/integrations/grape.rb +7 -0
  26. data/lib/appsignal/integrations/hanami.rb +8 -43
  27. data/lib/appsignal/integrations/http.rb +1 -0
  28. data/lib/appsignal/integrations/net_http.rb +1 -0
  29. data/lib/appsignal/integrations/object.rb +6 -0
  30. data/lib/appsignal/integrations/padrino.rb +8 -73
  31. data/lib/appsignal/integrations/que.rb +13 -20
  32. data/lib/appsignal/integrations/railtie.rb +36 -14
  33. data/lib/appsignal/integrations/rake.rb +1 -5
  34. data/lib/appsignal/integrations/redis.rb +1 -0
  35. data/lib/appsignal/integrations/redis_client.rb +1 -0
  36. data/lib/appsignal/integrations/resque.rb +2 -5
  37. data/lib/appsignal/integrations/shoryuken.rb +75 -0
  38. data/lib/appsignal/integrations/sidekiq.rb +7 -15
  39. data/lib/appsignal/integrations/sinatra.rb +8 -19
  40. data/lib/appsignal/integrations/unicorn.rb +1 -0
  41. data/lib/appsignal/integrations/webmachine.rb +2 -5
  42. data/lib/appsignal/loaders/grape.rb +13 -0
  43. data/lib/appsignal/loaders/hanami.rb +40 -0
  44. data/lib/appsignal/loaders/padrino.rb +68 -0
  45. data/lib/appsignal/loaders/sinatra.rb +24 -0
  46. data/lib/appsignal/loaders.rb +92 -0
  47. data/lib/appsignal/logger.rb +7 -3
  48. data/lib/appsignal/probes/helpers.rb +1 -0
  49. data/lib/appsignal/probes/mri.rb +1 -0
  50. data/lib/appsignal/probes/sidekiq.rb +1 -0
  51. data/lib/appsignal/probes.rb +3 -0
  52. data/lib/appsignal/rack/abstract_middleware.rb +20 -13
  53. data/lib/appsignal/rack/event_handler.rb +44 -13
  54. data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
  55. data/lib/appsignal/rack/grape_middleware.rb +2 -1
  56. data/lib/appsignal/rack/streaming_listener.rb +1 -0
  57. data/lib/appsignal/rack.rb +35 -0
  58. data/lib/appsignal/span.rb +1 -0
  59. data/lib/appsignal/transaction.rb +308 -101
  60. data/lib/appsignal/utils/data.rb +0 -1
  61. data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
  62. data/lib/appsignal/utils/integration_logger.rb +0 -13
  63. data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
  64. data/lib/appsignal/utils/json.rb +0 -1
  65. data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
  66. data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
  67. data/lib/appsignal/utils.rb +6 -0
  68. data/lib/appsignal/version.rb +1 -1
  69. data/lib/appsignal.rb +169 -14
  70. data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
  71. data/spec/lib/appsignal/cli/demo_spec.rb +0 -1
  72. data/spec/lib/appsignal/cli/diagnose/paths_spec.rb +1 -1
  73. data/spec/lib/appsignal/cli/diagnose_spec.rb +0 -1
  74. data/spec/lib/appsignal/config_spec.rb +291 -44
  75. data/spec/lib/appsignal/demo_spec.rb +1 -2
  76. data/spec/lib/appsignal/environment_spec.rb +4 -2
  77. data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
  78. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +3 -6
  79. data/spec/lib/appsignal/hooks/activejob_spec.rb +12 -3
  80. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
  81. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +4 -7
  82. data/spec/lib/appsignal/hooks/excon_spec.rb +3 -6
  83. data/spec/lib/appsignal/hooks/gvl_spec.rb +2 -2
  84. data/spec/lib/appsignal/hooks/http_spec.rb +1 -3
  85. data/spec/lib/appsignal/hooks/net_http_spec.rb +1 -1
  86. data/spec/lib/appsignal/hooks/redis_client_spec.rb +5 -8
  87. data/spec/lib/appsignal/hooks/redis_spec.rb +3 -6
  88. data/spec/lib/appsignal/hooks/resque_spec.rb +1 -1
  89. data/spec/lib/appsignal/hooks/sequel_spec.rb +3 -5
  90. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
  91. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +1 -1
  92. data/spec/lib/appsignal/hooks/webmachine_spec.rb +1 -1
  93. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
  94. data/spec/lib/appsignal/integrations/grape_spec.rb +36 -0
  95. data/spec/lib/appsignal/integrations/hanami_spec.rb +9 -178
  96. data/spec/lib/appsignal/integrations/http_spec.rb +1 -5
  97. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +4 -2
  98. data/spec/lib/appsignal/integrations/net_http_spec.rb +1 -1
  99. data/spec/lib/appsignal/integrations/object_spec.rb +1 -3
  100. data/spec/lib/appsignal/integrations/padrino_spec.rb +8 -330
  101. data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
  102. data/spec/lib/appsignal/integrations/railtie_spec.rb +275 -191
  103. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
  104. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +15 -13
  105. data/spec/lib/appsignal/integrations/sinatra_spec.rb +9 -104
  106. data/spec/lib/appsignal/integrations/webmachine_spec.rb +13 -1
  107. data/spec/lib/appsignal/loaders/grape_spec.rb +12 -0
  108. data/spec/lib/appsignal/loaders/hanami_spec.rb +95 -0
  109. data/spec/lib/appsignal/loaders/padrino_spec.rb +277 -0
  110. data/spec/lib/appsignal/loaders/sinatra_spec.rb +47 -0
  111. data/spec/lib/appsignal/loaders_spec.rb +137 -0
  112. data/spec/lib/appsignal/probes/sidekiq_spec.rb +1 -1
  113. data/spec/lib/appsignal/probes_spec.rb +6 -5
  114. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +51 -5
  115. data/spec/lib/appsignal/rack/event_handler_spec.rb +114 -10
  116. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +1 -1
  117. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +2 -35
  118. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +1 -1
  119. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
  120. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +3 -3
  121. data/spec/lib/appsignal/rack_spec.rb +63 -0
  122. data/spec/lib/appsignal/span_spec.rb +1 -3
  123. data/spec/lib/appsignal/transaction_spec.rb +1640 -1075
  124. data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
  125. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
  126. data/spec/lib/appsignal_spec.rb +601 -36
  127. data/spec/lib/puma/appsignal_spec.rb +0 -3
  128. data/spec/spec_helper.rb +5 -4
  129. data/spec/support/helpers/config_helpers.rb +2 -1
  130. data/spec/support/helpers/loader_helper.rb +21 -0
  131. data/spec/support/helpers/transaction_helpers.rb +44 -20
  132. data/spec/support/matchers/transaction.rb +15 -1
  133. data/spec/support/stubs/appsignal/loaders/loader_stub.rb +7 -0
  134. data/spec/support/testing.rb +47 -1
  135. metadata +19 -2
@@ -0,0 +1,167 @@
1
+ require "appsignal/integrations/shoryuken"
2
+
3
+ describe Appsignal::Integrations::ShoryukenMiddleware do
4
+ class DemoShoryukenWorker
5
+ end
6
+
7
+ let(:time) { "2010-01-01 10:01:00UTC" }
8
+ let(:worker_instance) { DemoShoryukenWorker.new }
9
+ let(:queue) { "some-funky-queue-name" }
10
+ let(:sqs_msg) { double(:message_id => "msg1", :attributes => {}) }
11
+ let(:body) { {} }
12
+ before { start_agent }
13
+ around { |example| keep_transactions { example.run } }
14
+
15
+ def perform_shoryuken_job(&block)
16
+ block ||= lambda {}
17
+ Timecop.freeze(Time.parse(time)) do
18
+ described_class.new.call(
19
+ worker_instance,
20
+ queue,
21
+ sqs_msg,
22
+ body,
23
+ &block
24
+ )
25
+ end
26
+ end
27
+
28
+ context "with a performance call" do
29
+ let(:sent_timestamp) { Time.parse("1976-11-18 0:00:00UTC").to_i * 1000 }
30
+ let(:sqs_msg) do
31
+ double(:message_id => "msg1", :attributes => { "SentTimestamp" => sent_timestamp })
32
+ end
33
+
34
+ context "with complex argument" do
35
+ let(:body) { { :foo => "Foo", :bar => "Bar" } }
36
+
37
+ it "wraps the job in a transaction with the correct params" do
38
+ expect { perform_shoryuken_job }.to change { created_transactions.length }.by(1)
39
+
40
+ transaction = last_transaction
41
+ expect(transaction).to have_id
42
+ expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
43
+ expect(transaction).to have_action("DemoShoryukenWorker#perform")
44
+ expect(transaction).to_not have_error
45
+ expect(transaction).to include_event(
46
+ "body" => "",
47
+ "body_format" => Appsignal::EventFormatter::DEFAULT,
48
+ "count" => 1,
49
+ "name" => "perform_job.shoryuken",
50
+ "title" => ""
51
+ )
52
+ expect(transaction).to include_params("foo" => "Foo", "bar" => "Bar")
53
+ expect(transaction).to include_tags(
54
+ "message_id" => "msg1",
55
+ "queue" => queue,
56
+ "SentTimestamp" => sent_timestamp
57
+ )
58
+ expect(transaction).to have_queue_start(sent_timestamp)
59
+ expect(transaction).to be_completed
60
+ end
61
+
62
+ context "with parameter filtering" do
63
+ before do
64
+ start_agent("production")
65
+ Appsignal.config[:filter_parameters] = ["foo"]
66
+ end
67
+
68
+ it "filters selected arguments" do
69
+ perform_shoryuken_job
70
+
71
+ expect(last_transaction).to include_params("foo" => "[FILTERED]", "bar" => "Bar")
72
+ end
73
+ end
74
+ end
75
+
76
+ context "with a string as an argument" do
77
+ let(:body) { "foo bar" }
78
+
79
+ it "handles string arguments" do
80
+ perform_shoryuken_job
81
+
82
+ expect(last_transaction).to include_params("params" => body)
83
+ end
84
+ end
85
+
86
+ context "with primitive type as argument" do
87
+ let(:body) { 1 }
88
+
89
+ it "handles primitive types as arguments" do
90
+ perform_shoryuken_job
91
+
92
+ expect(last_transaction).to include_params("params" => body)
93
+ end
94
+ end
95
+ end
96
+
97
+ context "with exception" do
98
+ it "sets the exception on the transaction" do
99
+ expect do
100
+ expect do
101
+ perform_shoryuken_job { raise ExampleException, "error message" }
102
+ end.to raise_error(ExampleException)
103
+ end.to change { created_transactions.length }.by(1)
104
+
105
+ transaction = last_transaction
106
+ expect(transaction).to have_id
107
+ expect(transaction).to have_action("DemoShoryukenWorker#perform")
108
+ expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
109
+ expect(transaction).to have_error("ExampleException", "error message")
110
+ expect(transaction).to be_completed
111
+ end
112
+ end
113
+
114
+ context "with batched jobs" do
115
+ let(:sqs_msg) do
116
+ [
117
+ double(
118
+ :message_id => "msg2",
119
+ :attributes => {
120
+ "SentTimestamp" => (Time.parse("1976-11-18 01:00:00UTC").to_i * 1000).to_s
121
+ }
122
+ ),
123
+ double(
124
+ :message_id => "msg1",
125
+ :attributes => { "SentTimestamp" => sent_timestamp.to_s }
126
+ )
127
+ ]
128
+ end
129
+ let(:body) do
130
+ [
131
+ "foo bar",
132
+ { :id => "123", :foo => "Foo", :bar => "Bar" }
133
+ ]
134
+ end
135
+ let(:sent_timestamp) { Time.parse("1976-11-18 01:00:00UTC").to_i * 1000 }
136
+
137
+ it "creates a transaction for the batch" do
138
+ expect do
139
+ perform_shoryuken_job {} # rubocop:disable Lint/EmptyBlock
140
+ end.to change { created_transactions.length }.by(1)
141
+
142
+ transaction = last_transaction
143
+ expect(transaction).to have_id
144
+ expect(transaction).to have_action("DemoShoryukenWorker#perform")
145
+ expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
146
+ expect(transaction).to_not have_error
147
+ expect(transaction).to include_event(
148
+ "body" => "",
149
+ "body_format" => Appsignal::EventFormatter::DEFAULT,
150
+ "count" => 1,
151
+ "name" => "perform_job.shoryuken",
152
+ "title" => ""
153
+ )
154
+ expect(transaction).to include_params(
155
+ "msg2" => "foo bar",
156
+ "msg1" => { "id" => "123", "foo" => "Foo", "bar" => "Bar" }
157
+ )
158
+ expect(transaction).to include_tags(
159
+ "batch" => true,
160
+ "queue" => "some-funky-queue-name",
161
+ "SentTimestamp" => sent_timestamp.to_s # Earliest/oldest timestamp from messages
162
+ )
163
+ # Queue time based on earliest/oldest timestamp from messages
164
+ expect(transaction).to have_queue_start(sent_timestamp)
165
+ end
166
+ end
167
+ end
@@ -243,7 +243,7 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
243
243
 
244
244
  context "with parameter filtering" do
245
245
  before do
246
- Appsignal.config = project_fixture_config("production")
246
+ start_agent("production")
247
247
  Appsignal.config[:filter_parameters] = ["foo"]
248
248
  end
249
249
 
@@ -362,7 +362,7 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
362
362
  perform_sidekiq_job { raise error, "uh oh" }
363
363
  end.to raise_error(error)
364
364
 
365
- expect(transaction).to have_id(jid)
365
+ expect(transaction).to have_id
366
366
  expect(transaction).to have_namespace(namespace)
367
367
  expect(transaction).to have_action("TestClass#perform")
368
368
  expect(transaction).to have_error("ExampleException", "uh oh")
@@ -373,7 +373,7 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
373
373
  )
374
374
  expect(transaction).to_not include_environment
375
375
  expect(transaction).to include_params(expected_args)
376
- expect(transaction).to_not include_tags
376
+ expect(transaction).to include_tags("request_id" => jid)
377
377
  expect(transaction).to_not include_breadcrumbs
378
378
  expect_transaction_to_have_sidekiq_event(transaction)
379
379
  end
@@ -384,7 +384,7 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
384
384
  include RailsHelper
385
385
 
386
386
  it "reports the worker name as the action, copies the namespace and tags" do
387
- Appsignal.config = project_fixture_config("production")
387
+ start_agent("production")
388
388
  with_rails_error_reporter do
389
389
  perform_sidekiq_job do
390
390
  Appsignal.tag_job("test_tag" => "value")
@@ -418,11 +418,11 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
418
418
  .with("sidekiq_queue_job_count", 1, { :queue => "default", :status => :processed })
419
419
  perform_sidekiq_job
420
420
 
421
- expect(transaction).to have_id(jid)
421
+ expect(transaction).to have_id
422
422
  expect(transaction).to have_namespace(namespace)
423
423
  expect(transaction).to have_action("TestClass#perform")
424
424
  expect(transaction).to_not have_error
425
- expect(transaction).to_not include_tags
425
+ expect(transaction).to include_tags("request_id" => jid)
426
426
  expect(transaction).to_not include_environment
427
427
  expect(transaction).to_not include_breadcrumbs
428
428
  expect(transaction).to_not include_params(expected_args)
@@ -527,6 +527,15 @@ if DependencyHelper.active_job_present?
527
527
  end
528
528
  end
529
529
  around do |example|
530
+ with_rails_error_reporter do
531
+ keep_transactions do
532
+ Sidekiq::Testing.fake! do
533
+ example.run
534
+ end
535
+ end
536
+ end
537
+ end
538
+ before do
530
539
  start_agent
531
540
  Appsignal.internal_logger = test_logger(log)
532
541
  ActiveJob::Base.queue_adapter = :sidekiq
@@ -551,13 +560,6 @@ if DependencyHelper.active_job_present?
551
560
  Sidekiq::Testing.server_middleware do |chain|
552
561
  chain.add Appsignal::Integrations::SidekiqMiddleware
553
562
  end
554
- with_rails_error_reporter do
555
- keep_transactions do
556
- Sidekiq::Testing.fake! do
557
- example.run
558
- end
559
- end
560
- end
561
563
  end
562
564
  after do
563
565
  Object.send(:remove_const, :ActiveJobSidekiqTestJob)
@@ -1,110 +1,15 @@
1
- if DependencyHelper.sinatra_present?
2
- require "appsignal/integrations/sinatra"
3
-
4
- def install_sinatra_integration
5
- load File.expand_path("lib/appsignal/integrations/sinatra.rb", project_dir)
6
- end
7
-
8
- # "Uninstall" the AppSignal integration
9
- def uninstall_sinatra_integration
10
- expected_middleware = [
11
- Rack::Events,
12
- Appsignal::Rack::SinatraBaseInstrumentation
13
- ]
14
- Sinatra::Base.instance_variable_get(:@middleware).delete_if do |middleware|
15
- expected_middleware.include?(middleware.first)
16
- end
17
- end
18
-
1
+ if DependencyHelper.padrino_present?
19
2
  describe "Sinatra integration" do
20
- before do
21
- Appsignal.config = nil
22
- end
23
- after { uninstall_sinatra_integration }
24
-
25
- context "when active" do
26
- before { allow(Appsignal).to receive(:active?).and_return(true) }
27
-
28
- it "does not start AppSignal again" do
29
- expect(Appsignal::Config).to_not receive(:new)
30
- expect(Appsignal).to_not receive(:start)
31
- install_sinatra_integration
32
- end
33
-
34
- it "adds the instrumentation middleware to Sinatra::Base" do
35
- install_sinatra_integration
36
- middlewares = Sinatra::Base.middleware.to_a
37
- expect(middlewares).to include(
38
- [Rack::Events, [[instance_of(Appsignal::Rack::EventHandler)]], nil]
39
- )
40
- expect(middlewares).to include(
41
- [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
42
- )
43
- end
44
- end
45
-
46
- context "when not active" do
47
- context "Appsignal.internal_logger" do
48
- subject { Appsignal.internal_logger }
49
-
50
- it "sets a logger" do
51
- install_sinatra_integration
52
- is_expected.to be_a Logger
53
- end
54
- end
55
-
56
- describe "middleware" do
57
- context "when AppSignal is not active" do
58
- it "does not add the instrumentation middleware to Sinatra::Base" do
59
- install_sinatra_integration
60
- middlewares = Sinatra::Base.middleware.to_a
61
- expect(middlewares).to_not include(
62
- [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
63
- )
64
- expect(middlewares).to_not include(
65
- [Rack::Events, [Appsignal::Rack::EventHandler], nil]
66
- )
67
- end
68
- end
69
-
70
- context "when the new AppSignal config is active" do
71
- it "adds the instrumentation middleware to Sinatra::Base" do
72
- ENV["APPSIGNAL_APP_NAME"] = "My Sinatra app name"
73
- ENV["APPSIGNAL_APP_ENV"] = "test"
74
- ENV["APPSIGNAL_PUSH_API_KEY"] = "my-key"
75
-
76
- install_sinatra_integration
77
- middlewares = Sinatra::Base.middleware.to_a
78
- expect(middlewares).to include(
79
- [Rack::Events, [[Appsignal::Rack::EventHandler]], nil],
80
- [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
81
- )
82
- end
83
- end
84
- end
85
-
86
- describe "environment" do
87
- subject { Appsignal.config.env }
88
-
89
- context "without APPSIGNAL_APP_ENV" do
90
- before { install_sinatra_integration }
91
-
92
- it "uses the app environment" do
93
- expect(subject).to eq("test")
94
- end
95
- end
3
+ it "loads the Sinatra loader" do
4
+ ENV["APPSIGNAL_APP_NAME"] = "test/sinatra"
5
+ ENV["APPSIGNAL_PUSH_API_KEY"] = "test-key"
96
6
 
97
- context "with APPSIGNAL_APP_ENV" do
98
- before do
99
- ENV["APPSIGNAL_APP_ENV"] = "env-staging"
100
- install_sinatra_integration
101
- end
7
+ require "appsignal/integrations/sinatra"
102
8
 
103
- it "uses the environment variable" do
104
- expect(subject).to eq("env-staging")
105
- end
106
- end
107
- end
9
+ expect(Appsignal::Loaders.instances).to include(
10
+ :sinatra => kind_of(Appsignal::Loaders::SinatraLoader)
11
+ )
12
+ expect(Appsignal.active?).to be(true)
108
13
  end
109
14
  end
110
15
  end
@@ -18,7 +18,11 @@ if DependencyHelper.webmachine_present?
18
18
  Webmachine::Request.new(
19
19
  "GET",
20
20
  "http://google.com:80/foo?param1=value1&param2=value2",
21
- {},
21
+ {
22
+ "REQUEST_METHOD" => "GET",
23
+ "PATH_INFO" => "/some/path",
24
+ "ignored_header" => "something"
25
+ },
22
26
  nil
23
27
  )
24
28
  end
@@ -81,6 +85,14 @@ if DependencyHelper.webmachine_present?
81
85
  expect(last_transaction).to include_params("param1" => "value1", "param2" => "value2")
82
86
  end
83
87
 
88
+ it "sets the headers" do
89
+ fsm.run
90
+ expect(last_transaction).to include_environment(
91
+ "REQUEST_METHOD" => "GET",
92
+ "PATH_INFO" => "/some/path"
93
+ )
94
+ end
95
+
84
96
  it "closes the transaction" do
85
97
  fsm.run
86
98
  expect(last_transaction).to be_completed
@@ -0,0 +1,12 @@
1
+ if DependencyHelper.grape_present?
2
+ describe "Appsignal::Loaders::PadrinoLoader" do
3
+ describe "#on_load" do
4
+ it "ensures the Grape middleware is loaded" do
5
+ load_loader(:grape)
6
+
7
+ # Calling this doesn't raise a NameError
8
+ Appsignal::Rack::GrapeMiddleware
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,95 @@
1
+ if DependencyHelper.hanami_present?
2
+ describe "Appsignal::Loaders::HanamiLoader" do
3
+ before { Appsignal.config = nil }
4
+
5
+ describe "#on_load" do
6
+ it "registers Hanami default config" do
7
+ load_loader(:hanami)
8
+
9
+ expect(Appsignal::Config.loader_defaults).to include([
10
+ :hanami,
11
+ {
12
+ :env => :test,
13
+ :root_path => Dir.pwd
14
+ }
15
+ ])
16
+ end
17
+ end
18
+
19
+ describe "#on_start" do
20
+ before do
21
+ allow(::Hanami::Action).to receive(:prepend)
22
+ load_loader(:hanami)
23
+ start_loader(:hanami)
24
+ end
25
+ after { uninstall_hanami_middleware }
26
+
27
+ def uninstall_hanami_middleware
28
+ middleware_stack = ::Hanami.app.config.middleware.stack[::Hanami::Router::DEFAULT_PREFIX]
29
+ middleware_stack.delete_if do |middleware|
30
+ middleware.first == Appsignal::Rack::HanamiMiddleware ||
31
+ middleware.first == Rack::Events
32
+ end
33
+ end
34
+
35
+ it "adds the instrumentation middleware to Sinatra::Base" do
36
+ expect(::Hanami.app.config.middleware.stack[::Hanami::Router::DEFAULT_PREFIX])
37
+ .to include(
38
+ [Rack::Events, [[kind_of(Appsignal::Rack::EventHandler)]], *hanami_middleware_options],
39
+ [Appsignal::Rack::HanamiMiddleware, [], *hanami_middleware_options]
40
+ )
41
+ end
42
+
43
+ it "prepends the integration to Hanami::Action" do
44
+ expect(::Hanami::Action)
45
+ .to have_received(:prepend).with(Appsignal::Loaders::HanamiLoader::HanamiIntegration)
46
+ end
47
+
48
+ def hanami_middleware_options
49
+ if DependencyHelper.hanami2_1_present?
50
+ [{}, nil]
51
+ else
52
+ [nil]
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "Appsignal::Loaders::HanamiLoader::HanamiIntegration" do
58
+ let(:transaction) { http_request_transaction }
59
+ let(:app) { HanamiApp::Actions::Books::Index }
60
+ around { |example| keep_transactions { example.run } }
61
+ before do
62
+ expect(::Hanami.app.config).to receive(:root).and_return(project_fixture_path)
63
+ Appsignal.load(:hanami)
64
+ start_agent
65
+ end
66
+
67
+ def make_request(env)
68
+ action = app.new
69
+ action.call(env)
70
+ end
71
+
72
+ describe "#call" do
73
+ context "without an active transaction" do
74
+ let(:env) { {} }
75
+
76
+ it "does not set the action name" do
77
+ make_request(env)
78
+
79
+ expect(transaction).to_not have_action
80
+ end
81
+ end
82
+
83
+ context "with an active transaction" do
84
+ let(:env) { { Appsignal::Rack::APPSIGNAL_TRANSACTION => transaction } }
85
+
86
+ it "sets action name on the transaction" do
87
+ make_request(env)
88
+
89
+ expect(transaction).to have_action("HanamiApp::Actions::Books::Index")
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end