appsignal 3.10.0-java → 3.12.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +197 -0
  4. data/Gemfile +1 -0
  5. data/Rakefile +1 -1
  6. data/benchmark.rake +99 -42
  7. data/lib/appsignal/cli/demo.rb +0 -1
  8. data/lib/appsignal/cli/diagnose.rb +1 -1
  9. data/lib/appsignal/config.rb +204 -130
  10. data/lib/appsignal/demo.rb +16 -26
  11. data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
  12. data/lib/appsignal/event_formatter.rb +3 -2
  13. data/lib/appsignal/helpers/instrumentation.rb +331 -19
  14. data/lib/appsignal/hooks/action_cable.rb +21 -16
  15. data/lib/appsignal/hooks/active_job.rb +14 -8
  16. data/lib/appsignal/hooks/delayed_job.rb +1 -1
  17. data/lib/appsignal/hooks/shoryuken.rb +3 -63
  18. data/lib/appsignal/integrations/action_cable.rb +5 -7
  19. data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
  20. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
  21. data/lib/appsignal/integrations/data_mapper.rb +1 -0
  22. data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
  23. data/lib/appsignal/integrations/dry_monitor.rb +1 -0
  24. data/lib/appsignal/integrations/excon.rb +1 -0
  25. data/lib/appsignal/integrations/grape.rb +7 -0
  26. data/lib/appsignal/integrations/hanami.rb +8 -43
  27. data/lib/appsignal/integrations/http.rb +1 -0
  28. data/lib/appsignal/integrations/net_http.rb +1 -0
  29. data/lib/appsignal/integrations/object.rb +6 -0
  30. data/lib/appsignal/integrations/padrino.rb +8 -73
  31. data/lib/appsignal/integrations/que.rb +13 -20
  32. data/lib/appsignal/integrations/railtie.rb +36 -14
  33. data/lib/appsignal/integrations/rake.rb +1 -5
  34. data/lib/appsignal/integrations/redis.rb +1 -0
  35. data/lib/appsignal/integrations/redis_client.rb +1 -0
  36. data/lib/appsignal/integrations/resque.rb +2 -5
  37. data/lib/appsignal/integrations/shoryuken.rb +75 -0
  38. data/lib/appsignal/integrations/sidekiq.rb +7 -15
  39. data/lib/appsignal/integrations/sinatra.rb +8 -19
  40. data/lib/appsignal/integrations/unicorn.rb +1 -0
  41. data/lib/appsignal/integrations/webmachine.rb +2 -5
  42. data/lib/appsignal/loaders/grape.rb +13 -0
  43. data/lib/appsignal/loaders/hanami.rb +40 -0
  44. data/lib/appsignal/loaders/padrino.rb +68 -0
  45. data/lib/appsignal/loaders/sinatra.rb +24 -0
  46. data/lib/appsignal/loaders.rb +92 -0
  47. data/lib/appsignal/logger.rb +7 -3
  48. data/lib/appsignal/probes/helpers.rb +1 -0
  49. data/lib/appsignal/probes/mri.rb +1 -0
  50. data/lib/appsignal/probes/sidekiq.rb +1 -0
  51. data/lib/appsignal/probes.rb +3 -0
  52. data/lib/appsignal/rack/abstract_middleware.rb +20 -13
  53. data/lib/appsignal/rack/event_handler.rb +44 -13
  54. data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
  55. data/lib/appsignal/rack/grape_middleware.rb +2 -1
  56. data/lib/appsignal/rack/streaming_listener.rb +1 -0
  57. data/lib/appsignal/rack.rb +35 -0
  58. data/lib/appsignal/span.rb +1 -0
  59. data/lib/appsignal/transaction.rb +308 -101
  60. data/lib/appsignal/utils/data.rb +0 -1
  61. data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
  62. data/lib/appsignal/utils/integration_logger.rb +0 -13
  63. data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
  64. data/lib/appsignal/utils/json.rb +0 -1
  65. data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
  66. data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
  67. data/lib/appsignal/utils.rb +6 -0
  68. data/lib/appsignal/version.rb +1 -1
  69. data/lib/appsignal.rb +169 -14
  70. data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
  71. data/spec/lib/appsignal/cli/demo_spec.rb +0 -1
  72. data/spec/lib/appsignal/cli/diagnose/paths_spec.rb +1 -1
  73. data/spec/lib/appsignal/cli/diagnose_spec.rb +0 -1
  74. data/spec/lib/appsignal/config_spec.rb +291 -44
  75. data/spec/lib/appsignal/demo_spec.rb +1 -2
  76. data/spec/lib/appsignal/environment_spec.rb +4 -2
  77. data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
  78. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +3 -6
  79. data/spec/lib/appsignal/hooks/activejob_spec.rb +12 -3
  80. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
  81. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +4 -7
  82. data/spec/lib/appsignal/hooks/excon_spec.rb +3 -6
  83. data/spec/lib/appsignal/hooks/gvl_spec.rb +2 -2
  84. data/spec/lib/appsignal/hooks/http_spec.rb +1 -3
  85. data/spec/lib/appsignal/hooks/net_http_spec.rb +1 -1
  86. data/spec/lib/appsignal/hooks/redis_client_spec.rb +5 -8
  87. data/spec/lib/appsignal/hooks/redis_spec.rb +3 -6
  88. data/spec/lib/appsignal/hooks/resque_spec.rb +1 -1
  89. data/spec/lib/appsignal/hooks/sequel_spec.rb +3 -5
  90. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
  91. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +1 -1
  92. data/spec/lib/appsignal/hooks/webmachine_spec.rb +1 -1
  93. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
  94. data/spec/lib/appsignal/integrations/grape_spec.rb +36 -0
  95. data/spec/lib/appsignal/integrations/hanami_spec.rb +9 -178
  96. data/spec/lib/appsignal/integrations/http_spec.rb +1 -5
  97. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +4 -2
  98. data/spec/lib/appsignal/integrations/net_http_spec.rb +1 -1
  99. data/spec/lib/appsignal/integrations/object_spec.rb +1 -3
  100. data/spec/lib/appsignal/integrations/padrino_spec.rb +8 -330
  101. data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
  102. data/spec/lib/appsignal/integrations/railtie_spec.rb +275 -191
  103. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
  104. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +15 -13
  105. data/spec/lib/appsignal/integrations/sinatra_spec.rb +9 -104
  106. data/spec/lib/appsignal/integrations/webmachine_spec.rb +13 -1
  107. data/spec/lib/appsignal/loaders/grape_spec.rb +12 -0
  108. data/spec/lib/appsignal/loaders/hanami_spec.rb +95 -0
  109. data/spec/lib/appsignal/loaders/padrino_spec.rb +277 -0
  110. data/spec/lib/appsignal/loaders/sinatra_spec.rb +47 -0
  111. data/spec/lib/appsignal/loaders_spec.rb +137 -0
  112. data/spec/lib/appsignal/probes/sidekiq_spec.rb +1 -1
  113. data/spec/lib/appsignal/probes_spec.rb +6 -5
  114. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +51 -5
  115. data/spec/lib/appsignal/rack/event_handler_spec.rb +114 -10
  116. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +1 -1
  117. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +2 -35
  118. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +1 -1
  119. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
  120. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +3 -3
  121. data/spec/lib/appsignal/rack_spec.rb +63 -0
  122. data/spec/lib/appsignal/span_spec.rb +1 -3
  123. data/spec/lib/appsignal/transaction_spec.rb +1640 -1075
  124. data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
  125. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
  126. data/spec/lib/appsignal_spec.rb +601 -36
  127. data/spec/lib/puma/appsignal_spec.rb +0 -3
  128. data/spec/spec_helper.rb +5 -4
  129. data/spec/support/helpers/config_helpers.rb +2 -1
  130. data/spec/support/helpers/loader_helper.rb +21 -0
  131. data/spec/support/helpers/transaction_helpers.rb +44 -20
  132. data/spec/support/matchers/transaction.rb +15 -1
  133. data/spec/support/stubs/appsignal/loaders/loader_stub.rb +7 -0
  134. data/spec/support/testing.rb +47 -1
  135. metadata +19 -2
@@ -2,22 +2,226 @@ describe Appsignal do
2
2
  include EnvironmentMetadataHelper
3
3
  around { |example| keep_transactions { example.run } }
4
4
 
5
- before do
6
- # Make sure we have a clean state because we want to test
7
- # initialization here.
8
- Appsignal.config = nil
9
- end
10
-
11
5
  let(:transaction) { http_request_transaction }
12
6
 
13
7
  describe ".config=" do
14
- it "should set the config" do
8
+ it "sets the config" do
15
9
  config = project_fixture_config
16
10
  expect(Appsignal.internal_logger).to_not receive(:level=)
17
11
 
18
- Appsignal.config = config
12
+ silence { Appsignal.config = config }
19
13
  expect(Appsignal.config).to eq config
20
14
  end
15
+
16
+ it "prints a deprecation warning" do
17
+ err_stream = std_stream
18
+ capture_std_streams(std_stream, err_stream) do
19
+ Appsignal.config = project_fixture_config
20
+ end
21
+ expect(err_stream.read).to include(
22
+ "appsignal WARNING: Configuring AppSignal with `Appsignal.config=` is deprecated."
23
+ )
24
+ end
25
+
26
+ it "logs a deprecation warning" do
27
+ logs = capture_logs { silence { Appsignal.config = project_fixture_config } }
28
+ expect(logs).to contains_log(
29
+ :warn,
30
+ "Configuring AppSignal with `Appsignal.config=` is deprecated."
31
+ )
32
+ end
33
+ end
34
+
35
+ describe ".configure" do
36
+ context "when active" do
37
+ it "doesn't update the config" do
38
+ start_agent
39
+ Appsignal::Testing.store[:config_called] = false
40
+ expect do
41
+ Appsignal.configure do |_config|
42
+ Appsignal::Testing.store[:config_called] = true
43
+ end
44
+ end.to_not(change { [Appsignal.config, Appsignal.active?] })
45
+ expect(Appsignal::Testing.store[:config_called]).to be(false)
46
+ end
47
+
48
+ it "logs a warning" do
49
+ start_agent
50
+ logs =
51
+ capture_logs do
52
+ Appsignal.configure do |_config|
53
+ # Do something
54
+ end
55
+ end
56
+ expect(logs).to contains_log(
57
+ :warn,
58
+ "AppSignal is already started. Ignoring `Appsignal.configure` call."
59
+ )
60
+ end
61
+ end
62
+
63
+ context "with config but not started" do
64
+ it "reuses the already loaded config if the env is the same" do
65
+ Appsignal._config = Appsignal::Config.new(
66
+ project_fixture_path,
67
+ :my_env,
68
+ :ignore_actions => ["My action"]
69
+ )
70
+
71
+ Appsignal.configure(:my_env) do |config|
72
+ expect(config.ignore_actions).to eq(["My action"])
73
+ config.active = true
74
+ config.name = "My app"
75
+ config.push_api_key = "key"
76
+ end
77
+ expect(Appsignal.config.valid?).to be(true)
78
+ expect(Appsignal.config.env).to eq("my_env")
79
+ expect(Appsignal.config[:active]).to be(true)
80
+ expect(Appsignal.config[:name]).to eq("My app")
81
+ expect(Appsignal.config[:push_api_key]).to eq("key")
82
+ end
83
+
84
+ it "loads a new config if the env is not the same" do
85
+ Appsignal._config = Appsignal::Config.new(
86
+ project_fixture_path,
87
+ :my_env,
88
+ :name => "Some name",
89
+ :push_api_key => "Some key",
90
+ :ignore_actions => ["My action"]
91
+ )
92
+
93
+ Appsignal.configure(:my_env2) do |config|
94
+ expect(config.ignore_actions).to be_empty
95
+ config.active = true
96
+ config.name = "My app"
97
+ config.push_api_key = "key"
98
+ end
99
+ expect(Appsignal.config.valid?).to be(true)
100
+ expect(Appsignal.config.env).to eq("my_env2")
101
+ expect(Appsignal.config[:active]).to be(true)
102
+ expect(Appsignal.config[:name]).to eq("My app")
103
+ expect(Appsignal.config[:push_api_key]).to eq("key")
104
+ end
105
+
106
+ it "calls configure if not started yet" do
107
+ Appsignal.configure(:my_env) do |config|
108
+ config.active = false
109
+ config.name = "Some name"
110
+ end
111
+ Appsignal.start
112
+ expect(Appsignal.started?).to be_falsy
113
+
114
+ Appsignal.configure(:my_env) do |config|
115
+ expect(config.ignore_actions).to be_empty
116
+ config.active = true
117
+ config.name = "My app"
118
+ config.push_api_key = "key"
119
+ end
120
+ expect(Appsignal.config.valid?).to be(true)
121
+ expect(Appsignal.config.env).to eq("my_env")
122
+ expect(Appsignal.config[:active]).to be(true)
123
+ expect(Appsignal.config[:name]).to eq("My app")
124
+ expect(Appsignal.config[:push_api_key]).to eq("key")
125
+ end
126
+ end
127
+
128
+ context "when not active" do
129
+ it "starts with the configured config" do
130
+ Appsignal.configure(:test) do |config|
131
+ config.push_api_key = "key"
132
+ end
133
+
134
+ Appsignal.start
135
+ expect(Appsignal.config[:push_api_key]).to eq("key")
136
+ end
137
+
138
+ it "uses the given env" do
139
+ ENV["APPSIGNAL_APP_ENV"] = "env_env"
140
+ Appsignal.configure(:env_arg)
141
+
142
+ Appsignal.start
143
+ expect(Appsignal.config.env).to eq("env_arg")
144
+ end
145
+
146
+ it "loads the config without a block being given" do
147
+ Dir.chdir project_fixture_path do
148
+ Appsignal.configure(:test)
149
+ end
150
+
151
+ expect(Appsignal.config.env).to eq("test")
152
+ expect(Appsignal.config[:push_api_key]).to eq("abc")
153
+ end
154
+
155
+ it "allows customization of config in the block" do
156
+ Appsignal.configure(:test) do |config|
157
+ config.push_api_key = "key"
158
+ end
159
+
160
+ expect(Appsignal.config.valid?).to be(true)
161
+ expect(Appsignal.config.env).to eq("test")
162
+ expect(Appsignal.config[:push_api_key]).to eq("key")
163
+ end
164
+
165
+ it "loads the default config" do
166
+ Appsignal.configure do |config|
167
+ Appsignal::Config::DEFAULT_CONFIG.each do |option, value|
168
+ expect(config.send(option)).to eq(value)
169
+ end
170
+ end
171
+ end
172
+
173
+ it "loads the config from the YAML file" do
174
+ Dir.chdir project_fixture_path do
175
+ Appsignal.configure(:test) do |config|
176
+ expect(config.name).to eq("TestApp")
177
+ end
178
+ end
179
+ end
180
+
181
+ it "recognizes valid config" do
182
+ Appsignal.configure(:my_env) do |config|
183
+ config.push_api_key = "key"
184
+ end
185
+
186
+ expect(Appsignal.config.valid?).to be(true)
187
+ end
188
+
189
+ it "recognizes invalid config" do
190
+ Appsignal.configure(:my_env) do |config|
191
+ config.push_api_key = ""
192
+ end
193
+
194
+ expect(Appsignal.config.valid?).to be(false)
195
+ end
196
+
197
+ it "sets the environment when given as an argument" do
198
+ Appsignal.configure(:my_env)
199
+
200
+ expect(Appsignal.config.env).to eq("my_env")
201
+ end
202
+
203
+ it "reads the environment from the environment" do
204
+ ENV["APPSIGNAL_APP_ENV"] = "env_env"
205
+ Appsignal.configure do |config|
206
+ expect(config.env).to eq("env_env")
207
+ end
208
+
209
+ expect(Appsignal.config.env).to eq("env_env")
210
+ end
211
+
212
+ it "allows modification of previously unset config options" do
213
+ expect do
214
+ Appsignal.configure do |config|
215
+ config.ignore_actions << "My action"
216
+ config.request_headers << "My allowed header"
217
+ end
218
+ end.to_not(change { Appsignal::Config::DEFAULT_CONFIG })
219
+
220
+ expect(Appsignal.config[:ignore_actions]).to eq(["My action"])
221
+ expect(Appsignal.config[:request_headers])
222
+ .to eq(Appsignal::Config::DEFAULT_CONFIG[:request_headers] + ["My allowed header"])
223
+ end
224
+ end
21
225
  end
22
226
 
23
227
  describe ".start" do
@@ -50,7 +254,7 @@ describe Appsignal do
50
254
  end
51
255
 
52
256
  context "when config is loaded" do
53
- before { Appsignal.config = project_fixture_config }
257
+ before { Appsignal._config = project_fixture_config }
54
258
 
55
259
  it "should initialize logging" do
56
260
  Appsignal.start
@@ -113,6 +317,27 @@ describe Appsignal do
113
317
  end
114
318
  end
115
319
 
320
+ describe "loaders" do
321
+ it "starts loaded loaders" do
322
+ Appsignal::Testing.store[:loader_loaded] = 0
323
+ Appsignal::Testing.store[:loader_started] = 0
324
+ define_loader(:start_loader) do
325
+ def on_load
326
+ Appsignal::Testing.store[:loader_loaded] += 1
327
+ end
328
+
329
+ def on_start
330
+ Appsignal::Testing.store[:loader_started] += 1
331
+ end
332
+ end
333
+ Appsignal::Loaders.load(:start_loader)
334
+ Appsignal::Loaders.start
335
+
336
+ expect(Appsignal::Testing.store[:loader_loaded]).to eq(1)
337
+ expect(Appsignal::Testing.store[:loader_started]).to eq(1)
338
+ end
339
+ end
340
+
116
341
  describe "environment metadata" do
117
342
  before { capture_environment_metadata_report_calls }
118
343
 
@@ -128,7 +353,7 @@ describe Appsignal do
128
353
  end
129
354
 
130
355
  context "with debug logging" do
131
- before { Appsignal.config = project_fixture_config("test") }
356
+ before { Appsignal._config = project_fixture_config("test") }
132
357
 
133
358
  it "should change the log level" do
134
359
  Appsignal.start
@@ -137,6 +362,22 @@ describe Appsignal do
137
362
  end
138
363
  end
139
364
 
365
+ describe ".load" do
366
+ before do
367
+ TestLoader = define_loader(:appsignal_loader)
368
+ end
369
+ after do
370
+ Object.send(:remove_const, :TestLoader)
371
+ end
372
+
373
+ it "loads a loader" do
374
+ expect(Appsignal::Loaders.instances).to be_empty
375
+ Appsignal.load(:appsignal_loader)
376
+ expect(Appsignal::Loaders.instances)
377
+ .to include(:appsignal_loader => instance_of(TestLoader))
378
+ end
379
+ end
380
+
140
381
  describe ".forked" do
141
382
  context "when not active" do
142
383
  it "does nothing" do
@@ -148,7 +389,7 @@ describe Appsignal do
148
389
 
149
390
  context "when active" do
150
391
  before do
151
- Appsignal.config = project_fixture_config
392
+ Appsignal._config = project_fixture_config
152
393
  end
153
394
 
154
395
  it "starts the logger and extension" do
@@ -162,7 +403,7 @@ describe Appsignal do
162
403
 
163
404
  describe ".stop" do
164
405
  it "calls stop on the extension" do
165
- expect(Appsignal.internal_logger).to receive(:debug).with("Stopping appsignal")
406
+ expect(Appsignal.internal_logger).to receive(:debug).with("Stopping AppSignal")
166
407
  expect(Appsignal::Extension).to receive(:stop)
167
408
  Appsignal.stop
168
409
  expect(Appsignal.active?).to be_falsy
@@ -177,7 +418,7 @@ describe Appsignal do
177
418
 
178
419
  context "with context specified" do
179
420
  it "should log the context" do
180
- expect(Appsignal.internal_logger).to receive(:debug).with("Stopping appsignal (something)")
421
+ expect(Appsignal.internal_logger).to receive(:debug).with("Stopping AppSignal (something)")
181
422
  expect(Appsignal::Extension).to receive(:stop)
182
423
  Appsignal.stop("something")
183
424
  expect(Appsignal.active?).to be_falsy
@@ -185,20 +426,34 @@ describe Appsignal do
185
426
  end
186
427
  end
187
428
 
188
- describe ".active?" do
189
- subject { Appsignal.active? }
429
+ describe ".started?" do
430
+ subject { Appsignal.started? }
190
431
 
191
- context "without config" do
432
+ context "when started with active config" do
433
+ before { start_agent }
434
+
435
+ it { is_expected.to be_truthy }
436
+ end
437
+
438
+ context "when started with inactive config" do
192
439
  before do
193
- Appsignal.config = nil
440
+ Appsignal._config = project_fixture_config("nonsense")
194
441
  end
195
442
 
196
443
  it { is_expected.to be_falsy }
197
444
  end
445
+ end
446
+
447
+ describe ".active?" do
448
+ subject { Appsignal.active? }
449
+
450
+ context "without config" do
451
+ it { is_expected.to be_falsy }
452
+ end
198
453
 
199
454
  context "with inactive config" do
200
455
  before do
201
- Appsignal.config = project_fixture_config("nonsense")
456
+ Appsignal._config = project_fixture_config("nonsense")
202
457
  end
203
458
 
204
459
  it { is_expected.to be_falsy }
@@ -206,7 +461,7 @@ describe Appsignal do
206
461
 
207
462
  context "with active config" do
208
463
  before do
209
- Appsignal.config = project_fixture_config
464
+ Appsignal._config = project_fixture_config
210
465
  end
211
466
 
212
467
  it { is_expected.to be_truthy }
@@ -232,7 +487,7 @@ describe Appsignal do
232
487
  end
233
488
 
234
489
  context "not active" do
235
- before { Appsignal.config = project_fixture_config("not_active") }
490
+ before { Appsignal._config = project_fixture_config("not_active") }
236
491
 
237
492
  describe ".monitor_transaction" do
238
493
  it "does not create a transaction" do
@@ -358,7 +613,178 @@ describe Appsignal do
358
613
  before { start_agent }
359
614
  around { |example| keep_transactions { example.run } }
360
615
 
616
+ describe ".monitor" do
617
+ it "creates a transaction" do
618
+ expect do
619
+ Appsignal.monitor(:action => "MyAction")
620
+ end.to(change { created_transactions.count }.by(1))
621
+
622
+ transaction = last_transaction
623
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
624
+ expect(transaction).to have_action("MyAction")
625
+ expect(transaction).to_not have_error
626
+ expect(transaction).to_not include_events
627
+ expect(transaction).to_not have_queue_start
628
+ expect(transaction).to be_completed
629
+ end
630
+
631
+ it "returns the block's return value" do
632
+ expect(Appsignal.monitor(:action => nil) { :return_value }).to eq(:return_value)
633
+ end
634
+
635
+ it "sets a custom namespace via the namespace argument" do
636
+ Appsignal.monitor(:namespace => "custom", :action => nil)
637
+
638
+ expect(last_transaction).to have_namespace("custom")
639
+ end
640
+
641
+ it "doesn't overwrite custom namespace set in the block" do
642
+ Appsignal.monitor(:namespace => "custom", :action => nil) do
643
+ Appsignal.set_namespace("more custom")
644
+ end
645
+
646
+ expect(last_transaction).to have_namespace("more custom")
647
+ end
648
+
649
+ it "sets the action via the action argument using a string" do
650
+ Appsignal.monitor(:action => "custom")
651
+
652
+ expect(last_transaction).to have_action("custom")
653
+ end
654
+
655
+ it "sets the action via the action argument using a symbol" do
656
+ Appsignal.monitor(:action => :custom)
657
+
658
+ expect(last_transaction).to have_action("custom")
659
+ end
660
+
661
+ it "doesn't overwrite custom action set in the block" do
662
+ Appsignal.monitor(:action => "custom") do
663
+ Appsignal.set_action("more custom")
664
+ end
665
+
666
+ expect(last_transaction).to have_action("more custom")
667
+ end
668
+
669
+ it "doesn't set the action when value is nil" do
670
+ Appsignal.monitor(:action => nil)
671
+
672
+ expect(last_transaction).to_not have_action
673
+ end
674
+
675
+ it "doesn't set the action when value is :set_later" do
676
+ Appsignal.monitor(:action => :set_later)
677
+
678
+ expect(last_transaction).to_not have_action
679
+ end
680
+
681
+ it "reports exceptions that occur in the block" do
682
+ expect do
683
+ Appsignal.monitor :action => nil do
684
+ raise ExampleException, "error message"
685
+ end
686
+ end.to raise_error(ExampleException, "error message")
687
+
688
+ expect(last_transaction).to have_error("ExampleException", "error message")
689
+ end
690
+
691
+ context "with already active transction" do
692
+ let(:err_stream) { std_stream }
693
+ let(:stderr) { err_stream.read }
694
+ let(:transaction) { http_request_transaction }
695
+ before do
696
+ set_current_transaction(transaction)
697
+ transaction.set_action("My action")
698
+ end
699
+
700
+ it "doesn't create a new transaction" do
701
+ logs = nil
702
+ expect do
703
+ logs =
704
+ capture_logs do
705
+ capture_std_streams(std_stream, err_stream) do
706
+ Appsignal.monitor(:action => nil)
707
+ end
708
+ end
709
+ end.to_not(change { created_transactions.count })
710
+
711
+ warning = "An active transaction around this 'Appsignal.monitor' call."
712
+ expect(logs).to contains_log(:warn, warning)
713
+ expect(stderr).to include("appsignal WARNING: #{warning}")
714
+ end
715
+
716
+ it "does not overwrite the parent transaction's namespace" do
717
+ silence { Appsignal.monitor(:namespace => "custom", :action => nil) }
718
+
719
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
720
+ end
721
+
722
+ it "does not overwrite the parent transaction's action" do
723
+ silence { Appsignal.monitor(:action => "custom") }
724
+
725
+ expect(transaction).to have_action("My action")
726
+ end
727
+
728
+ it "doesn't complete the parent transaction" do
729
+ silence { Appsignal.monitor(:action => nil) }
730
+
731
+ expect(transaction).to_not be_completed
732
+ end
733
+ end
734
+ end
735
+
736
+ describe ".monitor_and_stop" do
737
+ it "calls Appsignal.stop after the block" do
738
+ allow(Appsignal).to receive(:stop)
739
+ Appsignal.monitor_and_stop(:namespace => "custom", :action => "My Action")
740
+
741
+ transaction = last_transaction
742
+ expect(transaction).to have_namespace("custom")
743
+ expect(transaction).to have_action("My Action")
744
+ expect(transaction).to be_completed
745
+
746
+ expect(Appsignal).to have_received(:stop).with("monitor_and_stop")
747
+ end
748
+ end
749
+
361
750
  describe ".monitor_transaction" do
751
+ it "prints a deprecation warning" do
752
+ err_stream = std_stream
753
+ capture_std_streams(std_stream, err_stream) do
754
+ Appsignal.monitor_transaction(
755
+ "perform_job.something",
756
+ :class => "BackgroundJob",
757
+ :method => "perform"
758
+ ) do
759
+ :return_value
760
+ end
761
+ end
762
+
763
+ expect(err_stream.read).to include(
764
+ "appsignal WARNING: The `Appsignal.monitor_transaction` helper is deprecated."
765
+ )
766
+ end
767
+
768
+ it "logs a deprecation warning" do
769
+ logs =
770
+ capture_logs do
771
+ silence do
772
+ Appsignal.monitor_transaction(
773
+ "perform_job.something",
774
+ :class => "BackgroundJob",
775
+ :method => "perform"
776
+ ) do
777
+ :return_value
778
+ end
779
+ end
780
+ end
781
+
782
+ expect(logs).to contains_log(
783
+ :warn,
784
+ "The `Appsignal.monitor_transaction` helper is deprecated."
785
+ )
786
+ end
787
+
362
788
  context "with a successful call" do
363
789
  it "instruments and completes for a background job" do
364
790
  return_value = nil
@@ -368,7 +794,8 @@ describe Appsignal do
368
794
  "perform_job.something",
369
795
  {
370
796
  :class => "BackgroundJob",
371
- :method => "perform"
797
+ :method => "perform",
798
+ :queue_start => fixed_time.to_i
372
799
  }
373
800
  ) do
374
801
  :return_value
@@ -380,6 +807,7 @@ describe Appsignal do
380
807
  expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
381
808
  expect(transaction).to have_action("BackgroundJob#perform")
382
809
  expect(transaction).to include_event("name" => "perform_job.something")
810
+ expect(transaction).to have_queue_start(1_389_783_600_000)
383
811
  expect(transaction).to be_completed
384
812
  end
385
813
 
@@ -391,7 +819,8 @@ describe Appsignal do
391
819
  "process_action.something",
392
820
  {
393
821
  :controller => "BlogPostsController",
394
- :action => "show"
822
+ :action => "show",
823
+ "HTTP_X_REQUEST_START" => "t=#{fixed_time.to_i * 1000}"
395
824
  }
396
825
  ) do
397
826
  :return_value
@@ -403,6 +832,7 @@ describe Appsignal do
403
832
  expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
404
833
  expect(transaction).to have_action("BlogPostsController#show")
405
834
  expect(transaction).to include_event("name" => "process_action.something")
835
+ expect(transaction).to have_queue_start(1_389_783_600_000)
406
836
  expect(transaction).to be_completed
407
837
  end
408
838
  end
@@ -444,6 +874,43 @@ describe Appsignal do
444
874
  end
445
875
 
446
876
  describe ".monitor_single_transaction" do
877
+ it "prints a deprecation warning" do
878
+ err_stream = std_stream
879
+ capture_std_streams(std_stream, err_stream) do
880
+ Appsignal.monitor_single_transaction(
881
+ "perform_job.something",
882
+ :class => "BackgroundJob",
883
+ :method => "perform"
884
+ ) do
885
+ :return_value
886
+ end
887
+ end
888
+
889
+ expect(err_stream.read).to include(
890
+ "appsignal WARNING: The `Appsignal.monitor_single_transaction` helper is deprecated."
891
+ )
892
+ end
893
+
894
+ it "logs a deprecation warning" do
895
+ logs =
896
+ capture_logs do
897
+ silence do
898
+ Appsignal.monitor_single_transaction(
899
+ "perform_job.something",
900
+ :class => "BackgroundJob",
901
+ :method => "perform"
902
+ ) do
903
+ :return_value
904
+ end
905
+ end
906
+ end
907
+
908
+ expect(logs).to contains_log(
909
+ :warn,
910
+ "The `Appsignal.monitor_single_transaction` helper is deprecated."
911
+ )
912
+ end
913
+
447
914
  context "with a successful call" do
448
915
  it "calls monitor_transaction and Appsignal.stop" do
449
916
  expect(Appsignal).to receive(:stop)
@@ -521,9 +988,7 @@ describe Appsignal do
521
988
  end
522
989
 
523
990
  describe ".set_params" do
524
- before do
525
- start_agent
526
- end
991
+ before { start_agent }
527
992
 
528
993
  context "with transaction" do
529
994
  let(:transaction) { http_request_transaction }
@@ -561,6 +1026,84 @@ describe Appsignal do
561
1026
  end
562
1027
  end
563
1028
 
1029
+ describe ".set_session_data" do
1030
+ before { start_agent }
1031
+
1032
+ context "with transaction" do
1033
+ let(:transaction) { http_request_transaction }
1034
+ before { set_current_transaction(transaction) }
1035
+
1036
+ it "sets session data on the transaction" do
1037
+ Appsignal.set_session_data("data" => "value1")
1038
+
1039
+ transaction._sample
1040
+ expect(transaction).to include_session_data("data" => "value1")
1041
+ end
1042
+
1043
+ it "overwrites the session data if called multiple times" do
1044
+ Appsignal.set_session_data("data" => "value1")
1045
+ Appsignal.set_session_data("data" => "value2")
1046
+
1047
+ transaction._sample
1048
+ expect(transaction).to include_session_data("data" => "value2")
1049
+ end
1050
+
1051
+ it "sets session data with a block on the transaction" do
1052
+ Appsignal.set_session_data { { "data" => "value1" } }
1053
+
1054
+ transaction._sample
1055
+ expect(transaction).to include_session_data("data" => "value1")
1056
+ end
1057
+ end
1058
+
1059
+ context "without transaction" do
1060
+ it "does not set session data on the transaction" do
1061
+ Appsignal.set_session_data("a" => "b")
1062
+
1063
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_session_data)
1064
+ end
1065
+ end
1066
+ end
1067
+
1068
+ describe ".set_headers" do
1069
+ before { start_agent }
1070
+
1071
+ context "with transaction" do
1072
+ let(:transaction) { http_request_transaction }
1073
+ before { set_current_transaction(transaction) }
1074
+
1075
+ it "sets request headers on the transaction" do
1076
+ Appsignal.set_headers("PATH_INFO" => "/some-path")
1077
+
1078
+ transaction._sample
1079
+ expect(transaction).to include_environment("PATH_INFO" => "/some-path")
1080
+ end
1081
+
1082
+ it "overwrites the request headers if called multiple times" do
1083
+ Appsignal.set_headers("PATH_INFO" => "/some-path1")
1084
+ Appsignal.set_headers("PATH_INFO" => "/some-path2")
1085
+
1086
+ transaction._sample
1087
+ expect(transaction).to include_environment("PATH_INFO" => "/some-path2")
1088
+ end
1089
+
1090
+ it "sets request headers with a block on the transaction" do
1091
+ Appsignal.set_headers { { "PATH_INFO" => "/some-path" } }
1092
+
1093
+ transaction._sample
1094
+ expect(transaction).to include_environment("PATH_INFO" => "/some-path")
1095
+ end
1096
+ end
1097
+
1098
+ context "without transaction" do
1099
+ it "does not set request headers on the transaction" do
1100
+ Appsignal.set_headers("PATH_INFO" => "/some-path")
1101
+
1102
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_headers)
1103
+ end
1104
+ end
1105
+ end
1106
+
564
1107
  describe ".set_custom_data" do
565
1108
  before { start_agent }
566
1109
 
@@ -595,13 +1138,11 @@ describe Appsignal do
595
1138
  end
596
1139
 
597
1140
  describe ".add_breadcrumb" do
598
- around do |example|
599
- start_agent
600
- with_current_transaction(transaction) { example.run }
601
- end
1141
+ before { start_agent }
602
1142
 
603
1143
  context "with transaction" do
604
1144
  let(:transaction) { http_request_transaction }
1145
+ before { set_current_transaction(transaction) }
605
1146
 
606
1147
  it "adds the breadcrumb to the transaction" do
607
1148
  Appsignal.add_breadcrumb(
@@ -1269,7 +1810,7 @@ describe Appsignal do
1269
1810
  end
1270
1811
  end
1271
1812
 
1272
- describe ".without_instrumentation" do
1813
+ describe ".ignore_instrumentation_events" do
1273
1814
  around { |example| keep_transactions { example.run } }
1274
1815
  let(:transaction) { http_request_transaction }
1275
1816
 
@@ -1281,20 +1822,44 @@ describe Appsignal do
1281
1822
  expect(transaction).to receive(:resume!).and_call_original
1282
1823
 
1283
1824
  Appsignal.instrument("register.this.event") { :do_nothing }
1284
- Appsignal.without_instrumentation do
1825
+ Appsignal.ignore_instrumentation_events do
1285
1826
  Appsignal.instrument("dont.register.this.event") { :do_nothing }
1286
1827
  end
1287
1828
 
1288
1829
  expect(transaction).to include_event("name" => "register.this.event")
1289
1830
  expect(transaction).to_not include_event("name" => "dont.register.this.event")
1290
1831
  end
1832
+
1833
+ it "has a without_instrumentation alias that prints a deprecation warning" do
1834
+ Appsignal.instrument("register.this.event") { :do_nothing }
1835
+ err_stream = std_stream
1836
+ logs =
1837
+ capture_logs do
1838
+ capture_std_streams(std_stream, err_stream) do
1839
+ Appsignal.without_instrumentation do
1840
+ Appsignal.instrument("dont.register.this.event") { :do_nothing }
1841
+ end
1842
+ end
1843
+ end
1844
+
1845
+ expect(transaction).to include_event("name" => "register.this.event")
1846
+ expect(transaction).to_not include_event("name" => "dont.register.this.event")
1847
+
1848
+ expect(logs).to contains_log(
1849
+ :warn,
1850
+ "The `Appsignal.without_instrumentation` helper is deprecated."
1851
+ )
1852
+ expect(err_stream.read).to include(
1853
+ "appsignal WARNING: The `Appsignal.without_instrumentation` helper is deprecated."
1854
+ )
1855
+ end
1291
1856
  end
1292
1857
 
1293
1858
  context "without current transaction" do
1294
1859
  let(:transaction) { nil }
1295
1860
 
1296
1861
  it "does not crash" do
1297
- Appsignal.without_instrumentation { :do_nothing }
1862
+ Appsignal.ignore_instrumentation_events { :do_nothing }
1298
1863
  end
1299
1864
  end
1300
1865
  end
@@ -1312,8 +1877,9 @@ describe Appsignal do
1312
1877
  Appsignal.start_logger
1313
1878
  end
1314
1879
  end
1315
- expect(stderr).to include("appsignal WARNING: Callng 'Appsignal.start_logger' is deprecated.")
1316
- expect(log).to contains_log(:warn, "Callng 'Appsignal.start_logger' is deprecated.")
1880
+ expect(stderr)
1881
+ .to include("appsignal WARNING: Calling 'Appsignal.start_logger' is deprecated.")
1882
+ expect(log).to contains_log(:warn, "Calling 'Appsignal.start_logger' is deprecated.")
1317
1883
  end
1318
1884
  end
1319
1885
 
@@ -1335,7 +1901,7 @@ describe Appsignal do
1335
1901
  after { FileUtils.rm_rf(log_path) }
1336
1902
 
1337
1903
  def initialize_config
1338
- Appsignal.config = project_fixture_config(
1904
+ Appsignal._config = project_fixture_config(
1339
1905
  "production",
1340
1906
  :log_path => log_path,
1341
1907
  :log_level => log_level
@@ -1482,7 +2048,6 @@ describe Appsignal do
1482
2048
 
1483
2049
  context "when there is no config" do
1484
2050
  before do
1485
- Appsignal.config = nil
1486
2051
  capture_stdout(out_stream) do
1487
2052
  Appsignal._start_logger
1488
2053
  end