appsignal 3.1.3-java → 3.1.5-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: 5bb9d094ed8de471e90dea7cd631a31ffea0777c09dbe4bfac516cc1820cbdcf
4
- data.tar.gz: 790ec312c3349ee2b6889d8fca238e6cea7daa537c71cf81b7438152c2a2a2cb
3
+ metadata.gz: 20749c0f3826167272d727c37dd1e881502a9654f8b499d4f3fcdf40dd386178
4
+ data.tar.gz: 90ddbe20ee5243338aefdfbefbb1989bbe1df5cc57a56a4f277bcfa789086b41
5
5
  SHA512:
6
- metadata.gz: a3ecfceba446f9a876c903b796a2b91c4ba44ab53856e9a6518d4681f86144547bdffd6d367a309ae05c5e15ebc30a52ca4b666dcec1c651b321d90c0eb8014f
7
- data.tar.gz: c5705bfeca7ec423ee1888572f84ef70fd15abdb5501cd0c9e73c2d5855b498d7e03ac8c50ab1aa88137d3335376cd2d0b767503c0ec17d9b2c7b209cd04e80f
6
+ metadata.gz: c9f2133fe6f929ebbbee6b9c8f47f85bd3c895b518daf6a69b5ad8a2e9a29ebcd72ca1c25a7aef8512a8493f8941ab711fda9b0f16fff30cac73c40701376a47
7
+ data.tar.gz: bfe585b6c6ce5f8cc5e470c9a164e6690fc1834e40bb4bd27491f719cbdaf6ebd4b92d1f1ba2bc3001e157f5c35786f12143b29d9908e9ce73d9ca9712c7c5ef
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # AppSignal for Ruby gem Changelog
2
2
 
3
+ ## 3.1.5
4
+
5
+ ### Changed
6
+
7
+ - [4035c3c2](https://github.com/appsignal/appsignal-ruby/commit/4035c3c2d5c0b002119054014daddd193bd820f0) patch - Bump agent to version 813a59b
8
+
9
+ - Fix http proxy config option parsing for port 80.
10
+ - Fix the return value for appsignal_import_opentelemetry_span extension
11
+ function in `appsignal.h`.
12
+
13
+ ### Fixed
14
+
15
+ - [feb60fb8](https://github.com/appsignal/appsignal-ruby/commit/feb60fb877a2b264e587fe3d5d546e40d86c9c38) patch - Fix NoMethodError for AppSignal Puma plugin for Puma 6. Puma 5 is also still supported.
16
+
17
+ ## 3.1.4
18
+
19
+ ### Added
20
+
21
+ - [ffe49cfe](https://github.com/appsignal/appsignal-ruby/commit/ffe49cfe94f5269e59d6f168a73114f7a3914f79) patch - Support temporarily disabling GC profiling without reporting inaccurate `gc_time` metric durations. The MRI probe's `gc_time` will not report any value when the `GC::Profiler.enabled?` returns `false`.
22
+
23
+ ### Changed
24
+
25
+ - [af7e666c](https://github.com/appsignal/appsignal-ruby/commit/af7e666cf173ec1f42e9cf3fce2ab6c8e658440c) patch - Listen if the Ruby Garbage Collection profiler is enabled and collect how long the GC is running for the Ruby VM magic dashboard. An app will need to call `GC::Profiler.enable` to enable the GC profiler. Do not enable this in production environments, or at least not for long, because this can negatively impact performance of apps.
26
+
27
+ ### Fixed
28
+
29
+ - [b3a163be](https://github.com/appsignal/appsignal-ruby/commit/b3a163be154796e1f358c5061eaee99845c960ee) patch - Fix the MRI probe using the Garbage Collection profiler instead of the NilProfiler when garbage collection instrumentation is not enabled for MRI probe. This caused unnecessary overhead.
30
+
3
31
  ## 3.1.3
4
32
 
5
33
  ### Added
data/ext/agent.yml CHANGED
@@ -3,99 +3,99 @@
3
3
  # appsignal-agent repository.
4
4
  # Modifications to this file will be overwritten with the next agent release.
5
5
  ---
6
- version: '06391fb'
6
+ version: 813a59b
7
7
  mirrors:
8
8
  - https://appsignal-agent-releases.global.ssl.fastly.net
9
9
  - https://d135dj0rjqvssy.cloudfront.net
10
10
  triples:
11
11
  x86_64-darwin:
12
12
  static:
13
- checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
13
+ checksum: c8919a19a28950f726221829ea4d2b3312f1595a5e28ea134f8c41ed0814d7cd
14
14
  filename: appsignal-x86_64-darwin-all-static.tar.gz
15
15
  dynamic:
16
- checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
16
+ checksum: 1c10139bc4df56048a71766b64eba76462ee38d3cc814dc230e0fdb3c7e4fba3
17
17
  filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
18
18
  universal-darwin:
19
19
  static:
20
- checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
20
+ checksum: c8919a19a28950f726221829ea4d2b3312f1595a5e28ea134f8c41ed0814d7cd
21
21
  filename: appsignal-x86_64-darwin-all-static.tar.gz
22
22
  dynamic:
23
- checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
23
+ checksum: 1c10139bc4df56048a71766b64eba76462ee38d3cc814dc230e0fdb3c7e4fba3
24
24
  filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
25
25
  aarch64-darwin:
26
26
  static:
27
- checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
27
+ checksum: 40a38896132f418362af9fb2e9796eb4479e13cc0691b61f0f0b81b77e66ded6
28
28
  filename: appsignal-aarch64-darwin-all-static.tar.gz
29
29
  dynamic:
30
- checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
30
+ checksum: 40ec0c7db246cfc9b8eeebc882b07ba625948f376a53d8e24add7148d0f8c067
31
31
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
32
32
  arm64-darwin:
33
33
  static:
34
- checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
34
+ checksum: 40a38896132f418362af9fb2e9796eb4479e13cc0691b61f0f0b81b77e66ded6
35
35
  filename: appsignal-aarch64-darwin-all-static.tar.gz
36
36
  dynamic:
37
- checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
37
+ checksum: 40ec0c7db246cfc9b8eeebc882b07ba625948f376a53d8e24add7148d0f8c067
38
38
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
39
39
  arm-darwin:
40
40
  static:
41
- checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
41
+ checksum: 40a38896132f418362af9fb2e9796eb4479e13cc0691b61f0f0b81b77e66ded6
42
42
  filename: appsignal-aarch64-darwin-all-static.tar.gz
43
43
  dynamic:
44
- checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
44
+ checksum: 40ec0c7db246cfc9b8eeebc882b07ba625948f376a53d8e24add7148d0f8c067
45
45
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
46
46
  aarch64-linux:
47
47
  static:
48
- checksum: 0f2430e637eb77ce2093f021777087e87cb1e7be7c86a53771172696791c4879
48
+ checksum: c73b6e9de849a40290a0d90eaad43ea41a9a0293ba4b8bf99f69965c45c85514
49
49
  filename: appsignal-aarch64-linux-all-static.tar.gz
50
50
  dynamic:
51
- checksum: 0e4f9305aeaaa2d7847e83be04227b865723a0591574108d78040b5921a677a7
51
+ checksum: 90226eefe2e2f66833ca3e31c69ce70763ed57916bd0b5c1809bd99d61ff3429
52
52
  filename: appsignal-aarch64-linux-all-dynamic.tar.gz
53
53
  i686-linux:
54
54
  static:
55
- checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
55
+ checksum: 6741b9a068dc405b3d6d07953fab7fc876c21b4add1cbb2b4c4c4dfdeca5d387
56
56
  filename: appsignal-i686-linux-all-static.tar.gz
57
57
  dynamic:
58
- checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
58
+ checksum: 1af902b37af378a06251365fb637f86298380d3627c54f2945a85c1b7f075fda
59
59
  filename: appsignal-i686-linux-all-dynamic.tar.gz
60
60
  x86-linux:
61
61
  static:
62
- checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
62
+ checksum: 6741b9a068dc405b3d6d07953fab7fc876c21b4add1cbb2b4c4c4dfdeca5d387
63
63
  filename: appsignal-i686-linux-all-static.tar.gz
64
64
  dynamic:
65
- checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
65
+ checksum: 1af902b37af378a06251365fb637f86298380d3627c54f2945a85c1b7f075fda
66
66
  filename: appsignal-i686-linux-all-dynamic.tar.gz
67
67
  x86_64-linux:
68
68
  static:
69
- checksum: 394796c0ddeb4881c9f2e6ce82f840e66bcb69e027324f6c04f6671067445fbb
69
+ checksum: 8355b017093db606014023cc617d84d6375d503d7ffa54f62c7b3dc56fb64ead
70
70
  filename: appsignal-x86_64-linux-all-static.tar.gz
71
71
  dynamic:
72
- checksum: 9ca4762c464482b0a5a89898a839388597dd57a17a21527a67f3e3db0e540a03
72
+ checksum: 7c239a7ffe18cb173120bd67fb96563f4a81f0744bbbb47082f077a38ccbe5f1
73
73
  filename: appsignal-x86_64-linux-all-dynamic.tar.gz
74
74
  x86_64-linux-musl:
75
75
  static:
76
- checksum: 673271c8c5fd55053d8a719bcd307f787db4ca4633baf8cf961c442bf1805614
76
+ checksum: e9d98ed23b872dbf1e67a081473918cf88c4af775b1caadbfd93deda2635d9f8
77
77
  filename: appsignal-x86_64-linux-musl-all-static.tar.gz
78
78
  dynamic:
79
- checksum: 609d59376d6633652015e838eb649229fe2523d443a5471232b869f48eb99640
79
+ checksum: 5538172a95dfca1a4cf8e111ba61eab5e9c16314fa902259711cb9e8e0d2f85e
80
80
  filename: appsignal-x86_64-linux-musl-all-dynamic.tar.gz
81
81
  aarch64-linux-musl:
82
82
  static:
83
- checksum: e90ca19bf61596be022ba04897e8902b3401add58f351a40a3d3a7af241d0bbb
83
+ checksum: 0fb3eacfb8c8bc01c4acc8916327626720de376bcdd95104be71bb11a4ff9215
84
84
  filename: appsignal-aarch64-linux-musl-all-static.tar.gz
85
85
  dynamic:
86
- checksum: afb66c65fb82b672887bc6b6e82d82f09d9855a5497a7abb06b438dadea97aca
86
+ checksum: b87bcedaa2aa886acf3a93ce6e32762a843f3bee1ca7a8f9e0d17ca32f7a7d39
87
87
  filename: appsignal-aarch64-linux-musl-all-dynamic.tar.gz
88
88
  x86_64-freebsd:
89
89
  static:
90
- checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
90
+ checksum: b7d3c244b7068213840f5970df2e318d98f7909eb3b2b4ab42441d064ffb19ee
91
91
  filename: appsignal-x86_64-freebsd-all-static.tar.gz
92
92
  dynamic:
93
- checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
93
+ checksum: 0a739134f11d50318d14f247df1f8cc0f8aec1fbcb70a8bc48d5e1f22dc4aaba
94
94
  filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
95
95
  amd64-freebsd:
96
96
  static:
97
- checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
97
+ checksum: b7d3c244b7068213840f5970df2e318d98f7909eb3b2b4ab42441d064ffb19ee
98
98
  filename: appsignal-x86_64-freebsd-all-static.tar.gz
99
99
  dynamic:
100
- checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
100
+ checksum: 0a739134f11d50318d14f247df1f8cc0f8aec1fbcb70a8bc48d5e1f22dc4aaba
101
101
  filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
@@ -1,6 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'padrino', "~> 0.15"
4
- gem 'rack'
4
+ gem 'rack', "~> 2"
5
+ gem 'sinatra', "~> 2"
5
6
 
6
7
  gemspec :path => '../'
data/gemfiles/que.gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'que'
3
+ gem 'que', "~> 1.0"
4
4
 
5
5
  gemspec :path => '../'
@@ -15,7 +15,6 @@ module Appsignal
15
15
  :debug => false,
16
16
  :dns_servers => [],
17
17
  :enable_allocation_tracking => true,
18
- :enable_gc_instrumentation => false,
19
18
  :enable_host_metrics => true,
20
19
  :enable_minutely_probes => true,
21
20
  :enable_statsd => true,
@@ -63,7 +62,6 @@ module Appsignal
63
62
  "APPSIGNAL_DEBUG" => :debug,
64
63
  "APPSIGNAL_DNS_SERVERS" => :dns_servers,
65
64
  "APPSIGNAL_ENABLE_ALLOCATION_TRACKING" => :enable_allocation_tracking,
66
- "APPSIGNAL_ENABLE_GC_INSTRUMENTATION" => :enable_gc_instrumentation,
67
65
  "APPSIGNAL_ENABLE_HOST_METRICS" => :enable_host_metrics,
68
66
  "APPSIGNAL_ENABLE_MINUTELY_PROBES" => :enable_minutely_probes,
69
67
  "APPSIGNAL_ENABLE_STATSD" => :enable_statsd,
@@ -114,7 +112,6 @@ module Appsignal
114
112
  APPSIGNAL_ACTIVE
115
113
  APPSIGNAL_DEBUG
116
114
  APPSIGNAL_ENABLE_ALLOCATION_TRACKING
117
- APPSIGNAL_ENABLE_GC_INSTRUMENTATION
118
115
  APPSIGNAL_ENABLE_HOST_METRICS
119
116
  APPSIGNAL_ENABLE_MINUTELY_PROBES
120
117
  APPSIGNAL_ENABLE_STATSD
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ # @api private
5
+ module GarbageCollection
6
+ # Return the GC profiler wrapper.
7
+ #
8
+ # Returns {Profiler} if the Ruby Garbage Collection profiler is enabled.
9
+ # This is checked by calling `GC::Profiler.enabled?`.
10
+ #
11
+ # GC profiling is disabled by default due to the overhead it causes. Do not
12
+ # enable this in production for long periods of time.
13
+ def self.profiler
14
+ # Cached instances so it doesn't create a new object every time this
15
+ # method is called. Especially necessary for the {Profiler} because a new
16
+ # instance will have a new internal time counter.
17
+ @real_profiler ||= Profiler.new
18
+ @nil_profiler ||= NilProfiler.new
19
+
20
+ enabled? ? @real_profiler : @nil_profiler
21
+ end
22
+
23
+ # Check if Garbage Collection is enabled at the moment.
24
+ #
25
+ # @return [Boolean]
26
+ def self.enabled?
27
+ GC::Profiler.enabled?
28
+ end
29
+
30
+ # Unset the currently cached profilers.
31
+ #
32
+ # @return [void]
33
+ def self.clear_profiler!
34
+ @real_profiler = nil
35
+ @nil_profiler = nil
36
+ end
37
+
38
+ # A wrapper around Ruby's `GC::Profiler` that tracks garbage collection
39
+ # time, while clearing `GC::Profiler`'s total_time to make sure it doesn't
40
+ # leak memory by keeping garbage collection run samples in memory.
41
+ class Profiler
42
+ def self.lock
43
+ @lock ||= Mutex.new
44
+ end
45
+
46
+ def initialize
47
+ @total_time = 0
48
+ end
49
+
50
+ # Whenever {#total_time} is called, the current `GC::Profiler#total_time`
51
+ # gets added to `@total_time`, after which `GC::Profiler.clear` is called
52
+ # to prevent it from leaking memory. A class-level lock is used to make
53
+ # sure garbage collection time is never counted more than once.
54
+ #
55
+ # Whenever `@total_time` gets above two billion milliseconds (about 23
56
+ # days), it's reset to make sure the result fits in a signed 32-bit
57
+ # integer.
58
+ #
59
+ # @return [Integer]
60
+ def total_time
61
+ lock.synchronize do
62
+ @total_time += (internal_profiler.total_time * 1000).round
63
+ internal_profiler.clear
64
+ end
65
+
66
+ @total_time = 0 if @total_time > 2_000_000_000
67
+
68
+ @total_time
69
+ end
70
+
71
+ private
72
+
73
+ def internal_profiler
74
+ GC::Profiler
75
+ end
76
+
77
+ def lock
78
+ self.class.lock
79
+ end
80
+ end
81
+
82
+ # A dummy profiler that always returns 0 as the total time. Used when GC
83
+ # profiler is disabled.
84
+ class NilProfiler
85
+ def total_time
86
+ 0
87
+ end
88
+ end
89
+ end
90
+ end
@@ -8,7 +8,7 @@ module Appsignal
8
8
  defined?(::RubyVM) && ::RubyVM.respond_to?(:stat)
9
9
  end
10
10
 
11
- def initialize(appsignal: Appsignal, gc_profiler: Appsignal::GarbageCollectionProfiler.new)
11
+ def initialize(appsignal: Appsignal, gc_profiler: Appsignal::GarbageCollection.profiler)
12
12
  Appsignal.logger.debug("Initializing VM probe")
13
13
  @appsignal = appsignal
14
14
  @gc_profiler = gc_profiler
@@ -31,8 +31,10 @@ module Appsignal
31
31
  )
32
32
 
33
33
  set_gauge("thread_count", Thread.list.size)
34
- gauge_delta(:gc_time, @gc_profiler.total_time) do |gc_time|
35
- set_gauge("gc_time", gc_time) if gc_time > 0
34
+ if Appsignal::GarbageCollection.enabled?
35
+ gauge_delta(:gc_time, @gc_profiler.total_time) do |gc_time|
36
+ set_gauge("gc_time", gc_time) if gc_time > 0
37
+ end
36
38
  end
37
39
 
38
40
  gc_stats = GC.stat
@@ -66,11 +66,6 @@ module Appsignal
66
66
  def clear_current_transaction!
67
67
  Thread.current[:appsignal_transaction] = nil
68
68
  end
69
-
70
- def garbage_collection_profiler
71
- @garbage_collection_profiler ||=
72
- Appsignal.config[:enable_gc_instrumentation] ? Appsignal::GarbageCollectionProfiler.new : NilGarbageCollectionProfiler.new
73
- end
74
69
  end
75
70
 
76
71
  attr_reader :ext, :transaction_id, :action, :namespace, :request, :paused, :tags, :options, :discarded, :breadcrumbs
@@ -103,7 +98,7 @@ module Appsignal
103
98
  @ext = Appsignal::Extension.start_transaction(
104
99
  @transaction_id,
105
100
  @namespace,
106
- self.class.garbage_collection_profiler.total_time
101
+ 0
107
102
  ) || Appsignal::Extension::MockTransaction.new
108
103
  end
109
104
 
@@ -117,9 +112,7 @@ module Appsignal
117
112
  "because it was manually discarded."
118
113
  return
119
114
  end
120
- if @ext.finish(self.class.garbage_collection_profiler.total_time)
121
- sample_data
122
- end
115
+ sample_data if @ext.finish(0)
123
116
  @ext.complete
124
117
  end
125
118
 
@@ -355,7 +348,7 @@ module Appsignal
355
348
 
356
349
  def start_event
357
350
  return if paused?
358
- @ext.start_event(self.class.garbage_collection_profiler.total_time)
351
+ @ext.start_event(0)
359
352
  end
360
353
 
361
354
  def finish_event(name, title, body, body_format = Appsignal::EventFormatter::DEFAULT)
@@ -365,7 +358,7 @@ module Appsignal
365
358
  title || BLANK,
366
359
  body || BLANK,
367
360
  body_format || Appsignal::EventFormatter::DEFAULT,
368
- self.class.garbage_collection_profiler.total_time
361
+ 0
369
362
  )
370
363
  end
371
364
 
@@ -377,7 +370,7 @@ module Appsignal
377
370
  body || BLANK,
378
371
  body_format || Appsignal::EventFormatter::DEFAULT,
379
372
  duration,
380
- self.class.garbage_collection_profiler.total_time
373
+ 0
381
374
  )
382
375
  end
383
376
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.1.3".freeze
4
+ VERSION = "3.1.5".freeze
5
5
  end
data/lib/appsignal.rb CHANGED
@@ -115,11 +115,6 @@ module Appsignal
115
115
  Appsignal::Environment.report_enabled("allocation_tracking")
116
116
  end
117
117
 
118
- if config[:enable_gc_instrumentation]
119
- GC::Profiler.enable
120
- Appsignal::Environment.report_enabled("gc_instrumentation")
121
- end
122
-
123
118
  Appsignal::Minutely.start if config[:enable_minutely_probes]
124
119
 
125
120
  collect_environment_metadata
@@ -298,7 +293,7 @@ require "appsignal/hooks"
298
293
  require "appsignal/probes"
299
294
  require "appsignal/marker"
300
295
  require "appsignal/minutely"
301
- require "appsignal/garbage_collection_profiler"
296
+ require "appsignal/garbage_collection"
302
297
  require "appsignal/integrations/railtie" if defined?(::Rails)
303
298
  require "appsignal/transaction"
304
299
  require "appsignal/version"
@@ -11,9 +11,9 @@ require "json"
11
11
  Puma::Plugin.create do # rubocop:disable Metrics/BlockLength
12
12
  def start(launcher)
13
13
  @launcher = launcher
14
- @launcher.events.debug "AppSignal: Puma plugin start."
14
+ log_debug "AppSignal: Puma plugin start."
15
15
  in_background do
16
- @launcher.events.debug "AppSignal: Start Puma stats collection loop."
16
+ log_debug "AppSignal: Start Puma stats collection loop."
17
17
  plugin = AppsignalPumaPlugin.new
18
18
 
19
19
  loop do
@@ -24,12 +24,12 @@ Puma::Plugin.create do # rubocop:disable Metrics/BlockLength
24
24
  # metrics.
25
25
  sleep sleep_time
26
26
 
27
- @launcher.events.debug "AppSignal: Collecting Puma stats."
27
+ log_debug "AppSignal: Collecting Puma stats."
28
28
  stats = fetch_puma_stats
29
29
  if stats
30
30
  plugin.call(stats)
31
31
  else
32
- @launcher.events.log "AppSignal: No Puma stats to report."
32
+ log_debug "AppSignal: No Puma stats to report."
33
33
  end
34
34
  rescue StandardError => error
35
35
  log_error "Error while processing metrics.", error
@@ -44,8 +44,20 @@ Puma::Plugin.create do # rubocop:disable Metrics/BlockLength
44
44
  60 # seconds
45
45
  end
46
46
 
47
+ def logger
48
+ if @launcher.respond_to? :log_writer
49
+ @launcher.log_writer
50
+ else
51
+ @launcher.events
52
+ end
53
+ end
54
+
55
+ def log_debug(message)
56
+ logger.debug message
57
+ end
58
+
47
59
  def log_error(message, error)
48
- @launcher.events.log "AppSignal: #{message}\n" \
60
+ logger.error "AppSignal: #{message}\n" \
49
61
  "#{error.class}: #{error.message}\n#{error.backtrace.join("\n")}"
50
62
  end
51
63
 
@@ -156,7 +156,6 @@ describe Appsignal::Config do
156
156
  :debug => false,
157
157
  :dns_servers => [],
158
158
  :enable_allocation_tracking => true,
159
- :enable_gc_instrumentation => false,
160
159
  :enable_host_metrics => true,
161
160
  :enable_minutely_probes => true,
162
161
  :enable_statsd => true,
@@ -1,11 +1,33 @@
1
- describe Appsignal::GarbageCollectionProfiler do
1
+ describe Appsignal::GarbageCollection do
2
+ describe ".profiler" do
3
+ before do
4
+ # Unset the internal memoized variable to avoid state leaking
5
+ described_class.clear_profiler!
6
+ end
7
+
8
+ context "when GC instrumentation is disabled" do
9
+ it "returns the NilProfiler" do
10
+ expect(described_class.profiler).to be_a(Appsignal::GarbageCollection::NilProfiler)
11
+ end
12
+ end
13
+
14
+ context "when GC profiling is enabled" do
15
+ before { GC::Profiler.enable }
16
+ after { GC::Profiler.disable }
17
+
18
+ it "returns the Profiler" do
19
+ expect(described_class.profiler).to be_a(Appsignal::GarbageCollection::Profiler)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ describe Appsignal::GarbageCollection::Profiler do
2
26
  let(:internal_profiler) { FakeGCProfiler.new }
3
27
  let(:profiler) { described_class.new }
4
28
 
5
29
  before do
6
- allow_any_instance_of(described_class)
7
- .to receive(:internal_profiler)
8
- .and_return(internal_profiler)
30
+ stub_const("GC::Profiler", internal_profiler)
9
31
  end
10
32
 
11
33
  context "on initialization" do
@@ -54,7 +76,7 @@ describe Appsignal::GarbageCollectionProfiler do
54
76
 
55
77
  2.times do
56
78
  threads << Thread.new do
57
- profiler = Appsignal::GarbageCollectionProfiler.new
79
+ profiler = Appsignal::GarbageCollection::Profiler.new
58
80
  results << profiler.total_time
59
81
  end
60
82
  end
@@ -65,7 +87,7 @@ describe Appsignal::GarbageCollectionProfiler do
65
87
  end
66
88
  end
67
89
 
68
- describe Appsignal::NilGarbageCollectionProfiler do
90
+ describe Appsignal::GarbageCollection::NilProfiler do
69
91
  let(:profiler) { described_class.new }
70
92
 
71
93
  describe "#total_time" do
@@ -39,6 +39,7 @@ describe Appsignal::Probes::MriProbe do
39
39
  let(:hostname) { nil }
40
40
  before do
41
41
  allow(gc_profiler_mock).to receive(:total_time)
42
+ allow(GC::Profiler).to receive(:enabled?).and_return(true)
42
43
  end
43
44
 
44
45
  it "should track vm metrics" do
@@ -70,6 +71,40 @@ describe Appsignal::Probes::MriProbe do
70
71
  end
71
72
  end
72
73
 
74
+ context "when GC profiling is disabled" do
75
+ it "does not report a gc_time metric" do
76
+ allow(GC::Profiler).to receive(:enabled?).and_return(false)
77
+ expect(gc_profiler_mock).to_not receive(:total_time)
78
+ probe.call # Normal call, create a cache
79
+ probe.call # Report delta value based on cached value
80
+ metrics = appsignal_mock.gauges.map { |(key)| key }
81
+ expect(metrics).to_not include("gc_time")
82
+ end
83
+
84
+ it "does not report a gc_time metric while temporarily disabled" do
85
+ # While enabled
86
+ allow(GC::Profiler).to receive(:enabled?).and_return(true)
87
+ expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15)
88
+ probe.call # Normal call, create a cache
89
+ probe.call # Report delta value based on cached value
90
+ expect_gauges([["gc_time", 5]])
91
+
92
+ # While disabled
93
+ allow(GC::Profiler).to receive(:enabled?).and_return(false)
94
+ probe.call # Call twice to make sure any caches resets wouldn't mess up the assertion
95
+ probe.call
96
+ # Does not include any newly reported metrics
97
+ expect_gauges([["gc_time", 5]])
98
+
99
+ # When enabled after being disabled for a while, it only reports the
100
+ # newly reported time since it was renabled
101
+ allow(GC::Profiler).to receive(:enabled?).and_return(true)
102
+ expect(gc_profiler_mock).to receive(:total_time).and_return(25)
103
+ probe.call
104
+ expect_gauges([["gc_time", 5], ["gc_time", 10]])
105
+ end
106
+ end
107
+
73
108
  it "tracks GC run count" do
74
109
  expect(GC).to receive(:count).and_return(10, 15)
75
110
  expect(GC).to receive(:stat).and_return(
@@ -683,43 +683,36 @@ describe Appsignal::Transaction do
683
683
  end
684
684
 
685
685
  describe "#sample_data" do
686
- it "should sample data" do
687
- expect(transaction.ext).to receive(:set_sample_data).with(
688
- "environment",
689
- Appsignal::Utils::Data.generate(
690
- "CONTENT_LENGTH" => "0",
691
- "REQUEST_METHOD" => "GET",
692
- "SERVER_NAME" => "example.org",
693
- "SERVER_PORT" => "80",
694
- "PATH_INFO" => "/blog"
695
- )
696
- ).once
697
- expect(transaction.ext).to receive(:set_sample_data).with(
698
- "session_data",
699
- Appsignal::Utils::Data.generate({})
700
- ).once
701
- expect(transaction.ext).to receive(:set_sample_data).with(
702
- "params",
703
- Appsignal::Utils::Data.generate(
704
- "controller" => "blog_posts",
705
- "action" => "show",
706
- "id" => "1"
707
- )
708
- ).once
709
- expect(transaction.ext).to receive(:set_sample_data).with(
710
- "metadata",
711
- Appsignal::Utils::Data.generate("key" => "value")
712
- ).once
713
- expect(transaction.ext).to receive(:set_sample_data).with(
714
- "tags",
715
- Appsignal::Utils::Data.generate({})
716
- ).once
717
- expect(transaction.ext).to receive(:set_sample_data).with(
718
- "breadcrumbs",
719
- Appsignal::Utils::Data.generate([])
720
- ).once
686
+ let(:env) { { "rack.session" => { "session" => "value" } } }
721
687
 
688
+ it "sets sample data" do
689
+ transaction.set_tags "tag" => "value"
690
+ transaction.add_breadcrumb "category", "action", "message", "key" => "value"
722
691
  transaction.sample_data
692
+
693
+ sample_data = transaction.to_h["sample_data"]
694
+ expect(sample_data["environment"]).to include(
695
+ "CONTENT_LENGTH" => "0",
696
+ "REQUEST_METHOD" => "GET",
697
+ "SERVER_NAME" => "example.org",
698
+ "SERVER_PORT" => "80",
699
+ "PATH_INFO" => "/blog"
700
+ )
701
+ expect(sample_data["session_data"]).to eq("session" => "value")
702
+ expect(sample_data["params"]).to eq(
703
+ "controller" => "blog_posts",
704
+ "action" => "show",
705
+ "id" => "1"
706
+ )
707
+ expect(sample_data["metadata"]).to eq("key" => "value")
708
+ expect(sample_data["tags"]).to eq("tag" => "value")
709
+ expect(sample_data["breadcrumbs"]).to contain_exactly(
710
+ "action" => "action",
711
+ "category" => "category",
712
+ "message" => "message",
713
+ "metadata" => { "key" => "value" },
714
+ "time" => kind_of(Integer)
715
+ )
723
716
  end
724
717
  end
725
718
 
@@ -792,23 +785,6 @@ describe Appsignal::Transaction do
792
785
  end
793
786
  end
794
787
 
795
- describe "#garbage_collection_profiler" do
796
- before { Appsignal::Transaction.instance_variable_set(:@garbage_collection_profiler, nil) }
797
-
798
- it "returns the NilGarbageCollectionProfiler" do
799
- expect(Appsignal::Transaction.garbage_collection_profiler).to be_a(Appsignal::NilGarbageCollectionProfiler)
800
- end
801
-
802
- context "when gc profiling is enabled" do
803
- before { Appsignal.config.config_hash[:enable_gc_instrumentation] = true }
804
- after { Appsignal.config.config_hash[:enable_gc_instrumentation] = false }
805
-
806
- it "returns the GarbageCollectionProfiler" do
807
- expect(Appsignal::Transaction.garbage_collection_profiler).to be_a(Appsignal::GarbageCollectionProfiler)
808
- end
809
- end
810
- end
811
-
812
788
  describe "#start_event" do
813
789
  it "starts the event in the extension" do
814
790
  expect(transaction.ext).to receive(:start_event).with(0).and_call_original
@@ -827,11 +803,7 @@ describe Appsignal::Transaction do
827
803
  end
828
804
 
829
805
  describe "#finish_event" do
830
- let(:fake_gc_time) { 123 }
831
- before do
832
- expect(described_class.garbage_collection_profiler)
833
- .to receive(:total_time).at_least(:once).and_return(fake_gc_time)
834
- end
806
+ let(:fake_gc_time) { 0 }
835
807
 
836
808
  it "should finish the event in the extension" do
837
809
  expect(transaction.ext).to receive(:finish_event).with(
@@ -878,11 +850,7 @@ describe Appsignal::Transaction do
878
850
  end
879
851
 
880
852
  describe "#record_event" do
881
- let(:fake_gc_time) { 123 }
882
- before do
883
- expect(described_class.garbage_collection_profiler)
884
- .to receive(:total_time).at_least(:once).and_return(fake_gc_time)
885
- end
853
+ let(:fake_gc_time) { 0 }
886
854
 
887
855
  it "should record the event in the extension" do
888
856
  expect(transaction.ext).to receive(:record_event).with(
@@ -54,20 +54,12 @@ describe Appsignal do
54
54
  Appsignal.start
55
55
  end
56
56
 
57
- context "when allocation tracking and gc instrumentation have been enabled" do
57
+ context "when allocation tracking has been enabled" do
58
58
  before do
59
- allow(GC::Profiler).to receive(:enable)
60
59
  Appsignal.config.config_hash[:enable_allocation_tracking] = true
61
- Appsignal.config.config_hash[:enable_gc_instrumentation] = true
62
60
  capture_environment_metadata_report_calls
63
61
  end
64
62
 
65
- it "should enable Ruby's GC::Profiler" do
66
- expect(GC::Profiler).to receive(:enable)
67
- Appsignal.start
68
- expect_environment_metadata("ruby_gc_instrumentation_enabled", "true")
69
- end
70
-
71
63
  unless DependencyHelper.running_jruby?
72
64
  it "installs the allocation event hook" do
73
65
  expect(Appsignal::Extension).to receive(:install_allocation_event_hook)
@@ -78,29 +70,17 @@ describe Appsignal do
78
70
  end
79
71
  end
80
72
 
81
- context "when allocation tracking and gc instrumentation have been disabled" do
73
+ context "when allocation tracking has been disabled" do
82
74
  before do
83
75
  Appsignal.config.config_hash[:enable_allocation_tracking] = false
84
- Appsignal.config.config_hash[:enable_gc_instrumentation] = false
85
76
  capture_environment_metadata_report_calls
86
77
  end
87
78
 
88
- it "should not enable Ruby's GC::Profiler" do
89
- expect(GC::Profiler).not_to receive(:enable)
90
- Appsignal.start
91
- end
92
-
93
79
  it "should not install the allocation event hook" do
94
- expect(Appsignal::Minutely).not_to receive(:install_allocation_event_hook)
80
+ expect(Appsignal::Extension).not_to receive(:install_allocation_event_hook)
95
81
  Appsignal.start
96
82
  expect_not_environment_metadata("ruby_allocation_tracking_enabled")
97
83
  end
98
-
99
- it "should not add the gc probe to minutely" do
100
- expect(Appsignal::Minutely).not_to receive(:register_garbage_collection_probe)
101
- Appsignal.start
102
- expect_not_environment_metadata("ruby_gc_instrumentation_enabled")
103
- end
104
84
  end
105
85
 
106
86
  context "when minutely metrics has been enabled" do
@@ -2,14 +2,14 @@ RSpec.describe "Puma plugin" do
2
2
  include WaitForHelper
3
3
 
4
4
  class MockPumaLauncher
5
- def events
6
- return @events if defined?(@events)
5
+ def log_writer
6
+ return @log_writer if defined?(@log_writer)
7
7
 
8
- @events = MockPumaEvents.new
8
+ @log_writer = MockPumaLogWriter.new
9
9
  end
10
10
  end
11
11
 
12
- class MockPumaEvents
12
+ class MockPumaLogWriter
13
13
  attr_reader :logs
14
14
 
15
15
  def initialize
@@ -153,7 +153,7 @@ RSpec.describe "Puma plugin" do
153
153
  end
154
154
 
155
155
  def logs
156
- launcher.events.logs
156
+ launcher.log_writer.logs
157
157
  end
158
158
 
159
159
  def messages
@@ -281,7 +281,7 @@ RSpec.describe "Puma plugin" do
281
281
  it "does not fetch metrics" do
282
282
  run_plugin(appsignal_plugin) do
283
283
  expect(logs).to_not include([:error, kind_of(String)])
284
- expect(logs).to include([:log, "AppSignal: No Puma stats to report."])
284
+ expect(logs).to include([:debug, "AppSignal: No Puma stats to report."])
285
285
  expect(messages).to be_empty
286
286
  end
287
287
  end
@@ -296,4 +296,43 @@ RSpec.describe "Puma plugin" do
296
296
  end
297
297
  end
298
298
  end
299
+
300
+ context "with Puma < 6 Events class" do
301
+ class MockPumaEvents
302
+ attr_reader :logs
303
+
304
+ def initialize
305
+ @logs = []
306
+ end
307
+
308
+ def log(message)
309
+ @logs << [:log, message]
310
+ end
311
+
312
+ def debug(message)
313
+ @logs << [:debug, message]
314
+ end
315
+
316
+ def error(message)
317
+ @logs << [:error, message]
318
+ end
319
+ end
320
+
321
+ let(:launcher) do
322
+ Class.new do
323
+ def events
324
+ return @events if defined?(@events)
325
+
326
+ @events = MockPumaEvents.new
327
+ end
328
+ end.new
329
+ end
330
+ let(:stats_data) { { :max_threads => 5 } }
331
+
332
+ it "logs messages to the events class" do
333
+ run_plugin(appsignal_plugin) do
334
+ expect(launcher.events.logs).to_not be_empty
335
+ end
336
+ end
337
+ end
299
338
  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.1.3
4
+ version: 3.1.5
5
5
  platform: java
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: 2022-08-04 00:00:00.000000000 Z
13
+ date: 2022-10-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -218,7 +218,7 @@ files:
218
218
  - lib/appsignal/event_formatter/sequel/sql_formatter.rb
219
219
  - lib/appsignal/extension.rb
220
220
  - lib/appsignal/extension/jruby.rb
221
- - lib/appsignal/garbage_collection_profiler.rb
221
+ - lib/appsignal/garbage_collection.rb
222
222
  - lib/appsignal/helpers/instrumentation.rb
223
223
  - lib/appsignal/helpers/metrics.rb
224
224
  - lib/appsignal/hooks.rb
@@ -319,7 +319,7 @@ files:
319
319
  - spec/lib/appsignal/extension/jruby_spec.rb
320
320
  - spec/lib/appsignal/extension_install_failure_spec.rb
321
321
  - spec/lib/appsignal/extension_spec.rb
322
- - spec/lib/appsignal/garbage_collection_profiler_spec.rb
322
+ - spec/lib/appsignal/garbage_collection_spec.rb
323
323
  - spec/lib/appsignal/hooks/action_cable_spec.rb
324
324
  - spec/lib/appsignal/hooks/action_mailer_spec.rb
325
325
  - spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb
@@ -441,7 +441,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
441
441
  - !ruby/object:Gem::Version
442
442
  version: '0'
443
443
  requirements: []
444
- rubygems_version: 3.3.12
444
+ rubygems_version: 3.3.7
445
445
  signing_key:
446
446
  specification_version: 4
447
447
  summary: Logs performance and exception data from your app to appsignal.com
@@ -471,7 +471,7 @@ test_files:
471
471
  - spec/lib/appsignal/extension/jruby_spec.rb
472
472
  - spec/lib/appsignal/extension_install_failure_spec.rb
473
473
  - spec/lib/appsignal/extension_spec.rb
474
- - spec/lib/appsignal/garbage_collection_profiler_spec.rb
474
+ - spec/lib/appsignal/garbage_collection_spec.rb
475
475
  - spec/lib/appsignal/hooks/action_cable_spec.rb
476
476
  - spec/lib/appsignal/hooks/action_mailer_spec.rb
477
477
  - spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Appsignal
4
- # {Appsignal::GarbageCollectionProfiler} wraps Ruby's `GC::Profiler` to be
5
- # able to track garbage collection time for multiple transactions, while
6
- # constantly clearing `GC::Profiler`'s total_time to make sure it doesn't
7
- # leak memory by keeping garbage collection run samples in memory.
8
- #
9
- # @api private
10
- class GarbageCollectionProfiler
11
- def self.lock
12
- @lock ||= Mutex.new
13
- end
14
-
15
- def initialize
16
- @total_time = 0
17
- end
18
-
19
- # Whenever {#total_time} is called, the current `GC::Profiler#total_time`
20
- # gets added to `@total_time`, after which `GC::Profiler.clear` is called
21
- # to prevent it from leaking memory. A class-level lock is used to make
22
- # sure garbage collection time is never counted more than once.
23
- #
24
- # Whenever `@total_time` gets above two billion milliseconds (about 23
25
- # days), it's reset to make sure the result fits in a signed 32-bit
26
- # integer.
27
- #
28
- # @return [Integer]
29
- def total_time
30
- lock.synchronize do
31
- @total_time += (internal_profiler.total_time * 1000).round
32
- internal_profiler.clear
33
- end
34
-
35
- @total_time = 0 if @total_time > 2_000_000_000
36
-
37
- @total_time
38
- end
39
-
40
- private
41
-
42
- def internal_profiler
43
- GC::Profiler
44
- end
45
-
46
- def lock
47
- self.class.lock
48
- end
49
- end
50
-
51
- # {Appsignal::NilGarbageCollectionProfiler} is a dummy profiler
52
- # that always returns 0 as the total time.
53
- # Used when we don't want any profile information
54
- #
55
- # @api private
56
- class NilGarbageCollectionProfiler
57
- def total_time
58
- 0
59
- end
60
- end
61
- end