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,2 @@
1
+ # Since version 1.0 requiring this file is not necessary anymore to get
2
+ # Rake integration, it's just here for backward compatibility.
@@ -0,0 +1,20 @@
1
+ module Appsignal
2
+ module Integrations
3
+ # @api private
4
+ module ResquePlugin
5
+ # Do not use this file as a template for your own background processor
6
+ # Resque is an exception to the rule and the code below causes the
7
+ # extension to shut itself down after a single job.
8
+ # see http://docs.appsignal.com/background-monitoring/custom.html
9
+ def around_perform_resque_plugin(*_args)
10
+ Appsignal.monitor_single_transaction(
11
+ "perform_job.resque",
12
+ :class => to_s,
13
+ :method => "perform"
14
+ ) do
15
+ yield
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ module Appsignal
2
+ module Integrations
3
+ # @api private
4
+ module ResqueActiveJobPlugin
5
+ include Appsignal::Hooks::Helpers
6
+
7
+ def self.included(base)
8
+ base.class_eval do
9
+ around_perform do |job, block|
10
+ params = Appsignal::Utils::ParamsSanitizer.sanitize job.arguments,
11
+ :filter_parameters => Appsignal.config[:filter_parameters]
12
+
13
+ Appsignal.monitor_single_transaction(
14
+ "perform_job.resque",
15
+ :class => job.class.to_s,
16
+ :method => "perform",
17
+ :params => params,
18
+ :metadata => {
19
+ :id => job.job_id,
20
+ :queue => job.queue_name
21
+ }
22
+ ) do
23
+ block.call
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ require "appsignal"
2
+ require "appsignal/rack/sinatra_instrumentation"
3
+
4
+ Appsignal.logger.info("Loading Sinatra (#{Sinatra::VERSION}) integration")
5
+
6
+ app_settings = ::Sinatra::Application.settings
7
+ Appsignal.config = Appsignal::Config.new(
8
+ app_settings.root || Dir.pwd,
9
+ app_settings.environment
10
+ )
11
+
12
+ Appsignal.start_logger
13
+ Appsignal.start
14
+
15
+ if Appsignal.active?
16
+ ::Sinatra::Base.use(Appsignal::Rack::SinatraBaseInstrumentation)
17
+ end
@@ -0,0 +1,38 @@
1
+ module Appsignal
2
+ module Integrations
3
+ # @api private
4
+ module WebmachinePlugin
5
+ module FSM
6
+ def run_with_appsignal
7
+ transaction = Appsignal::Transaction.create(
8
+ SecureRandom.uuid,
9
+ Appsignal::Transaction::HTTP_REQUEST,
10
+ request,
11
+ :params_method => :query
12
+ )
13
+
14
+ transaction.set_action_if_nil("#{resource.class.name}##{request.method}")
15
+
16
+ Appsignal.instrument("process_action.webmachine") do
17
+ run_without_appsignal
18
+ end
19
+
20
+ Appsignal::Transaction.complete_current!
21
+ end
22
+
23
+ private
24
+
25
+ def handle_exceptions_with_appsignal
26
+ handle_exceptions_without_appsignal do
27
+ begin
28
+ yield
29
+ rescue Exception => e # rubocop:disable Lint/RescueException
30
+ Appsignal.set_error(e)
31
+ raise e
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,54 @@
1
+ module Appsignal
2
+ class JSExceptionTransaction
3
+ attr_reader :uuid, :ext
4
+
5
+ def initialize(data)
6
+ @data = data
7
+ @uuid = SecureRandom.uuid
8
+ @ext = Appsignal::Extension.start_transaction(@uuid, Appsignal::Transaction::FRONTEND, 0)
9
+
10
+ set_action
11
+ set_metadata
12
+ set_error
13
+ set_sample_data
14
+ end
15
+
16
+ def set_action
17
+ return unless @data["action"]
18
+ ext.set_action(@data["action"])
19
+ end
20
+
21
+ def set_metadata
22
+ return unless @data["path"]
23
+ ext.set_metadata("path", @data["path"])
24
+ end
25
+
26
+ def set_error
27
+ ext.set_error(
28
+ @data["name"],
29
+ @data["message"] || "",
30
+ Appsignal::Utils.data_generate(@data["backtrace"] || [])
31
+ )
32
+ end
33
+
34
+ def set_sample_data
35
+ {
36
+ :params => @data["params"],
37
+ :session_data => @data["session_data"],
38
+ :environment => @data["environment"],
39
+ :tags => @data["tags"]
40
+ }.each do |key, data|
41
+ next unless data.is_a?(Array) || data.is_a?(Hash)
42
+ ext.set_sample_data(
43
+ key.to_s,
44
+ Appsignal::Utils.data_generate(data)
45
+ )
46
+ end
47
+ end
48
+
49
+ def complete!
50
+ ext.finish(0)
51
+ ext.complete
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,63 @@
1
+ module Appsignal
2
+ # Deploy markers are used on AppSignal.com to indicate changes in an
3
+ # application, "Deploy markers" indicate a deploy of an application.
4
+ #
5
+ # Incidents for exceptions and performance issues will be closed and
6
+ # reopened if they occur again in the new deploy.
7
+ #
8
+ # This class will help send a request to the AppSignal Push API to create a
9
+ # Deploy marker for the application on AppSignal.com.
10
+ #
11
+ # @!attribute [r] marker_data
12
+ # @return [Hash] marker data to send.
13
+ #
14
+ # @!attribute [r] config
15
+ # @return [Appsignal::Config] config to use in the authentication request.
16
+ # Set config does not override data set in {#marker_data}.
17
+ #
18
+ # @see Appsignal::CLI::NotifyOfDeploy
19
+ # @see http://docs.appsignal.com/appsignal/terminology.html#markers
20
+ # Terminology: Deploy marker
21
+ # @api private
22
+ class Marker
23
+ # Path used on the AppSignal Push API
24
+ # https://push.appsignal.com/1/markers
25
+ ACTION = "markers".freeze
26
+
27
+ attr_reader :marker_data, :config
28
+
29
+ # @param marker_data [Hash] see {#marker_data}
30
+ # @option marker_data :environment [String] environment to load
31
+ # configuration for.
32
+ # @option marker_data :name [String] name of the application.
33
+ # @option marker_data :user [String] name of the user that is creating the
34
+ # marker.
35
+ # @option marker_data :revision [String] the revision that has been
36
+ # deployed. E.g. a git commit SHA.
37
+ # @param config [Appsignal::Config]
38
+ def initialize(marker_data, config)
39
+ @marker_data = marker_data
40
+ @config = config
41
+ end
42
+
43
+ # Send a request to create the marker.
44
+ #
45
+ # Prints output to STDOUT.
46
+ #
47
+ # @return [void]
48
+ def transmit
49
+ transmitter = Transmitter.new(ACTION, config)
50
+ puts "Notifying AppSignal of deploy with: "\
51
+ "revision: #{marker_data[:revision]}, user: #{marker_data[:user]}"
52
+
53
+ response = transmitter.transmit(marker_data)
54
+ if response.code == "200"
55
+ puts "AppSignal has been notified of this deploy!"
56
+ else
57
+ raise "#{response.code} at #{transmitter.uri}"
58
+ end
59
+ rescue => e
60
+ puts "Something went wrong while trying to notify AppSignal: #{e}"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,42 @@
1
+ module Appsignal
2
+ # @api private
3
+ class Minutely
4
+ class << self
5
+ # List of probes. Probes can be lamdba's or objects that
6
+ # respond to call.
7
+ def probes
8
+ @@probes ||= []
9
+ end
10
+
11
+ def start
12
+ Thread.new do
13
+ begin
14
+ loop do
15
+ Appsignal.logger.debug("Gathering minutely metrics with #{probes.count} probe(s)")
16
+ probes.each(&:call)
17
+ sleep(wait_time)
18
+ end
19
+ rescue => ex
20
+ Appsignal.logger.error("Error in minutely thread: #{ex}")
21
+ end
22
+ end
23
+ end
24
+
25
+ def wait_time
26
+ 60 - Time.now.sec
27
+ end
28
+
29
+ def add_gc_probe
30
+ probes << GCProbe.new
31
+ end
32
+ end
33
+
34
+ class GCProbe
35
+ def call
36
+ GC.stat.each do |key, value|
37
+ Appsignal.set_process_gauge("gc.#{key}", value)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,49 @@
1
+ require "rack"
2
+
3
+ module Appsignal
4
+ # @api private
5
+ module Rack
6
+ class GenericInstrumentation
7
+ def initialize(app, options = {})
8
+ Appsignal.logger.debug "Initializing Appsignal::Rack::GenericInstrumentation"
9
+ @app = app
10
+ @options = options
11
+ end
12
+
13
+ def call(env)
14
+ if Appsignal.active?
15
+ call_with_appsignal_monitoring(env)
16
+ else
17
+ @app.call(env)
18
+ end
19
+ end
20
+
21
+ def call_with_appsignal_monitoring(env)
22
+ request = ::Rack::Request.new(env)
23
+ transaction = Appsignal::Transaction.create(
24
+ SecureRandom.uuid,
25
+ Appsignal::Transaction::HTTP_REQUEST,
26
+ request
27
+ )
28
+ begin
29
+ Appsignal.instrument("process_action.generic") do
30
+ @app.call(env)
31
+ end
32
+ rescue Exception => error # rubocop:disable Lint/RescueException
33
+ transaction.set_error(error)
34
+ raise error
35
+ ensure
36
+ if env["appsignal.route"]
37
+ transaction.set_action_if_nil(env["appsignal.route"])
38
+ else
39
+ transaction.set_action_if_nil("unknown")
40
+ end
41
+ transaction.set_metadata("path", request.path)
42
+ transaction.set_metadata("method", request.request_method)
43
+ transaction.set_http_or_background_queue_start
44
+ Appsignal::Transaction.complete_current!
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,70 @@
1
+ module Appsignal
2
+ # @api private
3
+ module Rack
4
+ # JavaScript error catching middleware.
5
+ #
6
+ # Listens to the endpoint specified in the `frontend_error_catching_path`
7
+ # configuration option.
8
+ #
9
+ # This is automatically included middleware in Rails apps if the
10
+ # `frontend_error_catching_path` configuration option is active.
11
+ #
12
+ # If AppSignal is not active in the current environment, but does have
13
+ # JavaScript error catching turned on, we assume that a JavaScript script
14
+ # still sends errors to this endpoint. When AppSignal is not active in this
15
+ # scenario this middleware still listens to the endpoint, but won't record
16
+ # the error. It will return HTTP status code 202.
17
+ #
18
+ # @example with a Sinatra app
19
+ # Sinatra::Application.use(Appsignal::Rack::JSExceptionCatcher)
20
+ #
21
+ # @see http://docs.appsignal.com/front-end/error-handling.html
22
+ # @api private
23
+ class JSExceptionCatcher
24
+ def initialize(app, _options = nil)
25
+ Appsignal.logger.debug \
26
+ "Initializing Appsignal::Rack::JSExceptionCatcher"
27
+ @app = app
28
+ end
29
+
30
+ def call(env)
31
+ # Ignore other paths than the error catching path.
32
+ return @app.call(env) unless error_cathing_endpoint?(env)
33
+
34
+ # Prevent raising a 404 not found when a non-active environment posts
35
+ # to this endpoint.
36
+ unless Appsignal.active?
37
+ return [
38
+ 202,
39
+ {},
40
+ ["AppSignal JavaScript error catching endpoint is not active."]
41
+ ]
42
+ end
43
+
44
+ begin
45
+ body = JSON.parse(env["rack.input"].read)
46
+ rescue JSON::ParserError
47
+ return [400, {}, ["Request payload is not valid JSON."]]
48
+ end
49
+
50
+ if body["name"].is_a?(String) && !body["name"].empty?
51
+ transaction = JSExceptionTransaction.new(body)
52
+ transaction.complete!
53
+ code = 200
54
+ else
55
+ Appsignal.logger.debug \
56
+ "JSExceptionCatcher: Could not send exception, 'name' is empty."
57
+ code = 422
58
+ end
59
+
60
+ [code, {}, []]
61
+ end
62
+
63
+ private
64
+
65
+ def error_cathing_endpoint?(env)
66
+ env["PATH_INFO"] == Appsignal.config[:frontend_error_catching_path]
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,51 @@
1
+ require "rack"
2
+
3
+ module Appsignal
4
+ # @api private
5
+ module Rack
6
+ class RailsInstrumentation
7
+ def initialize(app, options = {})
8
+ Appsignal.logger.debug "Initializing Appsignal::Rack::RailsInstrumentation"
9
+ @app = app
10
+ @options = options
11
+ end
12
+
13
+ def call(env)
14
+ if Appsignal.active?
15
+ call_with_appsignal_monitoring(env)
16
+ else
17
+ @app.call(env)
18
+ end
19
+ end
20
+
21
+ def call_with_appsignal_monitoring(env)
22
+ request = ActionDispatch::Request.new(env)
23
+ transaction = Appsignal::Transaction.create(
24
+ request_id(env),
25
+ Appsignal::Transaction::HTTP_REQUEST,
26
+ request,
27
+ :params_method => :filtered_parameters
28
+ )
29
+ begin
30
+ @app.call(env)
31
+ rescue Exception => error # rubocop:disable Lint/RescueException
32
+ transaction.set_error(error)
33
+ raise error
34
+ ensure
35
+ controller = env["action_controller.instance"]
36
+ if controller
37
+ transaction.set_action_if_nil("#{controller.class}##{controller.action_name}")
38
+ end
39
+ transaction.set_http_or_background_queue_start
40
+ transaction.set_metadata("path", request.path)
41
+ transaction.set_metadata("method", request.request_method)
42
+ Appsignal::Transaction.complete_current!
43
+ end
44
+ end
45
+
46
+ def request_id(env)
47
+ env["action_dispatch.request_id"] || SecureRandom.uuid
48
+ end
49
+ end
50
+ end
51
+ end