appsignal 2.5.0.alpha.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.rspec +4 -0
  4. data/.rubocop.yml +66 -0
  5. data/.rubocop_todo.yml +124 -0
  6. data/.travis.yml +72 -0
  7. data/.yardopts +8 -0
  8. data/CHANGELOG.md +639 -0
  9. data/Gemfile +3 -0
  10. data/LICENSE +20 -0
  11. data/README.md +264 -0
  12. data/Rakefile +214 -0
  13. data/appsignal.gemspec +42 -0
  14. data/benchmark.rake +77 -0
  15. data/bin/appsignal +13 -0
  16. data/ext/Rakefile +27 -0
  17. data/ext/agent.yml +64 -0
  18. data/ext/appsignal_extension.c +692 -0
  19. data/ext/base.rb +79 -0
  20. data/ext/extconf.rb +35 -0
  21. data/gemfiles/capistrano2.gemfile +7 -0
  22. data/gemfiles/capistrano3.gemfile +7 -0
  23. data/gemfiles/grape.gemfile +7 -0
  24. data/gemfiles/no_dependencies.gemfile +5 -0
  25. data/gemfiles/padrino.gemfile +7 -0
  26. data/gemfiles/que.gemfile +5 -0
  27. data/gemfiles/rails-3.2.gemfile +6 -0
  28. data/gemfiles/rails-4.0.gemfile +6 -0
  29. data/gemfiles/rails-4.1.gemfile +6 -0
  30. data/gemfiles/rails-4.2.gemfile +10 -0
  31. data/gemfiles/rails-5.0.gemfile +5 -0
  32. data/gemfiles/rails-5.1.gemfile +5 -0
  33. data/gemfiles/resque.gemfile +12 -0
  34. data/gemfiles/sequel-435.gemfile +11 -0
  35. data/gemfiles/sequel.gemfile +11 -0
  36. data/gemfiles/sinatra.gemfile +6 -0
  37. data/gemfiles/webmachine.gemfile +5 -0
  38. data/lib/appsignal.rb +804 -0
  39. data/lib/appsignal/auth_check.rb +65 -0
  40. data/lib/appsignal/capistrano.rb +10 -0
  41. data/lib/appsignal/cli.rb +108 -0
  42. data/lib/appsignal/cli/demo.rb +63 -0
  43. data/lib/appsignal/cli/diagnose.rb +500 -0
  44. data/lib/appsignal/cli/helpers.rb +72 -0
  45. data/lib/appsignal/cli/install.rb +277 -0
  46. data/lib/appsignal/cli/notify_of_deploy.rb +113 -0
  47. data/lib/appsignal/config.rb +287 -0
  48. data/lib/appsignal/demo.rb +107 -0
  49. data/lib/appsignal/event_formatter.rb +74 -0
  50. data/lib/appsignal/event_formatter/action_view/render_formatter.rb +24 -0
  51. data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +14 -0
  52. data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +14 -0
  53. data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +32 -0
  54. data/lib/appsignal/event_formatter/faraday/request_formatter.rb +19 -0
  55. data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +89 -0
  56. data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
  57. data/lib/appsignal/extension.rb +63 -0
  58. data/lib/appsignal/extension/jruby.rb +460 -0
  59. data/lib/appsignal/garbage_collection_profiler.rb +48 -0
  60. data/lib/appsignal/hooks.rb +105 -0
  61. data/lib/appsignal/hooks/action_cable.rb +113 -0
  62. data/lib/appsignal/hooks/active_support_notifications.rb +52 -0
  63. data/lib/appsignal/hooks/celluloid.rb +30 -0
  64. data/lib/appsignal/hooks/data_mapper.rb +18 -0
  65. data/lib/appsignal/hooks/delayed_job.rb +19 -0
  66. data/lib/appsignal/hooks/mongo_ruby_driver.rb +21 -0
  67. data/lib/appsignal/hooks/net_http.rb +29 -0
  68. data/lib/appsignal/hooks/passenger.rb +22 -0
  69. data/lib/appsignal/hooks/puma.rb +35 -0
  70. data/lib/appsignal/hooks/que.rb +21 -0
  71. data/lib/appsignal/hooks/rake.rb +39 -0
  72. data/lib/appsignal/hooks/redis.rb +30 -0
  73. data/lib/appsignal/hooks/sequel.rb +60 -0
  74. data/lib/appsignal/hooks/shoryuken.rb +43 -0
  75. data/lib/appsignal/hooks/sidekiq.rb +144 -0
  76. data/lib/appsignal/hooks/unicorn.rb +40 -0
  77. data/lib/appsignal/hooks/webmachine.rb +23 -0
  78. data/lib/appsignal/integrations/capistrano/appsignal.cap +39 -0
  79. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +52 -0
  80. data/lib/appsignal/integrations/data_mapper.rb +33 -0
  81. data/lib/appsignal/integrations/delayed_job_plugin.rb +54 -0
  82. data/lib/appsignal/integrations/grape.rb +53 -0
  83. data/lib/appsignal/integrations/mongo_ruby_driver.rb +55 -0
  84. data/lib/appsignal/integrations/object.rb +35 -0
  85. data/lib/appsignal/integrations/padrino.rb +84 -0
  86. data/lib/appsignal/integrations/que.rb +43 -0
  87. data/lib/appsignal/integrations/railtie.rb +41 -0
  88. data/lib/appsignal/integrations/rake.rb +2 -0
  89. data/lib/appsignal/integrations/resque.rb +20 -0
  90. data/lib/appsignal/integrations/resque_active_job.rb +30 -0
  91. data/lib/appsignal/integrations/sinatra.rb +17 -0
  92. data/lib/appsignal/integrations/webmachine.rb +38 -0
  93. data/lib/appsignal/js_exception_transaction.rb +54 -0
  94. data/lib/appsignal/marker.rb +63 -0
  95. data/lib/appsignal/minutely.rb +42 -0
  96. data/lib/appsignal/rack/generic_instrumentation.rb +49 -0
  97. data/lib/appsignal/rack/js_exception_catcher.rb +70 -0
  98. data/lib/appsignal/rack/rails_instrumentation.rb +51 -0
  99. data/lib/appsignal/rack/sinatra_instrumentation.rb +99 -0
  100. data/lib/appsignal/rack/streaming_listener.rb +73 -0
  101. data/lib/appsignal/system.rb +81 -0
  102. data/lib/appsignal/transaction.rb +498 -0
  103. data/lib/appsignal/transmitter.rb +107 -0
  104. data/lib/appsignal/utils.rb +127 -0
  105. data/lib/appsignal/utils/params_sanitizer.rb +59 -0
  106. data/lib/appsignal/utils/query_params_sanitizer.rb +55 -0
  107. data/lib/appsignal/version.rb +3 -0
  108. data/lib/sequel/extensions/appsignal_integration.rb +3 -0
  109. data/resources/appsignal.yml.erb +39 -0
  110. data/resources/cacert.pem +3866 -0
  111. data/spec/.rubocop.yml +7 -0
  112. data/spec/lib/appsignal/auth_check_spec.rb +80 -0
  113. data/spec/lib/appsignal/capistrano2_spec.rb +224 -0
  114. data/spec/lib/appsignal/capistrano3_spec.rb +237 -0
  115. data/spec/lib/appsignal/cli/demo_spec.rb +67 -0
  116. data/spec/lib/appsignal/cli/diagnose_spec.rb +988 -0
  117. data/spec/lib/appsignal/cli/helpers_spec.rb +171 -0
  118. data/spec/lib/appsignal/cli/install_spec.rb +632 -0
  119. data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +168 -0
  120. data/spec/lib/appsignal/cli_spec.rb +56 -0
  121. data/spec/lib/appsignal/config_spec.rb +637 -0
  122. data/spec/lib/appsignal/demo_spec.rb +87 -0
  123. data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +44 -0
  124. data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +21 -0
  125. data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +21 -0
  126. data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +52 -0
  127. data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +21 -0
  128. data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +113 -0
  129. data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +112 -0
  130. data/spec/lib/appsignal/event_formatter_spec.rb +100 -0
  131. data/spec/lib/appsignal/extension/jruby_spec.rb +43 -0
  132. data/spec/lib/appsignal/extension_spec.rb +137 -0
  133. data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +66 -0
  134. data/spec/lib/appsignal/hooks/action_cable_spec.rb +370 -0
  135. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +92 -0
  136. data/spec/lib/appsignal/hooks/celluloid_spec.rb +35 -0
  137. data/spec/lib/appsignal/hooks/data_mapper_spec.rb +39 -0
  138. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +358 -0
  139. data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +44 -0
  140. data/spec/lib/appsignal/hooks/net_http_spec.rb +53 -0
  141. data/spec/lib/appsignal/hooks/passenger_spec.rb +30 -0
  142. data/spec/lib/appsignal/hooks/puma_spec.rb +80 -0
  143. data/spec/lib/appsignal/hooks/que_spec.rb +19 -0
  144. data/spec/lib/appsignal/hooks/rake_spec.rb +73 -0
  145. data/spec/lib/appsignal/hooks/redis_spec.rb +55 -0
  146. data/spec/lib/appsignal/hooks/sequel_spec.rb +46 -0
  147. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +192 -0
  148. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +419 -0
  149. data/spec/lib/appsignal/hooks/unicorn_spec.rb +52 -0
  150. data/spec/lib/appsignal/hooks/webmachine_spec.rb +35 -0
  151. data/spec/lib/appsignal/hooks_spec.rb +195 -0
  152. data/spec/lib/appsignal/integrations/data_mapper_spec.rb +65 -0
  153. data/spec/lib/appsignal/integrations/grape_spec.rb +225 -0
  154. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +127 -0
  155. data/spec/lib/appsignal/integrations/object_spec.rb +249 -0
  156. data/spec/lib/appsignal/integrations/padrino_spec.rb +323 -0
  157. data/spec/lib/appsignal/integrations/que_spec.rb +174 -0
  158. data/spec/lib/appsignal/integrations/railtie_spec.rb +129 -0
  159. data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +83 -0
  160. data/spec/lib/appsignal/integrations/resque_spec.rb +92 -0
  161. data/spec/lib/appsignal/integrations/sinatra_spec.rb +73 -0
  162. data/spec/lib/appsignal/integrations/webmachine_spec.rb +69 -0
  163. data/spec/lib/appsignal/js_exception_transaction_spec.rb +128 -0
  164. data/spec/lib/appsignal/marker_spec.rb +51 -0
  165. data/spec/lib/appsignal/minutely_spec.rb +50 -0
  166. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +90 -0
  167. data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +147 -0
  168. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +117 -0
  169. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +213 -0
  170. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +161 -0
  171. data/spec/lib/appsignal/system_spec.rb +131 -0
  172. data/spec/lib/appsignal/transaction_spec.rb +1146 -0
  173. data/spec/lib/appsignal/transmitter_spec.rb +152 -0
  174. data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +136 -0
  175. data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +192 -0
  176. data/spec/lib/appsignal/utils_spec.rb +150 -0
  177. data/spec/lib/appsignal_spec.rb +1049 -0
  178. data/spec/spec_helper.rb +116 -0
  179. data/spec/support/fixtures/containers/cgroups/docker +14 -0
  180. data/spec/support/fixtures/containers/cgroups/docker_systemd +8 -0
  181. data/spec/support/fixtures/containers/cgroups/lxc +10 -0
  182. data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
  183. data/spec/support/fixtures/containers/cgroups/none +1 -0
  184. data/spec/support/fixtures/generated_config.yml +24 -0
  185. data/spec/support/fixtures/uploaded_file.txt +0 -0
  186. data/spec/support/helpers/api_request_helper.rb +19 -0
  187. data/spec/support/helpers/cli_helpers.rb +26 -0
  188. data/spec/support/helpers/config_helpers.rb +21 -0
  189. data/spec/support/helpers/dependency_helper.rb +73 -0
  190. data/spec/support/helpers/directory_helper.rb +27 -0
  191. data/spec/support/helpers/env_helpers.rb +33 -0
  192. data/spec/support/helpers/example_exception.rb +13 -0
  193. data/spec/support/helpers/example_standard_error.rb +13 -0
  194. data/spec/support/helpers/log_helpers.rb +22 -0
  195. data/spec/support/helpers/std_streams_helper.rb +66 -0
  196. data/spec/support/helpers/system_helpers.rb +8 -0
  197. data/spec/support/helpers/time_helpers.rb +11 -0
  198. data/spec/support/helpers/transaction_helpers.rb +37 -0
  199. data/spec/support/matchers/contains_log.rb +7 -0
  200. data/spec/support/mocks/fake_gc_profiler.rb +19 -0
  201. data/spec/support/mocks/mock_extension.rb +6 -0
  202. data/spec/support/project_fixture/config/application.rb +0 -0
  203. data/spec/support/project_fixture/config/appsignal.yml +32 -0
  204. data/spec/support/project_fixture/config/environments/development.rb +0 -0
  205. data/spec/support/project_fixture/config/environments/production.rb +0 -0
  206. data/spec/support/project_fixture/config/environments/test.rb +0 -0
  207. data/spec/support/project_fixture/log/.gitkeep +0 -0
  208. data/spec/support/rails/my_app.rb +6 -0
  209. data/spec/support/shared_examples/instrument.rb +43 -0
  210. data/spec/support/stubs/delayed_job.rb +0 -0
  211. metadata +483 -0
@@ -0,0 +1,92 @@
1
+ describe Appsignal::Hooks::ActiveSupportNotificationsHook do
2
+ if active_support_present?
3
+ let(:notifier) { ActiveSupport::Notifications::Fanout.new }
4
+ let(:as) { ActiveSupport::Notifications }
5
+ before :context do
6
+ start_agent
7
+ end
8
+ before do
9
+ as.notifier = notifier
10
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
11
+ end
12
+
13
+ describe "#dependencies_present?" do
14
+ subject { described_class.new.dependencies_present? }
15
+
16
+ it { is_expected.to be_truthy }
17
+ end
18
+
19
+ it "instruments an ActiveSupport::Notifications.instrument event" do
20
+ expect(Appsignal::Transaction.current).to receive(:start_event)
21
+ .at_least(:once)
22
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
23
+ .at_least(:once)
24
+ .with("sql.active_record", nil, "SQL", 1)
25
+
26
+ return_value = as.instrument("sql.active_record", :sql => "SQL") do
27
+ "value"
28
+ end
29
+
30
+ expect(return_value).to eq "value"
31
+ end
32
+
33
+ it "should convert non-string names to strings" do
34
+ expect(Appsignal::Transaction.current).to receive(:start_event)
35
+ .at_least(:once)
36
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
37
+ .at_least(:once)
38
+ .with("not_a_string", nil, nil, nil)
39
+
40
+ as.instrument(:not_a_string) {}
41
+ end
42
+
43
+ it "does not instrument events whose name starts with a bang" do
44
+ expect(Appsignal::Transaction.current).not_to receive(:start_event)
45
+ expect(Appsignal::Transaction.current).not_to receive(:finish_event)
46
+
47
+ return_value = as.instrument("!sql.active_record", :sql => "SQL") do
48
+ "value"
49
+ end
50
+
51
+ expect(return_value).to eq "value"
52
+ end
53
+
54
+ context "when an error is raised in an instrumented block" do
55
+ it "instruments an ActiveSupport::Notifications.instrument event" do
56
+ expect(Appsignal::Transaction.current).to receive(:start_event)
57
+ .at_least(:once)
58
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
59
+ .at_least(:once)
60
+ .with("sql.active_record", nil, "SQL", 1)
61
+
62
+ expect do
63
+ as.instrument("sql.active_record", :sql => "SQL") do
64
+ raise ExampleException, "foo"
65
+ end
66
+ end.to raise_error(ExampleException, "foo")
67
+ end
68
+ end
69
+
70
+ context "when a message is thrown in an instrumented block" do
71
+ it "instruments an ActiveSupport::Notifications.instrument event" do
72
+ expect(Appsignal::Transaction.current).to receive(:start_event)
73
+ .at_least(:once)
74
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
75
+ .at_least(:once)
76
+ .with("sql.active_record", nil, "SQL", 1)
77
+
78
+ expect do
79
+ as.instrument("sql.active_record", :sql => "SQL") do
80
+ throw :foo
81
+ end
82
+ end.to throw_symbol(:foo)
83
+ end
84
+ end
85
+ else
86
+ describe "#dependencies_present?" do
87
+ subject { described_class.new.dependencies_present? }
88
+
89
+ it { is_expected.to be_falsy }
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,35 @@
1
+ describe Appsignal::Hooks::CelluloidHook do
2
+ context "with celluloid" do
3
+ before :context do
4
+ module Celluloid
5
+ def self.shutdown
6
+ end
7
+ end
8
+ Appsignal::Hooks::CelluloidHook.new.install
9
+ end
10
+ after :context do
11
+ Object.send(:remove_const, :Celluloid)
12
+ end
13
+
14
+ describe "#dependencies_present?" do
15
+ subject { described_class.new.dependencies_present? }
16
+
17
+ it { is_expected.to be_truthy }
18
+ end
19
+
20
+ specify { expect(Appsignal).to receive(:stop) }
21
+ specify { expect(Celluloid).to receive(:shutdown_without_appsignal) }
22
+
23
+ after do
24
+ Celluloid.shutdown
25
+ end
26
+ end
27
+
28
+ context "without celluloid" do
29
+ describe "#dependencies_present?" do
30
+ subject { described_class.new.dependencies_present? }
31
+
32
+ it { is_expected.to be_falsy }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,39 @@
1
+ describe Appsignal::Hooks::DataMapperHook do
2
+ context "with datamapper" do
3
+ before :context do
4
+ module DataMapper
5
+ end
6
+ module DataObjects
7
+ class Connection
8
+ end
9
+ end
10
+ Appsignal::Hooks::DataMapperHook.new.install
11
+ end
12
+
13
+ after :context do
14
+ Object.send(:remove_const, :DataMapper)
15
+ Object.send(:remove_const, :DataObjects)
16
+ end
17
+
18
+ describe "#dependencies_present?" do
19
+ subject { described_class.new.dependencies_present? }
20
+
21
+ it { is_expected.to be_truthy }
22
+ end
23
+
24
+ it "should install the listener" do
25
+ expect(::DataObjects::Connection).to receive(:include)
26
+ .with(Appsignal::Hooks::DataMapperLogListener)
27
+
28
+ Appsignal::Hooks::DataMapperHook.new.install
29
+ end
30
+ end
31
+
32
+ context "without datamapper" do
33
+ describe "#dependencies_present?" do
34
+ subject { described_class.new.dependencies_present? }
35
+
36
+ it { is_expected.to be_falsy }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,358 @@
1
+ describe Appsignal::Hooks::DelayedJobHook do
2
+ context "with delayed job" do
3
+ before(:context) do
4
+ module Delayed
5
+ class Plugin
6
+ def self.callbacks
7
+ end
8
+ end
9
+
10
+ class Worker
11
+ def self.plugins
12
+ @plugins ||= []
13
+ end
14
+ end
15
+ end
16
+ end
17
+ after(:context) { Object.send(:remove_const, :Delayed) }
18
+ before do
19
+ start_agent
20
+ end
21
+
22
+ describe "#dependencies_present?" do
23
+ subject { described_class.new.dependencies_present? }
24
+
25
+ it { is_expected.to be_truthy }
26
+ end
27
+
28
+ it "adds the plugin" do
29
+ expect(::Delayed::Worker.plugins).to include Appsignal::Hooks::DelayedJobPlugin
30
+ end
31
+
32
+ # We haven't found a way to test the hooks, we'll have to do that manually
33
+
34
+ describe ".invoke_with_instrumentation" do
35
+ let(:plugin) { Appsignal::Hooks::DelayedJobPlugin }
36
+ let(:time) { Time.parse("01-01-2001 10:01:00UTC") }
37
+ let(:created_at) { time - 3600 }
38
+ let(:run_at) { time - 3600 }
39
+ let(:job_data) do
40
+ {
41
+ :id => 123,
42
+ :name => "TestClass#perform",
43
+ :priority => 1,
44
+ :attempts => 1,
45
+ :queue => "default",
46
+ :created_at => created_at,
47
+ :run_at => run_at,
48
+ :payload_object => double(:args => args)
49
+ }
50
+ end
51
+ let(:args) { ["argument"] }
52
+ let(:job) { double(job_data) }
53
+ let(:invoked_block) { proc {} }
54
+
55
+ context "with a normal call" do
56
+ let(:default_params) do
57
+ {
58
+ :class => "TestClass",
59
+ :method => "perform",
60
+ :metadata => {
61
+ :priority => 1,
62
+ :attempts => 1,
63
+ :queue => "default",
64
+ :id => "123"
65
+ },
66
+ :params => args,
67
+ :queue_start => run_at
68
+ }
69
+ end
70
+ after do
71
+ Timecop.freeze(time) do
72
+ plugin.invoke_with_instrumentation(job, invoked_block)
73
+ end
74
+ end
75
+
76
+ it "wraps it in a transaction with the correct params" do
77
+ expect(Appsignal).to receive(:monitor_transaction).with(
78
+ "perform_job.delayed_job",
79
+ default_params.merge(:params => ["argument"])
80
+ )
81
+ end
82
+
83
+ context "with more complex params" do
84
+ let(:args) do
85
+ {
86
+ :foo => "Foo",
87
+ :bar => "Bar"
88
+ }
89
+ end
90
+
91
+ it "adds the more complex arguments" do
92
+ expect(Appsignal).to receive(:monitor_transaction).with(
93
+ "perform_job.delayed_job",
94
+ default_params.merge(
95
+ :params => {
96
+ :foo => "Foo",
97
+ :bar => "Bar"
98
+ }
99
+ )
100
+ )
101
+ end
102
+
103
+ context "with parameter filtering" do
104
+ before do
105
+ Appsignal.config = project_fixture_config("production")
106
+ Appsignal.config[:filter_parameters] = ["foo"]
107
+ end
108
+
109
+ it "filters selected arguments" do
110
+ expect(Appsignal).to receive(:monitor_transaction).with(
111
+ "perform_job.delayed_job",
112
+ default_params.merge(
113
+ :params => {
114
+ :foo => "[FILTERED]",
115
+ :bar => "Bar"
116
+ }
117
+ )
118
+ )
119
+ end
120
+ end
121
+ end
122
+
123
+ context "with run_at in the future" do
124
+ let(:run_at) { Time.parse("2017-01-01 10:01:00UTC") }
125
+
126
+ it "reports queue_start with run_at time" do
127
+ expect(Appsignal).to receive(:monitor_transaction).with(
128
+ "perform_job.delayed_job",
129
+ default_params.merge(:queue_start => run_at)
130
+ )
131
+ end
132
+ end
133
+
134
+ context "with custom name call" do
135
+ let(:job_data) do
136
+ {
137
+ :payload_object => double(
138
+ :appsignal_name => "CustomClass#perform",
139
+ :args => args
140
+ ),
141
+ :id => "123",
142
+ :name => "TestClass#perform",
143
+ :priority => 1,
144
+ :attempts => 1,
145
+ :queue => "default",
146
+ :created_at => created_at,
147
+ :run_at => run_at
148
+ }
149
+ end
150
+ let(:default_params) do
151
+ {
152
+ :class => "CustomClass",
153
+ :method => "perform",
154
+ :metadata => {
155
+ :priority => 1,
156
+ :attempts => 1,
157
+ :queue => "default",
158
+ :id => "123"
159
+ },
160
+ :queue_start => run_at
161
+ }
162
+ end
163
+
164
+ it "wraps it in a transaction with the correct params" do
165
+ expect(Appsignal).to receive(:monitor_transaction).with(
166
+ "perform_job.delayed_job",
167
+ default_params.merge(
168
+ :params => ["argument"]
169
+ )
170
+ )
171
+ end
172
+
173
+ context "with more complex params" do
174
+ let(:args) do
175
+ {
176
+ :foo => "Foo",
177
+ :bar => "Bar"
178
+ }
179
+ end
180
+
181
+ it "adds the more complex arguments" do
182
+ expect(Appsignal).to receive(:monitor_transaction).with(
183
+ "perform_job.delayed_job",
184
+ default_params.merge(
185
+ :params => {
186
+ :foo => "Foo",
187
+ :bar => "Bar"
188
+ }
189
+ )
190
+ )
191
+ end
192
+
193
+ context "with parameter filtering" do
194
+ before do
195
+ Appsignal.config = project_fixture_config("production")
196
+ Appsignal.config[:filter_parameters] = ["foo"]
197
+ end
198
+
199
+ it "filters selected arguments" do
200
+ expect(Appsignal).to receive(:monitor_transaction).with(
201
+ "perform_job.delayed_job",
202
+ default_params.merge(
203
+ :params => {
204
+ :foo => "[FILTERED]",
205
+ :bar => "Bar"
206
+ }
207
+ )
208
+ )
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ if active_job_present?
215
+ require "active_job"
216
+
217
+ context "when wrapped by ActiveJob" do
218
+ let(:wrapped_job) do
219
+ ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper.new(
220
+ "arguments" => args,
221
+ "job_class" => "TestClass",
222
+ "job_id" => 123,
223
+ "locale" => :en,
224
+ "queue_name" => "default"
225
+ )
226
+ end
227
+ let(:job) do
228
+ double(
229
+ :id => 123,
230
+ :name => "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper",
231
+ :priority => 1,
232
+ :attempts => 1,
233
+ :queue => "default",
234
+ :created_at => created_at,
235
+ :run_at => run_at,
236
+ :payload_object => wrapped_job
237
+ )
238
+ end
239
+ let(:default_params) do
240
+ {
241
+ :class => "TestClass",
242
+ :method => "perform",
243
+ :metadata => {
244
+ :priority => 1,
245
+ :attempts => 1,
246
+ :queue => "default",
247
+ :id => "123"
248
+ },
249
+ :queue_start => run_at,
250
+ :params => args
251
+ }
252
+ end
253
+ let(:args) { ["activejob_argument"] }
254
+
255
+ context "with simple params" do
256
+ it "wraps it in a transaction with the correct params" do
257
+ expect(Appsignal).to receive(:monitor_transaction).with(
258
+ "perform_job.delayed_job",
259
+ default_params.merge(:params => ["activejob_argument"])
260
+ )
261
+ end
262
+ end
263
+
264
+ context "with more complex params" do
265
+ let(:args) do
266
+ {
267
+ :foo => "Foo",
268
+ :bar => "Bar"
269
+ }
270
+ end
271
+
272
+ it "adds the more complex arguments" do
273
+ expect(Appsignal).to receive(:monitor_transaction).with(
274
+ "perform_job.delayed_job",
275
+ default_params.merge(
276
+ :params => {
277
+ :foo => "Foo",
278
+ :bar => "Bar"
279
+ }
280
+ )
281
+ )
282
+ end
283
+
284
+ context "with parameter filtering" do
285
+ before do
286
+ Appsignal.config = project_fixture_config("production")
287
+ Appsignal.config[:filter_parameters] = ["foo"]
288
+ end
289
+
290
+ it "filters selected arguments" do
291
+ expect(Appsignal).to receive(:monitor_transaction).with(
292
+ "perform_job.delayed_job",
293
+ default_params.merge(
294
+ :params => {
295
+ :foo => "[FILTERED]",
296
+ :bar => "Bar"
297
+ }
298
+ )
299
+ )
300
+ end
301
+ end
302
+ end
303
+
304
+ context "with run_at in the future" do
305
+ let(:run_at) { Time.parse("2017-01-01 10:01:00UTC") }
306
+
307
+ it "reports queue_start with run_at time" do
308
+ expect(Appsignal).to receive(:monitor_transaction).with(
309
+ "perform_job.delayed_job",
310
+ default_params.merge(:queue_start => run_at)
311
+ )
312
+ end
313
+ end
314
+ end
315
+ end
316
+ end
317
+
318
+ context "with an erroring call" do
319
+ let(:error) { ExampleException }
320
+ let(:transaction) do
321
+ Appsignal::Transaction.new(
322
+ SecureRandom.uuid,
323
+ Appsignal::Transaction::BACKGROUND_JOB,
324
+ Appsignal::Transaction::GenericRequest.new({})
325
+ )
326
+ end
327
+ before do
328
+ expect(invoked_block).to receive(:call).and_raise(error)
329
+
330
+ allow(Appsignal::Transaction).to receive(:current).and_return(transaction)
331
+ expect(Appsignal::Transaction).to receive(:create)
332
+ .with(
333
+ kind_of(String),
334
+ Appsignal::Transaction::BACKGROUND_JOB,
335
+ kind_of(Appsignal::Transaction::GenericRequest)
336
+ ).and_return(transaction)
337
+ end
338
+
339
+ it "adds the error to the transaction" do
340
+ expect(transaction).to receive(:set_error).with(error)
341
+ expect(transaction).to receive(:complete)
342
+
343
+ expect do
344
+ plugin.invoke_with_instrumentation(job, invoked_block)
345
+ end.to raise_error(error)
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ context "without delayed job" do
352
+ describe "#dependencies_present?" do
353
+ subject { described_class.new.dependencies_present? }
354
+
355
+ it { is_expected.to be_falsy }
356
+ end
357
+ end
358
+ end