appsignal 3.10.0-java → 3.12.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 (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