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.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.rspec +4 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +124 -0
- data/.travis.yml +72 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +639 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +264 -0
- data/Rakefile +214 -0
- data/appsignal.gemspec +42 -0
- data/benchmark.rake +77 -0
- data/bin/appsignal +13 -0
- data/ext/Rakefile +27 -0
- data/ext/agent.yml +64 -0
- data/ext/appsignal_extension.c +692 -0
- data/ext/base.rb +79 -0
- data/ext/extconf.rb +35 -0
- data/gemfiles/capistrano2.gemfile +7 -0
- data/gemfiles/capistrano3.gemfile +7 -0
- data/gemfiles/grape.gemfile +7 -0
- data/gemfiles/no_dependencies.gemfile +5 -0
- data/gemfiles/padrino.gemfile +7 -0
- data/gemfiles/que.gemfile +5 -0
- data/gemfiles/rails-3.2.gemfile +6 -0
- data/gemfiles/rails-4.0.gemfile +6 -0
- data/gemfiles/rails-4.1.gemfile +6 -0
- data/gemfiles/rails-4.2.gemfile +10 -0
- data/gemfiles/rails-5.0.gemfile +5 -0
- data/gemfiles/rails-5.1.gemfile +5 -0
- data/gemfiles/resque.gemfile +12 -0
- data/gemfiles/sequel-435.gemfile +11 -0
- data/gemfiles/sequel.gemfile +11 -0
- data/gemfiles/sinatra.gemfile +6 -0
- data/gemfiles/webmachine.gemfile +5 -0
- data/lib/appsignal.rb +804 -0
- data/lib/appsignal/auth_check.rb +65 -0
- data/lib/appsignal/capistrano.rb +10 -0
- data/lib/appsignal/cli.rb +108 -0
- data/lib/appsignal/cli/demo.rb +63 -0
- data/lib/appsignal/cli/diagnose.rb +500 -0
- data/lib/appsignal/cli/helpers.rb +72 -0
- data/lib/appsignal/cli/install.rb +277 -0
- data/lib/appsignal/cli/notify_of_deploy.rb +113 -0
- data/lib/appsignal/config.rb +287 -0
- data/lib/appsignal/demo.rb +107 -0
- data/lib/appsignal/event_formatter.rb +74 -0
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +24 -0
- data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +14 -0
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +14 -0
- data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +32 -0
- data/lib/appsignal/event_formatter/faraday/request_formatter.rb +19 -0
- data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +89 -0
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
- data/lib/appsignal/extension.rb +63 -0
- data/lib/appsignal/extension/jruby.rb +460 -0
- data/lib/appsignal/garbage_collection_profiler.rb +48 -0
- data/lib/appsignal/hooks.rb +105 -0
- data/lib/appsignal/hooks/action_cable.rb +113 -0
- data/lib/appsignal/hooks/active_support_notifications.rb +52 -0
- data/lib/appsignal/hooks/celluloid.rb +30 -0
- data/lib/appsignal/hooks/data_mapper.rb +18 -0
- data/lib/appsignal/hooks/delayed_job.rb +19 -0
- data/lib/appsignal/hooks/mongo_ruby_driver.rb +21 -0
- data/lib/appsignal/hooks/net_http.rb +29 -0
- data/lib/appsignal/hooks/passenger.rb +22 -0
- data/lib/appsignal/hooks/puma.rb +35 -0
- data/lib/appsignal/hooks/que.rb +21 -0
- data/lib/appsignal/hooks/rake.rb +39 -0
- data/lib/appsignal/hooks/redis.rb +30 -0
- data/lib/appsignal/hooks/sequel.rb +60 -0
- data/lib/appsignal/hooks/shoryuken.rb +43 -0
- data/lib/appsignal/hooks/sidekiq.rb +144 -0
- data/lib/appsignal/hooks/unicorn.rb +40 -0
- data/lib/appsignal/hooks/webmachine.rb +23 -0
- data/lib/appsignal/integrations/capistrano/appsignal.cap +39 -0
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +52 -0
- data/lib/appsignal/integrations/data_mapper.rb +33 -0
- data/lib/appsignal/integrations/delayed_job_plugin.rb +54 -0
- data/lib/appsignal/integrations/grape.rb +53 -0
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +55 -0
- data/lib/appsignal/integrations/object.rb +35 -0
- data/lib/appsignal/integrations/padrino.rb +84 -0
- data/lib/appsignal/integrations/que.rb +43 -0
- data/lib/appsignal/integrations/railtie.rb +41 -0
- data/lib/appsignal/integrations/rake.rb +2 -0
- data/lib/appsignal/integrations/resque.rb +20 -0
- data/lib/appsignal/integrations/resque_active_job.rb +30 -0
- data/lib/appsignal/integrations/sinatra.rb +17 -0
- data/lib/appsignal/integrations/webmachine.rb +38 -0
- data/lib/appsignal/js_exception_transaction.rb +54 -0
- data/lib/appsignal/marker.rb +63 -0
- data/lib/appsignal/minutely.rb +42 -0
- data/lib/appsignal/rack/generic_instrumentation.rb +49 -0
- data/lib/appsignal/rack/js_exception_catcher.rb +70 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +51 -0
- data/lib/appsignal/rack/sinatra_instrumentation.rb +99 -0
- data/lib/appsignal/rack/streaming_listener.rb +73 -0
- data/lib/appsignal/system.rb +81 -0
- data/lib/appsignal/transaction.rb +498 -0
- data/lib/appsignal/transmitter.rb +107 -0
- data/lib/appsignal/utils.rb +127 -0
- data/lib/appsignal/utils/params_sanitizer.rb +59 -0
- data/lib/appsignal/utils/query_params_sanitizer.rb +55 -0
- data/lib/appsignal/version.rb +3 -0
- data/lib/sequel/extensions/appsignal_integration.rb +3 -0
- data/resources/appsignal.yml.erb +39 -0
- data/resources/cacert.pem +3866 -0
- data/spec/.rubocop.yml +7 -0
- data/spec/lib/appsignal/auth_check_spec.rb +80 -0
- data/spec/lib/appsignal/capistrano2_spec.rb +224 -0
- data/spec/lib/appsignal/capistrano3_spec.rb +237 -0
- data/spec/lib/appsignal/cli/demo_spec.rb +67 -0
- data/spec/lib/appsignal/cli/diagnose_spec.rb +988 -0
- data/spec/lib/appsignal/cli/helpers_spec.rb +171 -0
- data/spec/lib/appsignal/cli/install_spec.rb +632 -0
- data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +168 -0
- data/spec/lib/appsignal/cli_spec.rb +56 -0
- data/spec/lib/appsignal/config_spec.rb +637 -0
- data/spec/lib/appsignal/demo_spec.rb +87 -0
- data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +44 -0
- data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +52 -0
- data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +113 -0
- data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +112 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +100 -0
- data/spec/lib/appsignal/extension/jruby_spec.rb +43 -0
- data/spec/lib/appsignal/extension_spec.rb +137 -0
- data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +66 -0
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +370 -0
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +92 -0
- data/spec/lib/appsignal/hooks/celluloid_spec.rb +35 -0
- data/spec/lib/appsignal/hooks/data_mapper_spec.rb +39 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +358 -0
- data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +44 -0
- data/spec/lib/appsignal/hooks/net_http_spec.rb +53 -0
- data/spec/lib/appsignal/hooks/passenger_spec.rb +30 -0
- data/spec/lib/appsignal/hooks/puma_spec.rb +80 -0
- data/spec/lib/appsignal/hooks/que_spec.rb +19 -0
- data/spec/lib/appsignal/hooks/rake_spec.rb +73 -0
- data/spec/lib/appsignal/hooks/redis_spec.rb +55 -0
- data/spec/lib/appsignal/hooks/sequel_spec.rb +46 -0
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +192 -0
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +419 -0
- data/spec/lib/appsignal/hooks/unicorn_spec.rb +52 -0
- data/spec/lib/appsignal/hooks/webmachine_spec.rb +35 -0
- data/spec/lib/appsignal/hooks_spec.rb +195 -0
- data/spec/lib/appsignal/integrations/data_mapper_spec.rb +65 -0
- data/spec/lib/appsignal/integrations/grape_spec.rb +225 -0
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +127 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +249 -0
- data/spec/lib/appsignal/integrations/padrino_spec.rb +323 -0
- data/spec/lib/appsignal/integrations/que_spec.rb +174 -0
- data/spec/lib/appsignal/integrations/railtie_spec.rb +129 -0
- data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +83 -0
- data/spec/lib/appsignal/integrations/resque_spec.rb +92 -0
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +73 -0
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +69 -0
- data/spec/lib/appsignal/js_exception_transaction_spec.rb +128 -0
- data/spec/lib/appsignal/marker_spec.rb +51 -0
- data/spec/lib/appsignal/minutely_spec.rb +50 -0
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +90 -0
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +147 -0
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +117 -0
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +213 -0
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +161 -0
- data/spec/lib/appsignal/system_spec.rb +131 -0
- data/spec/lib/appsignal/transaction_spec.rb +1146 -0
- data/spec/lib/appsignal/transmitter_spec.rb +152 -0
- data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +136 -0
- data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +192 -0
- data/spec/lib/appsignal/utils_spec.rb +150 -0
- data/spec/lib/appsignal_spec.rb +1049 -0
- data/spec/spec_helper.rb +116 -0
- data/spec/support/fixtures/containers/cgroups/docker +14 -0
- data/spec/support/fixtures/containers/cgroups/docker_systemd +8 -0
- data/spec/support/fixtures/containers/cgroups/lxc +10 -0
- data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
- data/spec/support/fixtures/containers/cgroups/none +1 -0
- data/spec/support/fixtures/generated_config.yml +24 -0
- data/spec/support/fixtures/uploaded_file.txt +0 -0
- data/spec/support/helpers/api_request_helper.rb +19 -0
- data/spec/support/helpers/cli_helpers.rb +26 -0
- data/spec/support/helpers/config_helpers.rb +21 -0
- data/spec/support/helpers/dependency_helper.rb +73 -0
- data/spec/support/helpers/directory_helper.rb +27 -0
- data/spec/support/helpers/env_helpers.rb +33 -0
- data/spec/support/helpers/example_exception.rb +13 -0
- data/spec/support/helpers/example_standard_error.rb +13 -0
- data/spec/support/helpers/log_helpers.rb +22 -0
- data/spec/support/helpers/std_streams_helper.rb +66 -0
- data/spec/support/helpers/system_helpers.rb +8 -0
- data/spec/support/helpers/time_helpers.rb +11 -0
- data/spec/support/helpers/transaction_helpers.rb +37 -0
- data/spec/support/matchers/contains_log.rb +7 -0
- data/spec/support/mocks/fake_gc_profiler.rb +19 -0
- data/spec/support/mocks/mock_extension.rb +6 -0
- data/spec/support/project_fixture/config/application.rb +0 -0
- data/spec/support/project_fixture/config/appsignal.yml +32 -0
- data/spec/support/project_fixture/config/environments/development.rb +0 -0
- data/spec/support/project_fixture/config/environments/production.rb +0 -0
- data/spec/support/project_fixture/config/environments/test.rb +0 -0
- data/spec/support/project_fixture/log/.gitkeep +0 -0
- data/spec/support/rails/my_app.rb +6 -0
- data/spec/support/shared_examples/instrument.rb +43 -0
- data/spec/support/stubs/delayed_job.rb +0 -0
- metadata +483 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
# {Appsignal::GarbageCollectionProfiler} wraps Ruby's `GC::Profiler` to be
|
|
3
|
+
# able to track garbage collection time for multiple transactions, while
|
|
4
|
+
# constantly clearing `GC::Profiler`'s total_time to make sure it doesn't
|
|
5
|
+
# leak memory by keeping garbage collection run samples in memory.
|
|
6
|
+
#
|
|
7
|
+
# @api private
|
|
8
|
+
class GarbageCollectionProfiler
|
|
9
|
+
def self.lock
|
|
10
|
+
@lock ||= Mutex.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@total_time = 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Whenever {#total_time} is called, the current `GC::Profiler#total_time`
|
|
18
|
+
# gets added to `@total_time`, after which `GC::Profiler.clear` is called
|
|
19
|
+
# to prevent it from leaking memory. A class-level lock is used to make
|
|
20
|
+
# sure garbage collection time is never counted more than once.
|
|
21
|
+
#
|
|
22
|
+
# Whenever `@total_time` gets above two billion milliseconds (about 23
|
|
23
|
+
# days), it's reset to make sure the result fits in a signed 32-bit
|
|
24
|
+
# integer.
|
|
25
|
+
#
|
|
26
|
+
# @return [Integer]
|
|
27
|
+
def total_time
|
|
28
|
+
lock.synchronize do
|
|
29
|
+
@total_time += (internal_profiler.total_time * 1000).round
|
|
30
|
+
internal_profiler.clear
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
@total_time = 0 if @total_time > 2_000_000_000
|
|
34
|
+
|
|
35
|
+
@total_time
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def internal_profiler
|
|
41
|
+
GC::Profiler
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def lock
|
|
45
|
+
self.class.lock
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
# @api private
|
|
3
|
+
class Hooks
|
|
4
|
+
class << self
|
|
5
|
+
def register(name, hook)
|
|
6
|
+
hooks[name] = hook
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def load_hooks
|
|
10
|
+
hooks.each do |name, hook|
|
|
11
|
+
hook.try_to_install(name)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def hooks
|
|
16
|
+
@hooks ||= {}
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Hook
|
|
21
|
+
def self.register(name, hook = self)
|
|
22
|
+
Appsignal::Hooks.register(name, hook.new)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
@installed = false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def try_to_install(name)
|
|
30
|
+
if dependencies_present? && !installed?
|
|
31
|
+
Appsignal.logger.info("Installing #{name} hook")
|
|
32
|
+
begin
|
|
33
|
+
install
|
|
34
|
+
@installed = true
|
|
35
|
+
rescue => ex
|
|
36
|
+
Appsignal.logger.error("Error while installing #{name} hook: #{ex}")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def installed?
|
|
42
|
+
@installed
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def dependencies_present?
|
|
46
|
+
raise NotImplementedError
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def install
|
|
50
|
+
raise NotImplementedError
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
module Helpers
|
|
55
|
+
def string_or_inspect(string_or_other)
|
|
56
|
+
if string_or_other.is_a?(String)
|
|
57
|
+
string_or_other
|
|
58
|
+
else
|
|
59
|
+
string_or_other.inspect
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def truncate(text)
|
|
64
|
+
text.size > 200 ? "#{text[0...197]}..." : text
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def extract_value(object_or_hash, field, default_value = nil, convert_to_s = false)
|
|
68
|
+
value =
|
|
69
|
+
if object_or_hash.respond_to?(:[])
|
|
70
|
+
begin
|
|
71
|
+
object_or_hash[field]
|
|
72
|
+
rescue NameError
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
75
|
+
elsif object_or_hash.respond_to?(field)
|
|
76
|
+
object_or_hash.send(field)
|
|
77
|
+
end || default_value
|
|
78
|
+
|
|
79
|
+
if convert_to_s
|
|
80
|
+
value.to_s
|
|
81
|
+
else
|
|
82
|
+
value
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
require "appsignal/hooks/action_cable"
|
|
90
|
+
require "appsignal/hooks/active_support_notifications"
|
|
91
|
+
require "appsignal/hooks/celluloid"
|
|
92
|
+
require "appsignal/hooks/delayed_job"
|
|
93
|
+
require "appsignal/hooks/net_http"
|
|
94
|
+
require "appsignal/hooks/passenger"
|
|
95
|
+
require "appsignal/hooks/puma"
|
|
96
|
+
require "appsignal/hooks/rake"
|
|
97
|
+
require "appsignal/hooks/redis"
|
|
98
|
+
require "appsignal/hooks/sequel"
|
|
99
|
+
require "appsignal/hooks/shoryuken"
|
|
100
|
+
require "appsignal/hooks/sidekiq"
|
|
101
|
+
require "appsignal/hooks/unicorn"
|
|
102
|
+
require "appsignal/hooks/mongo_ruby_driver"
|
|
103
|
+
require "appsignal/hooks/webmachine"
|
|
104
|
+
require "appsignal/hooks/data_mapper"
|
|
105
|
+
require "appsignal/hooks/que"
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class ActionCableHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :action_cable
|
|
6
|
+
|
|
7
|
+
REQUEST_ID = "_appsignal_action_cable.request_id".freeze
|
|
8
|
+
|
|
9
|
+
def dependencies_present?
|
|
10
|
+
defined?(::ActiveSupport::Notifications::Instrumenter) &&
|
|
11
|
+
defined?(::ActionCable)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def install
|
|
15
|
+
patch_perform_action
|
|
16
|
+
install_callbacks
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def patch_perform_action
|
|
22
|
+
ActionCable::Channel::Base.class_eval do
|
|
23
|
+
alias_method :original_perform_action, :perform_action
|
|
24
|
+
|
|
25
|
+
def perform_action(*args, &block)
|
|
26
|
+
# The request is only the original websocket request
|
|
27
|
+
env = connection.env
|
|
28
|
+
request = ActionDispatch::Request.new(env)
|
|
29
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID] ||=
|
|
30
|
+
request.request_id || SecureRandom.uuid
|
|
31
|
+
|
|
32
|
+
transaction = Appsignal::Transaction.create(
|
|
33
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID],
|
|
34
|
+
Appsignal::Transaction::ACTION_CABLE,
|
|
35
|
+
request
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
begin
|
|
39
|
+
original_perform_action(*args, &block)
|
|
40
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
|
41
|
+
transaction.set_error(exception)
|
|
42
|
+
raise exception
|
|
43
|
+
ensure
|
|
44
|
+
transaction.params = args.first
|
|
45
|
+
transaction.set_action_if_nil("#{self.class}##{args.first["action"]}")
|
|
46
|
+
transaction.set_metadata("path", request.path)
|
|
47
|
+
transaction.set_metadata("method", "websocket")
|
|
48
|
+
Appsignal::Transaction.complete_current!
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def install_callbacks
|
|
55
|
+
ActionCable::Channel::Base.set_callback :subscribe, :around, :prepend => true do |channel, inner|
|
|
56
|
+
# The request is only the original websocket request
|
|
57
|
+
env = channel.connection.env
|
|
58
|
+
request = ActionDispatch::Request.new(env)
|
|
59
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID] ||=
|
|
60
|
+
request.request_id || SecureRandom.uuid
|
|
61
|
+
|
|
62
|
+
transaction = Appsignal::Transaction.create(
|
|
63
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID],
|
|
64
|
+
Appsignal::Transaction::ACTION_CABLE,
|
|
65
|
+
request
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
begin
|
|
69
|
+
Appsignal.instrument "subscribed.action_cable" do
|
|
70
|
+
inner.call
|
|
71
|
+
end
|
|
72
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
|
73
|
+
transaction.set_error(exception)
|
|
74
|
+
raise exception
|
|
75
|
+
ensure
|
|
76
|
+
transaction.set_action_if_nil("#{channel.class}#subscribed")
|
|
77
|
+
transaction.set_metadata("path", request.path)
|
|
78
|
+
transaction.set_metadata("method", "websocket")
|
|
79
|
+
Appsignal::Transaction.complete_current!
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
ActionCable::Channel::Base.set_callback :unsubscribe, :around, :prepend => true do |channel, inner|
|
|
84
|
+
# The request is only the original websocket request
|
|
85
|
+
env = channel.connection.env
|
|
86
|
+
request = ActionDispatch::Request.new(env)
|
|
87
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID] ||=
|
|
88
|
+
request.request_id || SecureRandom.uuid
|
|
89
|
+
|
|
90
|
+
transaction = Appsignal::Transaction.create(
|
|
91
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID],
|
|
92
|
+
Appsignal::Transaction::ACTION_CABLE,
|
|
93
|
+
request
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
begin
|
|
97
|
+
Appsignal.instrument "unsubscribed.action_cable" do
|
|
98
|
+
inner.call
|
|
99
|
+
end
|
|
100
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
|
101
|
+
transaction.set_error(exception)
|
|
102
|
+
raise exception
|
|
103
|
+
ensure
|
|
104
|
+
transaction.set_action_if_nil("#{channel.class}#unsubscribed")
|
|
105
|
+
transaction.set_metadata("path", request.path)
|
|
106
|
+
transaction.set_metadata("method", "websocket")
|
|
107
|
+
Appsignal::Transaction.complete_current!
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class ActiveSupportNotificationsHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :active_support_notifications
|
|
6
|
+
|
|
7
|
+
BANG = "!".freeze
|
|
8
|
+
|
|
9
|
+
def dependencies_present?
|
|
10
|
+
defined?(::ActiveSupport::Notifications::Instrumenter)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def install
|
|
14
|
+
::ActiveSupport::Notifications.class_eval do
|
|
15
|
+
def self.instrument(name, payload = {})
|
|
16
|
+
# Don't check the notifier if any subscriber is listening:
|
|
17
|
+
# AppSignal is listening
|
|
18
|
+
instrumenter.instrument(name, payload) do
|
|
19
|
+
yield payload if block_given?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
::ActiveSupport::Notifications::Instrumenter.class_eval do
|
|
25
|
+
alias instrument_without_appsignal instrument
|
|
26
|
+
|
|
27
|
+
def instrument(name, payload = {}, &block)
|
|
28
|
+
# Events that start with a bang are internal to Rails
|
|
29
|
+
instrument_this = name[0] != BANG
|
|
30
|
+
|
|
31
|
+
if instrument_this
|
|
32
|
+
transaction = Appsignal::Transaction.current
|
|
33
|
+
transaction.start_event
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
instrument_without_appsignal(name, payload, &block)
|
|
37
|
+
ensure
|
|
38
|
+
if instrument_this
|
|
39
|
+
title, body, body_format = Appsignal::EventFormatter.format(name, payload)
|
|
40
|
+
transaction.finish_event(
|
|
41
|
+
name.to_s,
|
|
42
|
+
title,
|
|
43
|
+
body,
|
|
44
|
+
body_format
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class CelluloidHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :celluloid
|
|
6
|
+
|
|
7
|
+
def dependencies_present?
|
|
8
|
+
defined?(::Celluloid)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def install
|
|
12
|
+
# Some versions of Celluloid have race conditions while exiting
|
|
13
|
+
# that can result in a dead lock. We stop appsignal before shutting
|
|
14
|
+
# down Celluloid so we're sure our thread does not aggravate this situation.
|
|
15
|
+
# This way we also make sure any outstanding transactions get flushed.
|
|
16
|
+
|
|
17
|
+
::Celluloid.class_eval do
|
|
18
|
+
class << self
|
|
19
|
+
alias shutdown_without_appsignal shutdown
|
|
20
|
+
|
|
21
|
+
def shutdown
|
|
22
|
+
Appsignal.stop("celluloid")
|
|
23
|
+
shutdown_without_appsignal
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class DataMapperHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :data_mapper
|
|
6
|
+
|
|
7
|
+
def dependencies_present?
|
|
8
|
+
defined?(::DataMapper) &&
|
|
9
|
+
defined?(::DataObjects::Connection)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def install
|
|
13
|
+
require "appsignal/integrations/data_mapper"
|
|
14
|
+
::DataObjects::Connection.send(:include, Appsignal::Hooks::DataMapperLogListener)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class DelayedJobHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :delayed_job
|
|
6
|
+
|
|
7
|
+
def dependencies_present?
|
|
8
|
+
defined?(::Delayed::Plugin)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def install
|
|
12
|
+
# The DJ plugin is a subclass of Delayed::Plugin, so we can only
|
|
13
|
+
# require this code if we're actually installing.
|
|
14
|
+
require "appsignal/integrations/delayed_job_plugin"
|
|
15
|
+
::Delayed::Worker.plugins << Appsignal::Hooks::DelayedJobPlugin
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class MongoRubyDriverHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :mongo_ruby_driver
|
|
6
|
+
|
|
7
|
+
def dependencies_present?
|
|
8
|
+
defined?(::Mongo::Monitoring::Global)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def install
|
|
12
|
+
require "appsignal/integrations/mongo_ruby_driver"
|
|
13
|
+
|
|
14
|
+
Mongo::Monitoring::Global.subscribe(
|
|
15
|
+
Mongo::Monitoring::COMMAND,
|
|
16
|
+
Appsignal::Hooks::MongoMonitorSubscriber.new
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
|
|
3
|
+
module Appsignal
|
|
4
|
+
class Hooks
|
|
5
|
+
# @api private
|
|
6
|
+
class NetHttpHook < Appsignal::Hooks::Hook
|
|
7
|
+
register :net_http
|
|
8
|
+
|
|
9
|
+
def dependencies_present?
|
|
10
|
+
Appsignal.config && Appsignal.config[:instrument_net_http]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def install
|
|
14
|
+
Net::HTTP.class_eval do
|
|
15
|
+
alias request_without_appsignal request
|
|
16
|
+
|
|
17
|
+
def request(request, body = nil, &block)
|
|
18
|
+
Appsignal.instrument(
|
|
19
|
+
"request.net_http",
|
|
20
|
+
"#{request.method} #{use_ssl? ? "https" : "http"}://#{request["host"] || address}"
|
|
21
|
+
) do
|
|
22
|
+
request_without_appsignal(request, body, &block)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class PassengerHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :passenger
|
|
6
|
+
|
|
7
|
+
def dependencies_present?
|
|
8
|
+
defined?(::PhusionPassenger)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def install
|
|
12
|
+
::PhusionPassenger.on_event(:starting_worker_process) do |_forked|
|
|
13
|
+
Appsignal.forked
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
::PhusionPassenger.on_event(:stopping_worker_process) do
|
|
17
|
+
Appsignal.stop("passenger")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|