appsignal 3.9.3-java → 3.10.0-java

Sign up to get free protection for your applications and to get access to all the features.
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