appsignal 3.12.5 → 3.13.0

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.
@@ -0,0 +1,342 @@
1
+ describe Appsignal::Heartbeat do
2
+ let(:err_stream) { std_stream }
3
+
4
+ after do
5
+ Appsignal.instance_variable_set(:@heartbeat_constant_deprecation_warning_emitted, false)
6
+ end
7
+
8
+ it "returns the Cron constant calling the Heartbeat constant" do
9
+ silence { expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron) }
10
+ end
11
+
12
+ it "prints a deprecation warning to STDERR" do
13
+ capture_std_streams(std_stream, err_stream) do
14
+ expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
15
+ end
16
+
17
+ expect(err_stream.read)
18
+ .to include("appsignal WARNING: The constant Appsignal::Heartbeat has been deprecated.")
19
+ end
20
+
21
+ it "does not print a deprecation warning to STDERR more than once" do
22
+ capture_std_streams(std_stream, err_stream) do
23
+ expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
24
+ end
25
+
26
+ expect(err_stream.read)
27
+ .to include("appsignal WARNING: The constant Appsignal::Heartbeat has been deprecated.")
28
+
29
+ err_stream.truncate(0)
30
+
31
+ capture_std_streams(std_stream, err_stream) do
32
+ expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
33
+ end
34
+
35
+ expect(err_stream.read)
36
+ .not_to include("appsignal WARNING: The constant Appsignal::Heartbeat has been deprecated.")
37
+ end
38
+
39
+ it "logs a warning" do
40
+ logs =
41
+ capture_logs do
42
+ silence do
43
+ expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
44
+ end
45
+ end
46
+
47
+ expect(logs).to contains_log(
48
+ :warn,
49
+ "The constant Appsignal::Heartbeat has been deprecated."
50
+ )
51
+ end
52
+
53
+ it "does not log a warning more than once" do
54
+ logs =
55
+ capture_logs do
56
+ silence do
57
+ expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
58
+ end
59
+ end
60
+
61
+ expect(logs).to contains_log(
62
+ :warn,
63
+ "The constant Appsignal::Heartbeat has been deprecated."
64
+ )
65
+
66
+ logs =
67
+ capture_logs do
68
+ silence do
69
+ expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
70
+ end
71
+ end
72
+
73
+ expect(logs).not_to contains_log(
74
+ :warn,
75
+ "The constant Appsignal::Heartbeat has been deprecated."
76
+ )
77
+ end
78
+ end
79
+
80
+ describe "Appsignal.heartbeat" do
81
+ let(:err_stream) { std_stream }
82
+
83
+ before do
84
+ Appsignal.instance_variable_set(:@heartbeat_helper_deprecation_warning_emitted, false)
85
+ end
86
+
87
+ it "should forward the call to Appsignal::CheckIn.cron" do
88
+ expect(Appsignal::CheckIn).to receive(:cron).with("heartbeat-name")
89
+ expect do
90
+ Appsignal.heartbeat("heartbeat-name")
91
+ end.not_to raise_error
92
+
93
+ block = proc { 42 }
94
+ expect(Appsignal::CheckIn).to receive(:cron).with("heartbeat-name") do |&given_block|
95
+ expect(given_block).to be(block)
96
+ end.and_return("output")
97
+ expect(Appsignal.heartbeat("heartbeat-name", &block)).to eq("output")
98
+ end
99
+
100
+ it "prints a deprecation warning to STDERR" do
101
+ capture_std_streams(std_stream, err_stream) do
102
+ Appsignal.heartbeat("heartbeat-name")
103
+ end
104
+
105
+ expect(err_stream.read)
106
+ .to include("appsignal WARNING: The helper Appsignal.heartbeat has been deprecated.")
107
+ end
108
+
109
+ it "does not print a deprecation warning to STDERR more than once" do
110
+ capture_std_streams(std_stream, err_stream) do
111
+ Appsignal.heartbeat("heartbeat-name")
112
+ end
113
+
114
+ expect(err_stream.read)
115
+ .to include("appsignal WARNING: The helper Appsignal.heartbeat has been deprecated.")
116
+
117
+ err_stream.truncate(0)
118
+
119
+ capture_std_streams(std_stream, err_stream) do
120
+ Appsignal.heartbeat("heartbeat-name")
121
+ end
122
+
123
+ expect(err_stream.read)
124
+ .not_to include("appsignal WARNING: The helper Appsignal.heartbeat has been deprecated.")
125
+ end
126
+
127
+ it "logs a warning" do
128
+ logs =
129
+ capture_logs do
130
+ silence do
131
+ Appsignal.heartbeat("heartbeat-name")
132
+ end
133
+ end
134
+
135
+ expect(logs).to contains_log(
136
+ :warn,
137
+ "The helper Appsignal.heartbeat has been deprecated."
138
+ )
139
+ end
140
+
141
+ it "does not log a warning more than once" do
142
+ logs =
143
+ capture_logs do
144
+ silence do
145
+ Appsignal.heartbeat("heartbeat-name")
146
+ end
147
+ end
148
+
149
+ expect(logs).to contains_log(
150
+ :warn,
151
+ "The helper Appsignal.heartbeat has been deprecated."
152
+ )
153
+
154
+ logs =
155
+ capture_logs do
156
+ silence do
157
+ Appsignal.heartbeat("heartbeat-name")
158
+ end
159
+ end
160
+
161
+ expect(logs).not_to contains_log(
162
+ :warn,
163
+ "The helper Appsignal.heartbeat has been deprecated."
164
+ )
165
+ end
166
+ end
167
+
168
+ describe Appsignal::CheckIn::Cron do
169
+ let(:config) { project_fixture_config }
170
+ let(:cron_checkin) { described_class.new(:name => "cron-checkin-name") }
171
+ let(:transmitter) { Appsignal::Transmitter.new("http://cron_checkins/", config) }
172
+
173
+ before(:each) do
174
+ allow(Appsignal).to receive(:active?).and_return(true)
175
+ config.logger = Logger.new(StringIO.new)
176
+ allow(Appsignal::CheckIn::Cron).to receive(:transmitter).and_return(transmitter)
177
+ end
178
+
179
+ describe "when Appsignal is not active" do
180
+ it "should not transmit any events" do
181
+ allow(Appsignal).to receive(:active?).and_return(false)
182
+ expect(transmitter).not_to receive(:transmit)
183
+
184
+ cron_checkin.start
185
+ cron_checkin.finish
186
+ end
187
+ end
188
+
189
+ describe "#start" do
190
+ it "should send a cron check-in start" do
191
+ expect(transmitter).to receive(:transmit).with(hash_including(
192
+ :identifier => "cron-checkin-name",
193
+ :kind => "start",
194
+ :check_in_type => "cron"
195
+ )).and_return(Net::HTTPResponse.new(nil, "200", nil))
196
+
197
+ expect(Appsignal.internal_logger).to receive(:debug).with(
198
+ "Transmitted cron check-in `cron-checkin-name` (#{cron_checkin.digest}) start event"
199
+ )
200
+ expect(Appsignal.internal_logger).not_to receive(:error)
201
+
202
+ cron_checkin.start
203
+ end
204
+
205
+ it "should log an error if it fails" do
206
+ expect(transmitter).to receive(:transmit).with(hash_including(
207
+ :identifier => "cron-checkin-name",
208
+ :kind => "start",
209
+ :check_in_type => "cron"
210
+ )).and_return(Net::HTTPResponse.new(nil, "499", nil))
211
+
212
+ expect(Appsignal.internal_logger).not_to receive(:debug)
213
+ expect(Appsignal.internal_logger).to receive(:error).with(
214
+ "Failed to transmit cron check-in start event: status code was 499"
215
+ )
216
+
217
+ cron_checkin.start
218
+ end
219
+ end
220
+
221
+ describe "#finish" do
222
+ it "should send a cron check-in finish" do
223
+ expect(transmitter).to receive(:transmit).with(hash_including(
224
+ :identifier => "cron-checkin-name",
225
+ :kind => "finish",
226
+ :check_in_type => "cron"
227
+ )).and_return(Net::HTTPResponse.new(nil, "200", nil))
228
+
229
+ expect(Appsignal.internal_logger).to receive(:debug).with(
230
+ "Transmitted cron check-in `cron-checkin-name` (#{cron_checkin.digest}) finish event"
231
+ )
232
+ expect(Appsignal.internal_logger).not_to receive(:error)
233
+
234
+ cron_checkin.finish
235
+ end
236
+
237
+ it "should log an error if it fails" do
238
+ expect(transmitter).to receive(:transmit).with(hash_including(
239
+ :identifier => "cron-checkin-name",
240
+ :kind => "finish",
241
+ :check_in_type => "cron"
242
+ )).and_return(Net::HTTPResponse.new(nil, "499", nil))
243
+
244
+ expect(Appsignal.internal_logger).not_to receive(:debug)
245
+ expect(Appsignal.internal_logger).to receive(:error).with(
246
+ "Failed to transmit cron check-in finish event: status code was 499"
247
+ )
248
+
249
+ cron_checkin.finish
250
+ end
251
+ end
252
+
253
+ describe ".cron" do
254
+ describe "when a block is given" do
255
+ it "should send a cron check-in start and finish and return the block output" do
256
+ expect(transmitter).to receive(:transmit).with(hash_including(
257
+ :kind => "start",
258
+ :identifier => "cron-checkin-with-block",
259
+ :check_in_type => "cron"
260
+ )).and_return(nil)
261
+
262
+ expect(transmitter).to receive(:transmit).with(hash_including(
263
+ :kind => "finish",
264
+ :identifier => "cron-checkin-with-block",
265
+ :check_in_type => "cron"
266
+ )).and_return(nil)
267
+
268
+ output = Appsignal::CheckIn.cron("cron-checkin-with-block") { "output" }
269
+ expect(output).to eq("output")
270
+ end
271
+
272
+ it "should not send a cron check-in finish event when an error is raised" do
273
+ expect(transmitter).to receive(:transmit).with(hash_including(
274
+ :kind => "start",
275
+ :identifier => "cron-checkin-with-block",
276
+ :check_in_type => "cron"
277
+ )).and_return(nil)
278
+
279
+ expect(transmitter).not_to receive(:transmit).with(hash_including(
280
+ :kind => "finish",
281
+ :identifier => "cron-checkin-with-block",
282
+ :check_in_type => "cron"
283
+ ))
284
+
285
+ expect do
286
+ Appsignal::CheckIn.cron("cron-checkin-with-block") { raise "error" }
287
+ end.to raise_error(RuntimeError, "error")
288
+ end
289
+ end
290
+
291
+ describe "when no block is given" do
292
+ it "should only send a cron check-in finish event" do
293
+ expect(transmitter).to receive(:transmit).with(hash_including(
294
+ :kind => "finish",
295
+ :identifier => "cron-checkin-without-block",
296
+ :check_in_type => "cron"
297
+ )).and_return(nil)
298
+
299
+ Appsignal::CheckIn.cron("cron-checkin-without-block")
300
+ end
301
+ end
302
+ end
303
+
304
+ describe "#initialize" do
305
+ describe "when initialised with deprecated heartbeat keyword names" do
306
+ let(:err_stream) { std_stream }
307
+
308
+ after do
309
+ described_class.instance_variable_set(:@initializer_deprecation_warning_emitted, false)
310
+ end
311
+
312
+ it "can be initialised" do
313
+ cron_checkin = described_class.new(:name => "cron-checkin-name")
314
+ expect(cron_checkin.identifier).to eq("cron-checkin-name")
315
+ end
316
+
317
+ it "logs a deprecation warning" do
318
+ capture_std_streams(std_stream, err_stream) do
319
+ expect(described_class.new(:name => "cron-checkin-name"))
320
+ .to be_a(Appsignal::CheckIn::Cron)
321
+ end
322
+
323
+ expect(err_stream.read)
324
+ .to include(
325
+ "appsignal WARNING: Passing a `name` keyword argument to " \
326
+ "`Appsignal::CheckIn::Cron.new` is deprecated."
327
+ )
328
+ end
329
+ end
330
+
331
+ it "can be initialised with cron check-in keyword names" do
332
+ cron_checkin = described_class.new(:identifier => "cron-checkin-name")
333
+ expect(cron_checkin.identifier).to eq("cron-checkin-name")
334
+ end
335
+
336
+ it "raises an error when no identifier is given" do
337
+ expect do
338
+ described_class.new
339
+ end.to raise_error(ArgumentError, "missing keyword: :identifier")
340
+ end
341
+ end
342
+ end
@@ -30,7 +30,7 @@ describe Appsignal::CLI::Install do
30
30
 
31
31
  define :include_complete_install do
32
32
  match do |actual|
33
- actual.include?("AppSignal installation complete")
33
+ actual.include?("Please return to your browser and follow the instructions.")
34
34
  end
35
35
  end
36
36
 
@@ -105,7 +105,7 @@ describe Appsignal::CLI::Install do
105
105
  run
106
106
 
107
107
  expect(output).to include "Problem encountered:",
108
- "No push API key entered"
108
+ "No Push API key entered"
109
109
  end
110
110
  end
111
111
 
@@ -120,7 +120,7 @@ describe Appsignal::CLI::Install do
120
120
  choose_environment_config
121
121
  run
122
122
 
123
- expect(output).to include("Validating API key...", "API key valid")
123
+ expect(output).to include("Validating Push API key...", "Push API key valid")
124
124
  end
125
125
  end
126
126
 
@@ -129,7 +129,7 @@ describe Appsignal::CLI::Install do
129
129
 
130
130
  it "prints an error" do
131
131
  run
132
- expect(output).to include "API key 'my_key' is not valid"
132
+ expect(output).to include "Push API key 'my_key' is not valid"
133
133
  end
134
134
  end
135
135
 
@@ -140,7 +140,7 @@ describe Appsignal::CLI::Install do
140
140
 
141
141
  it "prints an error" do
142
142
  run
143
- expect(output).to include "There was an error validating your API key"
143
+ expect(output).to include "There was an error validating your Push API key"
144
144
  end
145
145
  end
146
146
  end
@@ -419,14 +419,16 @@ describe Appsignal::CLI::Install do
419
419
  expect(File.exist?(File.join(config_dir, "application.rb"))).to eql(false)
420
420
  end
421
421
 
422
- it "fails the installation" do
422
+ it "falls back on the unknown framework installation" do
423
+ enter_app_name app_name
424
+ choose_environment_config
423
425
  run
424
426
 
425
- expect(output).to include("We could not detect which framework you are using.")
427
+ expect(output)
428
+ .to include("\e[31mWarning: We could not detect which framework you are using\e[0m")
426
429
  expect(output).to_not include("Installing for Ruby on Rails")
430
+ expect(output).to include_env_push_api_key(push_api_key)
427
431
  expect(output).to include_complete_install
428
-
429
- expect(File.exist?(config_file_path)).to be(false)
430
432
  end
431
433
  end
432
434
 
@@ -465,8 +467,10 @@ describe Appsignal::CLI::Install do
465
467
  let(:installation_instructions) do
466
468
  [
467
469
  "Installing for Sinatra",
468
- "Sinatra requires some manual configuration.",
469
- "require 'appsignal/integrations/sinatra'",
470
+ "Sinatra apps requires some manual setup.",
471
+ %(require "appsignal"),
472
+ "Appsignal.load(:sinatra)",
473
+ "Appsignal.start",
470
474
  "https://docs.appsignal.com/ruby/integrations/sinatra.html"
471
475
  ]
472
476
  end
@@ -533,7 +537,10 @@ describe Appsignal::CLI::Install do
533
537
  let(:installation_instructions) do
534
538
  [
535
539
  "Installing for Padrino",
536
- "Padrino requires some manual configuration.",
540
+ "Padrino apps requires some manual setup.",
541
+ %(require "appsignal"),
542
+ "Appsignal.load(:padrino)",
543
+ "Appsignal.start",
537
544
  "https://docs.appsignal.com/ruby/integrations/padrino.html"
538
545
  ]
539
546
  end
@@ -600,7 +607,7 @@ describe Appsignal::CLI::Install do
600
607
  let(:installation_instructions) do
601
608
  [
602
609
  "Installing for Grape",
603
- "Manual Grape configuration needed",
610
+ "Grape apps require some manual setup.",
604
611
  "https://docs.appsignal.com/ruby/integrations/grape.html"
605
612
  ]
606
613
  end
@@ -624,6 +631,7 @@ describe Appsignal::CLI::Install do
624
631
  it "completes the installation" do
625
632
  run
626
633
 
634
+ puts output
627
635
  expect(output).to include(*installation_instructions)
628
636
  expect(output).to include_complete_install
629
637
  end
@@ -667,7 +675,10 @@ describe Appsignal::CLI::Install do
667
675
  let(:installation_instructions) do
668
676
  [
669
677
  "Installing for Hanami",
670
- "Hanami requires some manual configuration.",
678
+ "Hanami apps requires some manual setup.",
679
+ %(require "appsignal"),
680
+ "Appsignal.load(:hanami)",
681
+ "Appsignal.start",
671
682
  "https://docs.appsignal.com/ruby/integrations/hanami.html"
672
683
  ]
673
684
  end
@@ -728,47 +739,109 @@ describe Appsignal::CLI::Install do
728
739
  !hanami2_present?
729
740
  context "with unknown framework" do
730
741
  let(:push_api_key) { "my_key" }
742
+ let(:app_name) { "Test app" }
731
743
 
732
- it_behaves_like "windows installation"
733
744
  it_behaves_like "push_api_key validation"
734
- it_behaves_like "demo data"
745
+ it_behaves_like "requires an application name"
746
+
747
+ describe "unknown framework specific tests" do
748
+ let(:installation_instructions) do
749
+ [
750
+ "Installing",
751
+ "\e[31mWarning: We could not detect which framework you are using\e[0m",
752
+ "Some manual installation is most likely required.",
753
+ "https://docs.appsignal.com/ruby/integrations.html"
754
+ ]
755
+ end
756
+ before { enter_app_name app_name }
735
757
 
736
- context "without color options" do
737
- let(:options) { {} }
758
+ describe "configuration with environment variables" do
759
+ before { choose_environment_config }
738
760
 
739
- it "prints the instructions in color" do
740
- run
741
- expect(output).to have_colorized_text(:green, "## Starting AppSignal Installer ##")
761
+ it_behaves_like "windows installation"
762
+ it_behaves_like "capistrano install"
763
+ it_behaves_like "demo data"
764
+
765
+ it "prints environment variables" do
766
+ run
767
+
768
+ expect(output).to include_env_push_api_key(push_api_key)
769
+ expect(output).to include_env_app_name(app_name)
770
+ end
771
+
772
+ it "completes the installation" do
773
+ run
774
+
775
+ expect(output).to include(*installation_instructions)
776
+ expect(output).to include_complete_install
777
+ end
742
778
  end
743
- end
744
779
 
745
- context "with --color option" do
746
- let(:options) { { "color" => nil } }
780
+ describe "configure with a configuration file" do
781
+ before { choose_config_file }
747
782
 
748
- it "prints the instructions in color" do
749
- run
750
- expect(output).to have_colorized_text(:green, "## Starting AppSignal Installer ##")
783
+ it_behaves_like "windows installation"
784
+ it_behaves_like "capistrano install"
785
+ it_behaves_like "demo data"
786
+
787
+ it "writes configuration to file" do
788
+ run
789
+ expect(output).to include_file_config
790
+ expect(config_file).to configure_app_name(app_name)
791
+ expect(config_file).to configure_push_api_key(push_api_key)
792
+ expect(config_file).to configure_environment("development")
793
+ expect(config_file).to configure_environment("staging")
794
+ expect(config_file).to configure_environment("production")
795
+ end
796
+
797
+ it "completes the installation" do
798
+ run
799
+
800
+ expect(output).to include(*installation_instructions)
801
+ expect(output).to include_complete_install
802
+ end
751
803
  end
752
804
  end
753
805
 
754
- context "with --no-color option" do
755
- let(:options) { { "no-color" => nil } }
806
+ describe "color flag" do
807
+ before do
808
+ enter_app_name "Test app"
809
+ choose_environment_config
810
+ end
756
811
 
757
- it "prints the instructions without special colors" do
758
- run
759
- expect(output).to include("Starting AppSignal Installer")
760
- expect(output).to_not have_color_markers
812
+ context "without color options" do
813
+ let(:options) { {} }
814
+
815
+ it "prints the instructions in color" do
816
+ run
817
+ expect(output).to have_colorized_text(
818
+ :green,
819
+ "## Starting AppSignal Installer ##"
820
+ )
821
+ end
761
822
  end
762
- end
763
823
 
764
- it "prints a message about unknown framework" do
765
- run
824
+ context "with --color option" do
825
+ let(:options) { { "color" => nil } }
766
826
 
767
- expect(output).to include \
768
- "\e[31mWarning:\e[0m We could not detect which framework you are using."
769
- expect(output).to_not include_env_push_api_key
770
- expect(output).to_not include_env_app_name
771
- expect(File.exist?(config_file_path)).to be_falsy
827
+ it "prints the instructions in color" do
828
+ run
829
+ expect(output).to have_colorized_text(
830
+ :green,
831
+ "## Starting AppSignal Installer ##"
832
+ )
833
+ end
834
+ end
835
+
836
+ context "with --no-color option" do
837
+ let(:options) { { "no-color" => nil } }
838
+
839
+ it "prints the instructions without special colors" do
840
+ run
841
+ expect(output).to include("## Starting AppSignal Installer ##")
842
+ expect(output).to_not have_color_markers
843
+ end
844
+ end
772
845
  end
773
846
  end
774
847
  end
@@ -1439,5 +1439,29 @@ describe Appsignal::Config do
1439
1439
 
1440
1440
  expect(dsl.cpu_count).to eq(1.0)
1441
1441
  end
1442
+
1443
+ describe "#app_path=" do
1444
+ it "prints a deprecation warning" do
1445
+ err_stream = std_stream
1446
+ capture_std_streams(std_stream, err_stream) do
1447
+ dsl.app_path = "foo"
1448
+ end
1449
+
1450
+ expect(err_stream.read).to include(
1451
+ "appsignal WARNING: The `Appsignal.configure`'s `app_path=` writer is deprecated"
1452
+ )
1453
+ end
1454
+
1455
+ it "logs a deprecation warning" do
1456
+ logs = capture_logs do
1457
+ silence { dsl.app_path = "foo" }
1458
+ end
1459
+
1460
+ expect(logs).to contains_log(
1461
+ :warn,
1462
+ "The `Appsignal.configure`'s `app_path=` writer is deprecated"
1463
+ )
1464
+ end
1465
+ end
1442
1466
  end
1443
1467
  end
@@ -67,27 +67,6 @@ if DependencyHelper.http_present?
67
67
  end
68
68
  end
69
69
 
70
- context "with an HTTP exception" do
71
- let(:error) { ExampleException.new("oh no!") }
72
-
73
- it "reports the exception and re-raises it" do
74
- stub_request(:get, "https://www.google.com").and_raise(error)
75
-
76
- expect do
77
- HTTP.get("https://www.google.com")
78
- end.to raise_error(ExampleException)
79
-
80
- expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
81
- expect(transaction).to include_event(
82
- "body" => "",
83
- "body_format" => Appsignal::EventFormatter::DEFAULT,
84
- "name" => "request.http_rb",
85
- "title" => "GET https://www.google.com"
86
- )
87
- expect(transaction).to have_error(error.class.name, error.message)
88
- end
89
- end
90
-
91
70
  context "with various URI objects" do
92
71
  it "parses an object responding to #to_s" do
93
72
  request_uri = Struct.new(:uri) do