appsignal 3.9.3-java → 3.10.0-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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +22 -19
  3. data/CHANGELOG.md +92 -0
  4. data/README.md +0 -1
  5. data/Rakefile +1 -1
  6. data/build_matrix.yml +10 -12
  7. data/gemfiles/webmachine1.gemfile +5 -4
  8. data/lib/appsignal/config.rb +4 -0
  9. data/lib/appsignal/environment.rb +6 -1
  10. data/lib/appsignal/helpers/instrumentation.rb +163 -1
  11. data/lib/appsignal/hooks/active_job.rb +1 -6
  12. data/lib/appsignal/integrations/padrino.rb +21 -25
  13. data/lib/appsignal/integrations/rake.rb +46 -12
  14. data/lib/appsignal/integrations/sidekiq.rb +1 -11
  15. data/lib/appsignal/integrations/webmachine.rb +15 -9
  16. data/lib/appsignal/rack/abstract_middleware.rb +49 -12
  17. data/lib/appsignal/rack/body_wrapper.rb +143 -0
  18. data/lib/appsignal/rack/generic_instrumentation.rb +5 -4
  19. data/lib/appsignal/rack/grape_middleware.rb +1 -1
  20. data/lib/appsignal/rack/hanami_middleware.rb +1 -1
  21. data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
  22. data/lib/appsignal/rack/rails_instrumentation.rb +1 -3
  23. data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
  24. data/lib/appsignal/rack/streaming_listener.rb +13 -59
  25. data/lib/appsignal/rack.rb +31 -0
  26. data/lib/appsignal/transaction.rb +50 -8
  27. data/lib/appsignal/version.rb +1 -1
  28. data/lib/appsignal.rb +3 -1
  29. data/spec/lib/appsignal/config_spec.rb +1 -0
  30. data/spec/lib/appsignal/hooks/rake_spec.rb +100 -17
  31. data/spec/lib/appsignal/integrations/padrino_spec.rb +181 -131
  32. data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -2
  33. data/spec/lib/appsignal/integrations/webmachine_spec.rb +65 -17
  34. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +96 -8
  35. data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
  36. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -17
  37. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +1 -1
  38. data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
  39. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +43 -120
  40. data/spec/lib/appsignal/transaction_spec.rb +163 -4
  41. data/spec/lib/appsignal_spec.rb +197 -6
  42. data/spec/support/mocks/dummy_app.rb +1 -1
  43. metadata +8 -4
  44. data/support/check_versions +0 -22
@@ -74,7 +74,7 @@ module Appsignal
74
74
  end
75
75
 
76
76
  attr_reader :ext, :transaction_id, :action, :namespace, :request, :paused, :tags, :options,
77
- :discarded, :breadcrumbs
77
+ :discarded, :breadcrumbs, :custom_data
78
78
 
79
79
  def initialize(transaction_id, namespace, request, options = {})
80
80
  @transaction_id = transaction_id
@@ -84,10 +84,12 @@ module Appsignal
84
84
  @paused = false
85
85
  @discarded = false
86
86
  @tags = {}
87
+ @custom_data = nil
87
88
  @breadcrumbs = []
88
89
  @store = Hash.new({})
89
90
  @options = options
90
91
  @options[:params_method] ||= :params
92
+ @params = nil
91
93
 
92
94
  @ext = Appsignal::Extension.start_transaction(
93
95
  @transaction_id,
@@ -139,9 +141,13 @@ module Appsignal
139
141
  end
140
142
 
141
143
  def params
142
- return @params if defined?(@params)
144
+ parameters = @params || request_params
143
145
 
144
- request_params
146
+ if parameters.respond_to? :call
147
+ parameters.call
148
+ else
149
+ parameters
150
+ end
145
151
  end
146
152
 
147
153
  # Set parameters on the transaction.
@@ -152,9 +158,17 @@ module Appsignal
152
158
  # The parameters set using {#set_params} are leading over those extracted
153
159
  # from a request's environment.
154
160
  #
161
+ # When both the `given_params` and a block is given to this method, the
162
+ # `given_params` argument is leading and the block will _not_ be called.
163
+ #
164
+ # @since 3.9.1
155
165
  # @param given_params [Hash] The parameters to set on the transaction.
166
+ # @yield This block is called when the transaction is sampled. The block's
167
+ # return value will become the new parameters.
156
168
  # @return [void]
157
- def set_params(given_params)
169
+ # @see {Helpers::Instrumentation#set_params}
170
+ def set_params(given_params = nil, &block)
171
+ @params = block if block
158
172
  @params = given_params if given_params
159
173
  end
160
174
 
@@ -172,14 +186,20 @@ module Appsignal
172
186
  # When no parameters are set this way, the transaction will look for
173
187
  # parameters on the {#request} environment.
174
188
  #
189
+ # @since 3.9.1
175
190
  # @param given_params [Hash] The parameters to set on the transaction if none are already set.
191
+ # @yield This block is called when the transaction is sampled. The block's
192
+ # return value will become the new parameters.
176
193
  # @return [void]
177
- def set_params_if_nil(given_params)
178
- set_params(given_params) unless @params
194
+ # @see {Helpers::Instrumentation#set_params_if_nil}
195
+ def set_params_if_nil(given_params = nil, &block)
196
+ set_params(given_params, &block) unless @params
179
197
  end
180
198
 
181
199
  # Set tags on the transaction.
182
200
  #
201
+ # When this method is called multiple times, it will merge the tags.
202
+ #
183
203
  # @param given_tags [Hash] Collection of tags.
184
204
  # @option given_tags [String, Symbol, Integer] :any
185
205
  # The name of the tag as a Symbol.
@@ -187,13 +207,34 @@ module Appsignal
187
207
  # The name of the tag as a String.
188
208
  # @return [void]
189
209
  #
190
- # @see Appsignal.tag_request
210
+ # @see Helpers::Instrumentation#tag_request
191
211
  # @see https://docs.appsignal.com/ruby/instrumentation/tagging.html
192
212
  # Tagging guide
193
213
  def set_tags(given_tags = {})
194
214
  @tags.merge!(given_tags)
195
215
  end
196
216
 
217
+ # Set custom data on the transaction.
218
+ #
219
+ # When this method is called multiple times, it will overwrite the
220
+ # previously set value.
221
+ #
222
+ # @since 3.10.0
223
+ # @see Appsignal.set_custom_data
224
+ # @see https://docs.appsignal.com/guides/custom-data/sample-data.html
225
+ # Sample data guide
226
+ # @param data [Hash/Array]
227
+ # @return [void]
228
+ def set_custom_data(data)
229
+ case data
230
+ when Array, Hash
231
+ @custom_data = data
232
+ else
233
+ Appsignal.internal_logger
234
+ .error("set_custom_data: Unsupported data type #{data.class} received.")
235
+ end
236
+ end
237
+
197
238
  # Add breadcrumbs to the transaction.
198
239
  #
199
240
  # @param category [String] category of breadcrumb
@@ -376,7 +417,8 @@ module Appsignal
376
417
  :session_data => sanitized_session_data,
377
418
  :metadata => sanitized_metadata,
378
419
  :tags => sanitized_tags,
379
- :breadcrumbs => breadcrumbs
420
+ :breadcrumbs => breadcrumbs,
421
+ :custom_data => custom_data
380
422
  }.each do |key, data|
381
423
  set_sample_data(key, data)
382
424
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.9.3"
4
+ VERSION = "3.10.0"
5
5
  end
data/lib/appsignal.rb CHANGED
@@ -324,8 +324,10 @@ require "appsignal/hooks"
324
324
  require "appsignal/probes"
325
325
  require "appsignal/marker"
326
326
  require "appsignal/garbage_collection"
327
+ require "appsignal/rack"
328
+ require "appsignal/rack/body_wrapper"
327
329
  require "appsignal/rack/abstract_middleware"
328
- require "appsignal/rack/generic_instrumentation"
330
+ require "appsignal/rack/instrumentation_middleware"
329
331
  require "appsignal/rack/event_handler"
330
332
  require "appsignal/integrations/railtie" if defined?(::Rails)
331
333
  require "appsignal/transaction"
@@ -165,6 +165,7 @@ describe Appsignal::Config do
165
165
  :enable_statsd => true,
166
166
  :enable_nginx_metrics => false,
167
167
  :enable_rails_error_reporter => true,
168
+ :enable_rake_performance_instrumentation => false,
168
169
  :endpoint => "https://push.appsignal.com",
169
170
  :files_world_accessible => true,
170
171
  :filter_metadata => [],
@@ -1,41 +1,89 @@
1
1
  require "rake"
2
2
 
3
3
  describe Appsignal::Hooks::RakeHook do
4
+ let(:helper) { Appsignal::Integrations::RakeIntegrationHelper }
4
5
  let(:task) { Rake::Task.new("task:name", Rake::Application.new) }
5
6
  let(:arguments) { Rake::TaskArguments.new(["foo"], ["bar"]) }
6
- let(:generic_request) { Appsignal::Transaction::GenericRequest.new({}) }
7
- before(:context) { start_agent }
7
+ before do
8
+ start_agent
9
+ allow(Kernel).to receive(:at_exit)
10
+ end
11
+ around { |example| keep_transactions { example.run } }
12
+ after do
13
+ if helper.instance_variable_defined?(:@register_at_exit_hook)
14
+ helper.remove_instance_variable(:@register_at_exit_hook)
15
+ end
16
+ end
17
+
18
+ def expect_to_not_have_registered_at_exit_hook
19
+ expect(Kernel).to_not have_received(:at_exit)
20
+ end
21
+
22
+ def expect_to_have_registered_at_exit_hook
23
+ expect(Kernel).to have_received(:at_exit)
24
+ end
8
25
 
9
26
  describe "#execute" do
10
27
  context "without error" do
11
- before { expect(Appsignal).to_not receive(:stop) }
12
-
13
28
  def perform
14
29
  task.execute(arguments)
15
30
  end
16
31
 
17
- it "creates no transaction" do
18
- expect { perform }.to_not(change { created_transactions.count })
32
+ context "with :enable_rake_performance_instrumentation == false" do
33
+ before do
34
+ Appsignal.config[:enable_rake_performance_instrumentation] = false
35
+ end
36
+
37
+ it "creates no transaction" do
38
+ expect { perform }.to_not(change { created_transactions.count })
39
+ end
40
+
41
+ it "calls the original task" do
42
+ expect(perform).to eq([])
43
+ end
44
+
45
+ it "does not register an at_exit hook" do
46
+ perform
47
+ expect_to_not_have_registered_at_exit_hook
48
+ end
19
49
  end
20
50
 
21
- it "calls the original task" do
22
- expect(perform).to eq([])
51
+ context "with :enable_rake_performance_instrumentation == true" do
52
+ before do
53
+ Appsignal.config[:enable_rake_performance_instrumentation] = true
54
+ end
55
+
56
+ it "creates a transaction" do
57
+ expect { perform }.to(change { created_transactions.count }.by(1))
58
+
59
+ transaction = last_transaction
60
+ expect(transaction).to have_id
61
+ expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
62
+ expect(transaction).to have_action("task:name")
63
+ expect(transaction).to_not have_error
64
+ expect(transaction).to include_params("foo" => "bar")
65
+ expect(transaction).to include_event("name" => "task.rake")
66
+ expect(transaction).to be_completed
67
+ end
68
+
69
+ it "calls the original task" do
70
+ expect(perform).to eq([])
71
+ end
72
+
73
+ it "registers an at_exit hook" do
74
+ perform
75
+ expect_to_have_registered_at_exit_hook
76
+ end
23
77
  end
24
78
  end
25
79
 
26
80
  context "with error" do
27
- let(:error) { ExampleException }
28
81
  before do
29
- task.enhance { raise error, "my error message" }
30
- # We don't call `and_call_original` here as we don't want AppSignal to
31
- # stop and start for every spec.
32
- expect(Appsignal).to receive(:stop).with("rake")
82
+ task.enhance { raise ExampleException, "error message" }
33
83
  end
34
84
 
35
85
  def perform
36
- keep_transactions do
37
- expect { task.execute(arguments) }.to raise_error(error)
38
- end
86
+ expect { task.execute(arguments) }.to raise_error(ExampleException, "error message")
39
87
  end
40
88
 
41
89
  it "creates a background job transaction" do
@@ -45,11 +93,16 @@ describe Appsignal::Hooks::RakeHook do
45
93
  expect(transaction).to have_id
46
94
  expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
47
95
  expect(transaction).to have_action("task:name")
48
- expect(transaction).to have_error("ExampleException", "my error message")
96
+ expect(transaction).to have_error("ExampleException", "error message")
49
97
  expect(transaction).to include_params("foo" => "bar")
50
98
  expect(transaction).to be_completed
51
99
  end
52
100
 
101
+ it "registers an at_exit hook" do
102
+ perform
103
+ expect_to_have_registered_at_exit_hook
104
+ end
105
+
53
106
  context "when first argument is not a `Rake::TaskArguments`" do
54
107
  let(:arguments) { nil }
55
108
 
@@ -62,3 +115,33 @@ describe Appsignal::Hooks::RakeHook do
62
115
  end
63
116
  end
64
117
  end
118
+
119
+ describe "Appsignal::Integrations::RakeIntegrationHelper" do
120
+ let(:helper) { Appsignal::Integrations::RakeIntegrationHelper }
121
+ describe ".register_at_exit_hook" do
122
+ before do
123
+ start_agent
124
+ allow(Appsignal).to receive(:stop)
125
+ end
126
+
127
+ it "registers the at_exit hook only once" do
128
+ allow(Kernel).to receive(:at_exit)
129
+ helper.register_at_exit_hook
130
+ helper.register_at_exit_hook
131
+ expect(Kernel).to have_received(:at_exit).once
132
+ end
133
+ end
134
+
135
+ describe ".at_exit_hook" do
136
+ let(:helper) { Appsignal::Integrations::RakeIntegrationHelper }
137
+ before do
138
+ start_agent
139
+ allow(Appsignal).to receive(:stop)
140
+ end
141
+
142
+ it "calls Appsignal.stop" do
143
+ helper.at_exit_hook
144
+ expect(Appsignal).to have_received(:stop).with("rake")
145
+ end
146
+ end
147
+ end