appsignal 3.3.7 → 3.3.8
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 +12 -0
- data/lib/appsignal/config.rb +7 -0
- data/lib/appsignal/hooks/gvl.rb +22 -0
- data/lib/appsignal/hooks.rb +1 -0
- data/lib/appsignal/probes/gvl.rb +47 -0
- data/lib/appsignal/probes/helpers.rb +21 -0
- data/lib/appsignal/probes/mri.rb +12 -35
- data/lib/appsignal/probes.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +2 -0
- data/spec/lib/appsignal/hooks/gvl_spec.rb +140 -0
- data/spec/lib/appsignal/probes/gvl_spec.rb +39 -0
- data/spec/lib/appsignal/probes/mri_spec.rb +0 -19
- data/spec/support/mocks/appsignal_mock.rb +18 -0
- data/spec/support/mocks/fake_gvl_tools.rb +36 -0
- metadata +12 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a589c3f722ba5db3195ee2b9609e635b046790f296ff5985a8974f20f9b6c28f
|
|
4
|
+
data.tar.gz: 6b8e85945c4517cedff96f03d304e945f70dbc5f0ee53afb153fe0ed35a8bcdd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4beb87ea596e6c189b1ed6042fbfe202ce15e519e2e311c82cf2625a6feb7fa70aecbf4c367bfebec01088215fd1b8c1228204f9b684e8bb4ccc96cd531a78c9
|
|
7
|
+
data.tar.gz: 0b50957a4ba08682831a8f21c7b589f0a2658ed388b17fb6b9980802a8c83f181b8464976cc8a64ab16648a2d776dfe8c723f2cda227dc6c7d954eacd75ab09d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
# AppSignal for Ruby gem Changelog
|
|
2
2
|
|
|
3
|
+
## 3.3.8
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [2fc6ba85](https://github.com/appsignal/appsignal-ruby/commit/2fc6ba85be1e0cabc2bb8fb26469ad47d1c60243) patch - Support "warning" value for `log_level` config option. This option was documented, but wasn't accepted and fell back on the "info" log level if used. Now it works to configure it to the "warn"/"warning" log level.
|
|
8
|
+
- [c04f7783](https://github.com/appsignal/appsignal-ruby/commit/c04f778332048aeaad9f75c131247caa29e504fa) patch - Add global VM lock metrics. If the `gvltools` library is installed, AppSignal for Ruby will report metrics on the global VM lock and the number of waiting threads in your application.
|
|
9
|
+
|
|
3
10
|
## 3.3.7
|
|
4
11
|
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- [a815b298](https://github.com/appsignal/appsignal-ruby/commit/a815b29826a84f430384e7e735f79c8c312f1abf) patch - Support cgroups v2. Used by newer Docker engines to report host metrics. Upgrade if you receive no host metrics for Docker containers.
|
|
15
|
+
|
|
5
16
|
### Changed
|
|
6
17
|
|
|
7
18
|
- [8e67159e](https://github.com/appsignal/appsignal-ruby/commit/8e67159e2a57d3b697a07fadd8eb0e0234db9124) patch - Configure AppSignal with the RACK_ENV or RAILS_ENV environment variable in diagnose CLI, if present. Makes it easier to run the diagnose CLI in production, without having to always specify the environment with the `--environment` CLI option.
|
|
19
|
+
- [a815b298](https://github.com/appsignal/appsignal-ruby/commit/a815b29826a84f430384e7e735f79c8c312f1abf) patch - Allow transaction events to have a duration up to 48 hours before being discarded.
|
|
8
20
|
|
|
9
21
|
### Fixed
|
|
10
22
|
|
data/lib/appsignal/config.rb
CHANGED
|
@@ -19,6 +19,8 @@ module Appsignal
|
|
|
19
19
|
:enable_minutely_probes => true,
|
|
20
20
|
:enable_statsd => true,
|
|
21
21
|
:enable_nginx_metrics => false,
|
|
22
|
+
:enable_gvl_global_timer => true,
|
|
23
|
+
:enable_gvl_waiting_threads => true,
|
|
22
24
|
:endpoint => "https://push.appsignal.com",
|
|
23
25
|
:files_world_accessible => true,
|
|
24
26
|
:filter_parameters => [],
|
|
@@ -53,6 +55,7 @@ module Appsignal
|
|
|
53
55
|
LOG_LEVEL_MAP = {
|
|
54
56
|
"error" => ::Logger::ERROR,
|
|
55
57
|
"warn" => ::Logger::WARN,
|
|
58
|
+
"warning" => ::Logger::WARN,
|
|
56
59
|
"info" => ::Logger::INFO,
|
|
57
60
|
"debug" => ::Logger::DEBUG,
|
|
58
61
|
"trace" => ::Logger::DEBUG
|
|
@@ -69,6 +72,8 @@ module Appsignal
|
|
|
69
72
|
"APPSIGNAL_ENABLE_MINUTELY_PROBES" => :enable_minutely_probes,
|
|
70
73
|
"APPSIGNAL_ENABLE_STATSD" => :enable_statsd,
|
|
71
74
|
"APPSIGNAL_ENABLE_NGINX_METRICS" => :enable_nginx_metrics,
|
|
75
|
+
"APPSIGNAL_ENABLE_GVL_GLOBAL_TIMER" => :enable_gvl_global_timer,
|
|
76
|
+
"APPSIGNAL_ENABLE_GVL_WAITING_THREADS" => :enable_gvl_waiting_threads,
|
|
72
77
|
"APPSIGNAL_FILES_WORLD_ACCESSIBLE" => :files_world_accessible,
|
|
73
78
|
"APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
|
|
74
79
|
"APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
|
|
@@ -123,6 +128,8 @@ module Appsignal
|
|
|
123
128
|
APPSIGNAL_ENABLE_MINUTELY_PROBES
|
|
124
129
|
APPSIGNAL_ENABLE_STATSD
|
|
125
130
|
APPSIGNAL_ENABLE_NGINX_METRICS
|
|
131
|
+
APPSIGNAL_ENABLE_GVL_GLOBAL_TIMER
|
|
132
|
+
APPSIGNAL_ENABLE_GVL_WAITING_THREADS
|
|
126
133
|
APPSIGNAL_FILES_WORLD_ACCESSIBLE
|
|
127
134
|
APPSIGNAL_INSTRUMENT_HTTP_RB
|
|
128
135
|
APPSIGNAL_INSTRUMENT_NET_HTTP
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
class Hooks
|
|
3
|
+
# @api private
|
|
4
|
+
class GvlHook < Appsignal::Hooks::Hook
|
|
5
|
+
register :gvl
|
|
6
|
+
|
|
7
|
+
def dependencies_present?
|
|
8
|
+
return false if Appsignal::System.jruby?
|
|
9
|
+
require "gvltools"
|
|
10
|
+
Appsignal.config && Appsignal::Probes::GvlProbe.dependencies_present?
|
|
11
|
+
rescue LoadError
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def install
|
|
16
|
+
Appsignal::Minutely.probes.register :gvl, Appsignal::Probes::GvlProbe
|
|
17
|
+
::GVLTools::GlobalTimer.enable if Appsignal.config[:enable_gvl_global_timer]
|
|
18
|
+
::GVLTools::WaitingThreads.enable if Appsignal.config[:enable_gvl_waiting_threads]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/appsignal/hooks.rb
CHANGED
|
@@ -94,6 +94,7 @@ require "appsignal/hooks/active_job"
|
|
|
94
94
|
require "appsignal/hooks/active_support_notifications"
|
|
95
95
|
require "appsignal/hooks/celluloid"
|
|
96
96
|
require "appsignal/hooks/delayed_job"
|
|
97
|
+
require "appsignal/hooks/gvl"
|
|
97
98
|
require "appsignal/hooks/http"
|
|
98
99
|
require "appsignal/hooks/mri"
|
|
99
100
|
require "appsignal/hooks/net_http"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Appsignal
|
|
2
|
+
module Probes
|
|
3
|
+
class GvlProbe
|
|
4
|
+
include Helpers
|
|
5
|
+
|
|
6
|
+
# @api private
|
|
7
|
+
def self.dependencies_present?
|
|
8
|
+
defined?(::GVLTools) && gvltools_0_2_or_newer? && ruby_3_2_or_newer? && !Appsignal::System.jruby?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
def self.gvltools_0_2_or_newer?
|
|
13
|
+
Gem::Version.new(::GVLTools::VERSION) >= Gem::Version.new("0.2.0")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @api private
|
|
17
|
+
def self.ruby_3_2_or_newer?
|
|
18
|
+
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.2.0")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def initialize(appsignal: Appsignal, gvl_tools: ::GVLTools)
|
|
22
|
+
Appsignal.logger.debug("Initializing GVL probe")
|
|
23
|
+
@appsignal = appsignal
|
|
24
|
+
@gvl_tools = gvl_tools
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def call
|
|
28
|
+
probe_global_timer if @gvl_tools::GlobalTimer.enabled?
|
|
29
|
+
probe_waiting_threads if @gvl_tools::WaitingThreads.enabled?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def probe_global_timer
|
|
35
|
+
monotonic_time_ns = @gvl_tools::GlobalTimer.monotonic_time
|
|
36
|
+
gauge_delta :gvl_global_timer, monotonic_time_ns do |time_delta_ns|
|
|
37
|
+
time_delta_ms = time_delta_ns / 1_000_000
|
|
38
|
+
set_gauge_with_hostname("gvl_global_timer", time_delta_ms)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def probe_waiting_threads
|
|
43
|
+
set_gauge_with_hostname("gvl_waiting_threads", @gvl_tools::WaitingThreads.count)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -37,6 +37,27 @@ module Appsignal
|
|
|
37
37
|
|
|
38
38
|
yield value - previous_value
|
|
39
39
|
end
|
|
40
|
+
|
|
41
|
+
def hostname
|
|
42
|
+
return @hostname if defined?(@hostname)
|
|
43
|
+
|
|
44
|
+
config = @appsignal.config
|
|
45
|
+
@hostname =
|
|
46
|
+
if config[:hostname]
|
|
47
|
+
config[:hostname]
|
|
48
|
+
else
|
|
49
|
+
# Auto detect hostname as fallback. May be inaccurate.
|
|
50
|
+
Socket.gethostname
|
|
51
|
+
end
|
|
52
|
+
Appsignal.logger.debug "Probe helper: Using hostname config " \
|
|
53
|
+
"option '#{@hostname.inspect}' as hostname"
|
|
54
|
+
|
|
55
|
+
@hostname
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def set_gauge_with_hostname(metric, value, tags = {})
|
|
59
|
+
@appsignal.set_gauge(metric, value, { :hostname => hostname }.merge(tags))
|
|
60
|
+
end
|
|
40
61
|
end
|
|
41
62
|
end
|
|
42
63
|
end
|
data/lib/appsignal/probes/mri.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Appsignal
|
|
|
20
20
|
|
|
21
21
|
constant_cache_invalidations = stat[:constant_cache_invalidations]
|
|
22
22
|
if constant_cache_invalidations
|
|
23
|
-
|
|
23
|
+
set_gauge_with_hostname(
|
|
24
24
|
"ruby_vm",
|
|
25
25
|
constant_cache_invalidations,
|
|
26
26
|
:metric => :constant_cache_invalidations
|
|
@@ -29,7 +29,7 @@ module Appsignal
|
|
|
29
29
|
|
|
30
30
|
constant_cache_misses = stat[:constant_cache_misses]
|
|
31
31
|
if constant_cache_misses
|
|
32
|
-
|
|
32
|
+
set_gauge_with_hostname(
|
|
33
33
|
"ruby_vm",
|
|
34
34
|
constant_cache_misses,
|
|
35
35
|
:metric => :constant_cache_misses
|
|
@@ -38,23 +38,23 @@ module Appsignal
|
|
|
38
38
|
|
|
39
39
|
class_serial = stat[:class_serial]
|
|
40
40
|
if class_serial
|
|
41
|
-
|
|
41
|
+
set_gauge_with_hostname("ruby_vm", class_serial, :metric => :class_serial)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
global_constant_state =
|
|
45
45
|
stat[:constant_cache] ? stat[:constant_cache].values.sum : stat[:global_constant_state]
|
|
46
46
|
if global_constant_state
|
|
47
|
-
|
|
47
|
+
set_gauge_with_hostname(
|
|
48
48
|
"ruby_vm",
|
|
49
49
|
global_constant_state,
|
|
50
50
|
:metric => :global_constant_state
|
|
51
51
|
)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
set_gauge_with_hostname("thread_count", Thread.list.size)
|
|
55
55
|
if Appsignal::GarbageCollection.enabled?
|
|
56
56
|
gauge_delta(:gc_time, @gc_profiler.total_time) do |gc_time|
|
|
57
|
-
|
|
57
|
+
set_gauge_with_hostname("gc_time", gc_time) if gc_time > 0
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -63,44 +63,21 @@ module Appsignal
|
|
|
63
63
|
:allocated_objects,
|
|
64
64
|
gc_stats[:total_allocated_objects] || gc_stats[:total_allocated_object]
|
|
65
65
|
) do |allocated_objects|
|
|
66
|
-
|
|
66
|
+
set_gauge_with_hostname("allocated_objects", allocated_objects)
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
gauge_delta(:gc_count, GC.count) do |gc_count|
|
|
70
|
-
|
|
70
|
+
set_gauge_with_hostname("gc_count", gc_count, :metric => :gc_count)
|
|
71
71
|
end
|
|
72
72
|
gauge_delta(:minor_gc_count, gc_stats[:minor_gc_count]) do |minor_gc_count|
|
|
73
|
-
|
|
73
|
+
set_gauge_with_hostname("gc_count", minor_gc_count, :metric => :minor_gc_count)
|
|
74
74
|
end
|
|
75
75
|
gauge_delta(:major_gc_count, gc_stats[:major_gc_count]) do |major_gc_count|
|
|
76
|
-
|
|
76
|
+
set_gauge_with_hostname("gc_count", major_gc_count, :metric => :major_gc_count)
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
private
|
|
84
|
-
|
|
85
|
-
def set_gauge(metric, value, tags = {})
|
|
86
|
-
@appsignal.set_gauge(metric, value, { :hostname => hostname }.merge(tags))
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def hostname
|
|
90
|
-
return @hostname if defined?(@hostname)
|
|
91
|
-
|
|
92
|
-
config = @appsignal.config
|
|
93
|
-
@hostname =
|
|
94
|
-
if config[:hostname]
|
|
95
|
-
config[:hostname]
|
|
96
|
-
else
|
|
97
|
-
# Auto detect hostname as fallback. May be inaccurate.
|
|
98
|
-
Socket.gethostname
|
|
99
|
-
end
|
|
100
|
-
Appsignal.logger.debug "MRI probe: Using hostname config " \
|
|
101
|
-
"option '#{@hostname.inspect}' as hostname"
|
|
102
|
-
|
|
103
|
-
@hostname
|
|
79
|
+
set_gauge_with_hostname("heap_slots", gc_stats[:heap_live_slots] || gc_stats[:heap_live_slot], :metric => :heap_live)
|
|
80
|
+
set_gauge_with_hostname("heap_slots", gc_stats[:heap_free_slots] || gc_stats[:heap_free_slot], :metric => :heap_free)
|
|
104
81
|
end
|
|
105
82
|
end
|
|
106
83
|
end
|
data/lib/appsignal/probes.rb
CHANGED
data/lib/appsignal/version.rb
CHANGED
|
@@ -156,6 +156,8 @@ describe Appsignal::Config do
|
|
|
156
156
|
:debug => false,
|
|
157
157
|
:dns_servers => [],
|
|
158
158
|
:enable_allocation_tracking => true,
|
|
159
|
+
:enable_gvl_global_timer => true,
|
|
160
|
+
:enable_gvl_waiting_threads => true,
|
|
159
161
|
:enable_host_metrics => true,
|
|
160
162
|
:enable_minutely_probes => true,
|
|
161
163
|
:enable_statsd => true,
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
describe Appsignal::Hooks::GvlHook do
|
|
2
|
+
if DependencyHelper.running_jruby?
|
|
3
|
+
context "running JRuby" do
|
|
4
|
+
it "does not attempt to require GVLTools" do
|
|
5
|
+
expect_any_instance_of(described_class).not_to receive(:require).with("gvltools")
|
|
6
|
+
expect(described_class.new.dependencies_present?).to be_falsy
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
else
|
|
10
|
+
before(:context) do
|
|
11
|
+
Appsignal.config = project_fixture_config
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def expect_gvltools_require
|
|
15
|
+
expect_any_instance_of(described_class).to receive(:require).with("gvltools").and_return(true)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "without GVLTools" do
|
|
19
|
+
describe "#dependencies_present?" do
|
|
20
|
+
context "if requiring gvltools fails" do
|
|
21
|
+
it "is false" do
|
|
22
|
+
expect(described_class.new.dependencies_present?).to be_falsy
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "is false" do
|
|
27
|
+
expect_gvltools_require
|
|
28
|
+
expect(described_class.new.dependencies_present?).to be_falsy
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "with old versions of GVLTools" do
|
|
34
|
+
before(:context) do
|
|
35
|
+
module GVLTools
|
|
36
|
+
VERSION = "0.1.0".freeze
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
after(:context) { Object.send(:remove_const, :GVLTools) }
|
|
41
|
+
|
|
42
|
+
before(:each) { expect_gvltools_require }
|
|
43
|
+
|
|
44
|
+
describe "#dependencies_present?" do
|
|
45
|
+
it "is false" do
|
|
46
|
+
expect(described_class.new.dependencies_present?).to be_falsy
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "with new versions of GVLTools" do
|
|
52
|
+
before(:context) do
|
|
53
|
+
module GVLTools
|
|
54
|
+
VERSION = "0.2.0".freeze
|
|
55
|
+
|
|
56
|
+
module GlobalTimer
|
|
57
|
+
def self.enable
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
module WaitingThreads
|
|
62
|
+
def self.enable
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
after(:context) { Object.send(:remove_const, :GVLTools) }
|
|
69
|
+
|
|
70
|
+
describe "#dependencies_present?" do
|
|
71
|
+
before(:each) { expect_gvltools_require }
|
|
72
|
+
|
|
73
|
+
if DependencyHelper.ruby_3_2_or_newer?
|
|
74
|
+
it "is true" do
|
|
75
|
+
expect(described_class.new.dependencies_present?).to be_truthy
|
|
76
|
+
end
|
|
77
|
+
else
|
|
78
|
+
it "is false" do
|
|
79
|
+
expect(described_class.new.dependencies_present?).to be_falsy
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if DependencyHelper.ruby_3_2_or_newer?
|
|
85
|
+
describe "Appsignal::Hooks.load_hooks" do
|
|
86
|
+
before(:each) { expect_gvltools_require }
|
|
87
|
+
|
|
88
|
+
# After installing a hook once, it is marked as already installed,
|
|
89
|
+
# and subsequent calls to `load_hooks` silently do nothing.
|
|
90
|
+
# Because of this, only one of the tests for the installation uses
|
|
91
|
+
# `load_hooks`, while the rest call the `install` method directly.
|
|
92
|
+
|
|
93
|
+
it "is added to minutely probes" do
|
|
94
|
+
Appsignal::Hooks.load_hooks
|
|
95
|
+
|
|
96
|
+
expect(Appsignal::Minutely.probes[:gvl]).to be Appsignal::Probes::GvlProbe
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe "#install" do
|
|
102
|
+
context "with enable_gvl_global_timer" do
|
|
103
|
+
it "enables the GVL global timer" do
|
|
104
|
+
Appsignal.config[:enable_gvl_global_timer] = true
|
|
105
|
+
expect(::GVLTools::GlobalTimer).to receive(:enable)
|
|
106
|
+
|
|
107
|
+
described_class.new.install
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "without enable_gvl_global_timer" do
|
|
112
|
+
it "does not enable the GVL global timer" do
|
|
113
|
+
Appsignal.config[:enable_gvl_global_timer] = false
|
|
114
|
+
expect(::GVLTools::GlobalTimer).not_to receive(:enable)
|
|
115
|
+
|
|
116
|
+
described_class.new.install
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context "with enable_gvl_waiting_threads" do
|
|
121
|
+
it "enables the GVL waiting threads" do
|
|
122
|
+
Appsignal.config[:enable_gvl_global_timer] = true
|
|
123
|
+
expect(::GVLTools::WaitingThreads).to receive(:enable)
|
|
124
|
+
|
|
125
|
+
described_class.new.install
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context "without enable_gvl_waiting_threads" do
|
|
130
|
+
it "does not enable the GVL waiting threads" do
|
|
131
|
+
Appsignal.config[:enable_gvl_waiting_threads] = false
|
|
132
|
+
expect(::GVLTools::WaitingThreads).not_to receive(:enable)
|
|
133
|
+
|
|
134
|
+
described_class.new.install
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
describe Appsignal::Probes::GvlProbe do
|
|
2
|
+
let(:appsignal_mock) { AppsignalMock.new(:hostname => hostname) }
|
|
3
|
+
let(:probe) { described_class.new(:appsignal => appsignal_mock, :gvl_tools => FakeGVLTools) }
|
|
4
|
+
|
|
5
|
+
let(:hostname) { "some-host" }
|
|
6
|
+
|
|
7
|
+
after(:each) { FakeGVLTools.reset }
|
|
8
|
+
|
|
9
|
+
context "with global timer enabled" do
|
|
10
|
+
before(:each) { FakeGVLTools::GlobalTimer.enabled = true }
|
|
11
|
+
|
|
12
|
+
it "gauges the global timer delta" do
|
|
13
|
+
FakeGVLTools::GlobalTimer.monotonic_time = 100_000_000
|
|
14
|
+
probe.call
|
|
15
|
+
|
|
16
|
+
expect(appsignal_mock.gauges).to be_empty
|
|
17
|
+
|
|
18
|
+
FakeGVLTools::GlobalTimer.monotonic_time = 300_000_000
|
|
19
|
+
probe.call
|
|
20
|
+
|
|
21
|
+
expect(appsignal_mock.gauges).to eq [
|
|
22
|
+
["gvl_global_timer", 200, { :hostname => hostname }]
|
|
23
|
+
]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "with waiting threads enabled" do
|
|
28
|
+
before(:each) { FakeGVLTools::WaitingThreads.enabled = true }
|
|
29
|
+
|
|
30
|
+
it "gauges the waiting threads count" do
|
|
31
|
+
FakeGVLTools::WaitingThreads.count = 3
|
|
32
|
+
probe.call
|
|
33
|
+
|
|
34
|
+
expect(appsignal_mock.gauges).to eq [
|
|
35
|
+
["gvl_waiting_threads", 3, { :hostname => hostname }]
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -1,22 +1,3 @@
|
|
|
1
|
-
class AppsignalMock
|
|
2
|
-
attr_reader :gauges
|
|
3
|
-
|
|
4
|
-
def initialize(hostname: nil)
|
|
5
|
-
@hostname = hostname
|
|
6
|
-
@gauges = []
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def config
|
|
10
|
-
ConfigHelpers.project_fixture_config.tap do |conf|
|
|
11
|
-
conf[:hostname] = @hostname if @hostname
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def set_gauge(*args) # rubocop:disable Naming/AccessorMethodName
|
|
16
|
-
@gauges << args
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
1
|
describe Appsignal::Probes::MriProbe do
|
|
21
2
|
let(:appsignal_mock) { AppsignalMock.new(:hostname => hostname) }
|
|
22
3
|
let(:gc_profiler_mock) { instance_double("Appsignal::GarbageCollectionProfiler") }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class AppsignalMock
|
|
2
|
+
attr_reader :gauges
|
|
3
|
+
|
|
4
|
+
def initialize(hostname: nil)
|
|
5
|
+
@hostname = hostname
|
|
6
|
+
@gauges = []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def config
|
|
10
|
+
ConfigHelpers.project_fixture_config.tap do |conf|
|
|
11
|
+
conf[:hostname] = @hostname if @hostname
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def set_gauge(*args) # rubocop:disable Naming/AccessorMethodName
|
|
16
|
+
@gauges << args
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module FakeGVLTools
|
|
2
|
+
def self.reset
|
|
3
|
+
self::GlobalTimer.enabled = false
|
|
4
|
+
self::GlobalTimer.monotonic_time = 0
|
|
5
|
+
self::WaitingThreads.enabled = false
|
|
6
|
+
self::WaitingThreads.count = 0
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module GlobalTimer
|
|
10
|
+
@enabled = false
|
|
11
|
+
@monotonic_time = 0
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
attr_writer :enabled
|
|
15
|
+
attr_accessor :monotonic_time
|
|
16
|
+
|
|
17
|
+
def enabled?
|
|
18
|
+
@enabled
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module WaitingThreads
|
|
24
|
+
@enabled = false
|
|
25
|
+
@count = 0
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
attr_writer :enabled
|
|
29
|
+
attr_accessor :count
|
|
30
|
+
|
|
31
|
+
def enabled?
|
|
32
|
+
@enabled
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appsignal
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.3.
|
|
4
|
+
version: 3.3.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Beekman
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2023-03-
|
|
13
|
+
date: 2023-03-30 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rack
|
|
@@ -218,6 +218,7 @@ files:
|
|
|
218
218
|
- lib/appsignal/hooks/data_mapper.rb
|
|
219
219
|
- lib/appsignal/hooks/delayed_job.rb
|
|
220
220
|
- lib/appsignal/hooks/excon.rb
|
|
221
|
+
- lib/appsignal/hooks/gvl.rb
|
|
221
222
|
- lib/appsignal/hooks/http.rb
|
|
222
223
|
- lib/appsignal/hooks/mongo_ruby_driver.rb
|
|
223
224
|
- lib/appsignal/hooks/mri.rb
|
|
@@ -260,6 +261,7 @@ files:
|
|
|
260
261
|
- lib/appsignal/marker.rb
|
|
261
262
|
- lib/appsignal/minutely.rb
|
|
262
263
|
- lib/appsignal/probes.rb
|
|
264
|
+
- lib/appsignal/probes/gvl.rb
|
|
263
265
|
- lib/appsignal/probes/helpers.rb
|
|
264
266
|
- lib/appsignal/probes/mri.rb
|
|
265
267
|
- lib/appsignal/probes/sidekiq.rb
|
|
@@ -323,6 +325,7 @@ files:
|
|
|
323
325
|
- spec/lib/appsignal/hooks/data_mapper_spec.rb
|
|
324
326
|
- spec/lib/appsignal/hooks/delayed_job_spec.rb
|
|
325
327
|
- spec/lib/appsignal/hooks/excon_spec.rb
|
|
328
|
+
- spec/lib/appsignal/hooks/gvl_spec.rb
|
|
326
329
|
- spec/lib/appsignal/hooks/http_spec.rb
|
|
327
330
|
- spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb
|
|
328
331
|
- spec/lib/appsignal/hooks/mri_spec.rb
|
|
@@ -354,6 +357,7 @@ files:
|
|
|
354
357
|
- spec/lib/appsignal/logger_spec.rb
|
|
355
358
|
- spec/lib/appsignal/marker_spec.rb
|
|
356
359
|
- spec/lib/appsignal/minutely_spec.rb
|
|
360
|
+
- spec/lib/appsignal/probes/gvl_spec.rb
|
|
357
361
|
- spec/lib/appsignal/probes/mri_spec.rb
|
|
358
362
|
- spec/lib/appsignal/probes/sidekiq_spec.rb
|
|
359
363
|
- spec/lib/appsignal/rack/generic_instrumentation_spec.rb
|
|
@@ -402,7 +406,9 @@ files:
|
|
|
402
406
|
- spec/support/matchers/be_completed.rb
|
|
403
407
|
- spec/support/matchers/contains_log.rb
|
|
404
408
|
- spec/support/matchers/have_colorized_text.rb
|
|
409
|
+
- spec/support/mocks/appsignal_mock.rb
|
|
405
410
|
- spec/support/mocks/fake_gc_profiler.rb
|
|
411
|
+
- spec/support/mocks/fake_gvl_tools.rb
|
|
406
412
|
- spec/support/mocks/mock_probe.rb
|
|
407
413
|
- spec/support/rails/my_app.rb
|
|
408
414
|
- spec/support/shared_examples/instrument.rb
|
|
@@ -480,6 +486,7 @@ test_files:
|
|
|
480
486
|
- spec/lib/appsignal/hooks/data_mapper_spec.rb
|
|
481
487
|
- spec/lib/appsignal/hooks/delayed_job_spec.rb
|
|
482
488
|
- spec/lib/appsignal/hooks/excon_spec.rb
|
|
489
|
+
- spec/lib/appsignal/hooks/gvl_spec.rb
|
|
483
490
|
- spec/lib/appsignal/hooks/http_spec.rb
|
|
484
491
|
- spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb
|
|
485
492
|
- spec/lib/appsignal/hooks/mri_spec.rb
|
|
@@ -511,6 +518,7 @@ test_files:
|
|
|
511
518
|
- spec/lib/appsignal/logger_spec.rb
|
|
512
519
|
- spec/lib/appsignal/marker_spec.rb
|
|
513
520
|
- spec/lib/appsignal/minutely_spec.rb
|
|
521
|
+
- spec/lib/appsignal/probes/gvl_spec.rb
|
|
514
522
|
- spec/lib/appsignal/probes/mri_spec.rb
|
|
515
523
|
- spec/lib/appsignal/probes/sidekiq_spec.rb
|
|
516
524
|
- spec/lib/appsignal/rack/generic_instrumentation_spec.rb
|
|
@@ -559,7 +567,9 @@ test_files:
|
|
|
559
567
|
- spec/support/matchers/be_completed.rb
|
|
560
568
|
- spec/support/matchers/contains_log.rb
|
|
561
569
|
- spec/support/matchers/have_colorized_text.rb
|
|
570
|
+
- spec/support/mocks/appsignal_mock.rb
|
|
562
571
|
- spec/support/mocks/fake_gc_profiler.rb
|
|
572
|
+
- spec/support/mocks/fake_gvl_tools.rb
|
|
563
573
|
- spec/support/mocks/mock_probe.rb
|
|
564
574
|
- spec/support/rails/my_app.rb
|
|
565
575
|
- spec/support/shared_examples/instrument.rb
|