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,52 @@
1
+ module Appsignal
2
+ # @todo Move to sub-namespace
3
+ # @api private
4
+ class Capistrano
5
+ def self.tasks(config)
6
+ config.load do # rubocop:disable Metrics/BlockLength
7
+ after "deploy", "appsignal:deploy"
8
+ after "deploy:migrations", "appsignal:deploy"
9
+
10
+ namespace :appsignal do
11
+ task :deploy do
12
+ env = fetch(:appsignal_env, fetch(:stage, fetch(:rails_env, fetch(:rack_env, "production"))))
13
+ user = fetch(:appsignal_user, ENV["USER"] || ENV["USERNAME"])
14
+ revision = fetch(:appsignal_revision, fetch(:current_revision))
15
+
16
+ appsignal_config = Appsignal::Config.new(
17
+ ENV["PWD"],
18
+ env,
19
+ {},
20
+ Logger.new(StringIO.new)
21
+ ).tap do |c|
22
+ fetch(:appsignal_config, {}).each do |key, value|
23
+ c[key] = value
24
+ end
25
+ c.validate
26
+ end
27
+
28
+ if appsignal_config && appsignal_config.active?
29
+ marker_data = {
30
+ :revision => revision,
31
+ :user => user
32
+ }
33
+
34
+ marker = Marker.new(marker_data, appsignal_config)
35
+ if config.dry_run
36
+ puts "Dry run: AppSignal deploy marker not actually sent."
37
+ else
38
+ marker.transmit
39
+ end
40
+ else
41
+ puts "Not notifying of deploy, config is not active for environment: #{env}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ if ::Capistrano::Configuration.instance
51
+ Appsignal::Capistrano.tasks(::Capistrano::Configuration.instance)
52
+ end
@@ -0,0 +1,33 @@
1
+ module Appsignal
2
+ class Hooks
3
+ module DataMapperLogListener
4
+ SQL_CLASSES = [
5
+ "DataObjects::SqlServer::Connection",
6
+ "DataObjects::Sqlite3::Connection",
7
+ "DataObjects::Mysql::Connection",
8
+ "DataObjects::Postgres::Connection"
9
+ ].freeze
10
+
11
+ def log(message)
12
+ # If scheme is SQL-like, try to sanitize it, otherwise clear the body
13
+ if SQL_CLASSES.include?(self.class.to_s)
14
+ body_content = message.query
15
+ body_format = Appsignal::EventFormatter::SQL_BODY_FORMAT
16
+ else
17
+ body_content = ""
18
+ body_format = Appsignal::EventFormatter::DEFAULT
19
+ end
20
+
21
+ # Record event
22
+ Appsignal::Transaction.current.record_event(
23
+ "query.data_mapper",
24
+ "DataMapper Query",
25
+ body_content,
26
+ message.duration,
27
+ body_format
28
+ )
29
+ super
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ module Appsignal
2
+ class Hooks
3
+ # @api private
4
+ class DelayedJobPlugin < ::Delayed::Plugin
5
+ extend Appsignal::Hooks::Helpers
6
+
7
+ callbacks do |lifecycle|
8
+ lifecycle.around(:invoke_job) do |job, &block|
9
+ invoke_with_instrumentation(job, block)
10
+ end
11
+
12
+ lifecycle.after(:execute) do |_execute|
13
+ Appsignal.stop("delayed job")
14
+ end
15
+ end
16
+
17
+ def self.invoke_with_instrumentation(job, block)
18
+ payload = job.payload_object
19
+
20
+ if payload.respond_to? :job_data
21
+ # ActiveJob
22
+ job_data = payload.job_data
23
+ args = job_data.fetch("arguments", {})
24
+ class_name = job_data["job_class"]
25
+ method_name = "perform"
26
+ else
27
+ # Delayed Job
28
+ args = extract_value(job.payload_object, :args, {})
29
+ class_and_method_name = extract_value(job.payload_object, :appsignal_name, job.name)
30
+ class_name, method_name = class_and_method_name.split("#")
31
+ end
32
+
33
+ params = Appsignal::Utils::ParamsSanitizer.sanitize args,
34
+ :filter_parameters => Appsignal.config[:filter_parameters]
35
+
36
+ Appsignal.monitor_transaction(
37
+ "perform_job.delayed_job",
38
+ :class => class_name,
39
+ :method => method_name,
40
+ :metadata => {
41
+ :id => extract_value(job, :id, nil, true),
42
+ :queue => extract_value(job, :queue),
43
+ :priority => extract_value(job, :priority, 0),
44
+ :attempts => extract_value(job, :attempts, 0)
45
+ },
46
+ :params => params,
47
+ :queue_start => extract_value(job, :run_at)
48
+ ) do
49
+ block.call(job)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,53 @@
1
+ module Appsignal
2
+ # @todo Move to sub-namespace
3
+ # @api private
4
+ module Grape
5
+ class Middleware < ::Grape::Middleware::Base
6
+ def call(env)
7
+ if Appsignal.active?
8
+ call_with_appsignal_monitoring(env)
9
+ else
10
+ app.call(env)
11
+ end
12
+ end
13
+
14
+ def call_with_appsignal_monitoring(env)
15
+ request = ::Rack::Request.new(env)
16
+ transaction = Appsignal::Transaction.create(
17
+ SecureRandom.uuid,
18
+ Appsignal::Transaction::HTTP_REQUEST,
19
+ request
20
+ )
21
+ begin
22
+ app.call(env)
23
+ rescue Exception => error # rubocop:disable Lint/RescueException
24
+ transaction.set_error(error)
25
+ raise error
26
+ ensure
27
+ request_method = request.request_method.to_s.upcase
28
+ path = request.path # Path without namespaces
29
+ endpoint = env["api.endpoint"]
30
+
31
+ if endpoint && endpoint.options
32
+ options = endpoint.options
33
+ request_method = options[:method].first.to_s.upcase
34
+ klass = options[:for]
35
+ namespace = endpoint.namespace
36
+ namespace = "" if namespace == "/"
37
+
38
+ path = options[:path].first.to_s
39
+ path = "/#{path}" if path[0] != "/"
40
+ path = "#{namespace}#{path}"
41
+
42
+ transaction.set_action_if_nil("#{request_method}::#{klass}##{path}")
43
+ end
44
+
45
+ transaction.set_http_or_background_queue_start
46
+ transaction.set_metadata("path", path)
47
+ transaction.set_metadata("method", request_method)
48
+ Appsignal::Transaction.complete_current!
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,55 @@
1
+ module Appsignal
2
+ class Hooks
3
+ # @api private
4
+ class MongoMonitorSubscriber
5
+ # Called by Mongo::Monitor when query starts
6
+ def started(event)
7
+ transaction = Appsignal::Transaction.current
8
+ return if transaction.nil_transaction?
9
+ return if transaction.paused?
10
+
11
+ # Format the command
12
+ command = Appsignal::EventFormatter::MongoRubyDriver::QueryFormatter
13
+ .format(event.command_name, event.command)
14
+
15
+ # Store the query on the transaction, we need it when the event finishes
16
+ store = transaction.store("mongo_driver")
17
+ store[event.request_id] = command
18
+
19
+ # Start this event
20
+ transaction.start_event
21
+ end
22
+
23
+ # Called by Mongo::Monitor when query succeeds
24
+ def succeeded(event)
25
+ # Finish the event as succeeded
26
+ finish("SUCCEEDED", event)
27
+ end
28
+
29
+ # Called by Mongo::Monitor when query fails
30
+ def failed(event)
31
+ # Finish the event as failed
32
+ finish("FAILED", event)
33
+ end
34
+
35
+ # Finishes the event in the AppSignal extension
36
+ def finish(result, event)
37
+ transaction = Appsignal::Transaction.current
38
+ return if transaction.nil_transaction?
39
+ return if transaction.paused?
40
+
41
+ # Get the query from the transaction store
42
+ store = transaction.store("mongo_driver")
43
+ command = store.delete(event.request_id) || {}
44
+
45
+ # Finish the event in the extension.
46
+ transaction.finish_event(
47
+ "query.mongodb",
48
+ "#{event.command_name} | #{event.database_name} | #{result}",
49
+ Appsignal::Utils.data_generate(command),
50
+ Appsignal::EventFormatter::DEFAULT
51
+ )
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,35 @@
1
+ class Object
2
+ def self.appsignal_instrument_class_method(method_name, options = {})
3
+ singleton_class.send \
4
+ :alias_method, "appsignal_uninstrumented_#{method_name}", method_name
5
+ singleton_class.send(:define_method, method_name) do |*args, &block|
6
+ name = options.fetch(:name) do
7
+ "#{method_name}.class_method.#{appsignal_reverse_class_name}.other"
8
+ end
9
+ Appsignal.instrument name do
10
+ send "appsignal_uninstrumented_#{method_name}", *args, &block
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.appsignal_instrument_method(method_name, options = {})
16
+ alias_method "appsignal_uninstrumented_#{method_name}", method_name
17
+ define_method method_name do |*args, &block|
18
+ name = options.fetch(:name) do
19
+ "#{method_name}.#{appsignal_reverse_class_name}.other"
20
+ end
21
+ Appsignal.instrument name do
22
+ send "appsignal_uninstrumented_#{method_name}", *args, &block
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.appsignal_reverse_class_name
28
+ return "AnonymousClass" unless name
29
+ name.split("::").reverse.join(".")
30
+ end
31
+
32
+ def appsignal_reverse_class_name
33
+ self.class.appsignal_reverse_class_name
34
+ end
35
+ end
@@ -0,0 +1,84 @@
1
+ require "appsignal"
2
+
3
+ module Appsignal
4
+ module Integrations
5
+ # @api private
6
+ module PadrinoPlugin
7
+ def self.init
8
+ Appsignal.logger.info("Loading Padrino (#{Padrino::VERSION}) integration")
9
+
10
+ root = Padrino.mounted_root
11
+ Appsignal.config = Appsignal::Config.new(root, Padrino.env)
12
+
13
+ Appsignal.start_logger
14
+ Appsignal.start
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ module Padrino::Routing::InstanceMethods
21
+ alias route_without_appsignal route!
22
+
23
+ def route!(base = settings, pass_block = nil)
24
+ if !Appsignal.active? || env["sinatra.static_file"]
25
+ return route_without_appsignal(base, pass_block)
26
+ end
27
+
28
+ transaction = Appsignal::Transaction.create(
29
+ SecureRandom.uuid,
30
+ Appsignal::Transaction::HTTP_REQUEST,
31
+ request
32
+ )
33
+ begin
34
+ Appsignal.instrument("process_action.padrino") do
35
+ route_without_appsignal(base, pass_block)
36
+ end
37
+ rescue Exception => error # rubocop:disable Lint/RescueException
38
+ transaction.set_error(error)
39
+ raise error
40
+ ensure
41
+ transaction.set_action_if_nil(get_payload_action(request))
42
+ transaction.set_metadata("path", request.path)
43
+ transaction.set_metadata("method", request.request_method)
44
+ transaction.set_http_or_background_queue_start
45
+ Appsignal::Transaction.complete_current!
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def get_payload_action(request)
52
+ # Short-circut is there's no request object to obtain information from
53
+ return settings.name.to_s unless request
54
+
55
+ # Newer versions expose the action / controller on the request class.
56
+ # Newer versions also still expose a route_obj so we must prioritize the
57
+ # action/fullpath methods.
58
+ # The `request.action` and `request.controller` values are `nil` when a
59
+ # endpoint is not found, `""` if not specified by the user.
60
+ controller_name = request.controller if request.respond_to?(:controller)
61
+ action_name = request.action if request.respond_to?(:action)
62
+ action_name ||= ""
63
+ if action_name.empty? && request.respond_to?(:fullpath)
64
+ action_name = request.fullpath
65
+ end
66
+
67
+ unless action_name.empty?
68
+ return "#{settings.name}:#{controller_name}##{action_name}"
69
+ end
70
+
71
+ # Older versions of Padrino work with a route object
72
+ if request.respond_to?(:route_obj) && request.route_obj
73
+ return "#{settings.name}:#{request.route_obj.original_path}"
74
+ end
75
+
76
+ # Fall back to the application name if we haven't found an action name in
77
+ # any previous methods.
78
+ settings.name.to_s
79
+ end
80
+ end
81
+
82
+ Padrino.after_load do
83
+ Appsignal::Integrations::PadrinoPlugin.init
84
+ end
@@ -0,0 +1,43 @@
1
+ module Appsignal
2
+ module Integrations
3
+ module QuePlugin
4
+ def self.included(base)
5
+ base.class_eval do
6
+ def _run_with_appsignal
7
+ env = {
8
+ :metadata => {
9
+ :id => attrs[:job_id],
10
+ :queue => attrs[:queue],
11
+ :run_at => attrs[:run_at].to_s,
12
+ :priority => attrs[:priority],
13
+ :attempts => attrs[:error_count].to_i
14
+ },
15
+ :params => attrs[:args]
16
+ }
17
+
18
+ request = Appsignal::Transaction::GenericRequest.new(env)
19
+
20
+ transaction = Appsignal::Transaction.create(
21
+ SecureRandom.uuid,
22
+ Appsignal::Transaction::BACKGROUND_JOB,
23
+ request
24
+ )
25
+
26
+ begin
27
+ Appsignal.instrument("perform_job.que") { _run_without_appsignal }
28
+ rescue Exception => error # rubocop:disable Lint/RescueException
29
+ transaction.set_error(error)
30
+ raise error
31
+ ensure
32
+ transaction.set_action "#{attrs[:job_class]}#run"
33
+ Appsignal::Transaction.complete_current!
34
+ end
35
+ end
36
+
37
+ alias_method :_run_without_appsignal, :_run
38
+ alias_method :_run, :_run_with_appsignal
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ Appsignal.logger.info("Loading Rails (#{Rails.version}) integration")
2
+
3
+ require "appsignal/rack/rails_instrumentation"
4
+
5
+ module Appsignal
6
+ module Integrations
7
+ # @api private
8
+ class Railtie < ::Rails::Railtie
9
+ initializer "appsignal.configure_rails_initialization" do |app|
10
+ Appsignal::Integrations::Railtie.initialize_appsignal(app)
11
+ end
12
+
13
+ def self.initialize_appsignal(app)
14
+ # Load config
15
+ Appsignal.config = Appsignal::Config.new(
16
+ Rails.root,
17
+ Rails.env,
18
+ :name => Rails.application.class.parent_name,
19
+ :log_path => Rails.root.join("log")
20
+ )
21
+
22
+ # Start logger
23
+ Appsignal.start_logger
24
+
25
+ app.middleware.insert_after(
26
+ ActionDispatch::DebugExceptions,
27
+ Appsignal::Rack::RailsInstrumentation
28
+ )
29
+
30
+ if Appsignal.config[:enable_frontend_error_catching]
31
+ app.middleware.insert_before(
32
+ Appsignal::Rack::RailsInstrumentation,
33
+ Appsignal::Rack::JSExceptionCatcher
34
+ )
35
+ end
36
+
37
+ Appsignal.start
38
+ end
39
+ end
40
+ end
41
+ end