appsignal 4.0.4 → 4.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +151 -16
  3. data/CHANGELOG.md +42 -0
  4. data/build_matrix.yml +2 -1
  5. data/ext/agent.rb +27 -27
  6. data/gemfiles/que-1.gemfile +5 -0
  7. data/gemfiles/que-2.gemfile +5 -0
  8. data/lib/appsignal/check_in/scheduler.rb +3 -4
  9. data/lib/appsignal/config.rb +7 -0
  10. data/lib/appsignal/hooks/at_exit.rb +1 -0
  11. data/lib/appsignal/hooks/puma.rb +5 -1
  12. data/lib/appsignal/integrations/puma.rb +45 -0
  13. data/lib/appsignal/integrations/que.rb +8 -2
  14. data/lib/appsignal/rack/abstract_middleware.rb +3 -47
  15. data/lib/appsignal/rack/event_handler.rb +2 -0
  16. data/lib/appsignal/rack/hanami_middleware.rb +5 -1
  17. data/lib/appsignal/rack.rb +68 -0
  18. data/lib/appsignal/version.rb +1 -1
  19. data/spec/lib/appsignal/check_in/cron_spec.rb +134 -134
  20. data/spec/lib/appsignal/check_in/scheduler_spec.rb +297 -224
  21. data/spec/lib/appsignal/config_spec.rb +13 -0
  22. data/spec/lib/appsignal/hooks/at_exit_spec.rb +11 -0
  23. data/spec/lib/appsignal/hooks/puma_spec.rb +31 -23
  24. data/spec/lib/appsignal/integrations/puma_spec.rb +150 -0
  25. data/spec/lib/appsignal/integrations/que_spec.rb +56 -21
  26. data/spec/lib/appsignal/probes_spec.rb +4 -6
  27. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +41 -122
  28. data/spec/lib/appsignal/rack_spec.rb +180 -0
  29. data/spec/lib/appsignal/transaction_spec.rb +96 -92
  30. data/spec/spec_helper.rb +6 -7
  31. data/spec/support/helpers/api_request_helper.rb +40 -0
  32. data/spec/support/helpers/config_helpers.rb +2 -1
  33. data/spec/support/helpers/dependency_helper.rb +5 -0
  34. data/spec/support/matchers/contains_log.rb +10 -3
  35. data/spec/support/mocks/hash_like.rb +10 -0
  36. data/spec/support/mocks/puma_mock.rb +43 -0
  37. data/spec/support/testing.rb +9 -0
  38. metadata +8 -3
  39. data/gemfiles/que.gemfile +0 -5
@@ -2,29 +2,29 @@ describe Appsignal::CheckIn::Scheduler do
2
2
  include WaitForHelper
3
3
  include TakeAtMostHelper
4
4
 
5
- let(:transmitter) { Appsignal::Transmitter.new("http://checkin-endpoint.invalid") }
5
+ let(:log_stream) { std_stream }
6
+ let(:logs) { log_contents(log_stream) }
7
+ let(:appsignal_options) { {} }
8
+ let(:scheduler) { Appsignal::CheckIn.scheduler }
6
9
 
7
10
  before do
8
- allow(Appsignal).to receive(:active?).and_return(true)
9
- allow(transmitter).to receive(:transmit).and_return(Net::HTTPSuccess.new("1.1", 200, "OK"))
10
- allow(Appsignal::CheckIn).to receive(:transmitter).and_return(transmitter)
11
- allow(Appsignal::CheckIn).to receive(:scheduler).and_return(subject)
11
+ start_agent(:options => appsignal_options, :internal_logger => test_logger(log_stream))
12
12
  # Shorten debounce intervals to make the tests run faster.
13
13
  stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 0.1)
14
14
  stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 0.1)
15
15
  end
16
16
 
17
17
  after do
18
- subject.stop
18
+ scheduler.stop
19
19
  end
20
20
 
21
21
  describe "when no event is sent" do
22
22
  it "does not start a thread" do
23
- expect(subject.thread).to be_nil
23
+ expect(scheduler.thread).to be_nil
24
24
  end
25
25
 
26
26
  it "does not schedule a debounce" do
27
- expect(subject.waker).to be_nil
27
+ expect(scheduler.waker).to be_nil
28
28
  end
29
29
 
30
30
  it "can be stopped" do
@@ -35,7 +35,7 @@ describe Appsignal::CheckIn::Scheduler do
35
35
  stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
36
36
 
37
37
  take_at_most(0.1) do
38
- expect { subject.stop }.not_to raise_error
38
+ expect { scheduler.stop }.not_to raise_error
39
39
  end
40
40
  end
41
41
 
@@ -47,52 +47,63 @@ describe Appsignal::CheckIn::Scheduler do
47
47
  stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
48
48
 
49
49
  take_at_most(0.1) do
50
- expect { subject.stop }.not_to raise_error
51
- expect { subject.stop }.not_to raise_error
50
+ expect { scheduler.stop }.not_to raise_error
51
+ expect { scheduler.stop }.not_to raise_error
52
52
  end
53
53
  end
54
54
 
55
55
  it "closes the queue when stopped" do
56
- subject.stop
57
- expect(subject.queue.closed?).to be(true)
56
+ scheduler.stop
57
+ expect(scheduler.queue.closed?).to be(true)
58
58
  end
59
59
  end
60
60
 
61
61
  describe "when an event is sent" do
62
62
  it "starts a thread" do
63
+ stub_check_in_request(
64
+ :events => [
65
+ "identifier" => "test",
66
+ "kind" => "finish",
67
+ "check_in_type" => "cron"
68
+ ]
69
+ )
63
70
  Appsignal::CheckIn.cron("test")
64
- expect(subject.thread).to be_a(Thread)
71
+ expect(scheduler.thread).to be_a(Thread)
65
72
  end
66
73
 
67
74
  it "schedules a debounce" do
75
+ stub_check_in_request(
76
+ :events => [
77
+ "identifier" => "test",
78
+ "kind" => "finish",
79
+ "check_in_type" => "cron"
80
+ ]
81
+ )
68
82
  Appsignal::CheckIn.cron("test")
69
- expect(subject.waker).to be_a(Thread)
83
+ expect(scheduler.waker).to be_a(Thread)
70
84
  end
71
85
 
72
86
  it "schedules the event to be transmitted" do
73
- expect(transmitter).to receive(:transmit).with([hash_including(
74
- :identifier => "test",
75
- :check_in_type => "cron",
76
- :kind => "finish"
77
- )], :format => :ndjson)
78
-
79
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
80
- message.include?("Scheduling cron check-in `test` finish event")
81
- end)
87
+ stub_check_in_request(
88
+ :events => [
89
+ "identifier" => "test",
90
+ "kind" => "finish",
91
+ "check_in_type" => "cron"
92
+ ]
93
+ )
82
94
 
83
- expect(subject.events).to be_empty
95
+ expect(scheduler.events).to be_empty
84
96
 
85
97
  Appsignal::CheckIn.cron("test")
86
98
 
87
- expect(subject.events).not_to be_empty
99
+ expect(scheduler.events).not_to be_empty
88
100
 
89
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
90
- message.include?("Transmitted cron check-in `test` finish event")
91
- end)
101
+ wait_for("the event to be transmitted") { scheduler.transmitted == 1 }
92
102
 
93
- wait_for("the event to be transmitted") { subject.transmitted == 1 }
103
+ expect(scheduler.events).to be_empty
94
104
 
95
- expect(subject.events).to be_empty
105
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `test` finish event")
106
+ expect(logs).to contains_log(:debug, "Transmitted cron check-in `test` finish event")
96
107
  end
97
108
 
98
109
  it "waits for the event to be transmitted when stopped" do
@@ -103,33 +114,30 @@ describe Appsignal::CheckIn::Scheduler do
103
114
  stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
104
115
  stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
105
116
 
106
- expect(transmitter).to receive(:transmit).with([hash_including(
107
- :identifier => "test",
108
- :check_in_type => "cron",
109
- :kind => "finish"
110
- )], :format => :ndjson)
111
-
112
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
113
- message.include?("Scheduling cron check-in `test` finish event")
114
- end)
117
+ stub_check_in_request(
118
+ :events => [
119
+ "identifier" => "test",
120
+ "kind" => "finish",
121
+ "check_in_type" => "cron"
122
+ ]
123
+ )
115
124
 
116
125
  Appsignal::CheckIn.cron("test")
117
126
 
118
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
119
- message.include?("Transmitted cron check-in `test` finish event")
120
- end)
121
-
122
- expect(subject.events).not_to be_empty
127
+ expect(scheduler.events).not_to be_empty
123
128
 
124
129
  take_at_most(0.1) do
125
- expect { subject.stop }.not_to raise_error
130
+ expect { scheduler.stop }.not_to raise_error
126
131
  end
127
132
 
128
133
  # Check that the thread wasn't killed before the transmission was
129
134
  # completed.
130
- expect(subject.transmitted).to eq(1)
135
+ expect(scheduler.transmitted).to eq(1)
136
+
137
+ expect(scheduler.events).to be_empty
131
138
 
132
- expect(subject.events).to be_empty
139
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `test` finish event")
140
+ expect(logs).to contains_log(:debug, "Transmitted cron check-in `test` finish event")
133
141
  end
134
142
 
135
143
  it "can be stopped more than once" do
@@ -140,59 +148,87 @@ describe Appsignal::CheckIn::Scheduler do
140
148
  stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
141
149
  stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
142
150
 
151
+ stub_check_in_request(
152
+ :events => [
153
+ "identifier" => "test",
154
+ "kind" => "finish",
155
+ "check_in_type" => "cron"
156
+ ]
157
+ )
143
158
  Appsignal::CheckIn.cron("test")
144
159
  take_at_most(0.1) do
145
- expect { subject.stop }.not_to raise_error
160
+ expect { scheduler.stop }.not_to raise_error
146
161
  end
147
162
 
148
163
  # Check that the thread wasn't killed before the transmission was
149
164
  # completed.
150
- expect(subject.transmitted).to eq(1)
165
+ expect(scheduler.transmitted).to eq(1)
151
166
 
152
167
  take_at_most(0.1) do
153
- expect { subject.stop }.not_to raise_error
168
+ expect { scheduler.stop }.not_to raise_error
154
169
  end
155
170
  end
156
171
 
157
172
  it "closes the queue when stopped" do
173
+ stub_check_in_request(
174
+ :events => [
175
+ "identifier" => "test",
176
+ "kind" => "finish",
177
+ "check_in_type" => "cron"
178
+ ]
179
+ )
158
180
  Appsignal::CheckIn.cron("test")
159
- subject.stop
160
- expect(subject.queue.closed?).to be(true)
181
+ scheduler.stop
182
+ expect(scheduler.queue.closed?).to be(true)
161
183
  end
162
184
 
163
185
  it "kills the thread when stopped" do
186
+ stub_check_in_request(
187
+ :events => [
188
+ "identifier" => "test",
189
+ "kind" => "finish",
190
+ "check_in_type" => "cron"
191
+ ]
192
+ )
164
193
  Appsignal::CheckIn.cron("test")
165
- subject.stop
166
- expect(subject.thread.alive?).to be(false)
194
+ scheduler.stop
195
+ expect(scheduler.thread.alive?).to be(false)
167
196
  end
168
197
 
169
198
  it "unschedules the debounce when stopped" do
199
+ stub_check_in_request(
200
+ :events => [
201
+ "identifier" => "test",
202
+ "kind" => "finish",
203
+ "check_in_type" => "cron"
204
+ ]
205
+ )
170
206
  Appsignal::CheckIn.cron("test")
171
- waker = subject.waker
172
- subject.stop
207
+ waker = scheduler.waker
208
+ scheduler.stop
173
209
  expect(waker.alive?).to be(false)
174
- expect(subject.waker).to be_nil
210
+ expect(scheduler.waker).to be_nil
175
211
  end
176
212
  end
177
213
 
178
214
  describe "when many events are sent" do
179
215
  describe "within the short debounce interval" do
180
216
  it "transmits all events at once" do
181
- expect(transmitter).to receive(:transmit).with(
182
- ["first", "second", "third"].map do |identifier|
183
- hash_including(
184
- :identifier => identifier,
185
- :check_in_type => "cron",
186
- :kind => "finish"
187
- )
188
- end, :format => :ndjson
189
- )
217
+ ["first", "second", "third"].map do |identifier|
218
+ stub_check_in_request(
219
+ :events => [
220
+ "identifier" => identifier,
221
+ "kind" => "finish",
222
+ "check_in_type" => "cron"
223
+ ]
224
+ )
225
+ end
190
226
 
191
227
  Appsignal::CheckIn.cron("first")
192
228
  Appsignal::CheckIn.cron("second")
193
229
  Appsignal::CheckIn.cron("third")
194
230
 
195
- wait_for("the events to be transmitted") { subject.transmitted == 1 }
231
+ wait_for("the events to be transmitted") { scheduler.transmitted == 1 }
196
232
  end
197
233
 
198
234
  it "transmits all events at once when stopped" do
@@ -202,42 +238,58 @@ describe Appsignal::CheckIn::Scheduler do
202
238
  # stopped.
203
239
  stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
204
240
 
205
- expect(transmitter).to receive(:transmit).with(
206
- ["first", "second", "third"].map do |identifier|
207
- hash_including(
208
- :identifier => identifier,
209
- :check_in_type => "cron",
210
- :kind => "finish"
211
- )
212
- end, :format => :ndjson
213
- )
241
+ ["first", "second", "third"].map do |identifier|
242
+ stub_check_in_request(
243
+ :events => [
244
+ "identifier" => identifier,
245
+ "kind" => "finish",
246
+ "check_in_type" => "cron"
247
+ ]
248
+ )
249
+ end
214
250
 
215
251
  Appsignal::CheckIn.cron("first")
216
252
  Appsignal::CheckIn.cron("second")
217
253
  Appsignal::CheckIn.cron("third")
218
254
 
219
- subject.stop
255
+ scheduler.stop
220
256
 
221
- wait_for("the events to be transmitted") { subject.transmitted == 1 }
257
+ wait_for("the events to be transmitted") { scheduler.transmitted == 1 }
222
258
  end
223
259
  end
224
260
 
225
261
  describe "further apart than the short debounce interval" do
226
262
  it "transmits the first event and enqueues future events" do
227
- expect(transmitter).to receive(:transmit).with([hash_including(
228
- :identifier => "first",
229
- :check_in_type => "cron",
230
- :kind => "finish"
231
- )], :format => :ndjson)
263
+ stub_check_in_request(
264
+ :events => [
265
+ "identifier" => "first",
266
+ "kind" => "finish",
267
+ "check_in_type" => "cron"
268
+ ]
269
+ )
232
270
 
233
271
  Appsignal::CheckIn.cron("first")
234
272
 
235
- wait_for("the first event to be transmitted") { subject.transmitted == 1 }
236
-
273
+ wait_for("the first event to be transmitted") { scheduler.transmitted == 1 }
274
+
275
+ stub_check_in_request(
276
+ :events => [
277
+ {
278
+ "identifier" => "second",
279
+ "kind" => "finish",
280
+ "check_in_type" => "cron"
281
+ },
282
+ {
283
+ "identifier" => "third",
284
+ "kind" => "finish",
285
+ "check_in_type" => "cron"
286
+ }
287
+ ]
288
+ )
237
289
  Appsignal::CheckIn.cron("second")
238
290
  Appsignal::CheckIn.cron("third")
239
291
 
240
- expect(subject.events).to match(["second", "third"].map do |identifier|
292
+ expect(scheduler.events).to match(["second", "third"].map do |identifier|
241
293
  hash_including({
242
294
  :identifier => identifier,
243
295
  :check_in_type => "cron",
@@ -247,51 +299,46 @@ describe Appsignal::CheckIn::Scheduler do
247
299
  end
248
300
 
249
301
  it "transmits the other events after the debounce interval" do
250
- expect(transmitter).to receive(:transmit)
251
-
252
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
253
- message.include?("Scheduling cron check-in `first` finish event")
254
- end)
255
-
302
+ stub_check_in_request(
303
+ :events => [
304
+ "identifier" => "first",
305
+ "kind" => "finish",
306
+ "check_in_type" => "cron"
307
+ ]
308
+ )
256
309
  Appsignal::CheckIn.cron("first")
257
310
 
258
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
259
- message.include?("Transmitted cron check-in `first` finish event")
260
- end)
261
-
262
- wait_for("the first event to be transmitted") { subject.transmitted == 1 }
263
-
264
- expect(transmitter).to receive(:transmit).with(
265
- ["second", "third"].map do |identifier|
266
- hash_including(
267
- :identifier => identifier,
268
- :check_in_type => "cron",
269
- :kind => "finish"
270
- )
271
- end, :format => :ndjson
311
+ wait_for("the first event to be transmitted") { scheduler.transmitted == 1 }
312
+
313
+ stub_check_in_request(
314
+ :events => [
315
+ {
316
+ "identifier" => "second",
317
+ "kind" => "finish",
318
+ "check_in_type" => "cron"
319
+ },
320
+ {
321
+ "identifier" => "third",
322
+ "kind" => "finish",
323
+ "check_in_type" => "cron"
324
+ }
325
+ ]
272
326
  )
273
327
 
274
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
275
- message.include?("Scheduling cron check-in `second` finish event")
276
- end)
277
-
278
328
  Appsignal::CheckIn.cron("second")
279
-
280
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
281
- message.include?("Scheduling cron check-in `third` finish event")
282
- end)
283
-
284
329
  Appsignal::CheckIn.cron("third")
285
330
 
286
- expect(subject.events).to_not be_empty
331
+ expect(scheduler.events).to_not be_empty
287
332
 
288
- expect(Appsignal.internal_logger).to receive(:debug).with(
289
- "Transmitted 2 check-in events"
290
- )
333
+ wait_for("the other events to be transmitted") { scheduler.transmitted == 2 }
291
334
 
292
- wait_for("the other events to be transmitted") { subject.transmitted == 2 }
335
+ expect(scheduler.events).to be_empty
293
336
 
294
- expect(subject.events).to be_empty
337
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `first` finish event")
338
+ expect(logs).to contains_log(:debug, "Transmitted cron check-in `first` finish event")
339
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `second` finish event")
340
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `third` finish event")
341
+ expect(logs).to contains_log(:debug, "Transmitted 2 check-in events")
295
342
  end
296
343
 
297
344
  it "transmits the other events when stopped" do
@@ -301,53 +348,48 @@ describe Appsignal::CheckIn::Scheduler do
301
348
  # immediately when the scheduler is stopped.
302
349
  stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
303
350
 
304
- expect(transmitter).to receive(:transmit)
305
-
306
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
307
- message.include?("Scheduling cron check-in `first` finish event")
308
- end)
309
-
351
+ stub_check_in_request(
352
+ :events => [
353
+ "identifier" => "first",
354
+ "kind" => "finish",
355
+ "check_in_type" => "cron"
356
+ ]
357
+ )
310
358
  Appsignal::CheckIn.cron("first")
311
359
 
312
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
313
- message.include?("Transmitted cron check-in `first` finish event")
314
- end)
315
-
316
- wait_for("the event to be transmitted") { subject.transmitted == 1 }
317
-
318
- expect(transmitter).to receive(:transmit).with(
319
- ["second", "third"].map do |identifier|
320
- hash_including(
321
- :identifier => identifier,
322
- :check_in_type => "cron",
323
- :kind => "finish"
324
- )
325
- end, :format => :ndjson
360
+ wait_for("the event to be transmitted") { scheduler.transmitted == 1 }
361
+
362
+ stub_check_in_request(
363
+ :events => [
364
+ {
365
+ "identifier" => "second",
366
+ "kind" => "finish",
367
+ "check_in_type" => "cron"
368
+ },
369
+ {
370
+ "identifier" => "third",
371
+ "kind" => "finish",
372
+ "check_in_type" => "cron"
373
+ }
374
+ ]
326
375
  )
327
376
 
328
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
329
- message.include?("Scheduling cron check-in `second` finish event")
330
- end)
331
-
332
377
  Appsignal::CheckIn.cron("second")
333
-
334
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
335
- message.include?("Scheduling cron check-in `third` finish event")
336
- end)
337
-
338
378
  Appsignal::CheckIn.cron("third")
339
379
 
340
- expect(subject.events).to_not be_empty
380
+ expect(scheduler.events).to_not be_empty
341
381
 
342
- expect(Appsignal.internal_logger).to receive(:debug).with(
343
- "Transmitted 2 check-in events"
344
- )
382
+ scheduler.stop
345
383
 
346
- subject.stop
384
+ wait_for("the other events to be transmitted") { scheduler.transmitted == 2 }
347
385
 
348
- wait_for("the other events to be transmitted") { subject.transmitted == 2 }
386
+ expect(scheduler.events).to be_empty
349
387
 
350
- expect(subject.events).to be_empty
388
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `first` finish event")
389
+ expect(logs).to contains_log(:debug, "Transmitted cron check-in `first` finish event")
390
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `second` finish event")
391
+ expect(logs).to contains_log(:debug, "Scheduling cron check-in `third` finish event")
392
+ expect(logs).to contains_log(:debug, "Transmitted 2 check-in events")
351
393
  end
352
394
  end
353
395
  end
@@ -358,127 +400,158 @@ describe Appsignal::CheckIn::Scheduler do
358
400
  # `.cron` helper would use a different digest for each invocation.
359
401
  cron = Appsignal::CheckIn::Cron.new(:identifier => "test")
360
402
 
361
- expect(transmitter).to receive(:transmit).with([hash_including(
362
- :identifier => "test",
363
- :check_in_type => "cron",
364
- :kind => "start"
365
- )], :format => :ndjson)
366
-
367
- expect(Appsignal.internal_logger).to receive(:debug).with(
368
- "Scheduling cron check-in `test` start event (digest #{cron.digest}) to be transmitted"
403
+ stub_check_in_request(
404
+ :events => [
405
+ "identifier" => "test",
406
+ "kind" => "start",
407
+ "check_in_type" => "cron"
408
+ ]
369
409
  )
370
410
 
371
411
  cron.start
412
+ cron.start
413
+
414
+ wait_for("the event to be transmitted") { scheduler.transmitted == 1 }
372
415
 
373
- expect(Appsignal.internal_logger).to receive(:debug).with(
416
+ expect(logs).to contains_log(
417
+ :debug,
374
418
  "Scheduling cron check-in `test` start event (digest #{cron.digest}) to be transmitted"
375
419
  )
376
-
377
- expect(Appsignal.internal_logger).to receive(:debug).with(
420
+ expect(logs).to contains_log(
421
+ :debug,
422
+ "Scheduling cron check-in `test` start event (digest #{cron.digest}) to be transmitted"
423
+ )
424
+ expect(logs).to contains_log(
425
+ :debug,
378
426
  "Replacing previously scheduled cron check-in `test` start event (digest #{cron.digest})"
379
427
  )
380
-
381
- cron.start
382
-
383
- expect(Appsignal.internal_logger).to receive(:debug).with(
428
+ expect(logs).to contains_log(
429
+ :debug,
384
430
  "Transmitted cron check-in `test` start event (digest #{cron.digest})"
385
431
  )
386
-
387
- wait_for("the event to be transmitted") { subject.transmitted == 1 }
388
432
  end
389
433
  end
390
434
 
391
435
  describe "when the scheduler is stopped" do
392
436
  it "does not schedule any events to be transmitted" do
393
- expect(transmitter).not_to receive(:transmit)
394
-
395
- subject.stop
396
-
397
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
398
- message.include?("Cannot transmit cron check-in `test` finish event") &&
399
- message.include?("AppSignal is stopped")
400
- end)
437
+ scheduler.stop
401
438
 
402
439
  Appsignal::CheckIn.cron("test")
403
440
 
404
- expect(subject.events).to be_empty
441
+ expect(scheduler.events).to be_empty
442
+
443
+ expect(logs).to contains_log(
444
+ :debug,
445
+ /Cannot transmit cron check-in `test` finish event .+: AppSignal is stopped/
446
+ )
405
447
  end
406
448
  end
407
449
 
408
450
  describe "when AppSignal is not active" do
409
- it "does not schedule any events to be transmitted" do
410
- allow(Appsignal).to receive(:active?).and_return(false)
451
+ let(:appsignal_options) { { :active => false } }
411
452
 
412
- subject.stop
413
-
414
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
415
- message.include?("Cannot transmit cron check-in `test` finish event") &&
416
- message.include?("AppSignal is not active")
417
- end)
453
+ it "does not schedule any events to be transmitted" do
454
+ scheduler.stop
418
455
 
419
456
  Appsignal::CheckIn.cron("test")
420
457
 
421
- expect(subject.events).to be_empty
458
+ expect(scheduler.events).to be_empty
459
+
460
+ expect(logs).to contains_log(
461
+ :debug,
462
+ /Cannot transmit cron check-in `test` finish event .+: AppSignal is not active/
463
+ )
422
464
  end
423
465
  end
424
466
 
425
467
  describe "when transmitting returns a non-success response code" do
426
468
  it "logs the error and continues" do
427
- expect(transmitter).to receive(:transmit).and_return(
428
- Net::HTTPNotFound.new("1.1", 404, "Not Found")
469
+ stub_check_in_request(
470
+ :events => [
471
+ "identifier" => "first",
472
+ "kind" => "start",
473
+ "check_in_type" => "cron"
474
+ ],
475
+ :response => { :status => 404 }
476
+ )
477
+ stub_check_in_request(
478
+ :events => [
479
+ "identifier" => "first",
480
+ "kind" => "finish",
481
+ "check_in_type" => "cron"
482
+ ],
483
+ :response => { :status => 404 }
429
484
  )
430
485
 
431
486
  Appsignal::CheckIn.cron("first")
432
487
 
433
- expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
434
- message.include?("Failed to transmit cron check-in `first` finish event") &&
435
- message.include?("404 status code")
436
- end)
437
-
438
- wait_for("the first event to be transmitted") { subject.transmitted == 1 }
488
+ wait_for("the first event to be transmitted") { scheduler.transmitted == 1 }
439
489
 
440
- expect(transmitter).to receive(:transmit).and_return(
441
- Net::HTTPSuccess.new("1.1", 200, "OK")
490
+ stub_check_in_request(
491
+ :events => [
492
+ "identifier" => "second",
493
+ "kind" => "start",
494
+ "check_in_type" => "cron"
495
+ ]
496
+ )
497
+ stub_check_in_request(
498
+ :events => [
499
+ "identifier" => "second",
500
+ "kind" => "finish",
501
+ "check_in_type" => "cron"
502
+ ]
442
503
  )
443
504
 
444
505
  Appsignal::CheckIn.cron("second")
445
506
 
446
- expect(Appsignal.internal_logger).not_to receive(:error)
447
-
448
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
449
- message.include?("Transmitted cron check-in `second` finish event")
450
- end)
507
+ wait_for("the second event to be transmitted") { scheduler.transmitted == 2 }
451
508
 
452
- wait_for("the second event to be transmitted") { subject.transmitted == 2 }
509
+ expect(logs).to contains_log(
510
+ :error,
511
+ /Failed to transmit cron check-in `first` finish event .+: 404 status code/
512
+ )
513
+ expect(logs).to contains_log(
514
+ :debug,
515
+ "Transmitted cron check-in `second` finish event"
516
+ )
453
517
  end
454
518
  end
455
519
 
456
520
  describe "when transmitting throws an error" do
457
521
  it "logs the error and continues" do
458
- expect(transmitter).to receive(:transmit).and_raise("Something went wrong")
522
+ stub_check_in_request(
523
+ :events => [
524
+ "identifier" => "first",
525
+ "kind" => "finish",
526
+ "check_in_type" => "cron"
527
+ ],
528
+ :response => ExampleStandardError.new("Something went wrong")
529
+ )
459
530
 
460
531
  Appsignal::CheckIn.cron("first")
461
532
 
462
- expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
463
- message.include?("Failed to transmit cron check-in `first` finish event") &&
464
- message.include?("Something went wrong")
465
- end)
533
+ wait_for("the first event to be transmitted") { scheduler.transmitted == 1 }
466
534
 
467
- wait_for("the first event to be transmitted") { subject.transmitted == 1 }
468
-
469
- expect(transmitter).to receive(:transmit).and_return(
470
- Net::HTTPSuccess.new("1.1", 200, "OK")
535
+ stub_check_in_request(
536
+ :events => [
537
+ "identifier" => "second",
538
+ "kind" => "finish",
539
+ "check_in_type" => "cron"
540
+ ]
471
541
  )
472
542
 
473
543
  Appsignal::CheckIn.cron("second")
474
544
 
475
- expect(Appsignal.internal_logger).not_to receive(:error)
476
-
477
- expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
478
- message.include?("Transmitted cron check-in `second` finish event")
479
- end)
545
+ wait_for("the second event to be transmitted") { scheduler.transmitted == 2 }
480
546
 
481
- wait_for("the second event to be transmitted") { subject.transmitted == 2 }
547
+ expect(logs).to contains_log(
548
+ :error,
549
+ /Failed to transmit cron check-in `first` finish event .+: ExampleStandardError: Something went wrong/ # rubocop:disable Layout/LineLength
550
+ )
551
+ expect(logs).to contains_log(
552
+ :debug,
553
+ "Transmitted cron check-in `second` finish event"
554
+ )
482
555
  end
483
556
  end
484
557
  end