appsignal 4.5.17 → 4.6.0
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 +4 -4
- data/CHANGELOG.md +33 -0
- data/CLAUDE.md +177 -0
- data/README.md +17 -0
- data/appsignal.gemspec +1 -0
- data/build_matrix.yml +29 -0
- data/lib/appsignal/auth_check.rb +3 -3
- data/lib/appsignal/check_in/cron.rb +1 -1
- data/lib/appsignal/check_in/event.rb +1 -1
- data/lib/appsignal/check_in/scheduler.rb +3 -1
- data/lib/appsignal/check_in.rb +9 -6
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/cli.rb +1 -1
- data/lib/appsignal/config.rb +231 -30
- data/lib/appsignal/custom_marker.rb +3 -3
- data/lib/appsignal/environment.rb +7 -1
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/faraday/request_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/sequel/sql_formatter.rb +1 -1
- data/lib/appsignal/event_formatter/view_component/render_formatter.rb +1 -1
- data/lib/appsignal/event_formatter.rb +41 -3
- data/lib/appsignal/extension.rb +1 -1
- data/lib/appsignal/garbage_collection.rb +1 -1
- data/lib/appsignal/helpers/instrumentation.rb +82 -35
- data/lib/appsignal/helpers/metrics.rb +12 -9
- data/lib/appsignal/hooks/action_cable.rb +1 -1
- data/lib/appsignal/hooks/action_mailer.rb +1 -0
- data/lib/appsignal/hooks/active_job.rb +1 -1
- data/lib/appsignal/hooks/active_support_notifications.rb +1 -1
- data/lib/appsignal/hooks/at_exit.rb +1 -1
- data/lib/appsignal/hooks/celluloid.rb +1 -1
- data/lib/appsignal/hooks/data_mapper.rb +1 -1
- data/lib/appsignal/hooks/delayed_job.rb +1 -1
- data/lib/appsignal/hooks/dry_monitor.rb +1 -1
- data/lib/appsignal/hooks/excon.rb +1 -1
- data/lib/appsignal/hooks/gvl.rb +1 -1
- data/lib/appsignal/hooks/http.rb +1 -1
- data/lib/appsignal/hooks/mongo_ruby_driver.rb +1 -1
- data/lib/appsignal/hooks/mri.rb +1 -1
- data/lib/appsignal/hooks/net_http.rb +1 -1
- data/lib/appsignal/hooks/ownership.rb +1 -1
- data/lib/appsignal/hooks/passenger.rb +1 -1
- data/lib/appsignal/hooks/puma.rb +1 -1
- data/lib/appsignal/hooks/que.rb +1 -1
- data/lib/appsignal/hooks/rake.rb +1 -1
- data/lib/appsignal/hooks/redis.rb +1 -1
- data/lib/appsignal/hooks/redis_client.rb +1 -1
- data/lib/appsignal/hooks/resque.rb +1 -1
- data/lib/appsignal/hooks/sequel.rb +2 -1
- data/lib/appsignal/hooks/shoryuken.rb +1 -1
- data/lib/appsignal/hooks/sidekiq.rb +1 -0
- data/lib/appsignal/hooks/unicorn.rb +1 -1
- data/lib/appsignal/hooks/webmachine.rb +1 -1
- data/lib/appsignal/hooks.rb +5 -3
- data/lib/appsignal/integrations/action_cable.rb +1 -1
- data/lib/appsignal/integrations/active_support_notifications.rb +1 -1
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +1 -1
- data/lib/appsignal/integrations/data_mapper.rb +1 -1
- data/lib/appsignal/integrations/delayed_job_plugin.rb +1 -1
- data/lib/appsignal/integrations/dry_monitor.rb +1 -1
- data/lib/appsignal/integrations/excon.rb +1 -1
- data/lib/appsignal/integrations/http.rb +1 -1
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +1 -1
- data/lib/appsignal/integrations/net_http.rb +1 -1
- data/lib/appsignal/integrations/object.rb +18 -2
- data/lib/appsignal/integrations/ownership.rb +1 -1
- data/lib/appsignal/integrations/puma.rb +1 -1
- data/lib/appsignal/integrations/que.rb +1 -1
- data/lib/appsignal/integrations/railtie.rb +2 -2
- data/lib/appsignal/integrations/rake.rb +2 -2
- data/lib/appsignal/integrations/redis.rb +1 -1
- data/lib/appsignal/integrations/redis_client.rb +1 -1
- data/lib/appsignal/integrations/resque.rb +2 -2
- data/lib/appsignal/integrations/shoryuken.rb +1 -1
- data/lib/appsignal/integrations/sidekiq.rb +3 -3
- data/lib/appsignal/integrations/unicorn.rb +1 -1
- data/lib/appsignal/integrations/webmachine.rb +1 -1
- data/lib/appsignal/internal_errors.rb +2 -2
- data/lib/appsignal/loaders.rb +1 -1
- data/lib/appsignal/logger.rb +36 -19
- data/lib/appsignal/marker.rb +1 -1
- data/lib/appsignal/probes/gvl.rb +4 -3
- data/lib/appsignal/probes/helpers.rb +1 -1
- data/lib/appsignal/probes/mri.rb +3 -3
- data/lib/appsignal/probes/sidekiq.rb +4 -3
- data/lib/appsignal/probes.rb +20 -15
- data/lib/appsignal/rack.rb +1 -1
- data/lib/appsignal/sample_data.rb +31 -12
- data/lib/appsignal/span.rb +1 -1
- data/lib/appsignal/system.rb +9 -8
- data/lib/appsignal/transaction.rb +72 -52
- data/lib/appsignal/transmitter.rb +1 -1
- data/lib/appsignal/utils.rb +1 -1
- data/lib/appsignal/version.rb +2 -1
- data/lib/appsignal.rb +22 -14
- data/lib/puma/plugin/appsignal.rb +1 -1
- data/sig/appsignal.rbi +2599 -0
- data/sig/appsignal.rbs +2420 -0
- metadata +20 -6
data/lib/appsignal/probes/mri.rb
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module Appsignal
|
4
4
|
module Probes
|
5
|
-
#
|
5
|
+
# @!visibility private
|
6
6
|
class MriProbe
|
7
7
|
include Helpers
|
8
8
|
|
9
|
-
#
|
9
|
+
# @!visibility private
|
10
10
|
def self.dependencies_present?
|
11
11
|
defined?(::RubyVM) && ::RubyVM.respond_to?(:stat)
|
12
12
|
end
|
@@ -17,7 +17,7 @@ module Appsignal
|
|
17
17
|
@gc_profiler = gc_profiler
|
18
18
|
end
|
19
19
|
|
20
|
-
#
|
20
|
+
# @!visibility private
|
21
21
|
def call
|
22
22
|
stat = RubyVM.stat
|
23
23
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Appsignal
|
4
4
|
module Probes
|
5
|
-
#
|
5
|
+
# @!visibility private
|
6
6
|
class SidekiqProbe
|
7
7
|
include Helpers
|
8
8
|
|
@@ -38,14 +38,15 @@ module Appsignal
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
#
|
41
|
+
# @!visibility private
|
42
42
|
attr_reader :config
|
43
43
|
|
44
|
+
# @!visibility private
|
44
45
|
def self.sidekiq7_and_greater?
|
45
46
|
Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("7.0.0")
|
46
47
|
end
|
47
48
|
|
48
|
-
#
|
49
|
+
# @!visibility private
|
49
50
|
def self.dependencies_present?
|
50
51
|
return true if sidekiq7_and_greater?
|
51
52
|
return false unless defined?(::Redis::VERSION) # Sidekiq <= 6
|
data/lib/appsignal/probes.rb
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
module Appsignal
|
4
4
|
module Probes
|
5
|
-
# @
|
5
|
+
# @return [Integer]
|
6
|
+
# @!visibility private
|
6
7
|
ITERATION_IN_SECONDS = 60
|
7
8
|
|
8
|
-
#
|
9
|
+
# @!visibility private
|
9
10
|
class ProbeCollection
|
10
11
|
def initialize
|
11
12
|
@probes = {}
|
@@ -23,13 +24,12 @@ module Appsignal
|
|
23
24
|
end
|
24
25
|
|
25
26
|
# Fetch a probe using its name.
|
26
|
-
# @param key [Symbol
|
27
|
+
# @param key [Symbol, String] The name of the probe to fetch.
|
27
28
|
# @return [Object] Returns the registered probe.
|
28
29
|
def [](key)
|
29
30
|
probes[key]
|
30
31
|
end
|
31
32
|
|
32
|
-
# @api private
|
33
33
|
def internal_register(name, probe)
|
34
34
|
if probes.key?(name)
|
35
35
|
logger.debug "A probe with the name `#{name}` is already " \
|
@@ -38,12 +38,10 @@ module Appsignal
|
|
38
38
|
probes[name] = probe
|
39
39
|
end
|
40
40
|
|
41
|
-
# @api private
|
42
41
|
def unregister(name)
|
43
42
|
probes.delete(name)
|
44
43
|
end
|
45
44
|
|
46
|
-
# @api private
|
47
45
|
def each(&block)
|
48
46
|
probes.each(&block)
|
49
47
|
end
|
@@ -58,14 +56,14 @@ module Appsignal
|
|
58
56
|
end
|
59
57
|
|
60
58
|
class << self
|
61
|
-
#
|
59
|
+
# @!visibility private
|
62
60
|
def mutex
|
63
61
|
@mutex ||= Thread::Mutex.new
|
64
62
|
end
|
65
63
|
|
66
64
|
# @see ProbeCollection
|
67
65
|
# @return [ProbeCollection] Returns list of probes.
|
68
|
-
#
|
66
|
+
# @!visibility private
|
69
67
|
def probes
|
70
68
|
@probes ||= ProbeCollection.new
|
71
69
|
end
|
@@ -129,7 +127,7 @@ module Appsignal
|
|
129
127
|
# # "started" # Printed on Appsignal::Probes.start
|
130
128
|
# # "called" # Repeated every minute
|
131
129
|
#
|
132
|
-
# @param name [Symbol
|
130
|
+
# @param name [Symbol, String] Name of the probe. Can be used with
|
133
131
|
# {ProbeCollection#[]}. This name will be used in errors in the log and
|
134
132
|
# allows overwriting of probes by registering new ones with the same
|
135
133
|
# name.
|
@@ -153,7 +151,7 @@ module Appsignal
|
|
153
151
|
# # Then unregister a probe if needed
|
154
152
|
# Appsignal::Probes.unregister :my_probe
|
155
153
|
#
|
156
|
-
# @param name [Symbol
|
154
|
+
# @param name [Symbol, String] Name of the probe used to {register} the
|
157
155
|
# probe.
|
158
156
|
# @return [void]
|
159
157
|
def unregister(name)
|
@@ -162,6 +160,7 @@ module Appsignal
|
|
162
160
|
uninitialize_probe(name)
|
163
161
|
end
|
164
162
|
|
163
|
+
# @return [void]
|
165
164
|
# @api private
|
166
165
|
def start
|
167
166
|
stop
|
@@ -184,8 +183,10 @@ module Appsignal
|
|
184
183
|
logger.debug("Gathering minutely metrics with '#{name}' probe")
|
185
184
|
probe.call
|
186
185
|
rescue => ex
|
187
|
-
logger.error
|
188
|
-
|
186
|
+
logger.error(
|
187
|
+
"Error in minutely probe '#{name}': #{ex.class}: #{ex.message}\n" \
|
188
|
+
"#{ex.backtrace.join("\n")}"
|
189
|
+
)
|
189
190
|
end
|
190
191
|
end
|
191
192
|
end_time = Time.now
|
@@ -212,13 +213,15 @@ module Appsignal
|
|
212
213
|
|
213
214
|
# Stop the minutely probes mechanism. Stop the thread and clear all probe
|
214
215
|
# instances.
|
216
|
+
#
|
217
|
+
# @return [void]
|
215
218
|
def stop
|
216
219
|
defined?(@thread) && @thread.kill
|
217
220
|
@started = false
|
218
221
|
probe_instances.clear
|
219
222
|
end
|
220
223
|
|
221
|
-
#
|
224
|
+
# @!visibility private
|
222
225
|
def wait_time
|
223
226
|
ITERATION_IN_SECONDS - Time.now.sec
|
224
227
|
end
|
@@ -256,8 +259,10 @@ module Appsignal
|
|
256
259
|
end
|
257
260
|
rescue => error
|
258
261
|
logger = Appsignal.internal_logger
|
259
|
-
logger.error
|
260
|
-
|
262
|
+
logger.error(
|
263
|
+
"Error while initializing minutely probe '#{name}': #{error.class}: #{error.message}\n" \
|
264
|
+
"#{error.backtrace.join("\n")}"
|
265
|
+
)
|
261
266
|
end
|
262
267
|
|
263
268
|
def uninitialize_probe(name)
|
data/lib/appsignal/rack.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Appsignal
|
4
|
-
#
|
4
|
+
# @!visibility private
|
5
5
|
class SampleData
|
6
6
|
def initialize(key, accepted_type = nil)
|
7
7
|
@key = key
|
@@ -21,7 +21,6 @@ module Appsignal
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
# @api private
|
25
24
|
def set_empty_value!
|
26
25
|
@empty = true
|
27
26
|
@blocks.clear
|
@@ -36,12 +35,18 @@ module Appsignal
|
|
36
35
|
else
|
37
36
|
block_or_value
|
38
37
|
end
|
38
|
+
|
39
39
|
unless accepted_type?(new_value)
|
40
40
|
log_unsupported_data_type(new_value)
|
41
41
|
next
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
# Before trying to merge values, convert them to Ruby classes
|
45
|
+
# This way we don't need to check if something is of a type often
|
46
|
+
value_new = convert_to_ruby_class(new_value)
|
47
|
+
value_original = convert_to_ruby_class(value)
|
48
|
+
|
49
|
+
value = merge_values(value_original, value_new)
|
45
50
|
new_value
|
46
51
|
end
|
47
52
|
|
@@ -52,7 +57,6 @@ module Appsignal
|
|
52
57
|
@blocks.any?
|
53
58
|
end
|
54
59
|
|
55
|
-
# @api private
|
56
60
|
def empty?
|
57
61
|
@empty
|
58
62
|
end
|
@@ -81,15 +85,19 @@ module Appsignal
|
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
88
|
+
def mergable?(value_original, value_new)
|
89
|
+
value_new.instance_of?(value_original.class)
|
90
|
+
end
|
91
|
+
|
84
92
|
def merge_values(value_original, value_new)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
+
return value_new if value_original == UNSET_VALUE
|
94
|
+
|
95
|
+
unless mergable?(value_original, value_new)
|
96
|
+
Appsignal.internal_logger.warn(
|
97
|
+
"The sample data '#{@key}' changed type from " \
|
98
|
+
"'#{value_original.class}' to '#{value_new.class}'. " \
|
99
|
+
"These types can not be merged. Using new '#{value_new.class}' type."
|
100
|
+
)
|
93
101
|
return value_new
|
94
102
|
end
|
95
103
|
|
@@ -103,6 +111,17 @@ module Appsignal
|
|
103
111
|
end
|
104
112
|
end
|
105
113
|
|
114
|
+
# Convert any subclasses of Hash to a Ruby Hash class, so we don't have to
|
115
|
+
# account for the original value being a value that's not a pure Hash or
|
116
|
+
# Array object.
|
117
|
+
def convert_to_ruby_class(value)
|
118
|
+
if value.is_a? Hash
|
119
|
+
value.to_h
|
120
|
+
else
|
121
|
+
value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
106
125
|
def log_unsupported_data_type(value)
|
107
126
|
Appsignal.internal_logger.error(
|
108
127
|
"Sample data '#{@key}': Unsupported data type '#{value.class}' received: #{value.inspect}"
|
data/lib/appsignal/span.rb
CHANGED
data/lib/appsignal/system.rb
CHANGED
@@ -5,7 +5,7 @@ module Appsignal
|
|
5
5
|
#
|
6
6
|
# Provides useful methods to find out more about the host system.
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# @!visibility private
|
9
9
|
module System
|
10
10
|
LINUX_TARGET = "linux"
|
11
11
|
LINUX_ARM_ARCHITECTURE = "aarch64"
|
@@ -13,6 +13,9 @@ module Appsignal
|
|
13
13
|
FREEBSD_TARGET = "freebsd"
|
14
14
|
GEM_EXT_PATH = File.expand_path("../../ext", __dir__).freeze
|
15
15
|
|
16
|
+
# Returns if system is recognized as a Heroku dyno.
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
16
19
|
def self.heroku?
|
17
20
|
ENV.key? "DYNO"
|
18
21
|
end
|
@@ -27,7 +30,6 @@ module Appsignal
|
|
27
30
|
# - Use `export APPSIGNAL_BUILD_FOR_LINUX_ARM=1` to enable the experimental
|
28
31
|
# Linux ARM build.
|
29
32
|
#
|
30
|
-
# @api private
|
31
33
|
# @return [String]
|
32
34
|
def self.agent_platform
|
33
35
|
return LINUX_TARGET if force_linux_arm_build?
|
@@ -63,7 +65,6 @@ module Appsignal
|
|
63
65
|
# - Use `export APPSIGNAL_BUILD_FOR_LINUX_ARM=1` to enable the experimental
|
64
66
|
# Linux ARM build.
|
65
67
|
#
|
66
|
-
# @api private
|
67
68
|
# @return [String]
|
68
69
|
def self.agent_architecture
|
69
70
|
return LINUX_ARM_ARCHITECTURE if force_linux_arm_build?
|
@@ -74,34 +75,34 @@ module Appsignal
|
|
74
75
|
|
75
76
|
# Returns whether or not the musl build was forced by the user.
|
76
77
|
#
|
77
|
-
# @
|
78
|
+
# @return [Boolean]
|
78
79
|
def self.force_musl_build?
|
79
80
|
%w[true 1].include?(ENV.fetch("APPSIGNAL_BUILD_FOR_MUSL", nil))
|
80
81
|
end
|
81
82
|
|
82
83
|
# Returns whether or not the linux ARM build was selected by the user.
|
83
84
|
#
|
84
|
-
# @
|
85
|
+
# @return [Boolean]
|
85
86
|
def self.force_linux_arm_build?
|
86
87
|
%w[true 1].include?(ENV.fetch("APPSIGNAL_BUILD_FOR_LINUX_ARM", nil))
|
87
88
|
end
|
88
89
|
|
89
|
-
# @api private
|
90
90
|
def self.versionify(version)
|
91
91
|
Gem::Version.new(version)
|
92
92
|
end
|
93
93
|
|
94
|
-
# @api private
|
95
94
|
def self.ldd_version_output
|
96
95
|
`ldd --version 2>&1`
|
97
96
|
end
|
98
97
|
|
99
|
-
# @api private
|
100
98
|
def self.extract_ldd_version(string)
|
101
99
|
ldd_version = string.match(/\d+\.\d+/)
|
102
100
|
ldd_version && ldd_version[0]
|
103
101
|
end
|
104
102
|
|
103
|
+
# Returns if the app is recognized as a JRuby app.
|
104
|
+
#
|
105
|
+
# @return [Boolean]
|
105
106
|
def self.jruby?
|
106
107
|
RUBY_PLATFORM == "java"
|
107
108
|
end
|