appsignal 3.4.4 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/.semaphore/semaphore.yml +683 -52
- data/CHANGELOG.md +353 -4
- data/README.md +3 -0
- data/Rakefile +4 -2
- data/appsignal.gemspec +1 -1
- data/build_matrix.yml +27 -13
- data/ext/Rakefile +8 -1
- data/ext/agent.rb +27 -27
- data/ext/appsignal_extension.c +0 -24
- data/ext/base.rb +5 -2
- data/gemfiles/dry-monitor.gemfile +5 -0
- data/gemfiles/rails-7.1.gemfile +7 -0
- data/gemfiles/redis-4.gemfile +5 -0
- data/gemfiles/redis-5.gemfile +6 -0
- data/lib/appsignal/auth_check.rb +1 -1
- data/lib/appsignal/cli/diagnose/paths.rb +33 -10
- data/lib/appsignal/cli/diagnose.rb +15 -1
- data/lib/appsignal/config.rb +72 -7
- data/lib/appsignal/demo.rb +1 -1
- data/lib/appsignal/environment.rb +24 -13
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/rom/sql_formatter.rb +18 -0
- data/lib/appsignal/event_formatter/sequel/sql_formatter.rb +1 -1
- data/lib/appsignal/event_formatter.rb +2 -2
- data/lib/appsignal/extension/jruby.rb +4 -17
- data/lib/appsignal/extension.rb +1 -1
- data/lib/appsignal/heartbeat.rb +71 -0
- data/lib/appsignal/helpers/instrumentation.rb +10 -10
- data/lib/appsignal/helpers/metrics.rb +15 -13
- data/lib/appsignal/hooks/active_job.rb +9 -1
- data/lib/appsignal/hooks/active_support_notifications.rb +18 -9
- data/lib/appsignal/hooks/dry_monitor.rb +20 -0
- data/lib/appsignal/hooks/redis.rb +1 -0
- data/lib/appsignal/hooks/redis_client.rb +28 -0
- data/lib/appsignal/hooks.rb +4 -2
- data/lib/appsignal/integrations/active_support_notifications.rb +26 -0
- data/lib/appsignal/integrations/dry_monitor.rb +22 -0
- data/lib/appsignal/integrations/hanami.rb +1 -1
- data/lib/appsignal/integrations/padrino.rb +1 -1
- data/lib/appsignal/integrations/railtie.rb +28 -6
- data/lib/appsignal/integrations/redis_client.rb +20 -0
- data/lib/appsignal/integrations/sidekiq.rb +2 -2
- data/lib/appsignal/integrations/sinatra.rb +1 -1
- data/lib/appsignal/logger.rb +7 -5
- data/lib/appsignal/minutely.rb +4 -4
- data/lib/appsignal/probes/gvl.rb +1 -1
- data/lib/appsignal/probes/helpers.rb +1 -1
- data/lib/appsignal/probes/mri.rb +1 -1
- data/lib/appsignal/probes/sidekiq.rb +10 -8
- data/lib/appsignal/rack/generic_instrumentation.rb +1 -1
- data/lib/appsignal/rack/rails_instrumentation.rb +2 -2
- data/lib/appsignal/rack/sinatra_instrumentation.rb +5 -4
- data/lib/appsignal/rack/streaming_listener.rb +1 -1
- data/lib/appsignal/span.rb +2 -2
- data/lib/appsignal/transaction.rb +69 -14
- data/lib/appsignal/utils/deprecation_message.rb +2 -2
- data/lib/appsignal/utils/hash_sanitizer.rb +21 -9
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +38 -31
- data/lib/puma/plugin/appsignal.rb +1 -1
- data/resources/cacert.pem +321 -159
- data/spec/lib/appsignal/capistrano2_spec.rb +2 -2
- data/spec/lib/appsignal/capistrano3_spec.rb +2 -2
- data/spec/lib/appsignal/cli/diagnose/utils_spec.rb +11 -0
- data/spec/lib/appsignal/cli/diagnose_spec.rb +70 -13
- data/spec/lib/appsignal/config_spec.rb +75 -18
- data/spec/lib/appsignal/environment_spec.rb +3 -3
- data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +1 -1
- data/spec/lib/appsignal/event_formatter/rom/sql_formatter_spec.rb +22 -0
- data/spec/lib/appsignal/heartbeat_spec.rb +89 -0
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +6 -0
- data/spec/lib/appsignal/hooks/activejob_spec.rb +26 -1
- data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +104 -0
- data/spec/lib/appsignal/hooks/redis_client_spec.rb +238 -0
- data/spec/lib/appsignal/hooks/redis_spec.rb +98 -76
- data/spec/lib/appsignal/hooks/resque_spec.rb +1 -1
- data/spec/lib/appsignal/hooks_spec.rb +5 -5
- data/spec/lib/appsignal/integrations/railtie_spec.rb +128 -59
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +20 -15
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +2 -2
- data/spec/lib/appsignal/minutely_spec.rb +2 -2
- data/spec/lib/appsignal/probes/sidekiq_spec.rb +29 -6
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +1 -1
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +163 -71
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +1 -0
- data/spec/lib/appsignal/transaction_spec.rb +139 -10
- data/spec/lib/appsignal/utils/hash_sanitizer_spec.rb +42 -4
- data/spec/lib/appsignal_spec.rb +63 -61
- data/spec/lib/puma/appsignal_spec.rb +1 -1
- data/spec/spec_helper.rb +7 -7
- data/spec/support/fixtures/projects/valid/config/appsignal.yml +3 -3
- data/spec/support/helpers/config_helpers.rb +6 -2
- data/spec/support/helpers/dependency_helper.rb +13 -1
- data/spec/support/helpers/log_helpers.rb +2 -2
- data/spec/support/helpers/rails_helper.rb +28 -0
- data/spec/support/matchers/have_colorized_text.rb +1 -1
- metadata +19 -5
- data/ext/._appsignal-agent +0 -0
@@ -10,9 +10,9 @@ module Appsignal
|
|
10
10
|
#
|
11
11
|
# The value of the environment metadata is given as a block that captures
|
12
12
|
# errors that might be raised while fetching the value. It will not
|
13
|
-
# re-raise errors, but instead log them using the
|
14
|
-
# ensures AppSignal will not cause an
|
15
|
-
# collecting this metadata.
|
13
|
+
# re-raise errors, but instead log them using the
|
14
|
+
# {Appsignal.internal_logger}. This ensures AppSignal will not cause an
|
15
|
+
# error in the application when collecting this metadata.
|
16
16
|
#
|
17
17
|
# @example Reporting a key and value
|
18
18
|
# Appsignal::Environment.report("ruby_version") { RUBY_VERSION }
|
@@ -34,8 +34,8 @@ module Appsignal
|
|
34
34
|
when String
|
35
35
|
key
|
36
36
|
else
|
37
|
-
Appsignal.
|
38
|
-
"Unsupported value type for #{key.inspect}"
|
37
|
+
Appsignal.internal_logger.error "Unable to report on environment " \
|
38
|
+
"metadata: Unsupported value type for #{key.inspect}"
|
39
39
|
return
|
40
40
|
end
|
41
41
|
|
@@ -43,7 +43,7 @@ module Appsignal
|
|
43
43
|
begin
|
44
44
|
yield
|
45
45
|
rescue => e
|
46
|
-
Appsignal.
|
46
|
+
Appsignal.internal_logger.error \
|
47
47
|
"Unable to report on environment metadata #{key.inspect}:\n" \
|
48
48
|
"#{e.class}: #{e}"
|
49
49
|
return
|
@@ -56,26 +56,35 @@ module Appsignal
|
|
56
56
|
when String
|
57
57
|
yielded_value
|
58
58
|
else
|
59
|
-
Appsignal.
|
60
|
-
"#{key.inspect}: Unsupported value type for " \
|
59
|
+
Appsignal.internal_logger.error "Unable to report on environment " \
|
60
|
+
"metadata #{key.inspect}: Unsupported value type for " \
|
61
61
|
"#{yielded_value.inspect}"
|
62
62
|
return
|
63
63
|
end
|
64
64
|
|
65
65
|
Appsignal::Extension.set_environment_metadata(key, value)
|
66
66
|
rescue => e
|
67
|
-
Appsignal.
|
68
|
-
"#{e.class}: #{e}"
|
67
|
+
Appsignal.internal_logger.error "Unable to report on environment " \
|
68
|
+
"metadata:\n#{e.class}: #{e}"
|
69
69
|
end
|
70
70
|
|
71
71
|
# @see report_supported_gems
|
72
72
|
SUPPORTED_GEMS = %w[
|
73
73
|
actioncable
|
74
|
+
actionmailer
|
74
75
|
activejob
|
76
|
+
activerecord
|
75
77
|
capistrano
|
76
78
|
celluloid
|
77
79
|
data_mapper
|
78
80
|
delayed_job
|
81
|
+
dry-monitor
|
82
|
+
elasticsearch
|
83
|
+
excon
|
84
|
+
faraday
|
85
|
+
gvltools
|
86
|
+
hanami
|
87
|
+
hiredis
|
79
88
|
mongo_ruby_driver
|
80
89
|
padrino
|
81
90
|
passenger
|
@@ -85,7 +94,9 @@ module Appsignal
|
|
85
94
|
rails
|
86
95
|
rake
|
87
96
|
redis
|
97
|
+
redis-client
|
88
98
|
resque
|
99
|
+
rom
|
89
100
|
sequel
|
90
101
|
shoryuken
|
91
102
|
sidekiq
|
@@ -114,15 +125,15 @@ module Appsignal
|
|
114
125
|
report("ruby_#{gem_name}_version") { gem_spec.version.to_s }
|
115
126
|
end
|
116
127
|
rescue => e
|
117
|
-
Appsignal.
|
128
|
+
Appsignal.internal_logger.error "Unable to report supported gems:\n" \
|
118
129
|
"#{e.class}: #{e}"
|
119
130
|
end
|
120
131
|
|
121
132
|
def self.report_enabled(feature)
|
122
133
|
Appsignal::Environment.report("ruby_#{feature}_enabled") { true }
|
123
134
|
rescue => e
|
124
|
-
Appsignal.
|
125
|
-
"#{e.class}: #{e}"
|
135
|
+
Appsignal.internal_logger.error "Unable to report integration " \
|
136
|
+
"enabled:\n#{e.class}: #{e}"
|
126
137
|
end
|
127
138
|
end
|
128
139
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
class EventFormatter
|
5
|
+
module Rom
|
6
|
+
class SqlFormatter
|
7
|
+
def format(payload)
|
8
|
+
["query.#{payload[:name]}", payload[:query], SQL_BODY_FORMAT]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Appsignal::EventFormatter.register(
|
16
|
+
"sql.dry",
|
17
|
+
Appsignal::EventFormatter::Rom::SqlFormatter
|
18
|
+
)
|
@@ -4,7 +4,7 @@ module Appsignal
|
|
4
4
|
class EventFormatter
|
5
5
|
# @api private
|
6
6
|
module Sequel
|
7
|
-
#
|
7
|
+
# Compatibility with the sequel-rails gem.
|
8
8
|
# The sequel-rails gem adds its own ActiveSupport::Notifications events
|
9
9
|
# that conflict with our own sequel instrumentor. Without this event
|
10
10
|
# formatter the sequel-rails events are recorded without the SQL query
|
@@ -73,7 +73,7 @@ module Appsignal
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def logger
|
76
|
-
Appsignal.
|
76
|
+
Appsignal.internal_logger
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
@@ -84,6 +84,6 @@ module Appsignal
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
-
Dir.glob(File.expand_path("event_formatter/**/*.rb", __dir__)).each do |file|
|
87
|
+
Dir.glob(File.expand_path("event_formatter/**/*.rb", __dir__)).sort.each do |file|
|
88
88
|
require file
|
89
89
|
end
|
@@ -71,12 +71,6 @@ module Appsignal
|
|
71
71
|
attach_function :appsignal_set_gauge,
|
72
72
|
[:appsignal_string, :double, :pointer],
|
73
73
|
:void
|
74
|
-
attach_function :appsignal_set_host_gauge,
|
75
|
-
[:appsignal_string, :double],
|
76
|
-
:void
|
77
|
-
attach_function :appsignal_set_process_gauge,
|
78
|
-
[:appsignal_string, :double],
|
79
|
-
:void
|
80
74
|
attach_function :appsignal_increment_counter,
|
81
75
|
[:appsignal_string, :double, :pointer],
|
82
76
|
:void
|
@@ -248,14 +242,15 @@ module Appsignal
|
|
248
242
|
[:pointer],
|
249
243
|
:appsignal_string
|
250
244
|
|
251
|
-
Appsignal.extension_loaded = true
|
245
|
+
Appsignal.extension_loaded = true if Appsignal.respond_to? :extension_loaded=
|
252
246
|
rescue LoadError => error
|
253
247
|
error_message = "ERROR: AppSignal failed to load extension. " \
|
254
248
|
"Please run `appsignal diagnose` and email us at support@appsignal.com\n" \
|
255
249
|
"#{error.class}: #{error.message}"
|
256
|
-
Appsignal.
|
250
|
+
Appsignal.internal_logger.error(error_message) if Appsignal.respond_to? :internal_logger
|
257
251
|
Kernel.warn error_message
|
258
|
-
Appsignal.extension_loaded = false
|
252
|
+
Appsignal.extension_loaded = false if Appsignal.respond_to? :extension_loaded=
|
253
|
+
raise error if ENV["_APPSIGNAL_EXTENSION_INSTALL"] == "true"
|
259
254
|
end
|
260
255
|
|
261
256
|
def start
|
@@ -319,14 +314,6 @@ module Appsignal
|
|
319
314
|
appsignal_set_gauge(make_appsignal_string(key), value, tags.pointer)
|
320
315
|
end
|
321
316
|
|
322
|
-
def set_host_gauge(key, value)
|
323
|
-
appsignal_set_host_gauge(make_appsignal_string(key), value)
|
324
|
-
end
|
325
|
-
|
326
|
-
def set_process_gauge(key, value)
|
327
|
-
appsignal_set_process_gauge(make_appsignal_string(key), value)
|
328
|
-
end
|
329
|
-
|
330
317
|
def increment_counter(key, value, tags)
|
331
318
|
appsignal_increment_counter(make_appsignal_string(key), value, tags.pointer)
|
332
319
|
end
|
data/lib/appsignal/extension.rb
CHANGED
@@ -12,7 +12,7 @@ rescue LoadError => error
|
|
12
12
|
error_message = "ERROR: AppSignal failed to load extension. " \
|
13
13
|
"Please run `appsignal diagnose` and email us at support@appsignal.com\n" \
|
14
14
|
"#{error.class}: #{error.message}"
|
15
|
-
Appsignal.
|
15
|
+
Appsignal.internal_logger.error(error_message)
|
16
16
|
Kernel.warn error_message
|
17
17
|
Appsignal.extension_loaded = false
|
18
18
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
class Heartbeat
|
5
|
+
class << self
|
6
|
+
def transmitter
|
7
|
+
@transmitter ||= Appsignal::Transmitter.new(
|
8
|
+
"#{Appsignal.config[:logging_endpoint]}/heartbeats/json"
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :name, :id
|
14
|
+
|
15
|
+
def initialize(name:)
|
16
|
+
@name = name
|
17
|
+
@id = SecureRandom.hex(8)
|
18
|
+
end
|
19
|
+
|
20
|
+
def start
|
21
|
+
transmit_event("start")
|
22
|
+
end
|
23
|
+
|
24
|
+
def finish
|
25
|
+
transmit_event("finish")
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def event(kind)
|
31
|
+
{
|
32
|
+
:name => name,
|
33
|
+
:id => @id,
|
34
|
+
:kind => kind,
|
35
|
+
:timestamp => Time.now.utc.to_i
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def transmit_event(kind)
|
40
|
+
unless Appsignal.active?
|
41
|
+
Appsignal.internal_logger.debug("AppSignal not active, not transmitting heartbeat event")
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
response = self.class.transmitter.transmit(event(kind))
|
46
|
+
|
47
|
+
if response.code.to_i >= 200 && response.code.to_i < 300
|
48
|
+
Appsignal.internal_logger.trace("Transmitted heartbeat `#{name}` (#{id}) #{kind} event")
|
49
|
+
else
|
50
|
+
Appsignal.internal_logger.error(
|
51
|
+
"Failed to transmit heartbeat event: status code was #{response.code}"
|
52
|
+
)
|
53
|
+
end
|
54
|
+
rescue => e
|
55
|
+
Appsignal.internal_logger.error("Failed to transmit heartbeat event: #{e}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.heartbeat(name)
|
60
|
+
heartbeat = Appsignal::Heartbeat.new(:name => name)
|
61
|
+
output = nil
|
62
|
+
|
63
|
+
if block_given?
|
64
|
+
heartbeat.start
|
65
|
+
output = yield
|
66
|
+
end
|
67
|
+
|
68
|
+
heartbeat.finish
|
69
|
+
output
|
70
|
+
end
|
71
|
+
end
|
@@ -7,8 +7,8 @@ module Appsignal
|
|
7
7
|
|
8
8
|
# Creates an AppSignal transaction for the given block.
|
9
9
|
#
|
10
|
-
# If AppSignal is not {.active?} it will still execute the
|
11
|
-
# create a transaction for it.
|
10
|
+
# If AppSignal is not {Appsignal.active?} it will still execute the
|
11
|
+
# block, but not create a transaction for it.
|
12
12
|
#
|
13
13
|
# A event is created for this transaction with the name given in the
|
14
14
|
# `name` argument. The event name must start with either `perform_job` or
|
@@ -68,9 +68,9 @@ module Appsignal
|
|
68
68
|
namespace = Appsignal::Transaction::HTTP_REQUEST
|
69
69
|
request = ::Rack::Request.new(env)
|
70
70
|
else
|
71
|
-
|
72
|
-
"either 'perform_job' (for jobs and tasks) or
|
73
|
-
"(for HTTP requests)"
|
71
|
+
internal_logger.error "Unrecognized name '#{name}': names must " \
|
72
|
+
"start with either 'perform_job' (for jobs and tasks) or " \
|
73
|
+
"'process_action' (for HTTP requests)"
|
74
74
|
return yield
|
75
75
|
end
|
76
76
|
|
@@ -112,7 +112,7 @@ module Appsignal
|
|
112
112
|
# transaction. Does not add the error to the current transaction.
|
113
113
|
#
|
114
114
|
# Make sure that AppSignal is integrated in your application beforehand.
|
115
|
-
# AppSignal won't record errors unless {
|
115
|
+
# AppSignal won't record errors unless {Appsignal.active?} is `true`.
|
116
116
|
#
|
117
117
|
# @example
|
118
118
|
# # my_app.rb
|
@@ -228,8 +228,8 @@ module Appsignal
|
|
228
228
|
return unless active?
|
229
229
|
|
230
230
|
unless error.is_a?(Exception)
|
231
|
-
|
232
|
-
"value is not an exception: #{error.inspect}"
|
231
|
+
internal_logger.error "Appsignal.send_error: Cannot send error. " \
|
232
|
+
"The given value is not an exception: #{error.inspect}"
|
233
233
|
return
|
234
234
|
end
|
235
235
|
transaction = Appsignal::Transaction.new(
|
@@ -319,8 +319,8 @@ module Appsignal
|
|
319
319
|
"Appsignal.set_error called on location: #{call_location}"
|
320
320
|
end
|
321
321
|
unless exception.is_a?(Exception)
|
322
|
-
|
323
|
-
"value is not an exception: #{exception.inspect}"
|
322
|
+
internal_logger.error "Appsignal.set_error: Cannot set error. " \
|
323
|
+
"The given value is not an exception: #{exception.inspect}"
|
324
324
|
return
|
325
325
|
end
|
326
326
|
return if !active? || !Appsignal::Transaction.current?
|
@@ -10,22 +10,24 @@ module Appsignal
|
|
10
10
|
Appsignal::Utils::Data.generate(tags)
|
11
11
|
)
|
12
12
|
rescue RangeError
|
13
|
-
Appsignal.
|
13
|
+
Appsignal.internal_logger
|
14
14
|
.warn("Gauge value #{value} for key '#{key}' is too big")
|
15
15
|
end
|
16
16
|
|
17
|
-
def set_host_gauge(
|
18
|
-
Appsignal::
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def set_host_gauge(_key, _value)
|
18
|
+
Appsignal::Utils::DeprecationMessage.message \
|
19
|
+
"The `set_host_gauge` method has been deprecated. " \
|
20
|
+
"Calling this method has no effect. " \
|
21
|
+
"Please remove method call in the following file to remove " \
|
22
|
+
"this message.\n#{caller.first}"
|
22
23
|
end
|
23
24
|
|
24
|
-
def set_process_gauge(
|
25
|
-
Appsignal::
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
def set_process_gauge(_key, _value)
|
26
|
+
Appsignal::Utils::DeprecationMessage.message \
|
27
|
+
"The `set_process_gauge` method has been deprecated. " \
|
28
|
+
"Calling this method has no effect. " \
|
29
|
+
"Please remove method call in the following file to remove " \
|
30
|
+
"this message.\n#{caller.first}"
|
29
31
|
end
|
30
32
|
|
31
33
|
def increment_counter(key, value = 1.0, tags = {})
|
@@ -35,7 +37,7 @@ module Appsignal
|
|
35
37
|
Appsignal::Utils::Data.generate(tags)
|
36
38
|
)
|
37
39
|
rescue RangeError
|
38
|
-
Appsignal.
|
40
|
+
Appsignal.internal_logger
|
39
41
|
.warn("Counter value #{value} for key '#{key}' is too big")
|
40
42
|
end
|
41
43
|
|
@@ -46,7 +48,7 @@ module Appsignal
|
|
46
48
|
Appsignal::Utils::Data.generate(tags)
|
47
49
|
)
|
48
50
|
rescue RangeError
|
49
|
-
Appsignal.
|
51
|
+
Appsignal.internal_logger
|
50
52
|
.warn("Distribution value #{value} for key '#{key}' is too big")
|
51
53
|
end
|
52
54
|
end
|
@@ -56,7 +56,7 @@ module Appsignal
|
|
56
56
|
super
|
57
57
|
rescue Exception => exception # rubocop:disable Lint/RescueException
|
58
58
|
job_status = :failed
|
59
|
-
transaction
|
59
|
+
transaction_set_error(transaction, exception)
|
60
60
|
raise exception
|
61
61
|
ensure
|
62
62
|
if transaction
|
@@ -82,6 +82,14 @@ module Appsignal
|
|
82
82
|
tags.merge(:status => :processed)
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def transaction_set_error(transaction, exception)
|
89
|
+
return if Appsignal.config[:activejob_report_errors] == "none"
|
90
|
+
|
91
|
+
transaction.set_error(exception)
|
92
|
+
end
|
85
93
|
end
|
86
94
|
|
87
95
|
module ActiveJobHelpers
|
@@ -22,21 +22,30 @@ module Appsignal
|
|
22
22
|
end
|
23
23
|
|
24
24
|
require "appsignal/integrations/active_support_notifications"
|
25
|
-
instrumenter = ::ActiveSupport::Notifications::Instrumenter
|
26
25
|
parent_integration_module = Appsignal::Integrations::ActiveSupportNotificationsIntegration
|
27
|
-
|
28
|
-
|
26
|
+
|
27
|
+
if defined?(::ActiveSupport::Notifications::Fanout::Handle)
|
28
|
+
install_module(
|
29
|
+
parent_integration_module::StartFinishHandlerIntegration,
|
30
|
+
::ActiveSupport::Notifications::Fanout::Handle
|
31
|
+
)
|
29
32
|
else
|
30
|
-
|
31
|
-
end
|
33
|
+
instrumenter = ::ActiveSupport::Notifications::Instrumenter
|
32
34
|
|
33
|
-
|
35
|
+
if instrumenter.method_defined?(:start) && instrumenter.method_defined?(:finish)
|
36
|
+
install_module(parent_integration_module::StartFinishIntegration, instrumenter)
|
37
|
+
else
|
38
|
+
install_module(parent_integration_module::InstrumentIntegration, instrumenter)
|
39
|
+
end
|
34
40
|
|
35
|
-
|
41
|
+
return unless instrumenter.method_defined?(:finish_with_state)
|
42
|
+
|
43
|
+
install_module(parent_integration_module::FinishStateIntegration, instrumenter)
|
44
|
+
end
|
36
45
|
end
|
37
46
|
|
38
|
-
def install_module(mod)
|
39
|
-
|
47
|
+
def install_module(mod, instrumenter)
|
48
|
+
instrumenter.send(:prepend, mod)
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
class Hooks
|
5
|
+
# @api private
|
6
|
+
class DryMonitorHook < Appsignal::Hooks::Hook
|
7
|
+
register :dry_monitor
|
8
|
+
|
9
|
+
def dependencies_present?
|
10
|
+
defined?(::Dry::Monitor::Notifications)
|
11
|
+
end
|
12
|
+
|
13
|
+
def install
|
14
|
+
require "appsignal/integrations/dry_monitor"
|
15
|
+
|
16
|
+
::Dry::Monitor::Notifications.prepend(Appsignal::Integrations::DryMonitorIntegration)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
class Hooks
|
5
|
+
# @api private
|
6
|
+
class RedisClientHook < Appsignal::Hooks::Hook
|
7
|
+
register :redis_client
|
8
|
+
|
9
|
+
def dependencies_present?
|
10
|
+
defined?(::RedisClient) &&
|
11
|
+
Gem::Version.new(::RedisClient::VERSION) >= Gem::Version.new("0.14.0") &&
|
12
|
+
Appsignal.config &&
|
13
|
+
Appsignal.config[:instrument_redis]
|
14
|
+
end
|
15
|
+
|
16
|
+
def install
|
17
|
+
require "appsignal/integrations/redis_client"
|
18
|
+
::RedisClient::RubyConnection.prepend Appsignal::Integrations::RedisClientIntegration
|
19
|
+
Appsignal::Environment.report_enabled("redis")
|
20
|
+
|
21
|
+
return unless defined?(::RedisClient::HiredisConnection)
|
22
|
+
|
23
|
+
::RedisClient::HiredisConnection.prepend Appsignal::Integrations::RedisClientIntegration
|
24
|
+
Appsignal::Environment.report_enabled("hiredis")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/appsignal/hooks.rb
CHANGED
@@ -32,12 +32,12 @@ module Appsignal
|
|
32
32
|
return unless dependencies_present?
|
33
33
|
return if installed?
|
34
34
|
|
35
|
-
Appsignal.
|
35
|
+
Appsignal.internal_logger.debug("Installing #{name} hook")
|
36
36
|
begin
|
37
37
|
install
|
38
38
|
@installed = true
|
39
39
|
rescue => ex
|
40
|
-
logger = Appsignal.
|
40
|
+
logger = Appsignal.internal_logger
|
41
41
|
logger.error("Error while installing #{name} hook: #{ex}")
|
42
42
|
logger.debug ex.backtrace.join("\n")
|
43
43
|
end
|
@@ -95,6 +95,7 @@ require "appsignal/hooks/active_support_notifications"
|
|
95
95
|
require "appsignal/hooks/celluloid"
|
96
96
|
require "appsignal/hooks/delayed_job"
|
97
97
|
require "appsignal/hooks/gvl"
|
98
|
+
require "appsignal/hooks/dry_monitor"
|
98
99
|
require "appsignal/hooks/http"
|
99
100
|
require "appsignal/hooks/mri"
|
100
101
|
require "appsignal/hooks/net_http"
|
@@ -102,6 +103,7 @@ require "appsignal/hooks/passenger"
|
|
102
103
|
require "appsignal/hooks/puma"
|
103
104
|
require "appsignal/hooks/rake"
|
104
105
|
require "appsignal/hooks/redis"
|
106
|
+
require "appsignal/hooks/redis_client"
|
105
107
|
require "appsignal/hooks/resque"
|
106
108
|
require "appsignal/hooks/sequel"
|
107
109
|
require "appsignal/hooks/shoryuken"
|
@@ -54,6 +54,32 @@ module Appsignal
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
module StartFinishHandlerIntegration
|
58
|
+
def start
|
59
|
+
instrument_this = @name[0] != ActiveSupportNotificationsIntegration::BANG
|
60
|
+
|
61
|
+
Appsignal::Transaction.current.start_event if instrument_this
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
def finish_with_values(name, id, payload = {})
|
66
|
+
# Events that start with a bang are internal to Rails
|
67
|
+
instrument_this = name[0] != ActiveSupportNotificationsIntegration::BANG
|
68
|
+
|
69
|
+
if instrument_this
|
70
|
+
title, body, body_format = Appsignal::EventFormatter.format(name, payload)
|
71
|
+
Appsignal::Transaction.current.finish_event(
|
72
|
+
name.to_s,
|
73
|
+
title,
|
74
|
+
body,
|
75
|
+
body_format
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
57
83
|
module FinishStateIntegration
|
58
84
|
def finish_with_state(listeners_state, name, payload = {})
|
59
85
|
# Events that start with a bang are internal to Rails
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
module Integrations
|
5
|
+
module DryMonitorIntegration
|
6
|
+
def instrument(event_id, payload = {}, &block)
|
7
|
+
Appsignal::Transaction.current.start_event
|
8
|
+
|
9
|
+
super
|
10
|
+
ensure
|
11
|
+
title, body, body_format = Appsignal::EventFormatter.format("#{event_id}.dry", payload)
|
12
|
+
|
13
|
+
Appsignal::Transaction.current.finish_event(
|
14
|
+
title || event_id.to_s,
|
15
|
+
title,
|
16
|
+
body,
|
17
|
+
body_format
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -6,7 +6,7 @@ module Appsignal
|
|
6
6
|
module Integrations
|
7
7
|
module HanamiPlugin
|
8
8
|
def self.init
|
9
|
-
Appsignal.
|
9
|
+
Appsignal.internal_logger.debug("Loading Hanami integration")
|
10
10
|
|
11
11
|
hanami_app_config = ::Hanami.app.config
|
12
12
|
Appsignal.config = Appsignal::Config.new(
|
@@ -7,7 +7,7 @@ module Appsignal
|
|
7
7
|
# @api private
|
8
8
|
module PadrinoPlugin
|
9
9
|
def self.init
|
10
|
-
Appsignal.
|
10
|
+
Appsignal.internal_logger.debug("Loading Padrino (#{Padrino::VERSION}) integration")
|
11
11
|
|
12
12
|
root = Padrino.mounted_root
|
13
13
|
Appsignal.config = Appsignal::Config.new(root, Padrino.env)
|