appsignal 3.1.1 → 3.1.4

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: 39e822c17022591bf8b57632cf59b34af33bf5bfcbd5190b5db8fca836bebc91
4
- data.tar.gz: 0d9c3820cfe794ccabbcc1cda65fafec925cda36690b4caa179170e07a38a25c
3
+ metadata.gz: c21e4e80dd54b8a0f6619a40b7c046e6bc132634ce26666b281fdd4298c72c3f
4
+ data.tar.gz: 53743646f5cf821ab45559817cf65c2bf9ed483184725fca2413b3606fad6e1e
5
5
  SHA512:
6
- metadata.gz: f435df5112eabe0f6b119c62a4e729ca22ad1d7ab3d98810a97c0d7cd72521c9daccc3e44d6786a530abd8def55ca4b42e49fcb522c4af8fbeb2ad96b5b4f0a9
7
- data.tar.gz: 0167fd0f1bfa054e46f20ab12680529913da7b5b702fc119cbdb43e78e2e8cf3f459e7b4236413f394e51a0ed935e597806b8836b20d702ede7d0f26780f2590
6
+ metadata.gz: 36a34d74cf16e5f274e3485471833f516e34227546017d14f24d70fc75ca824b68261a7048924391135a3c0d815d7ef605b60ac19396bdeb9b9b46f1d4911daa
7
+ data.tar.gz: b03a309a6c8649397e6f5d9b62a65324e4b4e39a3a1eee77b6cb60280758838212e2de7ca3eb28c8f10b3b59cb5b02ca7d88347cc9f3995be0308bf5249cae70
data/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # AppSignal for Ruby gem Changelog
2
2
 
3
+ ## 3.1.4
4
+
5
+ ### Added
6
+
7
+ - [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`.
8
+
9
+ ### Changed
10
+
11
+ - [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.
12
+
13
+ ### Fixed
14
+
15
+ - [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.
16
+
17
+ ## 3.1.3
18
+
19
+ ### Added
20
+
21
+ - [811a1082](https://github.com/appsignal/appsignal-ruby/commit/811a10825043ed584f23d870e3a420ee409eb151) patch - Add the `Transaction.current?` helper to determine if any Transaction is currently active or not. AppSignal `NilTransaction`s are not considered active transactions.
22
+
23
+ ### Changed
24
+
25
+ - [dc50d889](https://github.com/appsignal/appsignal-ruby/commit/dc50d8892699bf17b2399865ead8b27ce45b60ed) patch - Rename the (so far privately reported) `gc_total_time` metric to `gc_time`. It no longer reports the total time of Garbage Collection measured, but only the time between two (minutely) measurements.
26
+
27
+ ### Fixed
28
+
29
+ - [7cfed987](https://github.com/appsignal/appsignal-ruby/commit/7cfed98761cf81d475261c553486b24843460cf3) patch - Fix error on unknown HTTP request method. When a request is made with an unknown request method, triggering and `ActionController::UnknownHttpMethod`, it will no longer break the AppSignal instrumentation but omit the request method in the sample data.
30
+
31
+ ## 3.1.2
32
+
33
+ ### Changed
34
+
35
+ - [1b95bb4c](https://github.com/appsignal/appsignal-ruby/commit/1b95bb4c8df08128cfa2db0d918ffcb909e5ee4c) patch - Report Garbage Collection total time metric as the delta between measurements. This reports a more user friendly metric that doesn't always goes up until the app restarts or gets a new deploy. This metric is reported 0 by default without `GC::Profiler.enable` having been called.
36
+ - [61a78fb0](https://github.com/appsignal/appsignal-ruby/commit/61a78fb028b04ae6f0a4ca1fc469d744f23c5029) patch - Bump agent to 06391fb
37
+
38
+ - Accept "warning" value for the `log_level` config option.
39
+ - Add aarch64 Linux musl build.
40
+ - Improve debug logging from the extension.
41
+ - Fix high CPU issue for appsignal-agent when nothing could be read from the socket.
42
+
3
43
  ## 3.1.1
4
44
 
5
45
  ### Changed
data/appsignal.gemspec CHANGED
@@ -39,12 +39,16 @@ Gem::Specification.new do |gem| # rubocop:disable Metrics/BlockLength
39
39
  gem.add_development_dependency "rake", ">= 12"
40
40
  gem.add_development_dependency "rspec", "~> 3.8"
41
41
  gem.add_development_dependency "timecop"
42
- gem.add_development_dependency "webmock"
43
42
  gem.add_development_dependency "yard", ">= 0.9.20"
44
43
  gem.add_development_dependency "pry"
45
44
 
46
45
  # Dependencies that need to be locked to a specific version in developement
47
46
  ruby_version = Gem::Version.new(RUBY_VERSION)
47
+ if ruby_version < Gem::Version.new("2.3.0")
48
+ gem.add_development_dependency "webmock", "3.14.0"
49
+ else
50
+ gem.add_development_dependency "webmock"
51
+ end
48
52
  if ruby_version > Gem::Version.new("2.5.0")
49
53
  # RuboCop dependency parallel depends on Ruby > 2.4
50
54
  gem.add_development_dependency "rubocop", "0.50.0"
data/ext/agent.yml CHANGED
@@ -3,92 +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: d573c9b
6
+ version: '06391fb'
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: a9a86594e50f22e7f7fd93a050e334048248a6dc971015e66c26150c4a689345
13
+ checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
14
14
  filename: appsignal-x86_64-darwin-all-static.tar.gz
15
15
  dynamic:
16
- checksum: 04a69d0b608aa0e834c96c75a3bb226e7ca252fd2c74e439fdd43bf297d6bde2
16
+ checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
17
17
  filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
18
18
  universal-darwin:
19
19
  static:
20
- checksum: a9a86594e50f22e7f7fd93a050e334048248a6dc971015e66c26150c4a689345
20
+ checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
21
21
  filename: appsignal-x86_64-darwin-all-static.tar.gz
22
22
  dynamic:
23
- checksum: 04a69d0b608aa0e834c96c75a3bb226e7ca252fd2c74e439fdd43bf297d6bde2
23
+ checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
24
24
  filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
25
25
  aarch64-darwin:
26
26
  static:
27
- checksum: 92f7f71b685985b310a9f3693a96a5db6b9133b0af807d000b90248e097063c7
27
+ checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
28
28
  filename: appsignal-aarch64-darwin-all-static.tar.gz
29
29
  dynamic:
30
- checksum: ffb54af4c35dd281a4735b57d8e537b8b08e87e08841e5d344caff325948a9e8
30
+ checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
31
31
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
32
32
  arm64-darwin:
33
33
  static:
34
- checksum: 92f7f71b685985b310a9f3693a96a5db6b9133b0af807d000b90248e097063c7
34
+ checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
35
35
  filename: appsignal-aarch64-darwin-all-static.tar.gz
36
36
  dynamic:
37
- checksum: ffb54af4c35dd281a4735b57d8e537b8b08e87e08841e5d344caff325948a9e8
37
+ checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
38
38
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
39
39
  arm-darwin:
40
40
  static:
41
- checksum: 92f7f71b685985b310a9f3693a96a5db6b9133b0af807d000b90248e097063c7
41
+ checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
42
42
  filename: appsignal-aarch64-darwin-all-static.tar.gz
43
43
  dynamic:
44
- checksum: ffb54af4c35dd281a4735b57d8e537b8b08e87e08841e5d344caff325948a9e8
44
+ checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
45
45
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
46
46
  aarch64-linux:
47
47
  static:
48
- checksum: 79f1e7f9c34ab36c06d5c3d676173ee7c1219af2f51dc77865897598dc01349a
48
+ checksum: 0f2430e637eb77ce2093f021777087e87cb1e7be7c86a53771172696791c4879
49
49
  filename: appsignal-aarch64-linux-all-static.tar.gz
50
50
  dynamic:
51
- checksum: cfd8e98238e2c7cdb10c0e136c47ab8e2dacab0a14d8ccf0e4c6c14946e325f1
51
+ checksum: 0e4f9305aeaaa2d7847e83be04227b865723a0591574108d78040b5921a677a7
52
52
  filename: appsignal-aarch64-linux-all-dynamic.tar.gz
53
53
  i686-linux:
54
54
  static:
55
- checksum: 835c6f823a2c6e9f8fa12704bf0953e3610dc9836355b57d2d6981e6ae412fb4
55
+ checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
56
56
  filename: appsignal-i686-linux-all-static.tar.gz
57
57
  dynamic:
58
- checksum: febc5d80a7b0fd9644e2d68d068d28c66359bbef9473f01e9f71fb07fd73bcb8
58
+ checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
59
59
  filename: appsignal-i686-linux-all-dynamic.tar.gz
60
60
  x86-linux:
61
61
  static:
62
- checksum: 835c6f823a2c6e9f8fa12704bf0953e3610dc9836355b57d2d6981e6ae412fb4
62
+ checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
63
63
  filename: appsignal-i686-linux-all-static.tar.gz
64
64
  dynamic:
65
- checksum: febc5d80a7b0fd9644e2d68d068d28c66359bbef9473f01e9f71fb07fd73bcb8
65
+ checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
66
66
  filename: appsignal-i686-linux-all-dynamic.tar.gz
67
67
  x86_64-linux:
68
68
  static:
69
- checksum: 6eb6f0df2f8c62a29769bf7f21cefaec92a24ee0ab363acc5bd4f9c2d1241c53
69
+ checksum: 394796c0ddeb4881c9f2e6ce82f840e66bcb69e027324f6c04f6671067445fbb
70
70
  filename: appsignal-x86_64-linux-all-static.tar.gz
71
71
  dynamic:
72
- checksum: ce710ff2edea2fc7b3b6bafd10af849e95f513abf5d775b9a8361ffed45b70c3
72
+ checksum: 9ca4762c464482b0a5a89898a839388597dd57a17a21527a67f3e3db0e540a03
73
73
  filename: appsignal-x86_64-linux-all-dynamic.tar.gz
74
74
  x86_64-linux-musl:
75
75
  static:
76
- checksum: b16d46074527da5700e10e5a8b176aeb46b7bbb19431653029eda04437bef918
76
+ checksum: 673271c8c5fd55053d8a719bcd307f787db4ca4633baf8cf961c442bf1805614
77
77
  filename: appsignal-x86_64-linux-musl-all-static.tar.gz
78
78
  dynamic:
79
- checksum: 261b79ab790e6a12a748d4649a4389e96d5cf7d1f981c3b56ed331f164d1627b
79
+ checksum: 609d59376d6633652015e838eb649229fe2523d443a5471232b869f48eb99640
80
80
  filename: appsignal-x86_64-linux-musl-all-dynamic.tar.gz
81
+ aarch64-linux-musl:
82
+ static:
83
+ checksum: e90ca19bf61596be022ba04897e8902b3401add58f351a40a3d3a7af241d0bbb
84
+ filename: appsignal-aarch64-linux-musl-all-static.tar.gz
85
+ dynamic:
86
+ checksum: afb66c65fb82b672887bc6b6e82d82f09d9855a5497a7abb06b438dadea97aca
87
+ filename: appsignal-aarch64-linux-musl-all-dynamic.tar.gz
81
88
  x86_64-freebsd:
82
89
  static:
83
- checksum: e7bfc1dc355ce1237aaee6fdf967c78ecca533db41b09c2b10716e7f8593dbe0
90
+ checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
84
91
  filename: appsignal-x86_64-freebsd-all-static.tar.gz
85
92
  dynamic:
86
- checksum: 97af9419cf00e22ea544a2365785a6b5df2a990f17e7735b3bbec1a690b68f0b
93
+ checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
87
94
  filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
88
95
  amd64-freebsd:
89
96
  static:
90
- checksum: e7bfc1dc355ce1237aaee6fdf967c78ecca533db41b09c2b10716e7f8593dbe0
97
+ checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
91
98
  filename: appsignal-x86_64-freebsd-all-static.tar.gz
92
99
  dynamic:
93
- checksum: 97af9419cf00e22ea544a2365785a6b5df2a990f17e7735b3bbec1a690b68f0b
100
+ checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
94
101
  filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
@@ -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
@@ -325,7 +325,8 @@ module Appsignal
325
325
  "value is not an exception: #{exception.inspect}"
326
326
  return
327
327
  end
328
- return if !active? || Appsignal::Transaction.current.nil?
328
+ return if !active? || !Appsignal::Transaction.current?
329
+
329
330
  transaction = Appsignal::Transaction.current
330
331
  transaction.set_error(exception)
331
332
  transaction.set_tags(tags) if tags
@@ -359,7 +360,7 @@ module Appsignal
359
360
  # @since 2.2.0
360
361
  def set_action(action)
361
362
  return if !active? ||
362
- Appsignal::Transaction.current.nil? ||
363
+ !Appsignal::Transaction.current? ||
363
364
  action.nil?
364
365
  Appsignal::Transaction.current.set_action(action)
365
366
  end
@@ -398,7 +399,7 @@ module Appsignal
398
399
  # @since 2.2.0
399
400
  def set_namespace(namespace)
400
401
  return if !active? ||
401
- Appsignal::Transaction.current.nil? ||
402
+ !Appsignal::Transaction.current? ||
402
403
  namespace.nil?
403
404
  Appsignal::Transaction.current.set_namespace(namespace)
404
405
  end
@@ -438,8 +439,9 @@ module Appsignal
438
439
  # Tagging guide
439
440
  def tag_request(tags = {})
440
441
  return unless active?
442
+ return unless Appsignal::Transaction.current?
443
+
441
444
  transaction = Appsignal::Transaction.current
442
- return false unless transaction
443
445
  transaction.set_tags(tags)
444
446
  end
445
447
  alias :tag_job :tag_request
@@ -471,8 +473,9 @@ module Appsignal
471
473
  # @since 2.12.0
472
474
  def add_breadcrumb(category, action, message = "", metadata = {}, time = Time.now.utc)
473
475
  return unless active?
476
+ return unless Appsignal::Transaction.current?
477
+
474
478
  transaction = Appsignal::Transaction.current
475
- return false unless transaction
476
479
  transaction.add_breadcrumb(category, action, message, metadata, time)
477
480
  end
478
481
 
@@ -20,9 +20,11 @@ module Appsignal
20
20
  module ActiveJobClassInstrumentation
21
21
  def execute(job)
22
22
  job_status = nil
23
- current_transaction = Appsignal::Transaction.current
23
+ has_wrapper_transaction = Appsignal::Transaction.current?
24
24
  transaction =
25
- if current_transaction.nil_transaction?
25
+ if has_wrapper_transaction
26
+ Appsignal::Transaction.current
27
+ else
26
28
  # No standalone integration started before ActiveJob integration.
27
29
  # We don't have a separate integration for this QueueAdapter like
28
30
  # we do for Sidekiq.
@@ -33,8 +35,6 @@ module Appsignal
33
35
  Appsignal::Transaction::BACKGROUND_JOB,
34
36
  Appsignal::Transaction::GenericRequest.new({})
35
37
  )
36
- else
37
- current_transaction
38
38
  end
39
39
 
40
40
  super
@@ -64,7 +64,7 @@ module Appsignal
64
64
  transaction.set_queue_start((Time.parse(enqueued_at).to_f * 1_000).to_i)
65
65
  end
66
66
 
67
- if current_transaction.nil_transaction?
67
+ unless has_wrapper_transaction
68
68
  # Only complete transaction if ActiveJob is not wrapped in
69
69
  # another supported integration, such as Sidekiq.
70
70
  Appsignal::Transaction.complete_current!
@@ -6,8 +6,9 @@ module Appsignal
6
6
  class MongoMonitorSubscriber
7
7
  # Called by Mongo::Monitor when query starts
8
8
  def started(event)
9
+ return unless Appsignal::Transaction.current?
10
+
9
11
  transaction = Appsignal::Transaction.current
10
- return if transaction.nil_transaction?
11
12
  return if transaction.paused?
12
13
 
13
14
  # Format the command
@@ -36,8 +37,9 @@ module Appsignal
36
37
 
37
38
  # Finishes the event in the AppSignal extension
38
39
  def finish(result, event)
40
+ return unless Appsignal::Transaction.current?
41
+
39
42
  transaction = Appsignal::Transaction.current
40
- return if transaction.nil_transaction?
41
43
  return if transaction.paused?
42
44
 
43
45
  # Get the query from the transaction store
@@ -10,21 +10,24 @@ module Appsignal
10
10
  # @api private
11
11
  class SidekiqErrorHandler
12
12
  def call(exception, sidekiq_context)
13
- transaction = Appsignal::Transaction.current
14
-
15
- if transaction.nil_transaction?
16
- # Sidekiq error outside of the middleware scope.
17
- # Can be a job JSON parse error or some other error happening in
18
- # Sidekiq.
19
- transaction = Appsignal::Transaction.create(
20
- SecureRandom.uuid, # Newly generated job id
21
- Appsignal::Transaction::BACKGROUND_JOB,
22
- Appsignal::Transaction::GenericRequest.new({})
23
- )
24
- transaction.set_action_if_nil("SidekiqInternal")
25
- transaction.set_metadata("sidekiq_error", sidekiq_context[:context])
26
- transaction.params = { :jobstr => sidekiq_context[:jobstr] }
27
- end
13
+ transaction =
14
+ if Appsignal::Transaction.current?
15
+ Appsignal::Transaction.current
16
+ else
17
+ # Sidekiq error outside of the middleware scope.
18
+ # Can be a job JSON parse error or some other error happening in
19
+ # Sidekiq.
20
+ transaction =
21
+ Appsignal::Transaction.create(
22
+ SecureRandom.uuid, # Newly generated job id
23
+ Appsignal::Transaction::BACKGROUND_JOB,
24
+ Appsignal::Transaction::GenericRequest.new({})
25
+ )
26
+ transaction.set_action_if_nil("SidekiqInternal")
27
+ transaction.set_metadata("sidekiq_error", sidekiq_context[:context])
28
+ transaction.params = { :jobstr => sidekiq_context[:jobstr] }
29
+ transaction
30
+ end
28
31
 
29
32
  transaction.set_error(exception)
30
33
  Appsignal::Transaction.complete_current!
@@ -7,22 +7,35 @@ module Appsignal
7
7
  @gauge_delta_cache ||= {}
8
8
  end
9
9
 
10
- # Calculate the delta of two values for a gauge metric
10
+ # Calculate the delta of two values for a gauge metric.
11
11
  #
12
- # First call will store the data for the metric in the cache and the
13
- # second call will return the delta of the gauge metric. This is used for
14
- # absolute counter values which we want to track as gauges.
12
+ # When this method is called, the given value is stored in a cache
13
+ # under the given cache key.
14
+ #
15
+ # A block must be passed to this method. The first time the method
16
+ # is called for a given cache key, the block will not be yielded to.
17
+ # In subsequent calls, the delta between the previously stored value
18
+ # in the cache for that key and the value given in this invocation
19
+ # will be yielded to the block.
20
+ #
21
+ # This is used for absolute counter values which we want to track as
22
+ # gauges.
15
23
  #
16
24
  # @example
17
- # gauge_delta :my_cache_key, 10
18
- # gauge_delta :my_cache_key, 15
19
- # # Returns a value of `5`
25
+ # gauge_delta :with_block, 10 do |delta|
26
+ # puts "this block will not be yielded to"
27
+ # end
28
+ # gauge_delta :with_block, 15 do |delta|
29
+ # # `delta` has a value of `5`
30
+ # puts "this block will be yielded to with delta = #{delta}"
31
+ # end
32
+ #
20
33
  def gauge_delta(cache_key, value)
21
34
  previous_value = gauge_delta_cache[cache_key]
22
35
  gauge_delta_cache[cache_key] = value
23
36
  return unless previous_value
24
37
 
25
- value - previous_value
38
+ yield value - previous_value
26
39
  end
27
40
  end
28
41
  end
@@ -8,13 +8,10 @@ module Appsignal
8
8
  defined?(::RubyVM) && ::RubyVM.respond_to?(:stat)
9
9
  end
10
10
 
11
- def self.garbage_collection_profiler
12
- @garbage_collection_profiler ||= Appsignal::GarbageCollectionProfiler.new
13
- end
14
-
15
- def initialize(appsignal = Appsignal)
11
+ def initialize(appsignal: Appsignal, gc_profiler: Appsignal::GarbageCollection.profiler)
16
12
  Appsignal.logger.debug("Initializing VM probe")
17
13
  @appsignal = appsignal
14
+ @gc_profiler = gc_profiler
18
15
  end
19
16
 
20
17
  # @api private
@@ -34,24 +31,27 @@ module Appsignal
34
31
  )
35
32
 
36
33
  set_gauge("thread_count", Thread.list.size)
37
- set_gauge("gc_total_time", MriProbe.garbage_collection_profiler.total_time)
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
38
+ end
38
39
 
39
40
  gc_stats = GC.stat
40
- allocated_objects =
41
- gauge_delta(
42
- :allocated_objects,
43
- gc_stats[:total_allocated_objects] || gc_stats[:total_allocated_object]
44
- )
45
- set_gauge("allocated_objects", allocated_objects) if allocated_objects
41
+ gauge_delta(
42
+ :allocated_objects,
43
+ gc_stats[:total_allocated_objects] || gc_stats[:total_allocated_object]
44
+ ) do |allocated_objects|
45
+ set_gauge("allocated_objects", allocated_objects)
46
+ end
46
47
 
47
- gc_count = gauge_delta(:gc_count, GC.count)
48
- set_gauge("gc_count", gc_count, :metric => :gc_count) if gc_count
49
- minor_gc_count = gauge_delta(:minor_gc_count, gc_stats[:minor_gc_count])
50
- if minor_gc_count
48
+ gauge_delta(:gc_count, GC.count) do |gc_count|
49
+ set_gauge("gc_count", gc_count, :metric => :gc_count)
50
+ end
51
+ gauge_delta(:minor_gc_count, gc_stats[:minor_gc_count]) do |minor_gc_count|
51
52
  set_gauge("gc_count", minor_gc_count, :metric => :minor_gc_count)
52
53
  end
53
- major_gc_count = gauge_delta(:major_gc_count, gc_stats[:major_gc_count])
54
- if major_gc_count
54
+ gauge_delta(:major_gc_count, gc_stats[:major_gc_count]) do |major_gc_count|
55
55
  set_gauge("gc_count", major_gc_count, :metric => :major_gc_count)
56
56
  end
57
57
 
@@ -44,15 +44,16 @@ module Appsignal
44
44
 
45
45
  gauge "worker_count", stats.workers_size
46
46
  gauge "process_count", stats.processes_size
47
- jobs_processed = gauge_delta :jobs_processed, stats.processed
48
- if jobs_processed
47
+ gauge_delta :jobs_processed, stats.processed do |jobs_processed|
49
48
  gauge "job_count", jobs_processed, :status => :processed
50
49
  end
51
- jobs_failed = gauge_delta :jobs_failed, stats.failed
52
- gauge "job_count", jobs_failed, :status => :failed if jobs_failed
50
+ gauge_delta :jobs_failed, stats.failed do |jobs_failed|
51
+ gauge "job_count", jobs_failed, :status => :failed
52
+ end
53
53
  gauge "job_count", stats.retry_size, :status => :retry_queue
54
- jobs_dead = gauge_delta :jobs_dead, stats.dead_size
55
- gauge "job_count", jobs_dead, :status => :died if jobs_dead
54
+ gauge_delta :jobs_dead, stats.dead_size do |jobs_dead|
55
+ gauge "job_count", jobs_dead, :status => :died
56
+ end
56
57
  gauge "job_count", stats.scheduled_size, :status => :scheduled
57
58
  gauge "job_count", stats.enqueued, :status => :enqueued
58
59
  end
@@ -40,7 +40,11 @@ module Appsignal
40
40
  end
41
41
  transaction.set_http_or_background_queue_start
42
42
  transaction.set_metadata("path", request.path)
43
- transaction.set_metadata("method", request.request_method)
43
+ begin
44
+ transaction.set_metadata("method", request.request_method)
45
+ rescue => error
46
+ Appsignal.logger.error("Unable to report HTTP request method: '#{error}'")
47
+ end
44
48
  Appsignal::Transaction.complete_current!
45
49
  end
46
50
  end