appsignal 3.1.0-java → 3.1.3-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 +4 -4
- data/CHANGELOG.md +36 -0
- data/appsignal.gemspec +5 -1
- data/ext/agent.yml +32 -25
- data/lib/appsignal/helpers/instrumentation.rb +8 -5
- data/lib/appsignal/hooks/active_job.rb +5 -5
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +4 -2
- data/lib/appsignal/integrations/sidekiq.rb +18 -15
- data/lib/appsignal/probes/helpers.rb +21 -8
- data/lib/appsignal/probes/mri.rb +44 -27
- data/lib/appsignal/probes/sidekiq.rb +7 -6
- data/lib/appsignal/rack/rails_instrumentation.rb +5 -1
- data/lib/appsignal/transaction.rb +14 -0
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/probes/mri_spec.rb +60 -26
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +79 -35
- data/spec/lib/appsignal/transaction_spec.rb +17 -7
- data/spec/lib/appsignal_spec.rb +8 -1
- data/spec/support/helpers/config_helpers.rb +1 -0
- data/spec/support/helpers/env_helpers.rb +9 -1
- data/spec/support/helpers/transaction_helpers.rb +6 -0
- data/spec/support/testing.rb +11 -0
- metadata +9 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5bb9d094ed8de471e90dea7cd631a31ffea0777c09dbe4bfac516cc1820cbdcf
|
|
4
|
+
data.tar.gz: 790ec312c3349ee2b6889d8fca238e6cea7daa537c71cf81b7438152c2a2a2cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3ecfceba446f9a876c903b796a2b91c4ba44ab53856e9a6518d4681f86144547bdffd6d367a309ae05c5e15ebc30a52ca4b666dcec1c651b321d90c0eb8014f
|
|
7
|
+
data.tar.gz: c5705bfeca7ec423ee1888572f84ef70fd15abdb5501cd0c9e73c2d5855b498d7e03ac8c50ab1aa88137d3335376cd2d0b767503c0ec17d9b2c7b209cd04e80f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# AppSignal for Ruby gem Changelog
|
|
2
2
|
|
|
3
|
+
## 3.1.3
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [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.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- [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.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- [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.
|
|
16
|
+
|
|
17
|
+
## 3.1.2
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- [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.
|
|
22
|
+
- [61a78fb0](https://github.com/appsignal/appsignal-ruby/commit/61a78fb028b04ae6f0a4ca1fc469d744f23c5029) patch - Bump agent to 06391fb
|
|
23
|
+
|
|
24
|
+
- Accept "warning" value for the `log_level` config option.
|
|
25
|
+
- Add aarch64 Linux musl build.
|
|
26
|
+
- Improve debug logging from the extension.
|
|
27
|
+
- Fix high CPU issue for appsignal-agent when nothing could be read from the socket.
|
|
28
|
+
|
|
29
|
+
## 3.1.1
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- [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.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- [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.
|
|
38
|
+
|
|
3
39
|
## 3.1.0
|
|
4
40
|
|
|
5
41
|
### Added
|
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:
|
|
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:
|
|
13
|
+
checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
|
|
14
14
|
filename: appsignal-x86_64-darwin-all-static.tar.gz
|
|
15
15
|
dynamic:
|
|
16
|
-
checksum:
|
|
16
|
+
checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
|
|
17
17
|
filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
|
|
18
18
|
universal-darwin:
|
|
19
19
|
static:
|
|
20
|
-
checksum:
|
|
20
|
+
checksum: 9bf41c183d94c80e980f57ea2e29d08bae97e8097b5284a2b91a5484bf866f8c
|
|
21
21
|
filename: appsignal-x86_64-darwin-all-static.tar.gz
|
|
22
22
|
dynamic:
|
|
23
|
-
checksum:
|
|
23
|
+
checksum: 4d3789e65cf00e446600e883d95d097323ebb3835703c67c8d09f434f09ab496
|
|
24
24
|
filename: appsignal-x86_64-darwin-all-dynamic.tar.gz
|
|
25
25
|
aarch64-darwin:
|
|
26
26
|
static:
|
|
27
|
-
checksum:
|
|
27
|
+
checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
|
|
28
28
|
filename: appsignal-aarch64-darwin-all-static.tar.gz
|
|
29
29
|
dynamic:
|
|
30
|
-
checksum:
|
|
30
|
+
checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
|
|
31
31
|
filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
|
|
32
32
|
arm64-darwin:
|
|
33
33
|
static:
|
|
34
|
-
checksum:
|
|
34
|
+
checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
|
|
35
35
|
filename: appsignal-aarch64-darwin-all-static.tar.gz
|
|
36
36
|
dynamic:
|
|
37
|
-
checksum:
|
|
37
|
+
checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
|
|
38
38
|
filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
|
|
39
39
|
arm-darwin:
|
|
40
40
|
static:
|
|
41
|
-
checksum:
|
|
41
|
+
checksum: 74edd7b97995f3314c10e3d84fc832c1b842c236c331ed4f2f77146ad004d179
|
|
42
42
|
filename: appsignal-aarch64-darwin-all-static.tar.gz
|
|
43
43
|
dynamic:
|
|
44
|
-
checksum:
|
|
44
|
+
checksum: 7165bb164a9cd7a2a5f97897d954390412f7034c667e5826b3307ffbd848bff9
|
|
45
45
|
filename: appsignal-aarch64-darwin-all-dynamic.tar.gz
|
|
46
46
|
aarch64-linux:
|
|
47
47
|
static:
|
|
48
|
-
checksum:
|
|
48
|
+
checksum: 0f2430e637eb77ce2093f021777087e87cb1e7be7c86a53771172696791c4879
|
|
49
49
|
filename: appsignal-aarch64-linux-all-static.tar.gz
|
|
50
50
|
dynamic:
|
|
51
|
-
checksum:
|
|
51
|
+
checksum: 0e4f9305aeaaa2d7847e83be04227b865723a0591574108d78040b5921a677a7
|
|
52
52
|
filename: appsignal-aarch64-linux-all-dynamic.tar.gz
|
|
53
53
|
i686-linux:
|
|
54
54
|
static:
|
|
55
|
-
checksum:
|
|
55
|
+
checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
|
|
56
56
|
filename: appsignal-i686-linux-all-static.tar.gz
|
|
57
57
|
dynamic:
|
|
58
|
-
checksum:
|
|
58
|
+
checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
|
|
59
59
|
filename: appsignal-i686-linux-all-dynamic.tar.gz
|
|
60
60
|
x86-linux:
|
|
61
61
|
static:
|
|
62
|
-
checksum:
|
|
62
|
+
checksum: 449ba623aaa1853c2d211bf1e2d3a14e5ae09225a62457cbdbcc0983a5713a52
|
|
63
63
|
filename: appsignal-i686-linux-all-static.tar.gz
|
|
64
64
|
dynamic:
|
|
65
|
-
checksum:
|
|
65
|
+
checksum: dae994292d602eaf0910bd2ce53f0163e19767a4cbb8e5d0db99c0010d6df486
|
|
66
66
|
filename: appsignal-i686-linux-all-dynamic.tar.gz
|
|
67
67
|
x86_64-linux:
|
|
68
68
|
static:
|
|
69
|
-
checksum:
|
|
69
|
+
checksum: 394796c0ddeb4881c9f2e6ce82f840e66bcb69e027324f6c04f6671067445fbb
|
|
70
70
|
filename: appsignal-x86_64-linux-all-static.tar.gz
|
|
71
71
|
dynamic:
|
|
72
|
-
checksum:
|
|
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:
|
|
76
|
+
checksum: 673271c8c5fd55053d8a719bcd307f787db4ca4633baf8cf961c442bf1805614
|
|
77
77
|
filename: appsignal-x86_64-linux-musl-all-static.tar.gz
|
|
78
78
|
dynamic:
|
|
79
|
-
checksum:
|
|
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:
|
|
90
|
+
checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
|
|
84
91
|
filename: appsignal-x86_64-freebsd-all-static.tar.gz
|
|
85
92
|
dynamic:
|
|
86
|
-
checksum:
|
|
93
|
+
checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
|
|
87
94
|
filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
|
|
88
95
|
amd64-freebsd:
|
|
89
96
|
static:
|
|
90
|
-
checksum:
|
|
97
|
+
checksum: cb45da91c51123859e5ef5cea850460c28d6e77dfa08b90375178d9017162ba8
|
|
91
98
|
filename: appsignal-x86_64-freebsd-all-static.tar.gz
|
|
92
99
|
dynamic:
|
|
93
|
-
checksum:
|
|
100
|
+
checksum: 6a03e02c2526e05edaa7fa932b2e764318c63ec93d517c6c00f6b7541bfe71f3
|
|
94
101
|
filename: appsignal-x86_64-freebsd-all-dynamic.tar.gz
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
-
|
|
23
|
+
has_wrapper_transaction = Appsignal::Transaction.current?
|
|
24
24
|
transaction =
|
|
25
|
-
if
|
|
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
|
-
|
|
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 =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
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 :
|
|
18
|
-
#
|
|
19
|
-
#
|
|
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
|
data/lib/appsignal/probes/mri.rb
CHANGED
|
@@ -8,59 +8,76 @@ module Appsignal
|
|
|
8
8
|
defined?(::RubyVM) && ::RubyVM.respond_to?(:stat)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def
|
|
12
|
-
@garbage_collection_profiler ||= Appsignal::GarbageCollectionProfiler.new
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def initialize(appsignal = Appsignal)
|
|
11
|
+
def initialize(appsignal: Appsignal, gc_profiler: Appsignal::GarbageCollectionProfiler.new)
|
|
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
|
|
21
18
|
def call
|
|
22
19
|
stat = RubyVM.stat
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
set_gauge(
|
|
25
22
|
"ruby_vm",
|
|
26
23
|
stat[:class_serial],
|
|
27
24
|
:metric => :class_serial
|
|
28
25
|
)
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
set_gauge(
|
|
31
28
|
"ruby_vm",
|
|
32
29
|
stat[:constant_cache] ? stat[:constant_cache].values.sum : stat[:global_constant_state],
|
|
33
30
|
:metric => :global_constant_state
|
|
34
31
|
)
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
36
|
+
end
|
|
38
37
|
|
|
39
38
|
gc_stats = GC.stat
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
45
|
-
if allocated_objects
|
|
46
|
-
@appsignal.set_gauge("allocated_objects", allocated_objects)
|
|
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)
|
|
47
44
|
end
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@appsignal.add_distribution_value("gc_count", gc_count, :metric => :gc_count)
|
|
46
|
+
gauge_delta(:gc_count, GC.count) do |gc_count|
|
|
47
|
+
set_gauge("gc_count", gc_count, :metric => :gc_count)
|
|
52
48
|
end
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
@appsignal.add_distribution_value("gc_count", minor_gc_count, :metric => :minor_gc_count)
|
|
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)
|
|
56
51
|
end
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
@appsignal.add_distribution_value("gc_count", major_gc_count, :metric => :major_gc_count)
|
|
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)
|
|
60
54
|
end
|
|
61
55
|
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
64
81
|
end
|
|
65
82
|
end
|
|
66
83
|
end
|
|
@@ -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
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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
|
|
@@ -35,10 +35,24 @@ module Appsignal
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
# Returns currently active transaction or a {NilTransaction} if none is
|
|
39
|
+
# active.
|
|
40
|
+
#
|
|
41
|
+
# @see .current?
|
|
42
|
+
# @return [Boolean]
|
|
38
43
|
def current
|
|
39
44
|
Thread.current[:appsignal_transaction] || NilTransaction.new
|
|
40
45
|
end
|
|
41
46
|
|
|
47
|
+
# Returns if any transaction is currently active or not. A
|
|
48
|
+
# {NilTransaction} is not considered an active transaction.
|
|
49
|
+
#
|
|
50
|
+
# @see .current
|
|
51
|
+
# @return [Boolean]
|
|
52
|
+
def current?
|
|
53
|
+
current && !current.nil_transaction?
|
|
54
|
+
end
|
|
55
|
+
|
|
42
56
|
def complete_current!
|
|
43
57
|
current.complete
|
|
44
58
|
rescue => e
|
data/lib/appsignal/version.rb
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
class AppsignalMock
|
|
2
|
-
attr_reader :
|
|
2
|
+
attr_reader :gauges
|
|
3
3
|
|
|
4
|
-
def initialize
|
|
5
|
-
@
|
|
4
|
+
def initialize(hostname: nil)
|
|
5
|
+
@hostname = hostname
|
|
6
6
|
@gauges = []
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def
|
|
10
|
-
|
|
9
|
+
def config
|
|
10
|
+
ConfigHelpers.project_fixture_config.tap do |conf|
|
|
11
|
+
conf[:hostname] = @hostname if @hostname
|
|
12
|
+
end
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def set_gauge(*args) # rubocop:disable Naming/AccessorMethodName
|
|
@@ -16,8 +18,9 @@ class AppsignalMock
|
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
describe Appsignal::Probes::MriProbe do
|
|
19
|
-
let(:appsignal_mock) { AppsignalMock.new }
|
|
20
|
-
let(:
|
|
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) }
|
|
21
24
|
|
|
22
25
|
describe ".dependencies_present?" do
|
|
23
26
|
if DependencyHelper.running_jruby? || DependencyHelper.running_ruby_2_0?
|
|
@@ -33,10 +36,15 @@ describe Appsignal::Probes::MriProbe do
|
|
|
33
36
|
|
|
34
37
|
unless DependencyHelper.running_jruby? || DependencyHelper.running_ruby_2_0?
|
|
35
38
|
describe "#call" do
|
|
39
|
+
let(:hostname) { nil }
|
|
40
|
+
before do
|
|
41
|
+
allow(gc_profiler_mock).to receive(:total_time)
|
|
42
|
+
end
|
|
43
|
+
|
|
36
44
|
it "should track vm metrics" do
|
|
37
45
|
probe.call
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
expect_gauge_value("ruby_vm", :tags => { :metric => :class_serial })
|
|
47
|
+
expect_gauge_value("ruby_vm", :tags => { :metric => :global_constant_state })
|
|
40
48
|
end
|
|
41
49
|
|
|
42
50
|
it "tracks thread counts" do
|
|
@@ -44,9 +52,22 @@ describe Appsignal::Probes::MriProbe do
|
|
|
44
52
|
expect_gauge_value("thread_count")
|
|
45
53
|
end
|
|
46
54
|
|
|
47
|
-
it "tracks GC
|
|
55
|
+
it "tracks GC time between measurements" do
|
|
56
|
+
expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15)
|
|
48
57
|
probe.call
|
|
49
|
-
|
|
58
|
+
probe.call
|
|
59
|
+
expect_gauge_value("gc_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_time", 5], ["gc_time", 10]])
|
|
70
|
+
end
|
|
50
71
|
end
|
|
51
72
|
|
|
52
73
|
it "tracks GC run count" do
|
|
@@ -57,9 +78,9 @@ describe Appsignal::Probes::MriProbe do
|
|
|
57
78
|
)
|
|
58
79
|
probe.call
|
|
59
80
|
probe.call
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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 })
|
|
63
84
|
end
|
|
64
85
|
|
|
65
86
|
it "tracks object allocation" do
|
|
@@ -75,30 +96,43 @@ describe Appsignal::Probes::MriProbe do
|
|
|
75
96
|
|
|
76
97
|
it "tracks heap slots" do
|
|
77
98
|
probe.call
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
80
110
|
end
|
|
81
111
|
end
|
|
82
112
|
end
|
|
83
113
|
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
|
88
119
|
next unless key == expected_key
|
|
89
120
|
next unless expected_value ? expected_value == value : !value.nil?
|
|
90
|
-
next unless
|
|
121
|
+
next unless tags == expected_tags
|
|
91
122
|
|
|
92
123
|
true
|
|
93
124
|
end
|
|
94
125
|
end
|
|
95
126
|
end
|
|
96
127
|
|
|
97
|
-
def
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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 || {})]
|
|
102
134
|
end
|
|
135
|
+
found_gauges = appsignal_mock.gauges.select { |(key)| keys.include? key }
|
|
136
|
+
expect(found_gauges).to eq(metrics)
|
|
103
137
|
end
|
|
104
138
|
end
|
|
@@ -3,20 +3,37 @@ if DependencyHelper.rails_present?
|
|
|
3
3
|
end
|
|
4
4
|
|
|
5
5
|
describe Appsignal::Rack::RailsInstrumentation do
|
|
6
|
-
|
|
6
|
+
let(:log) { StringIO.new }
|
|
7
|
+
before do
|
|
7
8
|
start_agent
|
|
9
|
+
Appsignal.logger = test_logger(log)
|
|
8
10
|
end
|
|
9
11
|
|
|
12
|
+
let(:params) do
|
|
13
|
+
{
|
|
14
|
+
"controller" => "blog_posts",
|
|
15
|
+
"action" => "show",
|
|
16
|
+
"id" => "1",
|
|
17
|
+
"my_custom_param" => "my custom secret",
|
|
18
|
+
"password" => "super secret"
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
let(:env_extra) { {} }
|
|
10
22
|
let(:app) { double(:call => true) }
|
|
11
23
|
let(:env) do
|
|
12
|
-
http_request_env_with_data(
|
|
13
|
-
|
|
24
|
+
http_request_env_with_data({
|
|
25
|
+
:params => params,
|
|
26
|
+
:with_queue_start => true,
|
|
27
|
+
"action_dispatch.request_id" => "1",
|
|
28
|
+
"action_dispatch.parameter_filter" => [:my_custom_param, :password],
|
|
29
|
+
"action_controller.instance" => double(
|
|
14
30
|
:class => MockController,
|
|
15
31
|
:action_name => "index"
|
|
16
32
|
)
|
|
17
|
-
|
|
33
|
+
}.merge(env_extra))
|
|
18
34
|
end
|
|
19
35
|
let(:middleware) { Appsignal::Rack::RailsInstrumentation.new(app, {}) }
|
|
36
|
+
around { |example| keep_transactions { example.run } }
|
|
20
37
|
|
|
21
38
|
describe "#call" do
|
|
22
39
|
before do
|
|
@@ -46,30 +63,62 @@ if DependencyHelper.rails_present?
|
|
|
46
63
|
after { middleware.call(env) }
|
|
47
64
|
end
|
|
48
65
|
|
|
49
|
-
describe "#call_with_appsignal_monitoring"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
).
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
describe "#call_with_appsignal_monitoring" do
|
|
67
|
+
def run
|
|
68
|
+
middleware.call(env)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "calls the wrapped app" do
|
|
72
|
+
run
|
|
73
|
+
expect(app).to have_received(:call).with(env)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "creates one transaction with metadata" do
|
|
77
|
+
run
|
|
78
|
+
|
|
79
|
+
expect(created_transactions.length).to eq(1)
|
|
80
|
+
transaction_hash = last_transaction.to_h
|
|
81
|
+
expect(transaction_hash).to include(
|
|
82
|
+
"namespace" => Appsignal::Transaction::HTTP_REQUEST,
|
|
83
|
+
"action" => "MockController#index",
|
|
84
|
+
"metadata" => hash_including(
|
|
85
|
+
"method" => "GET",
|
|
86
|
+
"path" => "/blog"
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
expect(last_transaction.ext.queue_start).to eq(
|
|
90
|
+
fixed_time * 1_000.0
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "filter parameters in Rails" do
|
|
95
|
+
run
|
|
96
|
+
|
|
97
|
+
transaction_hash = last_transaction.to_h
|
|
98
|
+
expect(transaction_hash).to include(
|
|
99
|
+
"sample_data" => hash_including(
|
|
100
|
+
"params" => params.merge(
|
|
101
|
+
"my_custom_param" => "[FILTERED]",
|
|
102
|
+
"password" => "[FILTERED]"
|
|
103
|
+
)
|
|
63
104
|
)
|
|
64
105
|
)
|
|
65
106
|
end
|
|
66
107
|
|
|
67
|
-
|
|
68
|
-
|
|
108
|
+
context "with an invalid HTTP request method" do
|
|
109
|
+
let(:env_extra) { { :request_method => "FOO", "REQUEST_METHOD" => "FOO" } }
|
|
110
|
+
|
|
111
|
+
it "does not store the HTTP request method" do
|
|
112
|
+
run
|
|
113
|
+
|
|
114
|
+
transaction_hash = last_transaction.to_h
|
|
115
|
+
expect(transaction_hash["metadata"]).to_not have_key("method")
|
|
116
|
+
expect(log_contents(log)).to contains_log(:error, "Unable to report HTTP request method: '")
|
|
117
|
+
end
|
|
69
118
|
end
|
|
70
119
|
|
|
71
|
-
context "with an exception"
|
|
72
|
-
let(:error) { ExampleException }
|
|
120
|
+
context "with an exception" do
|
|
121
|
+
let(:error) { ExampleException.new("ExampleException message") }
|
|
73
122
|
let(:app) do
|
|
74
123
|
double.tap do |d|
|
|
75
124
|
allow(d).to receive(:call).and_raise(error)
|
|
@@ -77,21 +126,16 @@ if DependencyHelper.rails_present?
|
|
|
77
126
|
end
|
|
78
127
|
|
|
79
128
|
it "records the exception" do
|
|
80
|
-
|
|
81
|
-
end
|
|
82
|
-
end
|
|
129
|
+
expect { run }.to raise_error(error)
|
|
83
130
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
131
|
+
transaction_hash = last_transaction.to_h
|
|
132
|
+
expect(transaction_hash["error"]).to include(
|
|
133
|
+
"name" => "ExampleException",
|
|
134
|
+
"message" => "ExampleException message",
|
|
135
|
+
"backtrace" => kind_of(String)
|
|
136
|
+
)
|
|
137
|
+
end
|
|
91
138
|
end
|
|
92
|
-
|
|
93
|
-
after(:error => false) { middleware.call(env) }
|
|
94
|
-
after(:error => true) { expect { middleware.call(env) }.to raise_error(error) }
|
|
95
139
|
end
|
|
96
140
|
|
|
97
141
|
describe "#request_id" do
|
|
@@ -85,7 +85,9 @@ describe Appsignal::Transaction do
|
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
describe ".current" do
|
|
88
|
-
|
|
88
|
+
def current_transaction
|
|
89
|
+
Appsignal::Transaction.current
|
|
90
|
+
end
|
|
89
91
|
|
|
90
92
|
context "when there is a current transaction" do
|
|
91
93
|
let!(:transaction) do
|
|
@@ -93,13 +95,17 @@ describe Appsignal::Transaction do
|
|
|
93
95
|
end
|
|
94
96
|
|
|
95
97
|
it "reads :appsignal_transaction from the current Thread" do
|
|
96
|
-
expect(
|
|
97
|
-
expect(
|
|
98
|
+
expect(current_transaction).to eq Thread.current[:appsignal_transaction]
|
|
99
|
+
expect(current_transaction).to eq transaction
|
|
98
100
|
end
|
|
99
101
|
|
|
100
102
|
it "is not a NilTransaction" do
|
|
101
|
-
expect(
|
|
102
|
-
expect(
|
|
103
|
+
expect(current_transaction.nil_transaction?).to eq false
|
|
104
|
+
expect(current_transaction).to be_a Appsignal::Transaction
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "returns true for current?" do
|
|
108
|
+
expect(Appsignal::Transaction.current?).to be(true)
|
|
103
109
|
end
|
|
104
110
|
end
|
|
105
111
|
|
|
@@ -109,8 +115,12 @@ describe Appsignal::Transaction do
|
|
|
109
115
|
end
|
|
110
116
|
|
|
111
117
|
it "returns a NilTransaction stub" do
|
|
112
|
-
expect(
|
|
113
|
-
expect(
|
|
118
|
+
expect(current_transaction.nil_transaction?).to eq true
|
|
119
|
+
expect(current_transaction).to be_a Appsignal::Transaction::NilTransaction
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "returns false for current?" do
|
|
123
|
+
expect(Appsignal::Transaction.current?).to be(false)
|
|
114
124
|
end
|
|
115
125
|
end
|
|
116
126
|
end
|
data/spec/lib/appsignal_spec.rb
CHANGED
|
@@ -511,7 +511,14 @@ describe Appsignal do
|
|
|
511
511
|
before { allow(Appsignal::Transaction).to receive(:current).and_return(transaction) }
|
|
512
512
|
|
|
513
513
|
context "with transaction" do
|
|
514
|
-
let(:transaction) {
|
|
514
|
+
let(:transaction) { http_request_transaction }
|
|
515
|
+
around do |example|
|
|
516
|
+
Appsignal.config = project_fixture_config
|
|
517
|
+
set_current_transaction transaction do
|
|
518
|
+
example.run
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
515
522
|
it "should call add_breadcrumb on transaction" do
|
|
516
523
|
expect(transaction).to receive(:add_breadcrumb)
|
|
517
524
|
.with("Network", "http", "User made network request", { :response => 200 }, fixed_time)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module EnvHelpers
|
|
2
2
|
def http_request_env_with_data(args = {})
|
|
3
|
+
with_queue_start = args.delete(:with_queue_start)
|
|
3
4
|
path = args.delete(:path) || "/blog"
|
|
4
|
-
Rack::MockRequest.env_for(
|
|
5
|
+
request = Rack::MockRequest.env_for(
|
|
5
6
|
path,
|
|
6
7
|
:params => args[:params] || {
|
|
7
8
|
"controller" => "blog_posts",
|
|
@@ -18,6 +19,13 @@ module EnvHelpers
|
|
|
18
19
|
:db_runtime => 500,
|
|
19
20
|
:metadata => { :key => "value" }
|
|
20
21
|
).merge(args)
|
|
22
|
+
|
|
23
|
+
# Set default queue value
|
|
24
|
+
if with_queue_start
|
|
25
|
+
request["HTTP_X_QUEUE_START"] = "t=#{(fixed_time * 1_000).to_i}" # in milliseconds
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
request
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
def background_env_with_data(args = {})
|
|
@@ -46,8 +46,14 @@ module TransactionHelpers
|
|
|
46
46
|
|
|
47
47
|
# Set current transaction manually.
|
|
48
48
|
# Cleared by {clear_current_transaction!}
|
|
49
|
+
#
|
|
50
|
+
# When a block is given, the current transaction is automatically unset after
|
|
51
|
+
# the block.
|
|
49
52
|
def set_current_transaction(transaction) # rubocop:disable Naming/AccessorMethodName
|
|
50
53
|
Thread.current[:appsignal_transaction] = transaction
|
|
54
|
+
yield if block_given?
|
|
55
|
+
ensure
|
|
56
|
+
clear_current_transaction! if block_given?
|
|
51
57
|
end
|
|
52
58
|
|
|
53
59
|
# Use when {Appsignal::Transaction.clear_current_transaction!} is stubbed to
|
data/spec/support/testing.rb
CHANGED
|
@@ -50,6 +50,17 @@ module Appsignal
|
|
|
50
50
|
|
|
51
51
|
class Extension
|
|
52
52
|
class Transaction
|
|
53
|
+
if Appsignal.extension_loaded?
|
|
54
|
+
attr_reader :queue_start
|
|
55
|
+
alias original_set_queue_start set_queue_start
|
|
56
|
+
# Temporary helper until the extension returns this information
|
|
57
|
+
# https://github.com/appsignal/appsignal-agent/issues/293
|
|
58
|
+
def set_queue_start(start) # rubocop:disable Naming/AccessorMethodName
|
|
59
|
+
@queue_start = start
|
|
60
|
+
original_set_queue_start(start)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
53
64
|
alias original_finish finish if method_defined? :finish
|
|
54
65
|
|
|
55
66
|
# Override default {Extension::Transaction#finish} behavior to always
|
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.
|
|
4
|
+
version: 3.1.3
|
|
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-
|
|
13
|
+
date: 2022-08-04 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rack
|
|
@@ -69,35 +69,35 @@ dependencies:
|
|
|
69
69
|
- !ruby/object:Gem::Version
|
|
70
70
|
version: '0'
|
|
71
71
|
- !ruby/object:Gem::Dependency
|
|
72
|
-
name:
|
|
72
|
+
name: yard
|
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
|
74
74
|
requirements:
|
|
75
75
|
- - ">="
|
|
76
76
|
- !ruby/object:Gem::Version
|
|
77
|
-
version:
|
|
77
|
+
version: 0.9.20
|
|
78
78
|
type: :development
|
|
79
79
|
prerelease: false
|
|
80
80
|
version_requirements: !ruby/object:Gem::Requirement
|
|
81
81
|
requirements:
|
|
82
82
|
- - ">="
|
|
83
83
|
- !ruby/object:Gem::Version
|
|
84
|
-
version:
|
|
84
|
+
version: 0.9.20
|
|
85
85
|
- !ruby/object:Gem::Dependency
|
|
86
|
-
name:
|
|
86
|
+
name: pry
|
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
|
88
88
|
requirements:
|
|
89
89
|
- - ">="
|
|
90
90
|
- !ruby/object:Gem::Version
|
|
91
|
-
version: 0
|
|
91
|
+
version: '0'
|
|
92
92
|
type: :development
|
|
93
93
|
prerelease: false
|
|
94
94
|
version_requirements: !ruby/object:Gem::Requirement
|
|
95
95
|
requirements:
|
|
96
96
|
- - ">="
|
|
97
97
|
- !ruby/object:Gem::Version
|
|
98
|
-
version: 0
|
|
98
|
+
version: '0'
|
|
99
99
|
- !ruby/object:Gem::Dependency
|
|
100
|
-
name:
|
|
100
|
+
name: webmock
|
|
101
101
|
requirement: !ruby/object:Gem::Requirement
|
|
102
102
|
requirements:
|
|
103
103
|
- - ">="
|