appsignal 3.0.27-java → 3.1.2-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.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # AppSignal for Ruby gem Changelog
2
2
 
3
+ ## 3.1.2
4
+
5
+ ### Changed
6
+
7
+ - [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.
8
+ - [61a78fb0](https://github.com/appsignal/appsignal-ruby/commit/61a78fb028b04ae6f0a4ca1fc469d744f23c5029) patch - Bump agent to 06391fb
9
+
10
+ - Accept "warning" value for the `log_level` config option.
11
+ - Add aarch64 Linux musl build.
12
+ - Improve debug logging from the extension.
13
+ - Fix high CPU issue for appsignal-agent when nothing could be read from the socket.
14
+
15
+ ## 3.1.1
16
+
17
+ ### Changed
18
+
19
+ - [e225c798](https://github.com/appsignal/appsignal-ruby/commit/e225c798c65aef6085bb689597b7f3359fe138f7) patch - Report all Ruby VM metrics as gauges. We previously reported some metrics as distributions, but all fields for those distributions would report the same values.
20
+
21
+ ### Fixed
22
+
23
+ - [31fd19c6](https://github.com/appsignal/appsignal-ruby/commit/31fd19c6019db2c68b359f1fc4ed3d5e4843e349) patch - Add hostname tag for Ruby VM metrics. This allows us to graph every host separately and multiple hosts won't overwrite each other metrics.
24
+
25
+ ## 3.1.0
26
+
27
+ ### Added
28
+
29
+ - [d10c3f32](https://github.com/appsignal/appsignal-ruby/commit/d10c3f32facbf399d7afe1d2ddbb5764fb57b008) minor - Add tracking of thread counts, garbage collection runs, heap slots and other garbage collection stats to the default MRI probe. These metrics will be shown in AppSignal.com in a new Ruby VM Magic Dashboard.
30
+
31
+ ### Changed
32
+
33
+ - [114fe4f9](https://github.com/appsignal/appsignal-ruby/commit/114fe4f92e621bc2e771bb0fb608b5c6189f2933) patch - Bump agent to v-d573c9b
34
+
35
+ - Display unsupported OpenTelemetry spans in limited form.
36
+ - Clean up payload storage before sending. Should fix issues with locally queued payloads blocking data from being sent.
37
+ - Add `appsignal_create_opentelemetry_span` function to create spans for further modification, rather than only import them.
38
+ - [dd803449](https://github.com/appsignal/appsignal-ruby/commit/dd803449bd3990ba020c0bec4429166977071c02) patch - Report gauge delta value for allocated objects. This reports a more user friendly metric we can graph with a more stable continuous value in apps with stable memory allocation.
39
+ - [547f925e](https://github.com/appsignal/appsignal-ruby/commit/547f925e392bb9f4f10ba95f371e42ddfe0de5de) patch - Report gauge delta value for Garbage Collection counts. This reports a more user friendly metric that doesn't always goes up until the app restarts or gets a new deploy.
40
+
41
+ ### Fixed
42
+
43
+ - [e555a81a](https://github.com/appsignal/appsignal-ruby/commit/e555a81ab65cc951383f54d0e9a6c57d8cc2ac51) patch - Fix FFI function calls missing arguments for `appsignal_free_transaction` and `appsignal_free_data` extension functions. This fixes a high CPU issue when these function calls would be retried indefinitely.
44
+
3
45
  ## 3.0.27
4
46
 
5
47
  ### Fixed
data/Rakefile CHANGED
@@ -77,11 +77,12 @@ namespace :build_matrix do
77
77
  "name" => "Ruby #{ruby_version} for #{gem["gem"]}",
78
78
  "env_vars" => env + ruby.fetch("env_vars", []),
79
79
  "commands" => [
80
- "./support/bundler_wrapper exec rake test",
81
- "./support/bundler_wrapper exec rake test:failure"
80
+ "./support/bundler_wrapper exec rake test"
82
81
  ]
83
82
  }
84
83
  if gem["gem"] == "no_dependencies"
84
+ # Only test the failure scenarios once per Ruby version
85
+ job["commands"] << "./support/bundler_wrapper exec rake test:failure"
85
86
  ruby_primary_block["task"]["jobs"] << job
86
87
  else
87
88
  ruby_secondary_block["task"]["jobs"] << job
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/build_matrix.yml CHANGED
@@ -33,7 +33,16 @@ semaphore: # Default `.semaphore/semaphore.yml` contents
33
33
  fi
34
34
  - |
35
35
  if [ -n "$RUBY_VERSION" ]; then
36
- sem-version ruby $RUBY_VERSION
36
+ if ! (sem-version ruby "$RUBY_VERSION"); then
37
+ ruby_key="rbenv-ruby-$RUBY_VERSION"
38
+ echo "Attempting to build Ruby $RUBY_VERSION from source"
39
+ git -C "$HOME/.rbenv/plugins/ruby-build" pull
40
+ cache restore "$ruby_key"
41
+ sem-version ruby "$RUBY_VERSION"
42
+ if ! cache has_key "$ruby_key"; then
43
+ cache store "$ruby_key" "$HOME/.rbenv/versions/$RUBY_VERSION"
44
+ fi
45
+ fi
37
46
  ./support/check_versions
38
47
  else
39
48
  echo Skipping Ruby install
@@ -190,11 +199,14 @@ matrix:
190
199
  - ruby: "2.7.5"
191
200
  - ruby: "3.0.3"
192
201
  - ruby: "3.1.1"
202
+ - ruby: "3.2.0-preview1"
193
203
  - ruby: "jruby-9.2.19.0"
194
204
  gems: "minimal"
195
205
  env_vars:
196
206
  - name: "_C_VERSION"
197
207
  value: "8"
208
+ - ruby: "jruby-9.3.6.0"
209
+ gems: "minimal"
198
210
  gems:
199
211
  - gem: "no_dependencies"
200
212
  - gem: "capistrano2"
@@ -206,11 +218,13 @@ matrix:
206
218
  ruby:
207
219
  - "3.0.3"
208
220
  - "3.1.1"
221
+ - "3.2.0-preview1"
209
222
  - gem: "psych-4"
210
223
  only:
211
224
  ruby:
212
225
  - "3.0.3"
213
226
  - "3.1.1"
227
+ - "3.2.0-preview1"
214
228
  - gem: "que"
215
229
  - gem: "que_beta"
216
230
  - gem: "rails-3.2"
@@ -283,13 +297,16 @@ matrix:
283
297
  - "2.7.5"
284
298
  - "3.0.3"
285
299
  - "3.1.1"
300
+ - "3.2.0-preview1"
286
301
  - "jruby-9.2.19.0"
302
+ - "jruby-9.3.6.0"
287
303
  - gem: "rails-7.0"
288
304
  only:
289
305
  ruby:
290
306
  - "2.7.5"
291
307
  - "3.0.3"
292
308
  - "3.1.1"
309
+ - "3.2.0-preview1"
293
310
  - gem: "resque-1"
294
311
  bundler: "1.17.3"
295
312
  only:
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: be3107a
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: 31b13af931f26832eb9b5f3283a0dcfc83e327a31570aef47704589de5bd54cc
13
+ checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
14
14
  filename: appsignal-x86_64-darwin-all-static.tar.gz
15
15
  dynamic:
16
- checksum: e9a8798df3774d3483d5c2b503f53fa797bcd1fe228c293448786773bad6518f
16
+ checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
17
17
  filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
18
18
  universal-darwin:
19
19
  static:
20
- checksum: 31b13af931f26832eb9b5f3283a0dcfc83e327a31570aef47704589de5bd54cc
20
+ checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
21
21
  filename: appsignal-x86_64-darwin-all-static.tar.gz
22
22
  dynamic:
23
- checksum: e9a8798df3774d3483d5c2b503f53fa797bcd1fe228c293448786773bad6518f
23
+ checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
24
24
  filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
25
25
  aarch64-darwin:
26
26
  static:
27
- checksum: 902649453b5cfe86dee86f053a7dbe7df35bc8bce0b9632bd5619a8c824f02af
27
+ checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
28
28
  filename: appsignal-aarch64-darwin-all-static.tar.gz
29
29
  dynamic:
30
- checksum: 8f334e011d9f624782c3a1766b6ffdf987fa58d5d8230ec7d65a1b0cbf43298d
30
+ checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
31
31
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
32
32
  arm64-darwin:
33
33
  static:
34
- checksum: 902649453b5cfe86dee86f053a7dbe7df35bc8bce0b9632bd5619a8c824f02af
34
+ checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
35
35
  filename: appsignal-aarch64-darwin-all-static.tar.gz
36
36
  dynamic:
37
- checksum: 8f334e011d9f624782c3a1766b6ffdf987fa58d5d8230ec7d65a1b0cbf43298d
37
+ checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
38
38
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
39
39
  arm-darwin:
40
40
  static:
41
- checksum: 902649453b5cfe86dee86f053a7dbe7df35bc8bce0b9632bd5619a8c824f02af
41
+ checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
42
42
  filename: appsignal-aarch64-darwin-all-static.tar.gz
43
43
  dynamic:
44
- checksum: 8f334e011d9f624782c3a1766b6ffdf987fa58d5d8230ec7d65a1b0cbf43298d
44
+ checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
45
45
  filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
46
46
  aarch64-linux:
47
47
  static:
48
- checksum: 37819d1df9b516d39a3aaf54bcc434f7d77e0067d75a86fff8c89be24cf16c28
48
+ checksum: 0f2430e637eb77ce2093f021777087e87cb1e7be7c86a53771172696791c4879
49
49
  filename: appsignal-aarch64-linux-all-static.tar.gz
50
50
  dynamic:
51
- checksum: d453b25ed0752b588aa6895ede513b3cdb1b62060343fff1ad9fb4ea79859888
51
+ checksum: 0e4f9305aeaaa2d7847e83be04227b865723a0591574108d78040b5921a677a7
52
52
  filename: appsignal-aarch64-linux-all-dynamic.tar.gz
53
53
  i686-linux:
54
54
  static:
55
- checksum: c372daebb69e9795c8dcd60f48cad2af66628e1e3c8211f00526bdc8c880fc97
55
+ checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
56
56
  filename: appsignal-i686-linux-all-static.tar.gz
57
57
  dynamic:
58
- checksum: 77e98bbf097148017bd1fd5c6e497e14d30ffb96cb385c7e4ebbaac82d292572
58
+ checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
59
59
  filename: appsignal-i686-linux-all-dynamic.tar.gz
60
60
  x86-linux:
61
61
  static:
62
- checksum: c372daebb69e9795c8dcd60f48cad2af66628e1e3c8211f00526bdc8c880fc97
62
+ checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
63
63
  filename: appsignal-i686-linux-all-static.tar.gz
64
64
  dynamic:
65
- checksum: 77e98bbf097148017bd1fd5c6e497e14d30ffb96cb385c7e4ebbaac82d292572
65
+ checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
66
66
  filename: appsignal-i686-linux-all-dynamic.tar.gz
67
67
  x86_64-linux:
68
68
  static:
69
- checksum: 972a8b02061d747fbe35f3dd8d3d5b7c34bf7a6a38d0526d0ff55b9e70b67f13
69
+ checksum: 394796c0ddeb4881c9f2e6ce82f840e66bcb69e027324f6c04f6671067445fbb
70
70
  filename: appsignal-x86_64-linux-all-static.tar.gz
71
71
  dynamic:
72
- checksum: 96d9303fbc12cd20f227f2e950e1807d56b7d68d1af2069c7d2c77fa2544c589
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: 4821b9d4e9b4501a5002f731b633a64b3991272fb0e6e57a61ce1e2a0b33bcad
76
+ checksum: 673271c8c5fd55053d8a719bcd307f787db4ca4633baf8cf961c442bf1805614
77
77
  filename: appsignal-x86_64-linux-musl-all-static.tar.gz
78
78
  dynamic:
79
- checksum: e11b87a336ea1c51858f488b029335ccf37610a21c9327aecbbc62c3693a1869
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: 2b8ff925dd40daab892cf66ad3fefb72559cab57433907d8f70ae41722716832
90
+ checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
84
91
  filename: appsignal-x86_64-freebsd-all-static.tar.gz
85
92
  dynamic:
86
- checksum: 174e1c7b58b9081383c438ba33d6981a0063ef6d740d6feec7d2ead4e607e769
93
+ checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
87
94
  filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
88
95
  amd64-freebsd:
89
96
  static:
90
- checksum: 2b8ff925dd40daab892cf66ad3fefb72559cab57433907d8f70ae41722716832
97
+ checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
91
98
  filename: appsignal-x86_64-freebsd-all-static.tar.gz
92
99
  dynamic:
93
- checksum: 174e1c7b58b9081383c438ba33d6981a0063ef6d740d6feec7d2ead4e607e769
100
+ checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
94
101
  filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'grape', '0.14.0'
3
+ gem 'grape'
4
4
  gem 'activesupport', '~> 4.2'
5
5
 
6
6
  gemspec :path => '../'
@@ -83,7 +83,7 @@ module Appsignal
83
83
 
84
84
  # Transaction methods
85
85
  attach_function :appsignal_free_transaction,
86
- [],
86
+ [:pointer],
87
87
  :void
88
88
  attach_function :appsignal_start_transaction,
89
89
  [:appsignal_string, :appsignal_string, :long],
@@ -191,7 +191,7 @@ module Appsignal
191
191
  :void
192
192
 
193
193
  # Data struct methods
194
- attach_function :appsignal_free_data, [], :void
194
+ attach_function :appsignal_free_data, [:pointer], :void
195
195
  attach_function :appsignal_data_map_new, [], :pointer
196
196
  attach_function :appsignal_data_array_new, [], :pointer
197
197
  attach_function :appsignal_data_map_set_string,
@@ -0,0 +1,42 @@
1
+ module Appsignal
2
+ module Probes
3
+ module Helpers
4
+ private
5
+
6
+ def gauge_delta_cache
7
+ @gauge_delta_cache ||= {}
8
+ end
9
+
10
+ # Calculate the delta of two values for a gauge metric.
11
+ #
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.
23
+ #
24
+ # @example
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
+ #
33
+ def gauge_delta(cache_key, value)
34
+ previous_value = gauge_delta_cache[cache_key]
35
+ gauge_delta_cache[cache_key] = value
36
+ return unless previous_value
37
+
38
+ yield value - previous_value
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,25 +1,83 @@
1
1
  module Appsignal
2
2
  module Probes
3
3
  class MriProbe
4
+ include Helpers
5
+
4
6
  # @api private
5
7
  def self.dependencies_present?
6
8
  defined?(::RubyVM) && ::RubyVM.respond_to?(:stat)
7
9
  end
8
10
 
9
- def initialize
11
+ def initialize(appsignal: Appsignal, gc_profiler: Appsignal::GarbageCollectionProfiler.new)
10
12
  Appsignal.logger.debug("Initializing VM probe")
13
+ @appsignal = appsignal
14
+ @gc_profiler = gc_profiler
11
15
  end
12
16
 
13
17
  # @api private
14
18
  def call
15
19
  stat = RubyVM.stat
16
- [:class_serial, :global_constant_state].each do |metric|
17
- Appsignal.add_distribution_value(
18
- "ruby_vm",
19
- stat[metric],
20
- :metric => metric
21
- )
20
+
21
+ set_gauge(
22
+ "ruby_vm",
23
+ stat[:class_serial],
24
+ :metric => :class_serial
25
+ )
26
+
27
+ set_gauge(
28
+ "ruby_vm",
29
+ stat[:constant_cache] ? stat[:constant_cache].values.sum : stat[:global_constant_state],
30
+ :metric => :global_constant_state
31
+ )
32
+
33
+ set_gauge("thread_count", Thread.list.size)
34
+ gauge_delta(:gc_total_time, @gc_profiler.total_time) do |total_time|
35
+ set_gauge("gc_total_time", total_time) if total_time > 0
36
+ end
37
+
38
+ gc_stats = GC.stat
39
+ gauge_delta(
40
+ :allocated_objects,
41
+ gc_stats[:total_allocated_objects] || gc_stats[:total_allocated_object]
42
+ ) do |allocated_objects|
43
+ set_gauge("allocated_objects", allocated_objects)
44
+ end
45
+
46
+ gauge_delta(:gc_count, GC.count) do |gc_count|
47
+ set_gauge("gc_count", gc_count, :metric => :gc_count)
48
+ end
49
+ gauge_delta(:minor_gc_count, gc_stats[:minor_gc_count]) do |minor_gc_count|
50
+ set_gauge("gc_count", minor_gc_count, :metric => :minor_gc_count)
22
51
  end
52
+ gauge_delta(:major_gc_count, gc_stats[:major_gc_count]) do |major_gc_count|
53
+ set_gauge("gc_count", major_gc_count, :metric => :major_gc_count)
54
+ end
55
+
56
+ set_gauge("heap_slots", gc_stats[:heap_live_slots] || gc_stats[:heap_live_slot], :metric => :heap_live)
57
+ set_gauge("heap_slots", gc_stats[:heap_free_slots] || gc_stats[:heap_free_slot], :metric => :heap_free)
58
+ end
59
+
60
+ private
61
+
62
+ def set_gauge(metric, value, tags = {})
63
+ @appsignal.set_gauge(metric, value, { :hostname => hostname }.merge(tags))
64
+ end
65
+
66
+ def hostname
67
+ return @hostname if defined?(@hostname)
68
+
69
+ config = @appsignal.config
70
+ @hostname =
71
+ if config[:hostname]
72
+ config[:hostname]
73
+ else
74
+ # Auto detect hostname as fallback. May be inaccurate.
75
+ Socket.gethostname
76
+ end
77
+ Appsignal.logger.debug "MRI probe: Using hostname config " \
78
+ "option '#{@hostname.inspect}' as hostname"
79
+
80
+ @hostname
23
81
  end
24
82
  end
25
83
  end
@@ -1,6 +1,8 @@
1
1
  module Appsignal
2
2
  module Probes
3
3
  class SidekiqProbe
4
+ include Helpers
5
+
4
6
  # @api private
5
7
  attr_reader :config
6
8
 
@@ -42,11 +44,16 @@ module Appsignal
42
44
 
43
45
  gauge "worker_count", stats.workers_size
44
46
  gauge "process_count", stats.processes_size
45
- gauge_delta :jobs_processed, "job_count", stats.processed,
46
- :status => :processed
47
- gauge_delta :jobs_failed, "job_count", stats.failed, :status => :failed
47
+ gauge_delta :jobs_processed, stats.processed do |jobs_processed|
48
+ gauge "job_count", jobs_processed, :status => :processed
49
+ end
50
+ gauge_delta :jobs_failed, stats.failed do |jobs_failed|
51
+ gauge "job_count", jobs_failed, :status => :failed
52
+ end
48
53
  gauge "job_count", stats.retry_size, :status => :retry_queue
49
- gauge_delta :jobs_dead, "job_count", stats.dead_size, :status => :died
54
+ gauge_delta :jobs_dead, stats.dead_size do |jobs_dead|
55
+ gauge "job_count", jobs_dead, :status => :died
56
+ end
50
57
  gauge "job_count", stats.scheduled_size, :status => :scheduled
51
58
  gauge "job_count", stats.enqueued, :status => :enqueued
52
59
  end
@@ -65,25 +72,6 @@ module Appsignal
65
72
  Appsignal.set_gauge "sidekiq_#{key}", value, tags
66
73
  end
67
74
 
68
- # Track the delta of two values for a gauge metric
69
- #
70
- # First call will store the data for the metric and the second call will
71
- # set a gauge metric with the difference. This is used for absolute
72
- # counter values which we want to track as gauges.
73
- #
74
- # @example
75
- # gauge_delta :my_cache_key, "my_gauge", 10
76
- # gauge_delta :my_cache_key, "my_gauge", 15
77
- # # Creates a gauge with the value `5`
78
- # @see #gauge
79
- def gauge_delta(cache_key, key, value, tags = {})
80
- previous_value = cache[cache_key]
81
- cache[cache_key] = value
82
- return unless previous_value
83
- new_value = value - previous_value
84
- gauge key, new_value, tags
85
- end
86
-
87
75
  def hostname
88
76
  return @hostname if defined?(@hostname)
89
77
  if config.key?(:hostname)
@@ -3,5 +3,6 @@ module Appsignal
3
3
  end
4
4
  end
5
5
 
6
+ require "appsignal/probes/helpers"
6
7
  require "appsignal/probes/mri"
7
8
  require "appsignal/probes/sidekiq"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.0.27".freeze
4
+ VERSION = "3.1.2".freeze
5
5
  end
data/script/lint_git CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  set -eu
4
4
 
5
- LINTJE_VERSION="0.6.1"
5
+ LINTJE_VERSION="0.7.1"
6
6
 
7
- mkdir -p $HOME/bin
7
+ mkdir -p "$HOME/bin"
8
8
  cache_key=v1-lintje-$LINTJE_VERSION
9
9
  cache restore $cache_key
10
10
 
@@ -15,8 +15,8 @@ else
15
15
  echo "Downloading Lintje $LINTJE_VERSION"
16
16
  curl -L \
17
17
  https://github.com/tombruijn/lintje/releases/download/v$LINTJE_VERSION/x86_64-unknown-linux-gnu.tar.gz | \
18
- tar -xz --directory $HOME/bin
19
- cache store $cache_key $HOME/bin/lintje
18
+ tar -xz --directory "$HOME/bin"
19
+ cache store $cache_key "$HOME/bin/lintje"
20
20
  fi
21
21
 
22
- $HOME/bin/lintje $SEMAPHORE_GIT_COMMIT_RANGE
22
+ "$HOME/bin/lintje" "$SEMAPHORE_GIT_COMMIT_RANGE"
@@ -1,5 +1,26 @@
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
+
1
20
  describe Appsignal::Probes::MriProbe do
2
- let(:probe) { described_class.new }
21
+ let(:appsignal_mock) { AppsignalMock.new(:hostname => hostname) }
22
+ let(:gc_profiler_mock) { instance_double("Appsignal::GarbageCollectionProfiler") }
23
+ let(:probe) { described_class.new(:appsignal => appsignal_mock, :gc_profiler => gc_profiler_mock) }
3
24
 
4
25
  describe ".dependencies_present?" do
5
26
  if DependencyHelper.running_jruby? || DependencyHelper.running_ruby_2_0?
@@ -15,19 +36,103 @@ describe Appsignal::Probes::MriProbe do
15
36
 
16
37
  unless DependencyHelper.running_jruby? || DependencyHelper.running_ruby_2_0?
17
38
  describe "#call" do
39
+ let(:hostname) { nil }
40
+ before do
41
+ allow(gc_profiler_mock).to receive(:total_time)
42
+ end
43
+
18
44
  it "should track vm metrics" do
19
- expect_distribution_value(:class_serial)
20
- expect_distribution_value(:global_constant_state)
45
+ probe.call
46
+ expect_gauge_value("ruby_vm", :tags => { :metric => :class_serial })
47
+ expect_gauge_value("ruby_vm", :tags => { :metric => :global_constant_state })
48
+ end
49
+
50
+ it "tracks thread counts" do
51
+ probe.call
52
+ expect_gauge_value("thread_count")
53
+ end
21
54
 
55
+ it "tracks GC total time" do
56
+ expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15)
57
+ probe.call
22
58
  probe.call
59
+ expect_gauge_value("gc_total_time", 5)
60
+ end
61
+
62
+ context "when GC total time overflows" do
63
+ it "skips one report" do
64
+ expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15, 0, 10)
65
+ probe.call # Normal call, create a cache
66
+ probe.call # Report delta value based on cached value
67
+ probe.call # The value overflows and reports no value. Then stores 0 in the cache
68
+ probe.call # Report new value based on cache of 0
69
+ expect_gauges([["gc_total_time", 5], ["gc_total_time", 10]])
70
+ end
71
+ end
72
+
73
+ it "tracks GC run count" do
74
+ expect(GC).to receive(:count).and_return(10, 15)
75
+ expect(GC).to receive(:stat).and_return(
76
+ { :minor_gc_count => 10, :major_gc_count => 10 },
77
+ :minor_gc_count => 16, :major_gc_count => 17
78
+ )
79
+ probe.call
80
+ probe.call
81
+ expect_gauge_value("gc_count", 5, :tags => { :metric => :gc_count })
82
+ expect_gauge_value("gc_count", 6, :tags => { :metric => :minor_gc_count })
83
+ expect_gauge_value("gc_count", 7, :tags => { :metric => :major_gc_count })
84
+ end
85
+
86
+ it "tracks object allocation" do
87
+ expect(GC).to receive(:stat).and_return(
88
+ { :total_allocated_objects => 10 },
89
+ :total_allocated_objects => 15
90
+ )
91
+ # Only tracks delta value so the needs to be called twice
92
+ probe.call
93
+ probe.call
94
+ expect_gauge_value("allocated_objects", 5)
95
+ end
96
+
97
+ it "tracks heap slots" do
98
+ probe.call
99
+ expect_gauge_value("heap_slots", :tags => { :metric => :heap_live })
100
+ expect_gauge_value("heap_slots", :tags => { :metric => :heap_free })
101
+ end
102
+
103
+ context "with custom hostname" do
104
+ let(:hostname) { "my hostname" }
105
+
106
+ it "reports custom hostname tag value" do
107
+ probe.call
108
+ expect_gauge_value("heap_slots", :tags => { :metric => :heap_live, :hostname => hostname })
109
+ end
23
110
  end
24
111
  end
112
+ end
113
+
114
+ def expect_gauge_value(expected_key, expected_value = nil, tags: {})
115
+ expected_tags = { :hostname => Socket.gethostname }.merge(tags)
116
+ expect(appsignal_mock.gauges).to satisfy do |gauges|
117
+ gauges.any? do |distribution_value|
118
+ key, value, tags = distribution_value
119
+ next unless key == expected_key
120
+ next unless expected_value ? expected_value == value : !value.nil?
121
+ next unless tags == expected_tags
122
+
123
+ true
124
+ end
125
+ end
126
+ end
25
127
 
26
- def expect_distribution_value(metric)
27
- expect(Appsignal).to receive(:add_distribution_value)
28
- .with("ruby_vm", kind_of(Numeric), :metric => metric)
29
- .and_call_original
30
- .once
128
+ def expect_gauges(expected_metrics)
129
+ default_tags = { :hostname => Socket.gethostname }
130
+ keys = expected_metrics.map { |(key)| key }
131
+ metrics = expected_metrics.map do |metric|
132
+ key, value, tags = metric
133
+ [key, value, default_tags.merge(tags || {})]
31
134
  end
135
+ found_gauges = appsignal_mock.gauges.select { |(key)| keys.include? key }
136
+ expect(found_gauges).to eq(metrics)
32
137
  end
33
138
  end