appsignal 3.1.2-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2509a780468f8298d79de2f28fd1ccf7ea5318a059d42edc6f719446cbcaa99f
4
- data.tar.gz: 2e39e33bc84d311184d446d24adf10629e3c62adde66e832cc64870504b1c6d0
3
+ metadata.gz: 5bb9d094ed8de471e90dea7cd631a31ffea0777c09dbe4bfac516cc1820cbdcf
4
+ data.tar.gz: 790ec312c3349ee2b6889d8fca238e6cea7daa537c71cf81b7438152c2a2a2cb
5
5
  SHA512:
6
- metadata.gz: b25fd36dad63cc9bc8a39c04f81aebfad62ca322d54e94778a6c8480660749930076f36f92c686ecd9bf212e4092a9290dd916f1af2580af1502543333a2a373
7
- data.tar.gz: 2a8b44f0c4c1a7828a6679000ed90a1f143a957757ee842fb59d078134502d88bb7dbc453a5dcf80e55ccaf7e265c191f6a2425853d570a6a48820c9972554f7
6
+ metadata.gz: a3ecfceba446f9a876c903b796a2b91c4ba44ab53856e9a6518d4681f86144547bdffd6d367a309ae05c5e15ebc30a52ca4b666dcec1c651b321d90c0eb8014f
7
+ data.tar.gz: c5705bfeca7ec423ee1888572f84ef70fd15abdb5501cd0c9e73c2d5855b498d7e03ac8c50ab1aa88137d3335376cd2d0b767503c0ec17d9b2c7b209cd04e80f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
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
+
3
17
  ## 3.1.2
4
18
 
5
19
  ### Changed
@@ -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!
@@ -31,8 +31,8 @@ module Appsignal
31
31
  )
32
32
 
33
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
34
+ gauge_delta(:gc_time, @gc_profiler.total_time) do |gc_time|
35
+ set_gauge("gc_time", gc_time) if gc_time > 0
36
36
  end
37
37
 
38
38
  gc_stats = GC.stat
@@ -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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.1.2".freeze
4
+ VERSION = "3.1.3".freeze
5
5
  end
@@ -52,11 +52,11 @@ describe Appsignal::Probes::MriProbe do
52
52
  expect_gauge_value("thread_count")
53
53
  end
54
54
 
55
- it "tracks GC total time" do
55
+ it "tracks GC time between measurements" do
56
56
  expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15)
57
57
  probe.call
58
58
  probe.call
59
- expect_gauge_value("gc_total_time", 5)
59
+ expect_gauge_value("gc_time", 5)
60
60
  end
61
61
 
62
62
  context "when GC total time overflows" do
@@ -66,7 +66,7 @@ describe Appsignal::Probes::MriProbe do
66
66
  probe.call # Report delta value based on cached value
67
67
  probe.call # The value overflows and reports no value. Then stores 0 in the cache
68
68
  probe.call # Report new value based on cache of 0
69
- expect_gauges([["gc_total_time", 5], ["gc_total_time", 10]])
69
+ expect_gauges([["gc_time", 5], ["gc_time", 10]])
70
70
  end
71
71
  end
72
72
 
@@ -3,20 +3,37 @@ if DependencyHelper.rails_present?
3
3
  end
4
4
 
5
5
  describe Appsignal::Rack::RailsInstrumentation do
6
- before :context do
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("action_dispatch.request_id" => "1").tap do |request|
13
- request["action_controller.instance"] = double(
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
- end
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", :error => false do
50
- it "should create a transaction" do
51
- expect(Appsignal::Transaction).to receive(:create).with(
52
- "1",
53
- Appsignal::Transaction::HTTP_REQUEST,
54
- kind_of(ActionDispatch::Request),
55
- :params_method => :filtered_parameters
56
- ).and_return(
57
- instance_double(
58
- "Appsignal::Transaction",
59
- :set_action => nil,
60
- :set_action_if_nil => nil,
61
- :set_http_or_background_queue_start => nil,
62
- :set_metadata => nil
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
- it "should call the app" do
68
- expect(app).to receive(:call).with(env)
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", :error => true do
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
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_error).with(error)
81
- end
82
- end
129
+ expect { run }.to raise_error(error)
83
130
 
84
- it "should set metadata" do
85
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata).twice
86
- end
87
-
88
- it "should set the action and queue start" do
89
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_action_if_nil).with("MockController#index")
90
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_http_or_background_queue_start)
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
- subject { Appsignal::Transaction.current }
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(subject).to eq Thread.current[:appsignal_transaction]
97
- expect(subject).to eq transaction
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(subject.nil_transaction?).to eq false
102
- expect(subject).to be_a Appsignal::Transaction
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(subject.nil_transaction?).to eq true
113
- expect(subject).to be_a Appsignal::Transaction::NilTransaction
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
@@ -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) { double }
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
@@ -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.2
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-08-02 00:00:00.000000000 Z
13
+ date: 2022-08-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack