appsignal 4.0.2-java → 4.0.4-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,210 @@
1
+ describe Appsignal::CheckIn::Cron do
2
+ let(:config) { project_fixture_config }
3
+ let(:cron_checkin) { described_class.new(:identifier => "cron-checkin-name") }
4
+ let(:transmitter) { Appsignal::Transmitter.new("https://checkin-endpoint.invalid") }
5
+ let(:scheduler) { Appsignal::CheckIn::Scheduler.new }
6
+
7
+ before do
8
+ allow(Appsignal).to receive(:active?).and_return(true)
9
+ config.logger = Logger.new(StringIO.new)
10
+ allow(Appsignal::CheckIn).to receive(:scheduler).and_return(scheduler)
11
+ allow(Appsignal::CheckIn).to receive(:transmitter).and_return(transmitter)
12
+ end
13
+
14
+ after do
15
+ scheduler.stop
16
+ end
17
+
18
+ describe "when Appsignal is not active" do
19
+ it "should not transmit any events" do
20
+ allow(Appsignal).to receive(:active?).and_return(false)
21
+
22
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
23
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` start event") &&
24
+ message.include?("AppSignal is not active")
25
+ end)
26
+
27
+ cron_checkin.start
28
+
29
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
30
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` finish event") &&
31
+ message.include?("AppSignal is not active")
32
+ end)
33
+
34
+ cron_checkin.finish
35
+
36
+ expect(transmitter).not_to receive(:transmit)
37
+
38
+ scheduler.stop
39
+ end
40
+ end
41
+
42
+ describe "when AppSignal is stopped" do
43
+ it "should not transmit any events" do
44
+ expect(transmitter).not_to receive(:transmit)
45
+
46
+ expect(Appsignal.internal_logger).to receive(:debug).with("Stopping AppSignal")
47
+
48
+ Appsignal.stop
49
+
50
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
51
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` start event") &&
52
+ message.include?("AppSignal is stopped")
53
+ end)
54
+
55
+ cron_checkin.start
56
+
57
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
58
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` finish event") &&
59
+ message.include?("AppSignal is stopped")
60
+ end)
61
+
62
+ cron_checkin.finish
63
+
64
+ expect(Appsignal.internal_logger).to receive(:debug).with("Stopping AppSignal")
65
+
66
+ Appsignal.stop
67
+ end
68
+ end
69
+
70
+ describe "#start" do
71
+ it "should send a cron check-in start" do
72
+ expect(Appsignal.internal_logger).not_to receive(:error)
73
+
74
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
75
+ message.include?("Scheduling cron check-in `cron-checkin-name` start event")
76
+ end)
77
+
78
+ cron_checkin.start
79
+
80
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
81
+ message.include?("Transmitted cron check-in `cron-checkin-name` start event")
82
+ end)
83
+
84
+ expect(transmitter).to receive(:transmit).with([hash_including(
85
+ :identifier => "cron-checkin-name",
86
+ :kind => "start",
87
+ :check_in_type => "cron"
88
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "200", nil))
89
+
90
+ scheduler.stop
91
+ end
92
+
93
+ it "should log an error if it fails" do
94
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
95
+ message.include?("Scheduling cron check-in `cron-checkin-name` start event")
96
+ end)
97
+
98
+ cron_checkin.start
99
+
100
+ expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
101
+ message.include?("Failed to transmit cron check-in `cron-checkin-name` start event") &&
102
+ message.include?("499 status code")
103
+ end)
104
+
105
+ expect(transmitter).to receive(:transmit).with([hash_including(
106
+ :identifier => "cron-checkin-name",
107
+ :kind => "start",
108
+ :check_in_type => "cron"
109
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "499", nil))
110
+
111
+ scheduler.stop
112
+ end
113
+ end
114
+
115
+ describe "#finish" do
116
+ it "should send a cron check-in finish" do
117
+ expect(Appsignal.internal_logger).not_to receive(:error)
118
+
119
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
120
+ message.include?("Scheduling cron check-in `cron-checkin-name` finish event")
121
+ end)
122
+
123
+ cron_checkin.finish
124
+
125
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
126
+ message.include?("Transmitted cron check-in `cron-checkin-name` finish event")
127
+ end)
128
+
129
+ expect(transmitter).to receive(:transmit).with([hash_including(
130
+ :identifier => "cron-checkin-name",
131
+ :kind => "finish",
132
+ :check_in_type => "cron"
133
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "200", nil))
134
+
135
+ scheduler.stop
136
+ end
137
+
138
+ it "should log an error if it fails" do
139
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
140
+ message.include?("Scheduling cron check-in `cron-checkin-name` finish event")
141
+ end)
142
+
143
+ cron_checkin.finish
144
+
145
+ expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
146
+ message.include?("Failed to transmit cron check-in `cron-checkin-name` finish event") &&
147
+ message.include?("499 status code")
148
+ end)
149
+
150
+ expect(transmitter).to receive(:transmit).with([hash_including(
151
+ :identifier => "cron-checkin-name",
152
+ :kind => "finish",
153
+ :check_in_type => "cron"
154
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "499", nil))
155
+
156
+ scheduler.stop
157
+ end
158
+ end
159
+
160
+ describe ".cron" do
161
+ describe "when a block is given" do
162
+ it "should send a cron check-in start and finish and return the block output" do
163
+ expect(scheduler).to receive(:schedule).with(hash_including(
164
+ :kind => "start",
165
+ :identifier => "cron-checkin-with-block",
166
+ :check_in_type => "cron"
167
+ ))
168
+
169
+ expect(scheduler).to receive(:schedule).with(hash_including(
170
+ :kind => "finish",
171
+ :identifier => "cron-checkin-with-block",
172
+ :check_in_type => "cron"
173
+ ))
174
+
175
+ output = Appsignal::CheckIn.cron("cron-checkin-with-block") { "output" }
176
+ expect(output).to eq("output")
177
+ end
178
+
179
+ it "should not send a cron check-in finish event when an error is raised" do
180
+ expect(scheduler).to receive(:schedule).with(hash_including(
181
+ :kind => "start",
182
+ :identifier => "cron-checkin-with-block",
183
+ :check_in_type => "cron"
184
+ ))
185
+
186
+ expect(scheduler).not_to receive(:schedule).with(hash_including(
187
+ :kind => "finish",
188
+ :identifier => "cron-checkin-with-block",
189
+ :check_in_type => "cron"
190
+ ))
191
+
192
+ expect do
193
+ Appsignal::CheckIn.cron("cron-checkin-with-block") { raise "error" }
194
+ end.to raise_error(RuntimeError, "error")
195
+ end
196
+ end
197
+
198
+ describe "when no block is given" do
199
+ it "should only send a cron check-in finish event" do
200
+ expect(scheduler).to receive(:schedule).with(hash_including(
201
+ :kind => "finish",
202
+ :identifier => "cron-checkin-without-block",
203
+ :check_in_type => "cron"
204
+ ))
205
+
206
+ Appsignal::CheckIn.cron("cron-checkin-without-block")
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,484 @@
1
+ describe Appsignal::CheckIn::Scheduler do
2
+ include WaitForHelper
3
+ include TakeAtMostHelper
4
+
5
+ let(:transmitter) { Appsignal::Transmitter.new("http://checkin-endpoint.invalid") }
6
+
7
+ 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)
12
+ # Shorten debounce intervals to make the tests run faster.
13
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 0.1)
14
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 0.1)
15
+ end
16
+
17
+ after do
18
+ subject.stop
19
+ end
20
+
21
+ describe "when no event is sent" do
22
+ it "does not start a thread" do
23
+ expect(subject.thread).to be_nil
24
+ end
25
+
26
+ it "does not schedule a debounce" do
27
+ expect(subject.waker).to be_nil
28
+ end
29
+
30
+ it "can be stopped" do
31
+ # Set all debounce intervals to 10 seconds, to make the assertion
32
+ # fail if it waits for the debounce -- this ensures that what is being
33
+ # tested is that no debounces are awaited when stopping the scheduler.
34
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
35
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
36
+
37
+ take_at_most(0.1) do
38
+ expect { subject.stop }.not_to raise_error
39
+ end
40
+ end
41
+
42
+ it "can be stopped more than once" do
43
+ # Set all debounce intervals to 10 seconds, to make the assertion
44
+ # fail if it waits for the debounce -- this ensures that what is being
45
+ # tested is that no debounces are awaited when stopping the scheduler.
46
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
47
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
48
+
49
+ take_at_most(0.1) do
50
+ expect { subject.stop }.not_to raise_error
51
+ expect { subject.stop }.not_to raise_error
52
+ end
53
+ end
54
+
55
+ it "closes the queue when stopped" do
56
+ subject.stop
57
+ expect(subject.queue.closed?).to be(true)
58
+ end
59
+ end
60
+
61
+ describe "when an event is sent" do
62
+ it "starts a thread" do
63
+ Appsignal::CheckIn.cron("test")
64
+ expect(subject.thread).to be_a(Thread)
65
+ end
66
+
67
+ it "schedules a debounce" do
68
+ Appsignal::CheckIn.cron("test")
69
+ expect(subject.waker).to be_a(Thread)
70
+ end
71
+
72
+ 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)
82
+
83
+ expect(subject.events).to be_empty
84
+
85
+ Appsignal::CheckIn.cron("test")
86
+
87
+ expect(subject.events).not_to be_empty
88
+
89
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
90
+ message.include?("Transmitted cron check-in `test` finish event")
91
+ end)
92
+
93
+ wait_for("the event to be transmitted") { subject.transmitted == 1 }
94
+
95
+ expect(subject.events).to be_empty
96
+ end
97
+
98
+ it "waits for the event to be transmitted when stopped" do
99
+ # Set all debounce intervals to 10 seconds, to make the test
100
+ # fail if it waits for the debounce -- this ensures that what is being
101
+ # tested is that the events are transmitted immediately when the
102
+ # scheduler is stopped, without waiting for any debounce.
103
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
104
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
105
+
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)
115
+
116
+ Appsignal::CheckIn.cron("test")
117
+
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
123
+
124
+ take_at_most(0.1) do
125
+ expect { subject.stop }.not_to raise_error
126
+ end
127
+
128
+ # Check that the thread wasn't killed before the transmission was
129
+ # completed.
130
+ expect(subject.transmitted).to eq(1)
131
+
132
+ expect(subject.events).to be_empty
133
+ end
134
+
135
+ it "can be stopped more than once" do
136
+ # Set all debounce intervals to 10 seconds, to make the test
137
+ # fail if it waits for the debounce -- this ensures that what is being
138
+ # tested is that the events are transmitted immediately when the
139
+ # scheduler is stopped, without waiting for the debounce interval.
140
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
141
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
142
+
143
+ Appsignal::CheckIn.cron("test")
144
+ take_at_most(0.1) do
145
+ expect { subject.stop }.not_to raise_error
146
+ end
147
+
148
+ # Check that the thread wasn't killed before the transmission was
149
+ # completed.
150
+ expect(subject.transmitted).to eq(1)
151
+
152
+ take_at_most(0.1) do
153
+ expect { subject.stop }.not_to raise_error
154
+ end
155
+ end
156
+
157
+ it "closes the queue when stopped" do
158
+ Appsignal::CheckIn.cron("test")
159
+ subject.stop
160
+ expect(subject.queue.closed?).to be(true)
161
+ end
162
+
163
+ it "kills the thread when stopped" do
164
+ Appsignal::CheckIn.cron("test")
165
+ subject.stop
166
+ expect(subject.thread.alive?).to be(false)
167
+ end
168
+
169
+ it "unschedules the debounce when stopped" do
170
+ Appsignal::CheckIn.cron("test")
171
+ waker = subject.waker
172
+ subject.stop
173
+ expect(waker.alive?).to be(false)
174
+ expect(subject.waker).to be_nil
175
+ end
176
+ end
177
+
178
+ describe "when many events are sent" do
179
+ describe "within the short debounce interval" do
180
+ 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
+ )
190
+
191
+ Appsignal::CheckIn.cron("first")
192
+ Appsignal::CheckIn.cron("second")
193
+ Appsignal::CheckIn.cron("third")
194
+
195
+ wait_for("the events to be transmitted") { subject.transmitted == 1 }
196
+ end
197
+
198
+ it "transmits all events at once when stopped" do
199
+ # Set a short debounce interval of 10 seconds, to make the final wait
200
+ # fail if it waits for the debounce -- this ensures that what is being
201
+ # tested is that the events are transmitted when the scheduler is
202
+ # stopped.
203
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
204
+
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
+ )
214
+
215
+ Appsignal::CheckIn.cron("first")
216
+ Appsignal::CheckIn.cron("second")
217
+ Appsignal::CheckIn.cron("third")
218
+
219
+ subject.stop
220
+
221
+ wait_for("the events to be transmitted") { subject.transmitted == 1 }
222
+ end
223
+ end
224
+
225
+ describe "further apart than the short debounce interval" do
226
+ 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)
232
+
233
+ Appsignal::CheckIn.cron("first")
234
+
235
+ wait_for("the first event to be transmitted") { subject.transmitted == 1 }
236
+
237
+ Appsignal::CheckIn.cron("second")
238
+ Appsignal::CheckIn.cron("third")
239
+
240
+ expect(subject.events).to match(["second", "third"].map do |identifier|
241
+ hash_including({
242
+ :identifier => identifier,
243
+ :check_in_type => "cron",
244
+ :kind => "finish"
245
+ })
246
+ end)
247
+ end
248
+
249
+ 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
+
256
+ Appsignal::CheckIn.cron("first")
257
+
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
272
+ )
273
+
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
+ 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
+ Appsignal::CheckIn.cron("third")
285
+
286
+ expect(subject.events).to_not be_empty
287
+
288
+ expect(Appsignal.internal_logger).to receive(:debug).with(
289
+ "Transmitted 2 check-in events"
290
+ )
291
+
292
+ wait_for("the other events to be transmitted") { subject.transmitted == 2 }
293
+
294
+ expect(subject.events).to be_empty
295
+ end
296
+
297
+ it "transmits the other events when stopped" do
298
+ # Restore the original long debounce interval of 10 seconds, to make
299
+ # the final wait fail if it waits for the debounce -- this ensures
300
+ # that what is being tested is that the events are transmitted
301
+ # immediately when the scheduler is stopped.
302
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
303
+
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
+
310
+ Appsignal::CheckIn.cron("first")
311
+
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
326
+ )
327
+
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
+ 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
+ Appsignal::CheckIn.cron("third")
339
+
340
+ expect(subject.events).to_not be_empty
341
+
342
+ expect(Appsignal.internal_logger).to receive(:debug).with(
343
+ "Transmitted 2 check-in events"
344
+ )
345
+
346
+ subject.stop
347
+
348
+ wait_for("the other events to be transmitted") { subject.transmitted == 2 }
349
+
350
+ expect(subject.events).to be_empty
351
+ end
352
+ end
353
+ end
354
+
355
+ describe "when a similar event is sent more than once" do
356
+ it "only transmits one of the similar events" do
357
+ # We must instantiate `Appsignal::CheckIn::Cron` directly, as the
358
+ # `.cron` helper would use a different digest for each invocation.
359
+ cron = Appsignal::CheckIn::Cron.new(:identifier => "test")
360
+
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"
369
+ )
370
+
371
+ cron.start
372
+
373
+ expect(Appsignal.internal_logger).to receive(:debug).with(
374
+ "Scheduling cron check-in `test` start event (digest #{cron.digest}) to be transmitted"
375
+ )
376
+
377
+ expect(Appsignal.internal_logger).to receive(:debug).with(
378
+ "Replacing previously scheduled cron check-in `test` start event (digest #{cron.digest})"
379
+ )
380
+
381
+ cron.start
382
+
383
+ expect(Appsignal.internal_logger).to receive(:debug).with(
384
+ "Transmitted cron check-in `test` start event (digest #{cron.digest})"
385
+ )
386
+
387
+ wait_for("the event to be transmitted") { subject.transmitted == 1 }
388
+ end
389
+ end
390
+
391
+ describe "when the scheduler is stopped" do
392
+ 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)
401
+
402
+ Appsignal::CheckIn.cron("test")
403
+
404
+ expect(subject.events).to be_empty
405
+ end
406
+ end
407
+
408
+ 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)
411
+
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)
418
+
419
+ Appsignal::CheckIn.cron("test")
420
+
421
+ expect(subject.events).to be_empty
422
+ end
423
+ end
424
+
425
+ describe "when transmitting returns a non-success response code" do
426
+ it "logs the error and continues" do
427
+ expect(transmitter).to receive(:transmit).and_return(
428
+ Net::HTTPNotFound.new("1.1", 404, "Not Found")
429
+ )
430
+
431
+ Appsignal::CheckIn.cron("first")
432
+
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 }
439
+
440
+ expect(transmitter).to receive(:transmit).and_return(
441
+ Net::HTTPSuccess.new("1.1", 200, "OK")
442
+ )
443
+
444
+ Appsignal::CheckIn.cron("second")
445
+
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)
451
+
452
+ wait_for("the second event to be transmitted") { subject.transmitted == 2 }
453
+ end
454
+ end
455
+
456
+ describe "when transmitting throws an error" do
457
+ it "logs the error and continues" do
458
+ expect(transmitter).to receive(:transmit).and_raise("Something went wrong")
459
+
460
+ Appsignal::CheckIn.cron("first")
461
+
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)
466
+
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")
471
+ )
472
+
473
+ Appsignal::CheckIn.cron("second")
474
+
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)
480
+
481
+ wait_for("the second event to be transmitted") { subject.transmitted == 2 }
482
+ end
483
+ end
484
+ end