appsignal 3.3.7-java → 3.3.9-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf316d2ff99ac803b94b624dc081c41a6c8d84d5ee659e3029870d7ed4d212ba
4
- data.tar.gz: 77177fc406fe073de5917b1829bc88f820ebfe941af8e1183be083d99d1735d6
3
+ metadata.gz: '0856b3ea91ba164241bcb2d0017fd9c5fe6e32c719d1fe05c7684079e20146d2'
4
+ data.tar.gz: 5cccb7e02b50707e3093025679cd48168379ed2300d855e851eb71d62095f4ff
5
5
  SHA512:
6
- metadata.gz: 66082238307235ccfeabf9a3b60c8f2b5702a4cb715cbd6dc260d786fde00032add30e6a44993a862f7bba8ef5a2698aa5d581adfc9c54ce9448816692b09add
7
- data.tar.gz: 79e3ead1f689f0f9dd1a2b207b5051ec92fffbbd270349aa407d56a0c69669e48f3a1fc681f59ee93d445d92224129e207981a1e84d019f44b7df8b425c8c673
6
+ metadata.gz: f271aa02a2ba9d57708bbb2f09021646e6ec48822a2f926a108f0b2e58ec2909bc6e8de64a82c00188620297a9f68eb1f5864aaff9a6931272deff871badabc7
7
+ data.tar.gz: bb15b922ac0460bd0d58d7c5dcf50e95665be21bfc35af5d1a2d8ca400f78c2857fcc0d78f806568927607f55edffc5891c7b536c0554e48abbf90b41a7cc5fd
@@ -846,7 +846,7 @@ blocks:
846
846
  value: latest
847
847
  commands:
848
848
  - "./support/bundler_wrapper exec rake test"
849
- - name: Ruby 2.6.9 for webmachine
849
+ - name: Ruby 2.6.9 for webmachine1
850
850
  env_vars:
851
851
  - *2
852
852
  - *3
@@ -855,9 +855,27 @@ blocks:
855
855
  - name: RUBY_VERSION
856
856
  value: 2.6.9
857
857
  - name: GEMSET
858
- value: webmachine
858
+ value: webmachine1
859
859
  - name: BUNDLE_GEMFILE
860
- value: gemfiles/webmachine.gemfile
860
+ value: gemfiles/webmachine1.gemfile
861
+ - name: _RUBYGEMS_VERSION
862
+ value: latest
863
+ - name: _BUNDLER_VERSION
864
+ value: latest
865
+ commands:
866
+ - "./support/bundler_wrapper exec rake test"
867
+ - name: Ruby 2.6.9 for webmachine2
868
+ env_vars:
869
+ - *2
870
+ - *3
871
+ - *4
872
+ - *5
873
+ - name: RUBY_VERSION
874
+ value: 2.6.9
875
+ - name: GEMSET
876
+ value: webmachine2
877
+ - name: BUNDLE_GEMFILE
878
+ value: gemfiles/webmachine2.gemfile
861
879
  - name: _RUBYGEMS_VERSION
862
880
  value: latest
863
881
  - name: _BUNDLER_VERSION
@@ -1239,7 +1257,25 @@ blocks:
1239
1257
  value: latest
1240
1258
  commands:
1241
1259
  - "./support/bundler_wrapper exec rake test"
1242
- - name: Ruby 2.7.7 for webmachine
1260
+ - name: Ruby 2.7.7 for webmachine1
1261
+ env_vars:
1262
+ - *2
1263
+ - *3
1264
+ - *4
1265
+ - *5
1266
+ - name: RUBY_VERSION
1267
+ value: 2.7.7
1268
+ - name: GEMSET
1269
+ value: webmachine1
1270
+ - name: BUNDLE_GEMFILE
1271
+ value: gemfiles/webmachine1.gemfile
1272
+ - name: _RUBYGEMS_VERSION
1273
+ value: latest
1274
+ - name: _BUNDLER_VERSION
1275
+ value: latest
1276
+ commands:
1277
+ - "./support/bundler_wrapper exec rake test"
1278
+ - name: Ruby 2.7.7 for webmachine2
1243
1279
  env_vars:
1244
1280
  - *2
1245
1281
  - *3
@@ -1248,9 +1284,9 @@ blocks:
1248
1284
  - name: RUBY_VERSION
1249
1285
  value: 2.7.7
1250
1286
  - name: GEMSET
1251
- value: webmachine
1287
+ value: webmachine2
1252
1288
  - name: BUNDLE_GEMFILE
1253
- value: gemfiles/webmachine.gemfile
1289
+ value: gemfiles/webmachine2.gemfile
1254
1290
  - name: _RUBYGEMS_VERSION
1255
1291
  value: latest
1256
1292
  - name: _BUNDLER_VERSION
@@ -1596,7 +1632,7 @@ blocks:
1596
1632
  value: latest
1597
1633
  commands:
1598
1634
  - "./support/bundler_wrapper exec rake test"
1599
- - name: Ruby 3.0.5 for webmachine
1635
+ - name: Ruby 3.0.5 for webmachine1
1600
1636
  env_vars:
1601
1637
  - *2
1602
1638
  - *3
@@ -1605,9 +1641,27 @@ blocks:
1605
1641
  - name: RUBY_VERSION
1606
1642
  value: 3.0.5
1607
1643
  - name: GEMSET
1608
- value: webmachine
1644
+ value: webmachine1
1609
1645
  - name: BUNDLE_GEMFILE
1610
- value: gemfiles/webmachine.gemfile
1646
+ value: gemfiles/webmachine1.gemfile
1647
+ - name: _RUBYGEMS_VERSION
1648
+ value: latest
1649
+ - name: _BUNDLER_VERSION
1650
+ value: latest
1651
+ commands:
1652
+ - "./support/bundler_wrapper exec rake test"
1653
+ - name: Ruby 3.0.5 for webmachine2
1654
+ env_vars:
1655
+ - *2
1656
+ - *3
1657
+ - *4
1658
+ - *5
1659
+ - name: RUBY_VERSION
1660
+ value: 3.0.5
1661
+ - name: GEMSET
1662
+ value: webmachine2
1663
+ - name: BUNDLE_GEMFILE
1664
+ value: gemfiles/webmachine2.gemfile
1611
1665
  - name: _RUBYGEMS_VERSION
1612
1666
  value: latest
1613
1667
  - name: _BUNDLER_VERSION
@@ -1935,7 +1989,7 @@ blocks:
1935
1989
  value: latest
1936
1990
  commands:
1937
1991
  - "./support/bundler_wrapper exec rake test"
1938
- - name: Ruby 3.1.3 for webmachine
1992
+ - name: Ruby 3.1.3 for webmachine1
1939
1993
  env_vars:
1940
1994
  - *2
1941
1995
  - *3
@@ -1944,9 +1998,27 @@ blocks:
1944
1998
  - name: RUBY_VERSION
1945
1999
  value: 3.1.3
1946
2000
  - name: GEMSET
1947
- value: webmachine
2001
+ value: webmachine1
1948
2002
  - name: BUNDLE_GEMFILE
1949
- value: gemfiles/webmachine.gemfile
2003
+ value: gemfiles/webmachine1.gemfile
2004
+ - name: _RUBYGEMS_VERSION
2005
+ value: latest
2006
+ - name: _BUNDLER_VERSION
2007
+ value: latest
2008
+ commands:
2009
+ - "./support/bundler_wrapper exec rake test"
2010
+ - name: Ruby 3.1.3 for webmachine2
2011
+ env_vars:
2012
+ - *2
2013
+ - *3
2014
+ - *4
2015
+ - *5
2016
+ - name: RUBY_VERSION
2017
+ value: 3.1.3
2018
+ - name: GEMSET
2019
+ value: webmachine2
2020
+ - name: BUNDLE_GEMFILE
2021
+ value: gemfiles/webmachine2.gemfile
1950
2022
  - name: _RUBYGEMS_VERSION
1951
2023
  value: latest
1952
2024
  - name: _BUNDLER_VERSION
@@ -2274,7 +2346,25 @@ blocks:
2274
2346
  value: latest
2275
2347
  commands:
2276
2348
  - "./support/bundler_wrapper exec rake test"
2277
- - name: Ruby 3.2.1 for webmachine
2349
+ - name: Ruby 3.2.1 for webmachine1
2350
+ env_vars:
2351
+ - *2
2352
+ - *3
2353
+ - *4
2354
+ - *5
2355
+ - name: RUBY_VERSION
2356
+ value: 3.2.1
2357
+ - name: GEMSET
2358
+ value: webmachine1
2359
+ - name: BUNDLE_GEMFILE
2360
+ value: gemfiles/webmachine1.gemfile
2361
+ - name: _RUBYGEMS_VERSION
2362
+ value: latest
2363
+ - name: _BUNDLER_VERSION
2364
+ value: latest
2365
+ commands:
2366
+ - "./support/bundler_wrapper exec rake test"
2367
+ - name: Ruby 3.2.1 for webmachine2
2278
2368
  env_vars:
2279
2369
  - *2
2280
2370
  - *3
@@ -2283,9 +2373,9 @@ blocks:
2283
2373
  - name: RUBY_VERSION
2284
2374
  value: 3.2.1
2285
2375
  - name: GEMSET
2286
- value: webmachine
2376
+ value: webmachine2
2287
2377
  - name: BUNDLE_GEMFILE
2288
- value: gemfiles/webmachine.gemfile
2378
+ value: gemfiles/webmachine2.gemfile
2289
2379
  - name: _RUBYGEMS_VERSION
2290
2380
  value: latest
2291
2381
  - name: _BUNDLER_VERSION
data/CHANGELOG.md CHANGED
@@ -1,10 +1,28 @@
1
1
  # AppSignal for Ruby gem Changelog
2
2
 
3
+ ## 3.3.9
4
+
5
+ ### Fixed
6
+
7
+ - [a6db61b9](https://github.com/appsignal/appsignal-ruby/commit/a6db61b9a14a5a3b4ba89c99d35229bcdee98f94) patch - Fixed an error when using our Logging feature with Ruby's default logger formatter.
8
+
9
+ ## 3.3.8
10
+
11
+ ### Added
12
+
13
+ - [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.
14
+ - [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.
15
+
3
16
  ## 3.3.7
4
17
 
18
+ ### Added
19
+
20
+ - [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.
21
+
5
22
  ### Changed
6
23
 
7
24
  - [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.
25
+ - [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
26
 
9
27
  ### Fixed
10
28
 
data/build_matrix.yml CHANGED
@@ -339,4 +339,5 @@ matrix:
339
339
  - "2.6.9"
340
340
  - "2.7.7"
341
341
  - gem: "sinatra"
342
- - gem: "webmachine"
342
+ - gem: "webmachine1"
343
+ - gem: "webmachine2"
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'webmachine'
3
+ gem 'webmachine', '~> 1.6'
4
4
  gem 'webrick'
5
5
 
6
6
  gemspec :path => '../'
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "webmachine", "~> 2.0"
4
+ gem "webrick"
5
+
6
+ gemspec :path => "../"
@@ -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
@@ -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"
@@ -9,6 +9,13 @@ module Appsignal
9
9
  PLAINTEXT = 0
10
10
  LOGFMT = 1
11
11
  JSON = 2
12
+ SEVERITY_MAP = {
13
+ DEBUG => 2,
14
+ INFO => 3,
15
+ WARN => 5,
16
+ ERROR => 6,
17
+ FATAL => 7
18
+ }.freeze
12
19
 
13
20
  # Create a new logger instance
14
21
  #
@@ -25,7 +32,7 @@ module Appsignal
25
32
  # We support the various methods in the Ruby
26
33
  # logger class by supplying this method.
27
34
  # @api private
28
- def add(severity, message = nil, group = nil) # rubocop:disable Metrics/CyclomaticComplexity
35
+ def add(severity, message = nil, group = nil)
29
36
  severity ||= UNKNOWN
30
37
  return true if severity < level
31
38
  group = @group if group.nil?
@@ -38,24 +45,11 @@ module Appsignal
38
45
  end
39
46
  end
40
47
  return if message.nil?
41
- message = formatter.call(severity, 0, group, message) if formatter
42
- severity_number = case severity
43
- when DEBUG
44
- 2
45
- when INFO
46
- 3
47
- when WARN
48
- 5
49
- when ERROR
50
- 6
51
- when FATAL
52
- 7
53
- else
54
- 0
55
- end
48
+ message = formatter.call(severity, Time.now, group, message) if formatter
49
+
56
50
  Appsignal::Extension.log(
57
51
  group,
58
- severity_number,
52
+ SEVERITY_MAP.fetch(severity, 0),
59
53
  @format,
60
54
  message,
61
55
  Appsignal::Utils::Data.generate({})
@@ -71,7 +65,7 @@ module Appsignal
71
65
  return if DEBUG < level
72
66
  message = yield if message.nil? && block_given?
73
67
  return if message.nil?
74
- message = formatter.call(DEBUG, 0, @group, message) if formatter
68
+ message = formatter.call(DEBUG, Time.now, @group, message) if formatter
75
69
  Appsignal::Extension.log(
76
70
  @group,
77
71
  2,
@@ -89,7 +83,7 @@ module Appsignal
89
83
  return if INFO < level
90
84
  message = yield if message.nil? && block_given?
91
85
  return if message.nil?
92
- message = formatter.call(INFO, 0, @group, message) if formatter
86
+ message = formatter.call(INFO, Time.now, @group, message) if formatter
93
87
  Appsignal::Extension.log(
94
88
  @group,
95
89
  3,
@@ -107,7 +101,7 @@ module Appsignal
107
101
  return if WARN < level
108
102
  message = yield if message.nil? && block_given?
109
103
  return if message.nil?
110
- message = formatter.call(WARN, 0, @group, message) if formatter
104
+ message = formatter.call(WARN, Time.now, @group, message) if formatter
111
105
  Appsignal::Extension.log(
112
106
  @group,
113
107
  5,
@@ -125,7 +119,7 @@ module Appsignal
125
119
  return if ERROR < level
126
120
  message = yield if message.nil? && block_given?
127
121
  return if message.nil?
128
- message = formatter.call(ERROR, 0, @group, message) if formatter
122
+ message = formatter.call(ERROR, Time.now, @group, message) if formatter
129
123
  Appsignal::Extension.log(
130
124
  @group,
131
125
  6,
@@ -143,7 +137,7 @@ module Appsignal
143
137
  return if FATAL < level
144
138
  message = yield if message.nil? && block_given?
145
139
  return if message.nil?
146
- message = formatter.call(FATAL, 0, @group, message) if formatter
140
+ message = formatter.call(FATAL, Time.now, @group, message) if formatter
147
141
  Appsignal::Extension.log(
148
142
  @group,
149
143
  7,
@@ -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
@@ -20,7 +20,7 @@ module Appsignal
20
20
 
21
21
  constant_cache_invalidations = stat[:constant_cache_invalidations]
22
22
  if constant_cache_invalidations
23
- set_gauge(
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
- set_gauge(
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
- set_gauge("ruby_vm", class_serial, :metric => :class_serial)
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
- set_gauge(
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
- set_gauge("thread_count", Thread.list.size)
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
- set_gauge("gc_time", gc_time) if gc_time > 0
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
- set_gauge("allocated_objects", allocated_objects)
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
- set_gauge("gc_count", gc_count, :metric => :gc_count)
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
- set_gauge("gc_count", minor_gc_count, :metric => :minor_gc_count)
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
- set_gauge("gc_count", major_gc_count, :metric => :major_gc_count)
76
+ set_gauge_with_hostname("gc_count", major_gc_count, :metric => :major_gc_count)
77
77
  end
78
78
 
79
- set_gauge("heap_slots", gc_stats[:heap_live_slots] || gc_stats[:heap_live_slot], :metric => :heap_live)
80
- set_gauge("heap_slots", gc_stats[:heap_free_slots] || gc_stats[:heap_free_slot], :metric => :heap_free)
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
@@ -4,5 +4,6 @@ module Appsignal
4
4
  end
5
5
 
6
6
  require "appsignal/probes/helpers"
7
+ require "appsignal/probes/gvl"
7
8
  require "appsignal/probes/mri"
8
9
  require "appsignal/probes/sidekiq"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.3.7".freeze
4
+ VERSION = "3.3.9".freeze
5
5
  end
@@ -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
@@ -115,14 +115,29 @@ describe Appsignal::Logger do
115
115
 
116
116
  context "with a formatter set" do
117
117
  before do
118
- logger.formatter = proc do |_level, _timestamp, _appname, message|
119
- "formatted: '#{message}'"
118
+ Timecop.freeze(Time.local(2023))
119
+ logger.formatter = logger.formatter = proc do |_level, timestamp, _appname, message|
120
+ # This line replicates the behaviour of the Ruby default Logger::Formatter
121
+ # which expects a timestamp object as a second argument
122
+ # https://github.com/ruby/ruby/blob/master/lib/logger/formatter.rb#L15-L17
123
+ time = timestamp.strftime("%Y-%m-%dT%H:%M:%S.%6N")
124
+ "formatted: #{time} '#{message}'"
120
125
  end
121
126
  end
122
127
 
128
+ after do
129
+ Timecop.return
130
+ end
131
+
123
132
  it "should log with a level, message and group" do
124
133
  expect(Appsignal::Extension).to receive(:log)
125
- .with("group", method[1], 0, "formatted: 'Log message'", instance_of(Appsignal::Extension::Data))
134
+ .with(
135
+ "group",
136
+ method[1],
137
+ 0,
138
+ "formatted: 2023-01-01T00:00:00.000000 'Log message'",
139
+ instance_of(Appsignal::Extension::Data)
140
+ )
126
141
  logger.send(method[0], "Log message")
127
142
  end
128
143
  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,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.7
4
+ version: 3.3.9
5
5
  platform: java
6
6
  authors:
7
7
  - Robert Beekman
8
8
  - Thijs Cadier
9
9
  - Tom de Bruijn
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-03-09 00:00:00.000000000 Z
13
+ date: 2023-03-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -196,7 +196,8 @@ files:
196
196
  - gemfiles/sequel-435.gemfile
197
197
  - gemfiles/sequel.gemfile
198
198
  - gemfiles/sinatra.gemfile
199
- - gemfiles/webmachine.gemfile
199
+ - gemfiles/webmachine1.gemfile
200
+ - gemfiles/webmachine2.gemfile
200
201
  - lib/appsignal.rb
201
202
  - lib/appsignal/auth_check.rb
202
203
  - lib/appsignal/capistrano.rb
@@ -232,6 +233,7 @@ files:
232
233
  - lib/appsignal/hooks/data_mapper.rb
233
234
  - lib/appsignal/hooks/delayed_job.rb
234
235
  - lib/appsignal/hooks/excon.rb
236
+ - lib/appsignal/hooks/gvl.rb
235
237
  - lib/appsignal/hooks/http.rb
236
238
  - lib/appsignal/hooks/mongo_ruby_driver.rb
237
239
  - lib/appsignal/hooks/mri.rb
@@ -274,6 +276,7 @@ files:
274
276
  - lib/appsignal/marker.rb
275
277
  - lib/appsignal/minutely.rb
276
278
  - lib/appsignal/probes.rb
279
+ - lib/appsignal/probes/gvl.rb
277
280
  - lib/appsignal/probes/helpers.rb
278
281
  - lib/appsignal/probes/mri.rb
279
282
  - lib/appsignal/probes/sidekiq.rb
@@ -337,6 +340,7 @@ files:
337
340
  - spec/lib/appsignal/hooks/data_mapper_spec.rb
338
341
  - spec/lib/appsignal/hooks/delayed_job_spec.rb
339
342
  - spec/lib/appsignal/hooks/excon_spec.rb
343
+ - spec/lib/appsignal/hooks/gvl_spec.rb
340
344
  - spec/lib/appsignal/hooks/http_spec.rb
341
345
  - spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb
342
346
  - spec/lib/appsignal/hooks/mri_spec.rb
@@ -368,6 +372,7 @@ files:
368
372
  - spec/lib/appsignal/logger_spec.rb
369
373
  - spec/lib/appsignal/marker_spec.rb
370
374
  - spec/lib/appsignal/minutely_spec.rb
375
+ - spec/lib/appsignal/probes/gvl_spec.rb
371
376
  - spec/lib/appsignal/probes/mri_spec.rb
372
377
  - spec/lib/appsignal/probes/sidekiq_spec.rb
373
378
  - spec/lib/appsignal/rack/generic_instrumentation_spec.rb
@@ -416,7 +421,9 @@ files:
416
421
  - spec/support/matchers/be_completed.rb
417
422
  - spec/support/matchers/contains_log.rb
418
423
  - spec/support/matchers/have_colorized_text.rb
424
+ - spec/support/mocks/appsignal_mock.rb
419
425
  - spec/support/mocks/fake_gc_profiler.rb
426
+ - spec/support/mocks/fake_gvl_tools.rb
420
427
  - spec/support/mocks/mock_probe.rb
421
428
  - spec/support/rails/my_app.rb
422
429
  - spec/support/shared_examples/instrument.rb
@@ -436,7 +443,7 @@ metadata:
436
443
  documentation_uri: https://docs.appsignal.com/ruby/
437
444
  homepage_uri: https://docs.appsignal.com/ruby/
438
445
  source_code_uri: https://github.com/appsignal/appsignal-ruby
439
- post_install_message:
446
+ post_install_message:
440
447
  rdoc_options: []
441
448
  require_paths:
442
449
  - lib
@@ -452,8 +459,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
452
459
  - !ruby/object:Gem::Version
453
460
  version: '0'
454
461
  requirements: []
455
- rubygems_version: 3.1.6
456
- signing_key:
462
+ rubygems_version: 3.1.4
463
+ signing_key:
457
464
  specification_version: 4
458
465
  summary: Logs performance and exception data from your app to appsignal.com
459
466
  test_files:
@@ -494,6 +501,7 @@ test_files:
494
501
  - spec/lib/appsignal/hooks/data_mapper_spec.rb
495
502
  - spec/lib/appsignal/hooks/delayed_job_spec.rb
496
503
  - spec/lib/appsignal/hooks/excon_spec.rb
504
+ - spec/lib/appsignal/hooks/gvl_spec.rb
497
505
  - spec/lib/appsignal/hooks/http_spec.rb
498
506
  - spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb
499
507
  - spec/lib/appsignal/hooks/mri_spec.rb
@@ -525,6 +533,7 @@ test_files:
525
533
  - spec/lib/appsignal/logger_spec.rb
526
534
  - spec/lib/appsignal/marker_spec.rb
527
535
  - spec/lib/appsignal/minutely_spec.rb
536
+ - spec/lib/appsignal/probes/gvl_spec.rb
528
537
  - spec/lib/appsignal/probes/mri_spec.rb
529
538
  - spec/lib/appsignal/probes/sidekiq_spec.rb
530
539
  - spec/lib/appsignal/rack/generic_instrumentation_spec.rb
@@ -573,7 +582,9 @@ test_files:
573
582
  - spec/support/matchers/be_completed.rb
574
583
  - spec/support/matchers/contains_log.rb
575
584
  - spec/support/matchers/have_colorized_text.rb
585
+ - spec/support/mocks/appsignal_mock.rb
576
586
  - spec/support/mocks/fake_gc_profiler.rb
587
+ - spec/support/mocks/fake_gvl_tools.rb
577
588
  - spec/support/mocks/mock_probe.rb
578
589
  - spec/support/rails/my_app.rb
579
590
  - spec/support/shared_examples/instrument.rb