appsignal 2.5.0.alpha.1-java

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.
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,44 @@
1
+ describe Appsignal::Hooks::MongoRubyDriverHook do
2
+ require "appsignal/integrations/mongo_ruby_driver"
3
+
4
+ context "with mongo ruby driver" do
5
+ let(:subscriber) { Appsignal::Hooks::MongoMonitorSubscriber.new }
6
+ before { allow(Appsignal::Hooks::MongoMonitorSubscriber).to receive(:new).and_return(subscriber) }
7
+
8
+ before(:context) do
9
+ module Mongo
10
+ module Monitoring
11
+ COMMAND = "command".freeze
12
+
13
+ class Global
14
+ def subscribe
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ after(:context) { Object.send(:remove_const, :Mongo) }
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 a subscriber to Mongo::Monitoring" do
29
+ expect(Mongo::Monitoring::Global).to receive(:subscribe)
30
+ .with("command", subscriber)
31
+ .at_least(:once)
32
+
33
+ Appsignal::Hooks::MongoRubyDriverHook.new.install
34
+ end
35
+ end
36
+
37
+ context "without mongo ruby driver" do
38
+ describe "#dependencies_present?" do
39
+ subject { described_class.new.dependencies_present? }
40
+
41
+ it { is_expected.to be_falsy }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,53 @@
1
+ describe Appsignal::Hooks::NetHttpHook do
2
+ before :context do
3
+ start_agent
4
+ end
5
+
6
+ context "with Net::HTTP instrumentation enabled" do
7
+ describe "#dependencies_present?" do
8
+ subject { described_class.new.dependencies_present? }
9
+
10
+ it { is_expected.to be_truthy }
11
+ end
12
+
13
+ it "should instrument a http request" do
14
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
15
+ expect(Appsignal::Transaction.current).to receive(:start_event)
16
+ .at_least(:once)
17
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
18
+ .at_least(:once)
19
+ .with("request.net_http", "GET http://www.google.com", nil, 0)
20
+
21
+ stub_request(:any, "http://www.google.com/")
22
+
23
+ Net::HTTP.get_response(URI.parse("http://www.google.com"))
24
+ end
25
+
26
+ it "should instrument a https request" do
27
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
28
+ expect(Appsignal::Transaction.current).to receive(:start_event)
29
+ .at_least(:once)
30
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
31
+ .at_least(:once)
32
+ .with("request.net_http", "GET https://www.google.com", nil, 0)
33
+
34
+ stub_request(:any, "https://www.google.com/")
35
+
36
+ uri = URI.parse("https://www.google.com")
37
+ http = Net::HTTP.new(uri.host, uri.port)
38
+ http.use_ssl = true
39
+ http.get(uri.request_uri)
40
+ end
41
+ end
42
+
43
+ context "with Net::HTTP instrumentation disabled" do
44
+ before { Appsignal.config.config_hash[:instrument_net_http] = false }
45
+ after { Appsignal.config.config_hash[:instrument_net_http] = true }
46
+
47
+ describe "#dependencies_present?" do
48
+ subject { described_class.new.dependencies_present? }
49
+
50
+ it { is_expected.to be_falsy }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ describe Appsignal::Hooks::PassengerHook do
2
+ context "with passenger" do
3
+ before(:context) do
4
+ module PhusionPassenger
5
+ end
6
+ end
7
+ after(:context) { Object.send(:remove_const, :PhusionPassenger) }
8
+
9
+ describe "#dependencies_present?" do
10
+ subject { described_class.new.dependencies_present? }
11
+
12
+ it { is_expected.to be_truthy }
13
+ end
14
+
15
+ it "adds behavior to stopping_worker_process and starting_worker_process" do
16
+ expect(PhusionPassenger).to receive(:on_event).with(:starting_worker_process)
17
+ expect(PhusionPassenger).to receive(:on_event).with(:stopping_worker_process)
18
+
19
+ Appsignal::Hooks::PassengerHook.new.install
20
+ end
21
+ end
22
+
23
+ context "without passenger" do
24
+ describe "#dependencies_present?" do
25
+ subject { described_class.new.dependencies_present? }
26
+
27
+ it { is_expected.to be_falsy }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,80 @@
1
+ describe Appsignal::Hooks::PumaHook do
2
+ context "with puma" do
3
+ before(:context) do
4
+ class Puma
5
+ def self.cli_config
6
+ @cli_config ||= CliConfig.new
7
+ end
8
+
9
+ class Cluster
10
+ def stop_workers
11
+ end
12
+ end
13
+ end
14
+
15
+ class CliConfig
16
+ attr_accessor :options
17
+
18
+ def initialize
19
+ @options = {}
20
+ end
21
+ end
22
+ end
23
+ after(:context) { Object.send(:remove_const, :Puma) }
24
+
25
+ describe "#dependencies_present?" do
26
+ subject { described_class.new.dependencies_present? }
27
+
28
+ it { is_expected.to be_truthy }
29
+ end
30
+
31
+ context "when installed" do
32
+ before do
33
+ Appsignal::Hooks::PumaHook.new.install
34
+ end
35
+
36
+ it "adds behavior to Unicorn::Worker#close" do
37
+ cluster = Puma::Cluster.new
38
+
39
+ expect(Appsignal).to receive(:stop)
40
+ expect(cluster).to receive(:stop_workers_without_appsignal)
41
+
42
+ cluster.stop_workers
43
+ end
44
+ end
45
+
46
+ context "with nil hooks" do
47
+ before do
48
+ Puma.cli_config.options.delete(:before_worker_boot)
49
+ Puma.cli_config.options.delete(:before_worker_shutdown)
50
+ Appsignal::Hooks::PumaHook.new.install
51
+ end
52
+
53
+ it "should add a before shutdown worker callback" do
54
+ expect(Puma.cli_config.options[:before_worker_boot].first).to be_a(Proc)
55
+ expect(Puma.cli_config.options[:before_worker_shutdown].first).to be_a(Proc)
56
+ end
57
+ end
58
+
59
+ context "with existing hooks" do
60
+ before do
61
+ Puma.cli_config.options[:before_worker_boot] = []
62
+ Puma.cli_config.options[:before_worker_shutdown] = []
63
+ Appsignal::Hooks::PumaHook.new.install
64
+ end
65
+
66
+ it "should add a before shutdown worker callback" do
67
+ expect(Puma.cli_config.options[:before_worker_boot].first).to be_a(Proc)
68
+ expect(Puma.cli_config.options[:before_worker_shutdown].first).to be_a(Proc)
69
+ end
70
+ end
71
+ end
72
+
73
+ context "without puma" do
74
+ describe "#dependencies_present?" do
75
+ subject { described_class.new.dependencies_present? }
76
+
77
+ it { is_expected.to be_falsy }
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,19 @@
1
+ describe Appsignal::Hooks::QueHook do
2
+ if DependencyHelper.que_present?
3
+ describe "#dependencies_present?" do
4
+ subject { described_class.new.dependencies_present? }
5
+
6
+ it { is_expected.to be_truthy }
7
+ end
8
+
9
+ it "installs the QuePlugin" do
10
+ expect(Que::Job.included_modules).to include(Appsignal::Integrations::QuePlugin)
11
+ end
12
+ else
13
+ describe "#dependencies_present?" do
14
+ subject { described_class.new.dependencies_present? }
15
+
16
+ it { is_expected.to be_falsy }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,73 @@
1
+ require "rake"
2
+
3
+ describe Appsignal::Hooks::RakeHook do
4
+ let(:task) { Rake::Task.new("task:name", Rake::Application.new) }
5
+ let(:arguments) { Rake::TaskArguments.new(["foo"], ["bar"]) }
6
+ let(:generic_request) { Appsignal::Transaction::GenericRequest.new({}) }
7
+ before(:context) do
8
+ Appsignal.config = project_fixture_config
9
+ expect(Appsignal.active?).to be_truthy
10
+ Appsignal::Hooks.load_hooks
11
+ end
12
+
13
+ describe "#execute" do
14
+ context "without error" do
15
+ it "creates no transaction" do
16
+ expect(Appsignal::Transaction).to_not receive(:create)
17
+ end
18
+
19
+ it "calls the original task" do
20
+ expect(task).to receive(:execute_without_appsignal).with("foo")
21
+ end
22
+
23
+ after { task.execute("foo") }
24
+ end
25
+
26
+ context "with error" do
27
+ let(:error) { ExampleException }
28
+ let(:transaction) { background_job_transaction }
29
+ before do
30
+ task.enhance { raise error }
31
+
32
+ expect(Appsignal::Transaction).to receive(:create).with(
33
+ kind_of(String),
34
+ Appsignal::Transaction::BACKGROUND_JOB,
35
+ kind_of(Appsignal::Transaction::GenericRequest)
36
+ ).and_return(transaction)
37
+ end
38
+
39
+ it "sets the action" do
40
+ expect(transaction).to receive(:set_action).with("task:name")
41
+ end
42
+
43
+ it "sets the error" do
44
+ expect(transaction).to receive(:set_error).with(error)
45
+ end
46
+
47
+ it "completes the transaction and stops" do
48
+ expect(transaction).to receive(:complete).ordered
49
+ expect(Appsignal).to receive(:stop).with("rake").ordered
50
+ end
51
+
52
+ it "adds the task arguments to the request" do
53
+ expect(Appsignal::Transaction::GenericRequest).to receive(:new)
54
+ .with(:params => { :foo => "bar" })
55
+ .and_return(generic_request)
56
+ end
57
+
58
+ context "when first argument is not a `Rake::TaskArguments`" do
59
+ let(:arguments) { nil }
60
+
61
+ it "adds the first argument regardless" do
62
+ expect(Appsignal::Transaction::GenericRequest).to receive(:new)
63
+ .with(:params => nil)
64
+ .and_return(generic_request)
65
+ end
66
+ end
67
+
68
+ after do
69
+ expect { task.execute(arguments) }.to raise_error ExampleException
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,55 @@
1
+ describe Appsignal::Hooks::RedisHook do
2
+ before do
3
+ Appsignal.config = project_fixture_config
4
+ Appsignal::Hooks.load_hooks
5
+ end
6
+
7
+ if DependencyHelper.redis_present?
8
+ context "with redis" do
9
+ context "with instrumentation enabled" do
10
+ before do
11
+ Appsignal.config.config_hash[:instrument_redis] = true
12
+ allow_any_instance_of(Redis::Client).to receive(:process_without_appsignal).and_return(1)
13
+ end
14
+
15
+ describe "#dependencies_present?" do
16
+ subject { described_class.new.dependencies_present? }
17
+
18
+ it { is_expected.to be_truthy }
19
+ end
20
+
21
+ it "should instrument a redis call" do
22
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
23
+ expect(Appsignal::Transaction.current).to receive(:start_event)
24
+ .at_least(:once)
25
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
26
+ .at_least(:once)
27
+ .with("query.redis", "redis://127.0.0.1:6379/0", "get ?", 0)
28
+
29
+ client = Redis::Client.new
30
+ expect(client.process([[:get, "key"]])).to eq 1
31
+ end
32
+ end
33
+
34
+ context "with instrumentation disabled" do
35
+ before do
36
+ Appsignal.config.config_hash[:instrument_redis] = false
37
+ end
38
+
39
+ describe "#dependencies_present?" do
40
+ subject { described_class.new.dependencies_present? }
41
+
42
+ it { is_expected.to be_falsy }
43
+ end
44
+ end
45
+ end
46
+ else
47
+ context "without redis" do
48
+ describe "#dependencies_present?" do
49
+ subject { described_class.new.dependencies_present? }
50
+
51
+ it { is_expected.to be_falsy }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ describe Appsignal::Hooks::SequelHook do
2
+ if DependencyHelper.sequel_present?
3
+ let(:db) do
4
+ if Appsignal::System.jruby?
5
+ Sequel.connect("jdbc:sqlite::memory:")
6
+ else
7
+ Sequel.sqlite
8
+ end
9
+ end
10
+
11
+ before :context do
12
+ start_agent
13
+ end
14
+
15
+ describe "#dependencies_present?" do
16
+ subject { described_class.new.dependencies_present? }
17
+
18
+ it { is_expected.to be_truthy }
19
+ end
20
+
21
+ context "with a transaction" do
22
+ let(:transaction) { Appsignal::Transaction.current }
23
+ before do
24
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
25
+ db.logger = Logger.new($stdout) # To test #log_duration call
26
+ end
27
+
28
+ it "should instrument queries" do
29
+ expect(transaction).to receive(:start_event).at_least(:once)
30
+ expect(transaction).to receive(:finish_event)
31
+ .at_least(:once)
32
+ .with("sql.sequel", nil, kind_of(String), 1)
33
+
34
+ expect(db).to receive(:log_duration).at_least(:once)
35
+
36
+ db["SELECT 1"].all.to_a
37
+ end
38
+ end
39
+ else
40
+ describe "#dependencies_present?" do
41
+ subject { described_class.new.dependencies_present? }
42
+
43
+ it { is_expected.to be_falsy }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,192 @@
1
+ describe Appsignal::Hooks::ShoryukenMiddleware do
2
+ let(:current_transaction) { background_job_transaction }
3
+
4
+ class DemoShoryukenWorker
5
+ end
6
+
7
+ let(:worker_instance) { DemoShoryukenWorker.new }
8
+ let(:queue) { double }
9
+ let(:sqs_msg) { double(:attributes => {}) }
10
+ let(:body) { {} }
11
+
12
+ before do
13
+ allow(Appsignal::Transaction).to receive(:current).and_return(current_transaction)
14
+ start_agent
15
+ end
16
+
17
+ context "with a performance call" do
18
+ let(:queue) { "some-funky-queue-name" }
19
+ let(:sqs_msg) do
20
+ double(:attributes => { "SentTimestamp" => Time.parse("1976-11-18 0:00:00UTC").to_i * 1000 })
21
+ end
22
+
23
+ context "with complex argument" do
24
+ let(:body) do
25
+ {
26
+ :foo => "Foo",
27
+ :bar => "Bar"
28
+ }
29
+ end
30
+ after do
31
+ Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
32
+ Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
33
+ # nothing
34
+ end
35
+ end
36
+ end
37
+
38
+ it "wraps the job in a transaction with the correct params" do
39
+ expect(Appsignal).to receive(:monitor_transaction).with(
40
+ "perform_job.shoryuken",
41
+ :class => "DemoShoryukenWorker",
42
+ :method => "perform",
43
+ :metadata => {
44
+ :queue => "some-funky-queue-name",
45
+ "SentTimestamp" => 217_123_200_000
46
+ },
47
+ :params => {
48
+ :foo => "Foo",
49
+ :bar => "Bar"
50
+ },
51
+ :queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
52
+ )
53
+ end
54
+
55
+ context "with parameter filtering" do
56
+ before do
57
+ Appsignal.config = project_fixture_config("production")
58
+ Appsignal.config[:filter_parameters] = ["foo"]
59
+ end
60
+
61
+ it "filters selected arguments" do
62
+ expect(Appsignal).to receive(:monitor_transaction).with(
63
+ "perform_job.shoryuken",
64
+ :class => "DemoShoryukenWorker",
65
+ :method => "perform",
66
+ :metadata => {
67
+ :queue => "some-funky-queue-name",
68
+ "SentTimestamp" => 217_123_200_000
69
+ },
70
+ :params => {
71
+ :foo => "[FILTERED]",
72
+ :bar => "Bar"
73
+ },
74
+ :queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
75
+ )
76
+ end
77
+ end
78
+ end
79
+
80
+ context "with a string as an argument" do
81
+ let(:body) { "foo bar" }
82
+
83
+ it "handles string arguments" do
84
+ expect(Appsignal).to receive(:monitor_transaction).with(
85
+ "perform_job.shoryuken",
86
+ :class => "DemoShoryukenWorker",
87
+ :method => "perform",
88
+ :metadata => {
89
+ :queue => "some-funky-queue-name",
90
+ "SentTimestamp" => 217_123_200_000
91
+ },
92
+ :params => { :params => body },
93
+ :queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
94
+ )
95
+
96
+ Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
97
+ Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
98
+ # nothing
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ context "with primitive type as argument" do
105
+ let(:body) { 1 }
106
+
107
+ it "handles primitive types as arguments" do
108
+ expect(Appsignal).to receive(:monitor_transaction).with(
109
+ "perform_job.shoryuken",
110
+ :class => "DemoShoryukenWorker",
111
+ :method => "perform",
112
+ :metadata => {
113
+ :queue => "some-funky-queue-name",
114
+ "SentTimestamp" => 217_123_200_000
115
+ },
116
+ :params => { :params => body },
117
+ :queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
118
+ )
119
+
120
+ Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
121
+ Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
122
+ # nothing
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ context "with exception" do
130
+ let(:transaction) do
131
+ Appsignal::Transaction.new(
132
+ SecureRandom.uuid,
133
+ Appsignal::Transaction::BACKGROUND_JOB,
134
+ Appsignal::Transaction::GenericRequest.new({})
135
+ )
136
+ end
137
+
138
+ before do
139
+ allow(Appsignal::Transaction).to receive(:current).and_return(transaction)
140
+ expect(Appsignal::Transaction).to receive(:create)
141
+ .with(
142
+ kind_of(String),
143
+ Appsignal::Transaction::BACKGROUND_JOB,
144
+ kind_of(Appsignal::Transaction::GenericRequest)
145
+ ).and_return(transaction)
146
+ end
147
+
148
+ it "sets the exception on the transaction" do
149
+ expect(transaction).to receive(:set_error).with(ExampleException)
150
+ end
151
+
152
+ after do
153
+ expect do
154
+ Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
155
+ Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
156
+ raise ExampleException
157
+ end
158
+ end
159
+ end.to raise_error(ExampleException)
160
+ end
161
+ end
162
+ end
163
+
164
+ describe Appsignal::Hooks::ShoryukenHook do
165
+ context "with shoryuken" do
166
+ before(:context) do
167
+ module Shoryuken
168
+ def self.configure_server
169
+ end
170
+ end
171
+ Appsignal::Hooks::ShoryukenHook.new.install
172
+ end
173
+
174
+ after(:context) do
175
+ Object.send(:remove_const, :Shoryuken)
176
+ end
177
+
178
+ describe "#dependencies_present?" do
179
+ subject { described_class.new.dependencies_present? }
180
+
181
+ it { is_expected.to be_truthy }
182
+ end
183
+ end
184
+
185
+ context "without shoryuken" do
186
+ describe "#dependencies_present?" do
187
+ subject { described_class.new.dependencies_present? }
188
+
189
+ it { is_expected.to be_falsy }
190
+ end
191
+ end
192
+ end