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,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