appsignal 2.8.0.alpha.1 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,28 +1,39 @@
1
1
  describe Appsignal::Config do
2
2
  describe "#initialize" do
3
- subject { config.env }
4
-
5
3
  describe "environment" do
6
4
  context "when environment is nil" do
7
- let(:config) { described_class.new("", "") }
5
+ let(:config) { described_class.new("", nil) }
8
6
 
9
7
  it "sets an empty string" do
10
- expect(subject).to eq("")
8
+ expect(config.env).to eq("")
11
9
  end
12
10
  end
13
11
 
14
12
  context "when environment is given" do
13
+ let(:env) { "my_env" }
15
14
  let(:config) { described_class.new("", "my_env") }
16
15
 
17
16
  it "sets the environment" do
18
- expect(subject).to eq("my_env")
17
+ expect(config.env).to eq(env)
18
+ end
19
+
20
+ it "sets the environment as loaded through the initial_config" do
21
+ expect(config.initial_config).to eq(:env => env)
22
+ expect(config.config_hash).to_not have_key(:env)
19
23
  end
20
24
 
21
25
  context "with APPSIGNAL_APP_ENV environment variable" do
22
- before { ENV["APPSIGNAL_APP_ENV"] = "my_env_env" }
26
+ let(:env_env) { "my_env_env" }
27
+ before { ENV["APPSIGNAL_APP_ENV"] = env_env }
23
28
 
24
29
  it "uses the environment variable" do
25
- expect(subject).to eq("my_env_env")
30
+ expect(config.env).to eq(env_env)
31
+ end
32
+
33
+ it "sets the environment as loaded through the env_config" do
34
+ expect(config.initial_config).to eq(:env => env)
35
+ expect(config.env_config).to eq(:env => env_env)
36
+ expect(config.config_hash).to_not have_key(:env)
26
37
  end
27
38
  end
28
39
  end
@@ -41,6 +52,11 @@ describe Appsignal::Config do
41
52
  it "becomes active" do
42
53
  expect(subject).to be_truthy
43
54
  end
55
+
56
+ it "sets the push_api_key as loaded through the env_config" do
57
+ expect(config.env_config).to eq(:push_api_key => "abc")
58
+ expect(config.system_config).to eq(:active => true)
59
+ end
44
60
  end
45
61
 
46
62
  context "without APPSIGNAL_PUSH_API_KEY env variable" do
@@ -59,27 +75,36 @@ describe Appsignal::Config do
59
75
  it "is set to stdout" do
60
76
  expect(subject).to eq("stdout")
61
77
  end
78
+
79
+ it "sets the log as loaded through the system" do
80
+ expect(config.system_config).to eq(:log => "stdout")
81
+ end
62
82
  end
63
83
 
64
84
  context "when not running on Heroku" do
65
85
  it "is set to file" do
66
86
  expect(subject).to eq("file")
67
87
  end
88
+
89
+ it "does not set log as loaded through the system" do
90
+ expect(config.system_config).to eq({})
91
+ end
68
92
  end
69
93
  end
70
94
  end
71
95
 
72
96
  describe "initial config" do
73
- let(:config) do
74
- described_class.new(
75
- "non-existing-path",
76
- "production",
97
+ let(:initial_config) do
98
+ {
77
99
  :push_api_key => "abc",
78
100
  :name => "TestApp",
79
101
  :active => true,
80
102
  :revision => "v2.5.1",
81
103
  :request_headers => []
82
- )
104
+ }
105
+ end
106
+ let(:config) do
107
+ described_class.new("non-existing-path", "production", initial_config)
83
108
  end
84
109
 
85
110
  it "merges with the default config" do
@@ -114,6 +139,10 @@ describe Appsignal::Config do
114
139
  )
115
140
  end
116
141
 
142
+ it "sets the initial_config" do
143
+ expect(config.initial_config).to eq(initial_config)
144
+ end
145
+
117
146
  describe "overriding system detected config" do
118
147
  describe ":running_in_container" do
119
148
  let(:config) do
@@ -183,6 +212,16 @@ describe Appsignal::Config do
183
212
  config
184
213
  end
185
214
 
215
+ it "sets the file_config" do
216
+ # config found in spec/support/project_fixture/config/appsignal.yml
217
+ expect(config.file_config).to match(
218
+ :active => true,
219
+ :push_api_key => "abc",
220
+ :name => "TestApp",
221
+ :request_headers => kind_of(Array)
222
+ )
223
+ end
224
+
186
225
  describe "overriding system and defaults config" do
187
226
  let(:config) do
188
227
  described_class.new(
@@ -228,8 +267,11 @@ describe Appsignal::Config do
228
267
  end
229
268
 
230
269
  describe "support for old config keys" do
270
+ let(:out_stream) { std_stream }
271
+ let(:output) { out_stream.read }
231
272
  let(:config) { project_fixture_config(env, {}, test_logger(log)) }
232
273
  let(:log) { StringIO.new }
274
+ before { capture_stdout(out_stream) { config } }
233
275
 
234
276
  describe ":api_key" do
235
277
  context "without :push_api_key" do
@@ -238,8 +280,10 @@ describe Appsignal::Config do
238
280
  it "sets the :push_api_key with the old :api_key value" do
239
281
  expect(config[:push_api_key]).to eq "def"
240
282
  expect(config.config_hash).to_not have_key :api_key
241
- expect(log_contents(log)).to contains_log :warn,
242
- "Old configuration key found. Please update the 'api_key' to 'push_api_key'"
283
+
284
+ message = "Old configuration key found. Please update the 'api_key' to 'push_api_key'"
285
+ expect(output).to include "appsignal WARNING: #{message}"
286
+ expect(log_contents(log)).to contains_log :warn, message
243
287
  end
244
288
  end
245
289
 
@@ -249,8 +293,10 @@ describe Appsignal::Config do
249
293
  it "ignores the :api_key config and deletes it" do
250
294
  expect(config[:push_api_key]).to eq "ghi"
251
295
  expect(config.config_hash).to_not have_key :api_key
252
- expect(log_contents(log)).to contains_log :warn,
253
- "Old configuration key found. Please update the 'api_key' to 'push_api_key'"
296
+
297
+ message = "Old configuration key found. Please update the 'api_key' to 'push_api_key'"
298
+ expect(output).to include "appsignal WARNING: #{message}"
299
+ expect(log_contents(log)).to contains_log :warn, message
254
300
  end
255
301
  end
256
302
  end
@@ -262,8 +308,10 @@ describe Appsignal::Config do
262
308
  it "sets :ignore_errors with the old :ignore_exceptions value" do
263
309
  expect(config[:ignore_errors]).to eq ["StandardError"]
264
310
  expect(config.config_hash).to_not have_key :ignore_exceptions
265
- expect(log_contents(log)).to contains_log :warn,
266
- "Old configuration key found. Please update the 'ignore_exceptions' to 'ignore_errors'"
311
+
312
+ message = "Old configuration key found. Please update the 'ignore_exceptions' to 'ignore_errors'"
313
+ expect(output).to include "appsignal WARNING: #{message}"
314
+ expect(log_contents(log)).to contains_log :warn, message
267
315
  end
268
316
  end
269
317
 
@@ -273,8 +321,10 @@ describe Appsignal::Config do
273
321
  it "ignores the :ignore_exceptions config" do
274
322
  expect(config[:ignore_errors]).to eq ["NoMethodError"]
275
323
  expect(config.config_hash).to_not have_key :ignore_exceptions
276
- expect(log_contents(log)).to contains_log :warn,
277
- "Old configuration key found. Please update the 'ignore_exceptions' to 'ignore_errors'"
324
+
325
+ message = "Old configuration key found. Please update the 'ignore_exceptions' to 'ignore_errors'"
326
+ expect(output).to include "appsignal WARNING: #{message}"
327
+ expect(log_contents(log)).to contains_log :warn, message
278
328
  end
279
329
  end
280
330
  end
@@ -290,6 +340,24 @@ describe Appsignal::Config do
290
340
  :debug => true
291
341
  )
292
342
  end
343
+ let(:env_config) do
344
+ {
345
+ :running_in_container => true,
346
+ :push_api_key => "aaa-bbb-ccc",
347
+ :active => true,
348
+ :name => "App name",
349
+ :debug => true,
350
+ :ignore_actions => %w[action1 action2],
351
+ :ignore_errors => %w[ExampleStandardError AnotherError],
352
+ :ignore_namespaces => %w[admin private_namespace],
353
+ :instrument_net_http => false,
354
+ :instrument_redis => false,
355
+ :instrument_sequel => false,
356
+ :files_world_accessible => false,
357
+ :request_headers => %w[accept accept-charset],
358
+ :revision => "v2.5.1"
359
+ }
360
+ end
293
361
  before do
294
362
  ENV["APPSIGNAL_RUNNING_IN_CONTAINER"] = "true"
295
363
  ENV["APPSIGNAL_PUSH_API_KEY"] = "aaa-bbb-ccc"
@@ -310,21 +378,7 @@ describe Appsignal::Config do
310
378
  it "overrides config with environment values" do
311
379
  expect(config.valid?).to be_truthy
312
380
  expect(config.active?).to be_truthy
313
-
314
- expect(config[:running_in_container]).to be_truthy
315
- expect(config[:push_api_key]).to eq "aaa-bbb-ccc"
316
- expect(config[:active]).to eq(true)
317
- expect(config[:name]).to eq "App name"
318
- expect(config[:debug]).to eq(true)
319
- expect(config[:ignore_actions]).to eq %w[action1 action2]
320
- expect(config[:ignore_errors]).to eq %w[ExampleStandardError AnotherError]
321
- expect(config[:ignore_namespaces]).to eq %w[admin private_namespace]
322
- expect(config[:instrument_net_http]).to eq(false)
323
- expect(config[:instrument_redis]).to eq(false)
324
- expect(config[:instrument_sequel]).to eq(false)
325
- expect(config[:files_world_accessible]).to eq(false)
326
- expect(config[:request_headers]).to eq(%w[accept accept-charset])
327
- expect(config[:revision]).to eq("v2.5.1")
381
+ expect(config.config_hash).to include(env_config)
328
382
  end
329
383
 
330
384
  context "with mixed case `true` env variables values" do
@@ -338,6 +392,10 @@ describe Appsignal::Config do
338
392
  expect(config[:instrument_sequel]).to eq(true)
339
393
  end
340
394
  end
395
+
396
+ it "sets the env_config" do
397
+ expect(config.env_config).to eq(env_config)
398
+ end
341
399
  end
342
400
 
343
401
  describe "config keys" do
@@ -432,7 +490,6 @@ describe Appsignal::Config do
432
490
  expect(ENV["_APPSIGNAL_IGNORE_ACTIONS"]).to eq "action1,action2"
433
491
  expect(ENV["_APPSIGNAL_IGNORE_ERRORS"]).to eq "ExampleStandardError,AnotherError"
434
492
  expect(ENV["_APPSIGNAL_IGNORE_NAMESPACES"]).to eq "admin,private_namespace"
435
- expect(ENV["_APPSIGNAL_SEND_PARAMS"]).to eq "true"
436
493
  expect(ENV["_APPSIGNAL_RUNNING_IN_CONTAINER"]).to eq "false"
437
494
  expect(ENV["_APPSIGNAL_ENABLE_HOST_METRICS"]).to eq "true"
438
495
  expect(ENV["_APPSIGNAL_ENABLE_MINUTELY_PROBES"]).to eq "false"
@@ -35,7 +35,7 @@ describe Appsignal::EventFormatter::ElasticSearch::SearchFormatter do
35
35
  }
36
36
  end
37
37
 
38
- it "should sanitize non-whitelisted params" do
38
+ it "should sanitize non-allowlisted params" do
39
39
  expect(
40
40
  formatter.sanitized_search(search)
41
41
  ).to eql(:index => "users", :type => "user", :q => "?", :other => "?")
@@ -46,6 +46,9 @@ describe Appsignal::EventFormatter do
46
46
  end
47
47
 
48
48
  context "registering and unregistering formatters" do
49
+ let(:out_stream) { std_stream }
50
+ let(:output) { out_stream.read }
51
+
49
52
  it "registers a formatter" do
50
53
  expect(klass.formatters["mock"]).to be_instance_of(MockFormatter)
51
54
  end
@@ -92,19 +95,21 @@ describe Appsignal::EventFormatter do
92
95
  end
93
96
 
94
97
  it "does not register deprecated formatters" do
95
- expect(Appsignal.logger).to receive(:warn)
96
- .with("Formatter for 'mock.deprecated' is using a deprecated registration method. " \
97
- "This event formatter will not be loaded. " \
98
- "Please update the formatter according to the documentation at: " \
99
- "https://docs.appsignal.com/ruby/instrumentation/event-formatters.html")
98
+ message = "Formatter for 'mock.deprecated' is using a deprecated registration method. " \
99
+ "This event formatter will not be loaded. " \
100
+ "Please update the formatter according to the documentation at: " \
101
+ "https://docs.appsignal.com/ruby/instrumentation/event-formatters.html"
102
+ expect(Appsignal.logger).to receive(:warn).with(message)
100
103
 
101
- deprecated_formatter
104
+ capture_stdout(out_stream) { deprecated_formatter }
105
+ expect(output).to include "appsignal WARNING: #{message}"
102
106
 
103
107
  expect(Appsignal::EventFormatter.deprecated_formatter_classes.keys).to include("mock.deprecated")
104
108
  end
105
109
 
106
110
  it "initializes deprecated formatters" do
107
- deprecated_formatter
111
+ # Silence deprecation warning
112
+ capture_stdout(out_stream) { deprecated_formatter }
108
113
  Appsignal::EventFormatter.initialize_deprecated_formatters
109
114
 
110
115
  expect(klass.registered?("mock.deprecated")).to be_truthy
@@ -29,8 +29,11 @@ describe Appsignal::Extension do
29
29
  subject.start
30
30
  end
31
31
 
32
- expect(output).to include \
33
- "WARNING: Error when reading appsignal config, appsignal not starting"
32
+ expect(output).to match \
33
+ %r{
34
+ WARNING:\sError\swhen\sreading\sappsignal\sconfig,\s
35
+ appsignal\s\(as\s(\d{2,4})/(\d{2,4})\)\snot\sstarting
36
+ }x
34
37
  end
35
38
  end
36
39
 
@@ -64,3 +64,13 @@ describe Appsignal::GarbageCollectionProfiler do
64
64
  end
65
65
  end
66
66
  end
67
+
68
+ describe Appsignal::NilGarbageCollectionProfiler do
69
+ let(:profiler) { described_class.new }
70
+
71
+ describe "#total_time" do
72
+ it "has a total time of 0" do
73
+ expect(profiler.total_time).to eq(0)
74
+ end
75
+ end
76
+ end
@@ -123,7 +123,7 @@ describe Appsignal::System do
123
123
  let(:os) { "freebsd11" }
124
124
  let(:ldd_output) { "ldd: illegal option -- -" }
125
125
 
126
- it "returns the darwin build" do
126
+ it "returns the FreeBSD build" do
127
127
  is_expected.to eq("freebsd")
128
128
  end
129
129
  end
@@ -672,6 +672,23 @@ describe Appsignal::Transaction do
672
672
  end
673
673
  end
674
674
 
675
+ describe "#garbage_collection_profiler" do
676
+ before { Appsignal::Transaction.instance_variable_set(:@garbage_collection_profiler, nil) }
677
+
678
+ it "returns the NilGarbageCollectionProfiler" do
679
+ expect(Appsignal::Transaction.garbage_collection_profiler).to be_a(Appsignal::NilGarbageCollectionProfiler)
680
+ end
681
+
682
+ context "when gc profiling is enabled" do
683
+ before { Appsignal.config.config_hash[:enable_gc_instrumentation] = true }
684
+ after { Appsignal.config.config_hash[:enable_gc_instrumentation] = false }
685
+
686
+ it "returns the GarbageCollectionProfiler" do
687
+ expect(Appsignal::Transaction.garbage_collection_profiler).to be_a(Appsignal::GarbageCollectionProfiler)
688
+ end
689
+ end
690
+ end
691
+
675
692
  describe "#start_event" do
676
693
  it "should start the event in the extension" do
677
694
  expect(transaction.ext).to receive(:start_event).with(0).and_call_original
@@ -986,7 +1003,7 @@ describe Appsignal::Transaction do
986
1003
  end
987
1004
 
988
1005
  describe "#sanitized_environment" do
989
- let(:whitelisted_keys) { Appsignal.config[:request_headers] }
1006
+ let(:allowlisted_keys) { Appsignal.config[:request_headers] }
990
1007
  subject { transaction.send(:sanitized_environment) }
991
1008
 
992
1009
  context "when request is nil" do
@@ -1004,14 +1021,14 @@ describe Appsignal::Transaction do
1004
1021
  context "when env is present" do
1005
1022
  let(:env) do
1006
1023
  {}.tap do |hash|
1007
- whitelisted_keys.each { |o| hash[o] = 1 } # use all whitelisted keys
1008
- hash[whitelisted_keys] = nil # don't add if nil
1009
- hash[:not_whitelisted] = "I will be sanitized"
1024
+ allowlisted_keys.each { |o| hash[o] = 1 } # use all allowlisted keys
1025
+ hash[allowlisted_keys] = nil # don't add if nil
1026
+ hash[:not_allowlisted] = "I will be sanitized"
1010
1027
  end
1011
1028
  end
1012
1029
 
1013
- it "only sets whitelisted keys" do
1014
- expect(subject.keys).to match_array(whitelisted_keys)
1030
+ it "only sets allowlisted keys" do
1031
+ expect(subject.keys).to match_array(allowlisted_keys)
1015
1032
  end
1016
1033
 
1017
1034
  context "with configured request_headers" do
@@ -1019,7 +1036,7 @@ describe Appsignal::Transaction do
1019
1036
  Appsignal.config.config_hash[:request_headers] = %w[CONTENT_LENGTH]
1020
1037
  end
1021
1038
 
1022
- it "only sets whitelisted keys" do
1039
+ it "only sets allowlisted keys" do
1023
1040
  expect(subject.keys).to match_array(%w[CONTENT_LENGTH])
1024
1041
  end
1025
1042
  end
@@ -56,18 +56,41 @@ module StdStreamsHelper
56
56
  # If an error is found the output the output is raised as an error, failing
57
57
  # the spec. Warnings and other AppSignal messages are ignored.
58
58
  #
59
- # Usage
59
+ # @example
60
+ # silence { do_something }
61
+ # # Does nothing
62
+ #
63
+ # silence { puts "ERROR!" }
64
+ # # => Error found in silenced output:
65
+ # # ERROR!
60
66
  #
61
- # silence { do_something }
67
+ # @example Ignore certain errors
68
+ # silence(:allowed => ["my error"]) { puts "my error!" }
69
+ # # Does nothing
62
70
  #
63
- # silence { puts "ERROR!" }
64
- # # => Error found in silenced output:
65
- # # ERROR!
66
- def silence(&block)
71
+ # silence { puts "my error!" }
72
+ # # => Error found in silenced output:
73
+ # # my error!
74
+ def silence(options = {}, &block)
67
75
  stream = Tempfile.new(SecureRandom.uuid)
68
76
  capture_std_streams(stream, stream, &block)
69
77
  ensure
70
- output = stream.read
71
- raise "Error found in silenced output:\n#{output}" if output =~ /(ERR|Error|error)/
78
+ output = filter_allowed_errors(stream.read, options.fetch(:allowed, []))
79
+ if output =~ /(ERR|Error|error)/
80
+ raise "Error found in silenced output:\n#{output}"
81
+ end
82
+ end
83
+
84
+ def filter_allowed_errors(output, allowed_errors)
85
+ output.lines.reject do |line|
86
+ reject = false
87
+ allowed_errors.each do |error|
88
+ if line.include?(error)
89
+ reject = true
90
+ break
91
+ end
92
+ end
93
+ reject
94
+ end.join(",")
72
95
  end
73
96
  end