prefab-cloud-ruby 1.5.1 → 1.6.0.pre1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -2
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +3 -0
  5. data/README.md +24 -15
  6. data/VERSION +1 -1
  7. data/lib/prefab/client.rb +2 -7
  8. data/lib/prefab/config_client.rb +12 -16
  9. data/lib/prefab/config_loader.rb +1 -1
  10. data/lib/prefab/config_value_unwrapper.rb +1 -1
  11. data/lib/prefab/context_shape_aggregator.rb +1 -2
  12. data/lib/prefab/criteria_evaluator.rb +3 -3
  13. data/lib/prefab/evaluation_summary_aggregator.rb +1 -2
  14. data/lib/prefab/example_contexts_aggregator.rb +1 -2
  15. data/lib/prefab/feature_flag_client.rb +2 -1
  16. data/lib/prefab/internal_logger.rb +36 -10
  17. data/lib/prefab/log_path_aggregator.rb +1 -2
  18. data/lib/prefab/logger_client.rb +34 -213
  19. data/lib/prefab/options.rb +0 -44
  20. data/lib/prefab/periodic_sync.rb +2 -1
  21. data/lib/prefab/prefab.rb +23 -1
  22. data/lib/prefab/yaml_config_parser.rb +1 -1
  23. data/lib/prefab-cloud-ruby.rb +2 -5
  24. data/prefab-cloud-ruby.gemspec +6 -8
  25. data/test/support/common_helpers.rb +14 -13
  26. data/test/support/mock_base_client.rb +0 -1
  27. data/test/test_client.rb +1 -10
  28. data/test/test_config_client.rb +1 -2
  29. data/test/test_context_shape_aggregator.rb +2 -5
  30. data/test/test_criteria_evaluator.rb +0 -4
  31. data/test/test_integration.rb +1 -1
  32. data/test/test_internal_logger.rb +25 -0
  33. data/test/test_log_path_aggregator.rb +5 -10
  34. data/test/test_logger.rb +57 -453
  35. data/test/test_logger_initialization.rb +1 -1
  36. metadata +18 -8
  37. data/lib/prefab/log_subscribers/action_controller_subscriber.rb +0 -55
  38. data/lib/prefab/logging/formatter_base.rb +0 -21
  39. data/lib/prefab/sse_logger.rb +0 -14
  40. data/lib/prefab/static_logger.rb +0 -29
  41. data/test/test_action_controller.rb +0 -81
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TestInternalLogger < Minitest::Test
6
+
7
+ def test_levels
8
+ logger_a = Prefab::InternalLogger.new(A)
9
+ logger_b = Prefab::InternalLogger.new(B)
10
+
11
+ assert_equal :warn, logger_a.level
12
+ assert_equal :warn, logger_b.level
13
+
14
+ Prefab::InternalLogger.using_prefab_log_filter!
15
+ assert_equal :trace, logger_a.level
16
+ assert_equal :trace, logger_b.level
17
+ end
18
+
19
+ end
20
+
21
+ class A
22
+ end
23
+
24
+ class B
25
+ end
@@ -25,10 +25,10 @@ class TestLogPathAggregator < Minitest::Test
25
25
 
26
26
  def test_sync
27
27
  Timecop.freeze do
28
- client = new_client(namespace: 'this.is.a.namespace')
28
+ client = new_client(namespace: 'this.is.a.namespace', allow_telemetry_in_local_mode: true)
29
29
 
30
- 2.times { client.log.info('here is a message') }
31
- 3.times { client.log.error('here is a message') }
30
+ 2.times { client.log.should_log? 1, "test.test_log_path_aggregator.test_sync"}
31
+ 3.times { client.log.should_log? 3, "test.test_log_path_aggregator.test_sync"}
32
32
 
33
33
  requests = wait_for_post_requests(client) do
34
34
  client.log_path_aggregator.send(:sync)
@@ -41,12 +41,6 @@ class TestLogPathAggregator < Minitest::Test
41
41
  assert_equal Prefab::TimeHelpers.now_in_ms, sent_logger.end_at
42
42
  assert_equal client.instance_hash, sent_logger.instance_hash
43
43
  assert_includes sent_logger.loggers, PrefabProto::Logger.new(logger_name: 'test.test_log_path_aggregator.test_sync', infos: 2, errors: 3)
44
- assert_includes sent_logger.loggers, PrefabProto::Logger.new(logger_name: 'cloud.prefab.client.client', debugs: 1) # spot test that internal logging is here too
45
-
46
- assert_logged [
47
- 'WARN 2023-08-09 15:18:12 -0400: cloud.prefab.client.configclient No success loading checkpoints',
48
- 'ERROR 2023-08-09 15:18:12 -0400: test.test_log_path_aggregator.test_sync here is a message'
49
- ]
50
44
  end
51
45
  end
52
46
 
@@ -54,8 +48,9 @@ class TestLogPathAggregator < Minitest::Test
54
48
 
55
49
  def new_client(overrides = {})
56
50
  super(**{
57
- prefab_datasources: Prefab::Options::DATASOURCES::ALL,
51
+ prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY,
58
52
  api_key: '123-development-yourapikey-SDK',
53
+ collect_max_paths: 1000,
59
54
  collect_sync_interval: 1000 # we'll trigger sync manually in our test
60
55
  }.merge(overrides))
61
56
  end
data/test/test_logger.rb CHANGED
@@ -20,165 +20,41 @@ class TestLogger < Minitest::Test
20
20
 
21
21
  def setup
22
22
  super
23
- Prefab::LoggerClient.send(:public, :get_path)
24
- Prefab::LoggerClient.send(:public, :get_loc_path)
23
+ Prefab::LoggerClient.send(:public, :class_path_name)
25
24
  Prefab::LoggerClient.send(:public, :level_of)
26
- @logger = Prefab::LoggerClient.new($stdout)
25
+ @client = new_client
26
+ @logger = @client.log
27
27
  end
28
28
 
29
- def test_get_path
30
- assert_equal 'test_l.foo_warn',
31
- @logger.get_path('/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb',
32
- 'foo_warn')
33
-
34
- assert_equal 'active_support.log_subscriber.info',
35
- @logger.get_path('/Users/jdwyah/.rvm/gems/ruby-2.3.3@forcerank/gems/activesupport-4.1.16/lib/active_support/log_subscriber.rb',
36
- 'info')
37
- assert_equal 'active_support.log_subscriber.info',
38
- @logger.get_path("/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'",
39
- 'info')
40
- assert_equal 'unknown.info',
41
- @logger.get_path(nil,
42
- 'info')
43
- end
44
-
45
- def test_loc_resolution
46
- backtrace_location = Struct.new(:absolute_path, :base_label, :string) do
47
- def to_s
48
- string
49
- end
50
- end # https://ruby-doc.org/core-3.0.0/Thread/Backtrace/Location.html
51
-
52
- # verify that even if the Thread::Backtrace::Location does not have an absolute_location, we do our best
53
- assert_equal 'active_support.log_subscriber.info',
54
- @logger.get_loc_path(backtrace_location.new(nil,
55
- 'info',
56
- "/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'"))
57
- assert_equal 'test_l.info',
58
- @logger.get_loc_path(backtrace_location.new('/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb',
59
- 'info',
60
- "/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'"))
61
- end
62
-
63
- def test_level_of
29
+ def test_bootstrap_log_level
30
+ assert !Prefab.bootstrap_log_level(SemanticLogger::Log.new("TestLogger",:info))
64
31
  with_env('PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL', 'info') do
65
- # env var overrides the default level
66
- assert_equal ::Logger::INFO,
67
- @logger.level_of('app.models.user'), 'PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info'
68
-
69
- @logger.config_client = MockConfigClient.new({})
70
- assert_equal ::Logger::WARN,
71
- @logger.level_of('app.models.user'), 'default is warn'
72
-
73
- @logger.config_client = MockConfigClient.new('log-level.app' => :INFO)
74
- assert_equal ::Logger::INFO,
75
- @logger.level_of('app.models.user')
76
-
77
- @logger.config_client = MockConfigClient.new('log-level.app' => :DEBUG)
78
- assert_equal ::Logger::DEBUG,
79
- @logger.level_of('app.models.user')
80
-
81
- @logger.config_client = MockConfigClient.new('log-level.app' => :DEBUG,
82
- 'log-level.app.models' => :ERROR)
83
- assert_equal ::Logger::ERROR,
84
- @logger.level_of('app.models.user'), 'test leveling'
85
- end
86
- end
87
-
88
- def test_log_internal
89
- prefab, io = captured_logger
90
- prefab.log.log_internal(::Logger::WARN, 'test message', 'cloud.prefab.client.test.path')
91
- assert_logged io, 'WARN', "cloud.prefab.client.test.path", "test message"
92
- end
93
-
94
- def test_log_internal_unknown
95
- prefab, io = captured_logger
96
- prefab.log.log_internal(::Logger::UNKNOWN, 'test message', 'cloud.prefab.client.test.path')
97
- assert_logged io, 'ANY', "cloud.prefab.client.test.path", "test message"
98
- end
99
-
100
- def test_log_internal_silencing
101
- prefab, io = captured_logger
102
- prefab.log.silence do
103
- prefab.log.log_internal(::Logger::WARN, 'should not log', 'cloud.prefab.client.test.path')
104
- end
105
- prefab.log.log_internal(::Logger::WARN, 'should log', 'cloud.prefab.client.test.path')
106
- assert_logged io, 'WARN', "cloud.prefab.client.test.path", "should log"
107
- refute_logged io, 'should not log'
108
- end
109
-
110
- def test_log
111
- prefab, io = captured_logger
112
- prefab.log.log('test message', 'test.path', '', ::Logger::WARN)
113
- assert_logged io, 'WARN', "test.path", "test message"
114
- end
115
-
116
- def test_log_unknown
117
- prefab, io = captured_logger
118
- prefab.log.log('test message', 'test.path', '', ::Logger::UNKNOWN)
119
- assert_logged io, 'ANY', "test.path", "test message"
120
- end
121
-
122
- def test_log_silencing
123
- prefab, io = captured_logger
124
- prefab.log.silence do
125
- prefab.log.log('should not log', 'test.path', '', ::Logger::WARN)
32
+ assert Prefab.bootstrap_log_level(SemanticLogger::Log.new("TestLogger",:info))
126
33
  end
127
- prefab.log.log('should log', 'test.path', '', ::Logger::WARN)
128
- assert_logged io, 'WARN', "test.path", "should log"
129
- refute_logged io, 'should not log'
130
- end
131
-
132
- def test_logging_with_prefix
133
- prefix = 'my.own.prefix'
134
- message = 'this is a test'
135
-
136
- prefab, io = captured_logger(log_prefix: prefix)
137
-
138
- prefixed_logger = prefab.log
139
- prefixed_logger.error message
140
-
141
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_prefix", message
142
- end
143
-
144
- def test_logging_without_a_progname
145
- prefab, io = captured_logger
146
- message = 'MY MESSAGE'
147
-
148
- prefab.log.error message
149
-
150
- assert_logged io, 'ERROR', 'test.test_logger.test_logging_without_a_progname', message
151
34
  end
152
35
 
153
- def test_logging_without_a_progname_or_message
154
- prefab, io = captured_logger
36
+ def test_level_of
37
+ @logger.config_client = MockConfigClient.new({})
38
+ assert_equal SemanticLogger::Levels.index(:warn),
39
+ @logger.level_of('app.models.user'), 'default is warn'
155
40
 
156
- prefab.log.error
41
+ @logger.config_client = MockConfigClient.new('log-level.app' => :INFO)
42
+ assert_equal SemanticLogger::Levels.index(:info),
43
+ @logger.level_of('app.models.user')
157
44
 
158
- assert_logged io, 'ERROR', 'test.test_logger.test_logging_without_a_progname_or_message', ''
159
- end
45
+ @logger.config_client = MockConfigClient.new('log-level.app' => :DEBUG)
46
+ assert_equal SemanticLogger::Levels.index(:debug),
47
+ @logger.level_of('app.models.user')
160
48
 
161
- def test_logging_with_a_progname
162
- prefab, io = captured_logger
163
- message = 'MY MESSAGE'
49
+ @logger.config_client = MockConfigClient.new('log-level.app' => :DEBUG,
50
+ 'log-level.app.models' => :ERROR)
51
+ assert_equal SemanticLogger::Levels.index(:error),
52
+ @logger.level_of('app.models.user'), 'test leveling'
164
53
 
165
- prefab.log.progname = 'MY_PROGNAME'
166
- prefab.log.error message
167
-
168
- assert_logged io, 'ERROR', 'MY_PROGNAME: test.test_logger.test_logging_with_a_progname', message
169
54
  end
170
55
 
171
- def test_logging_with_a_progname_and_no_message
172
- prefab, io = captured_logger
173
-
174
- prefab.log.progname = 'MY_PROGNAME'
175
- prefab.log.error
176
-
177
- assert_logged io, 'ERROR', 'MY_PROGNAME: test.test_logger.test_logging_with_a_progname_and_no_message', 'MY_PROGNAME'
178
- end
179
56
 
180
57
  def test_logging_with_criteria_on_top_level_key
181
- prefix = 'my.own.prefix'
182
58
 
183
59
  config = PrefabProto::Config.new(
184
60
  key: 'log-level',
@@ -224,57 +100,36 @@ class TestLogger < Minitest::Test
224
100
  ]
225
101
  )
226
102
 
227
- prefab, io = captured_logger(log_prefix: prefix)
228
-
229
- inject_config(prefab, config)
230
- inject_project_env_id(prefab, PROJECT_ENV_ID)
103
+ inject_config(@client, config)
104
+ inject_project_env_id(@client, PROJECT_ENV_ID)
231
105
 
232
106
  # without any context, the level should be the default for the env (info)
233
- prefab.with_context({}) do
234
- prefab.log.debug 'Test debug'
235
- refute_logged io, 'Test debug'
236
-
237
- prefab.log.info 'Test info'
238
- assert_logged io, 'INFO', "#{prefix}.test.test_logger.test_logging_with_criteria_on_top_level_key", 'Test info'
239
-
240
- prefab.log.error 'Test error'
241
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_criteria_on_top_level_key", 'Test error'
107
+ @client.with_context({}) do
108
+ refute @logger.should_log?(SemanticLogger::Levels.index(:debug), "test.test_logger" )
109
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
110
+ assert @logger.should_log?(SemanticLogger::Levels.index(:error), "test.test_logger" )
242
111
  end
243
112
 
244
- reset_io(io)
245
113
 
246
114
  # with the wrong context, the level should be the default for the env (info)
247
- prefab.with_context(user: { email_suffix: 'yahoo.com' }) do
248
- prefab.log.debug 'Test debug'
249
- refute_logged io, 'Test debug'
250
-
251
- prefab.log.info 'Test info'
252
- assert_logged io, 'INFO', "#{prefix}.test.test_logger.test_logging_with_criteria_on_top_level_key", 'Test info'
253
-
254
- prefab.log.error 'Test error'
255
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_criteria_on_top_level_key", 'Test error'
115
+ @client.with_context(user: { email_suffix: 'yahoo.com' }) do
116
+ refute @logger.should_log?(SemanticLogger::Levels.index(:debug), "test.test_logger" )
117
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
118
+ assert @logger.should_log?(SemanticLogger::Levels.index(:error), "test.test_logger" )
256
119
  end
257
120
 
258
- reset_io(io)
259
-
260
121
  # with the correct context, the level should be the desired value (debug)
261
- prefab.with_context(user: { email_suffix: 'hotmail.com' }) do
262
- prefab.log.debug 'Test debug'
263
- assert_logged io, 'DEBUG', "#{prefix}.test.test_logger.test_logging_with_criteria_on_top_level_key", 'Test debug'
264
-
265
- prefab.log.info 'Test info'
266
- assert_logged io, 'INFO', "#{prefix}.test.test_logger.test_logging_with_criteria_on_top_level_key", 'Test info'
267
-
268
- prefab.log.error 'Test error'
269
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_criteria_on_top_level_key", 'Test error'
122
+ @client.with_context(user: { email_suffix: 'hotmail.com' }) do
123
+ assert @logger.should_log?(SemanticLogger::Levels.index(:debug), "test.test_logger" )
124
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
125
+ assert @logger.should_log?(SemanticLogger::Levels.index(:error), "test.test_logger" )
270
126
  end
271
127
  end
272
128
 
273
129
  def test_logging_with_criteria_on_key_path
274
- prefix = 'my.own.prefix'
275
130
 
276
131
  config = PrefabProto::Config.new(
277
- key: 'log-level.my.own.prefix.test.test_logger',
132
+ key: 'log-level.test.test_logger',
278
133
  rows: [
279
134
  DEFAULT_ROW,
280
135
 
@@ -328,294 +183,43 @@ class TestLogger < Minitest::Test
328
183
  )
329
184
  ]
330
185
  )
186
+ inject_config(@client, config)
187
+ inject_project_env_id(@client, PROJECT_ENV_ID)
331
188
 
332
- prefab, io = captured_logger(log_prefix: prefix)
333
-
334
- inject_config(prefab, config)
335
- inject_project_env_id(prefab, PROJECT_ENV_ID)
336
189
 
337
190
  # without any context, the level should be the default for the env (info)
338
- prefab.with_context({}) do
339
- prefab.log.debug 'Test debug'
340
- refute_logged io, 'Test debug'
341
-
342
- prefab.log.info 'Test info'
343
- assert_logged io, 'INFO', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test info'
344
-
345
- prefab.log.error 'Test error'
346
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test error'
191
+ @client.with_context({ }) do
192
+ refute @logger.should_log?(SemanticLogger::Levels.index(:debug), "test.test_logger" )
193
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
194
+ assert @logger.should_log?(SemanticLogger::Levels.index(:error), "test.test_logger" )
347
195
  end
348
196
 
349
- reset_io(io)
350
-
351
197
  # with the wrong context, the level should be the default for the env (info)
352
- prefab.with_context(user: { email_suffix: 'yahoo.com' }) do
353
- prefab.log.debug 'Test debug'
354
- refute_logged io, 'Test debug'
355
-
356
- prefab.log.info 'Test info'
357
- assert_logged io, 'INFO', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test info'
358
-
359
- prefab.log.error 'Test error'
360
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test error'
198
+ @client.with_context(user: { email_suffix: 'yahoo.com' }) do
199
+ refute @logger.should_log?(SemanticLogger::Levels.index(:debug), "test.test_logger" )
200
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
201
+ assert @logger.should_log?(SemanticLogger::Levels.index(:error), "test.test_logger" )
361
202
  end
362
203
 
363
- reset_io(io)
364
-
365
204
  # with the correct context, the level should be the desired value (debug)
366
- prefab.with_context(user: { email_suffix: 'hotmail.com' }) do
367
- prefab.log.debug 'Test debug'
368
- assert_logged io, 'DEBUG', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test debug'
369
-
370
- prefab.log.info 'Test info'
371
- assert_logged io, 'INFO', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test info'
372
-
373
- prefab.log.error 'Test error'
374
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test error'
205
+ @client.with_context(user: { email_suffix: 'hotmail.com' }) do
206
+ assert @logger.should_log?(SemanticLogger::Levels.index(:debug), "test.test_logger" )
207
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
208
+ assert @logger.should_log?(SemanticLogger::Levels.index(:error), "test.test_logger" )
375
209
  end
376
210
 
377
- reset_io(io)
378
-
379
211
  # with the correct lookup key
380
- prefab.with_context(user: { tracking_id: 'user:4567' }) do
381
- prefab.log.debug 'Test debug'
382
- assert_logged io, 'DEBUG', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test debug'
383
-
384
- prefab.log.info 'Test info'
385
- assert_logged io, 'INFO', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test info'
386
-
387
- prefab.log.error 'Test error'
388
- assert_logged io, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_criteria_on_key_path", 'Test error'
212
+ @client.with_context(user: { tracking_id: 'user:4567' }) do
213
+ assert @logger.should_log?(SemanticLogger::Levels.index(:debug), "test.test_logger" )
214
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
215
+ assert @logger.should_log?(SemanticLogger::Levels.index(:info), "test.test_logger" )
389
216
  end
390
217
  end
391
218
 
392
- def test_logging_with_a_block
393
- prefab, io = captured_logger
394
- message = 'MY MESSAGE'
395
-
396
- prefab.log.error do
397
- message
398
- end
399
-
400
- prefab.log.info do
401
- raise 'THIS WILL NEVER BE EVALUATED'
402
- end
403
-
404
- assert_logged io, 'ERROR', 'test.test_logger.test_logging_with_a_block', message
219
+ def test_class_path_name
220
+ assert_equal "minitest.test.test_logger", @logger.class_path_name("TestLogger")
221
+ assert_equal "prefab.logger_client", @logger.class_path_name("Prefab::LoggerClient")
222
+ assert_equal "semantic_logger.logger.prefab.internal_logger", @logger.class_path_name("Prefab::InternalLogger")
405
223
  end
406
224
 
407
- def test_add_context_keys
408
- assert @logger.context_keys.empty?
409
- @logger.add_context_keys("user.name", "role.admin", "company.name")
410
-
411
- assert @logger.context_keys.to_a == %w(user.name role.admin company.name)
412
- end
413
-
414
- def test_context_keys_are_a_set
415
- @logger.add_context_keys("user.name", "role.admin", "company.name")
416
-
417
- assert @logger.context_keys.to_a == %w(user.name role.admin company.name)
418
-
419
- @logger.add_context_keys("user.name", "user.role")
420
-
421
- assert @logger.context_keys.to_a == %w(user.name role.admin company.name user.role)
422
- end
423
-
424
- def test_with_context_keys
425
- @logger.add_context_keys("company.name")
426
-
427
- assert @logger.context_keys.to_a == %w(company.name)
428
-
429
- @logger.with_context_keys("user.name", "role.admin") do
430
- assert @logger.context_keys.to_a == %w(company.name user.name role.admin)
431
- end
432
-
433
- assert @logger.context_keys.to_a == %w(company.name)
434
- end
435
-
436
- def test_structured_logging
437
- prefab, io = captured_logger
438
- message = 'HELLO'
439
-
440
- prefab.log.error message, user: "michael", id: 123
441
-
442
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_logging', "#{message} id=123 user=michael"
443
- end
444
-
445
- def test_structured_json_logging
446
- prefab, io = captured_logger(log_formatter: Prefab::Options::JSON_LOG_FORMATTER)
447
- message = 'HELLO'
448
-
449
- prefab.log.error message, user: "michael", id: 123
450
-
451
- log_data = JSON.parse(io.string)
452
- assert log_data["message"] == message
453
- assert log_data["user"] == "michael"
454
- assert log_data["id"] == 123
455
- end
456
-
457
- def test_structured_internal_logging
458
- prefab, io = captured_logger
459
-
460
- prefab.log.log_internal(::Logger::WARN, 'test', 'cloud.prefab.client.test.path', user: "michael")
461
-
462
- assert_logged io, 'WARN', 'cloud.prefab.client.test.path', "test user=michael"
463
- end
464
-
465
- def test_structured_block_logger
466
- prefab, io = captured_logger
467
- message = 'MY MESSAGE'
468
-
469
- prefab.log.error user: "michael" do
470
- message
471
- end
472
-
473
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_block_logger', "#{message} user=michael"
474
- end
475
-
476
- def test_structured_logger_with_context_keys
477
- prefab, io = captured_logger
478
-
479
- prefab.with_context({user: {name: "michael", job: "developer", admin: false}, company: { name: "Prefab" }}) do
480
-
481
- prefab.log.add_context_keys "user.name", "company.name", "user.admin"
482
-
483
- prefab.log.error "UH OH"
484
-
485
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_logger_with_context_keys',
486
- "UH OH company.name=Prefab user.admin=false user.name=michael"
487
- end
488
- end
489
-
490
- def test_structured_logger_with_context_keys_ignores_nils
491
- prefab, io = captured_logger
492
-
493
- prefab.with_context({user: {name: "michael", job: "developer"}, company: { name: "Prefab" }}) do
494
-
495
- prefab.log.add_context_keys "user.name", "company.name", "user.admin"
496
-
497
- prefab.log.error "UH OH"
498
-
499
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_logger_with_context_keys_ignores_nils',
500
- "UH OH company.name=Prefab user.name=michael"
501
- end
502
- end
503
-
504
- def test_structured_logger_with_context_keys_and_log_hash
505
- prefab, io = captured_logger
506
-
507
- prefab.with_context({user: {name: "michael", job: "developer", admin: false}, company: { name: "Prefab" }}) do
508
-
509
- prefab.log.add_context_keys "user.name", "company.name", "user.admin"
510
-
511
- prefab.log.error "UH OH", user_id: 6
512
-
513
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_logger_with_context_keys_and_log_hash',
514
- "UH OH company.name=Prefab user.admin=false user.name=michael user_id=6"
515
- end
516
-
517
- end
518
-
519
- def test_structured_logger_with_context_keys_block
520
- prefab, io = captured_logger
521
-
522
- prefab.with_context({user: {name: "michael", job: "developer", admin: false}, company: { name: "Prefab" }}) do
523
-
524
- prefab.log.add_context_keys "user.name"
525
-
526
- prefab.log.error "UH OH"
527
-
528
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_logger_with_context_keys_block',
529
- 'UH OH user.name=michael'
530
-
531
- prefab.log.with_context_keys("company.name") do
532
- prefab.log.error "UH OH"
533
-
534
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_logger_with_context_keys_block',
535
- 'UH OH company.name=Prefab user.name=michael'
536
- end
537
-
538
- prefab.log.error "UH OH"
539
-
540
- assert_logged io, 'ERROR', 'test.test_logger.test_structured_logger_with_context_keys_block',
541
- 'UH OH user.name=michael'
542
- end
543
- end
544
-
545
- def test_context_key_threads
546
- prefab, io = captured_logger
547
-
548
- threads = []
549
- 1000.times.map do |i|
550
- threads << Thread.new do
551
- prefab.with_context({test: {"thread_#{i}": "thread_#{i}"}}) do
552
- prefab.log.add_context_keys "test.thread_#{i}"
553
- prefab.log.error "UH OH"
554
- assert_logged io, 'ERROR', 'test.test_logger.test_context_key_threads',
555
- "UH OH test.thread_#{i}=thread_#{i}"
556
- end
557
- end
558
- end
559
- threads.each { |thr| thr.join }
560
- end
561
-
562
- def test_tagged
563
- prefab, io = captured_logger
564
-
565
- prefab.log.tagged([[]]) do # rails sends some of these
566
- prefab.log.tagged("outside") do
567
- prefab.log.tagged("nested", "tag2") do
568
- prefab.log.error "msg"
569
- assert_logged io, 'ERROR', 'test.test_logger.test_tagged',
570
- 'msg log.tags=\["outside", "nested", "tag2"\]'
571
- end
572
- end
573
- end
574
- end
575
-
576
- def test_req_tagged
577
- prefab, io = captured_logger
578
- prefab.log.tagged("tag-1").error "first"
579
- assert_logged io, 'ERROR', 'test.test_logger.test_req_tagged',
580
- 'first req.tags=\["tag-1"\]'
581
- reset_io(io)
582
-
583
- prefab.log.tagged("tag-2").error "2nd"
584
- assert_logged io, 'ERROR', 'test.test_logger.test_req_tagged',
585
- '2nd req.tags=\["tag-1", "tag-2"\]'
586
- prefab.log.flush
587
-
588
- prefab.log.tagged("tag-3").error "3rd"
589
- assert_logged io, 'ERROR', 'test.test_logger.test_req_tagged',
590
- '3rd req.tags=\["tag-3"\]'
591
- prefab.log.flush
592
- end
593
-
594
- private
595
-
596
- def assert_logged(logged_io, level, path, message)
597
- assert_match(/#{level}\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]?\d+:\s+#{path} #{message}\n/, logged_io.string)
598
- end
599
-
600
- def refute_logged(logged_io, message)
601
- refute_match(/#{message}/, logged_io.string)
602
- end
603
-
604
- def captured_logger(options = {})
605
- io = StringIO.new
606
- options = Prefab::Options.new(**options.merge(
607
- logdev: io,
608
- prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
609
- ))
610
- prefab = Prefab::Client.new(options)
611
-
612
- [prefab, io]
613
- end
614
-
615
- def reset_io(io)
616
- io.close
617
- io.reopen
618
-
619
- assert_equal '', io.string
620
- end
621
225
  end
@@ -6,7 +6,7 @@ class TestLoggerInitialization < Minitest::Test
6
6
 
7
7
  def test_init_out_of_order
8
8
  # assert nothing blows up
9
- Prefab::LoggerClient.instance.info "anything"
9
+ Prefab.log_filter
10
10
  end
11
11
 
12
12
  end