prefab-cloud-ruby 1.5.0 → 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 +6 -0
  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 -42
  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 +7 -9
  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 +19 -9
  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
@@ -1,99 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Prefab
4
- class LoggerClient < ::Logger
4
+ class LoggerClient
5
5
  SEP = '.'
6
6
  BASE_KEY = 'log-level'
7
- UNKNOWN_PATH = 'unknown.'
8
- LOG_TAGS = 'log.tags'
9
- REQ_TAGS = 'req.tags'
7
+ NO_DEFAULT = nil
10
8
 
11
9
  LOG_LEVEL_LOOKUPS = {
12
- PrefabProto::LogLevel::NOT_SET_LOG_LEVEL => ::Logger::DEBUG,
13
- PrefabProto::LogLevel::TRACE => ::Logger::DEBUG,
14
- PrefabProto::LogLevel::DEBUG => ::Logger::DEBUG,
15
- PrefabProto::LogLevel::INFO => ::Logger::INFO,
16
- PrefabProto::LogLevel::WARN => ::Logger::WARN,
17
- PrefabProto::LogLevel::ERROR => ::Logger::ERROR,
18
- PrefabProto::LogLevel::FATAL => ::Logger::FATAL
10
+ PrefabProto::LogLevel::NOT_SET_LOG_LEVEL => :trace,
11
+ PrefabProto::LogLevel::TRACE => :trace,
12
+ PrefabProto::LogLevel::DEBUG => :debug,
13
+ PrefabProto::LogLevel::INFO => :info,
14
+ PrefabProto::LogLevel::WARN => :warn,
15
+ PrefabProto::LogLevel::ERROR => :error,
16
+ PrefabProto::LogLevel::FATAL => :fatal
19
17
  }.freeze
20
18
 
21
- def self.instance
22
- @@shared_instance ||= LoggerClient.new($stdout)
23
- end
24
-
25
- def initialize(logdev, log_path_aggregator: nil, formatter: Options::DEFAULT_LOG_FORMATTER, prefix: nil)
26
- super(logdev)
27
- self.formatter = Prefab::Logging::FormatterBase.new(formatter_proc: formatter, logger_client: self)
28
- @config_client = BootstrappingConfigClient.new
29
- @silences = Concurrent::Map.new(initial_capacity: 2)
30
- @recurse_check = Concurrent::Map.new(initial_capacity: 2)
31
- @prefix = "#{prefix}#{prefix && '.'}"
32
-
33
- @context_keys_map = Concurrent::Map.new(initial_capacity: 4)
34
-
19
+ def initialize(client: ,log_path_aggregator: )
20
+ @config_client = client
35
21
  @log_path_aggregator = log_path_aggregator
36
- @@shared_instance = self
37
- end
38
-
39
- def add_context_keys(*keys)
40
- context_keys.merge(keys)
41
- end
42
-
43
- def with_context_keys(*keys)
44
- context_keys.merge(keys)
45
- yield
46
- ensure
47
- context_keys.subtract(keys)
48
- end
49
-
50
- def internal_logger(path = nil)
51
- InternalLogger.new(path, self)
52
- end
53
-
54
- def context_keys
55
- @context_keys_map.fetch_or_store(local_log_id, Concurrent::Set.new)
56
- end
57
-
58
- # InternalLoggers Will Call This
59
- def add_internal(severity, message, progname, loc, log_context = {}, &block)
60
- path_loc = get_loc_path(loc)
61
- path = @prefix + path_loc
62
-
63
- log(message, path, progname, severity, log_context, &block)
64
- end
65
-
66
- def log_internal(severity, message, path, log_context = {}, &block)
67
- return if @recurse_check[local_log_id]
68
- @recurse_check[local_log_id] = true
69
- begin
70
- log(message, path, nil, severity, log_context, &block)
71
- ensure
72
- @recurse_check[local_log_id] = false
73
- end
74
- end
75
-
76
- def log(message, path, progname, severity, log_context = {})
77
- severity ||= ::Logger::UNKNOWN
78
-
79
- return true if !should_log? severity, path
80
- return true if @logdev.nil? || @silences[local_log_id]
81
-
82
- progname = @progname if progname.nil?
83
-
84
- if message.nil?
85
- if block_given?
86
- message = yield
87
- else
88
- message = progname
89
- progname = @progname
90
- end
91
- end
92
-
93
- @logdev.write(
94
- format_message(format_severity(severity), Time.now, progname, message, path, stringify_keys(log_context.merge(fetch_context_for_context_keys)))
95
- )
96
- true
97
22
  end
98
23
 
99
24
  def should_log?(severity, path)
@@ -101,106 +26,32 @@ module Prefab
101
26
  severity >= level_of(path)
102
27
  end
103
28
 
104
- def debug(progname = nil, **log_context, &block)
105
- add_internal(DEBUG, nil, progname, caller_locations(1, 1)[0], log_context, &block)
106
- end
107
-
108
- def info(progname = nil, **log_context, &block)
109
- add_internal(INFO, nil, progname, caller_locations(1, 1)[0], log_context, &block)
110
- end
111
-
112
- def warn(progname = nil, **log_context, &block)
113
- add_internal(WARN, nil, progname, caller_locations(1, 1)[0], log_context, &block)
114
- end
115
-
116
- def error(progname = nil, **log_context, &block)
117
- add_internal(ERROR, nil, progname, caller_locations(1, 1)[0], log_context, &block)
118
- end
119
-
120
- def fatal(progname = nil, **log_context, &block)
121
- add_internal(FATAL, nil, progname, caller_locations(1, 1)[0], log_context, &block)
29
+ def semantic_filter(log)
30
+ class_path = class_path_name(log.name)
31
+ lookup_path = "#{logger_prefix}.#{class_path}"
32
+ level = SemanticLogger::Levels.index(log.level)
33
+ log.named_tags.merge!({ path: lookup_path })
34
+ should_log? level, lookup_path
122
35
  end
123
36
 
124
- def debug?
125
- true
126
- end
127
-
128
- def info?
129
- true
130
- end
131
-
132
- def warn?
133
- true
134
- end
135
-
136
- def error?
137
- true
138
- end
139
-
140
- def fatal?
141
- true
142
- end
143
-
144
- def level
145
- DEBUG
146
- end
147
-
148
- def tagged(*tags)
149
- to_add = tags.flatten.compact
150
- if block_given?
151
- new_log_tags = current_tags
152
- new_log_tags += to_add unless to_add.empty?
153
- Prefab::Context.with_merged_context({ "log" => { "tags" => new_log_tags } }) do
154
- with_context_keys LOG_TAGS do
155
- yield self
156
- end
157
- end
158
- else
159
- new_log_tags = Prefab::Context.current.get(REQ_TAGS) || []
160
- new_log_tags += to_add unless to_add.empty?
161
- add_context_keys REQ_TAGS
162
- Prefab::Context.current.set("req", {"tags": new_log_tags})
163
- self
164
- end
165
- end
166
-
167
- def current_tags
168
- Prefab::Context.current.get(LOG_TAGS) || []
169
- end
170
-
171
- def flush
172
- Prefab::Context.current.set("req", {"tags": nil})
173
- super if defined?(super)
174
- end
175
37
 
176
38
  def config_client=(config_client)
177
39
  @config_client = config_client
178
40
  end
179
41
 
180
- def local_log_id
181
- Thread.current.__id__
182
- end
183
-
184
- def silence
185
- @silences[local_log_id] = true
186
- yield self
187
- ensure
188
- @silences[local_log_id] = false
189
- end
190
-
191
42
  private
192
43
 
193
- NO_DEFAULT = nil
194
-
195
- def stringify_keys(hash)
196
- Hash[hash.map { |k, v| [k.to_s, v] }]
44
+ def class_path_name(class_name)
45
+ log_class = Logger.const_get(class_name)
46
+ if log_class.respond_to?(:superclass) && log_class.superclass != Object
47
+ underscore("#{log_class.superclass.name}.#{log_class.name}")
48
+ else
49
+ underscore("#{log_class.name}")
50
+ end.gsub(/[^a-z_]/i, '.')
197
51
  end
198
52
 
199
- def fetch_context_for_context_keys
200
- context = Prefab::Context.current.to_h
201
- Hash[context_keys.map do |key|
202
- [key, context.dig(*key.split("."))]
203
- end]
53
+ def logger_prefix
54
+ Context.current.get("application.key") || "prefab-cloud-ruby"
204
55
  end
205
56
 
206
57
  # Find the closest match to 'log_level.path' in config
@@ -219,46 +70,16 @@ module Prefab
219
70
  end
220
71
 
221
72
  closest_log_level_match_int = PrefabProto::LogLevel.resolve(closest_log_level_match)
222
- LOG_LEVEL_LOOKUPS[closest_log_level_match_int]
73
+ internal_convert = LOG_LEVEL_LOOKUPS[closest_log_level_match_int]
74
+ return SemanticLogger::Levels.index(internal_convert)
223
75
  end
224
76
 
225
- def get_loc_path(loc)
226
- loc_path = loc.absolute_path || loc.to_s
227
- get_path(loc_path, loc.base_label)
228
- end
229
-
230
- # sanitize & clean the path of the caller so the key
231
- # looks like log_level.app.models.user
232
- def get_path(absolute_path, base_label)
233
- path = (absolute_path || UNKNOWN_PATH).dup
234
- path.slice! Dir.pwd
235
- path.gsub!(%r{(.*)?(?=/lib)}im, '') # replace everything before first lib
236
-
237
- path = path.gsub('/', SEP).gsub(/.rb.*/, '') + SEP + base_label
238
- path.slice! '.lib'
239
- path.slice! SEP
240
- path
241
- end
242
-
243
- def format_message(severity, datetime, progname, msg, path = nil, log_context = {})
244
- formatter = (@formatter || @default_formatter)
245
- compact_context = log_context.reject{ |_, v| v.nil? || ((v.is_a? Array) && v.empty?) }
246
- @formatter.call_proc(
247
- severity: severity,
248
- datetime: datetime,
249
- progname: progname,
250
- path: path,
251
- message: msg,
252
- log_context: compact_context
253
- )
254
- end
255
- end
256
-
257
- # StubConfigClient to be used while config client initializes
258
- # since it may log
259
- class BootstrappingConfigClient
260
- def get(_key, default = nil, _properties = {})
261
- ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'] ? ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'].upcase.to_sym : default
77
+ def underscore(string)
78
+ string.gsub(/::/, '/').
79
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
80
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
81
+ tr("-", "_").
82
+ downcase
262
83
  end
263
84
  end
264
85
  end
@@ -4,9 +4,6 @@ module Prefab
4
4
  # This class contains all the options that can be passed to the Prefab client.
5
5
  class Options
6
6
  attr_reader :api_key
7
- attr_reader :logdev
8
- attr_reader :log_prefix
9
- attr_reader :log_formatter
10
7
  attr_reader :namespace
11
8
  attr_reader :prefab_api_url
12
9
  attr_reader :on_no_default
@@ -21,39 +18,6 @@ module Prefab
21
18
  attr_reader :disable_action_controller_logging
22
19
  attr_accessor :is_fork
23
20
 
24
- DEFAULT_LOG_FORMATTER = proc { |data|
25
- severity = data[:severity]
26
- datetime = data[:datetime]
27
- progname = data[:progname]
28
- path = data[:path]
29
- msg = data[:message]
30
- log_context = data[:log_context]
31
-
32
- progname = (progname.nil? || progname.empty?) ? path : "#{progname}: #{path}"
33
-
34
- formatted_log_context = log_context.sort.map do |k, v|
35
- "#{k}=#{v}"
36
- end.join(" ")
37
- "#{severity.ljust(5)} #{datetime}:#{' ' if progname}#{progname} #{msg}#{log_context.any? ? " " + formatted_log_context : ""}\n"
38
- }
39
-
40
- JSON_LOG_FORMATTER = proc { |data|
41
- log_context = data.delete(:log_context)
42
- data.merge(log_context).compact.to_json << "\n"
43
- }
44
-
45
- COMPACT_LOG_FORMATTER = proc { |data|
46
- severity = data[:severity]
47
- msg = data[:message]
48
- log_context = data[:log_context]
49
- log_context["path"] = data[:path] || ""
50
-
51
- formatted_log_context = log_context.sort.map do |k, v|
52
- "#{k}=#{v}"
53
- end.join(" ")
54
- "#{severity.ljust(5)} #{msg&.strip} #{formatted_log_context}\n"
55
- }
56
-
57
21
  module ON_INITIALIZATION_FAILURE
58
22
  RAISE = :raise
59
23
  RETURN = :return
@@ -76,10 +40,7 @@ module Prefab
76
40
 
77
41
  private def init(
78
42
  api_key: ENV['PREFAB_API_KEY'],
79
- logdev: $stdout,
80
43
  namespace: '',
81
- log_formatter: DEFAULT_LOG_FORMATTER,
82
- log_prefix: nil,
83
44
  prefab_api_url: ENV['PREFAB_API_URL'] || 'https://api.prefab.cloud',
84
45
  on_no_default: ON_NO_DEFAULT::RAISE, # options :raise, :warn_and_return_nil,
85
46
  initialization_timeout_sec: 10, # how long to wait before on_init_failure
@@ -101,10 +62,7 @@ module Prefab
101
62
  disable_action_controller_logging: false
102
63
  )
103
64
  @api_key = api_key
104
- @logdev = logdev
105
65
  @namespace = namespace
106
- @log_formatter = log_formatter
107
- @log_prefix = log_prefix
108
66
  @prefab_api_url = remove_trailing_slash(prefab_api_url)
109
67
  @on_no_default = on_no_default
110
68
  @initialization_timeout_sec = initialization_timeout_sec
@@ -2,7 +2,8 @@
2
2
 
3
3
  module Prefab
4
4
  module PeriodicSync
5
- LOG = Prefab::InternalLogger.new("periodsync")
5
+ LOG = Prefab::InternalLogger.new(self)
6
+
6
7
  def sync
7
8
  return if @data.size.zero?
8
9
 
data/lib/prefab/prefab.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Prefab
4
+ LOG = Prefab::InternalLogger.new(self)
4
5
  @@lock = Concurrent::ReadWriteLock.new
6
+ @config_has_loaded = false
5
7
 
6
8
  def self.init(options = Prefab::Options.new)
7
9
  unless @singleton.nil?
8
- Prefab::LoggerClient.instance.warn 'Prefab already initialized.'
10
+ LOG.warn 'Prefab already initialized.'
9
11
  return @singleton
10
12
  end
11
13
 
@@ -46,6 +48,26 @@ module Prefab
46
48
  @singleton
47
49
  end
48
50
 
51
+ def self.log_filter
52
+ InternalLogger.using_prefab_log_filter!
53
+ return Proc.new do |log|
54
+ if defined?(@singleton) && !@singleton.nil? && @singleton.config_client.initialized?
55
+ @singleton.log.semantic_filter(log)
56
+ else
57
+ bootstrap_log_level(log)
58
+ end
59
+ end
60
+ end
61
+
62
+ def self.finish_init!
63
+ @config_has_loaded = true
64
+ end
65
+
66
+ def self.bootstrap_log_level(log)
67
+ level = ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'] ? ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'].downcase.to_sym : :warn
68
+ SemanticLogger::Levels.index(level) <= SemanticLogger::Levels.index(log.level)
69
+ end
70
+
49
71
  private
50
72
 
51
73
  def self.ensure_initialized(key = nil)
@@ -2,7 +2,7 @@ require 'yaml'
2
2
 
3
3
  module Prefab
4
4
  class YAMLConfigParser
5
- LOG = Prefab::InternalLogger.new(YAMLConfigParser)
5
+ LOG = Prefab::InternalLogger.new(self)
6
6
 
7
7
  def initialize(file, client)
8
8
  @file = file
@@ -5,6 +5,8 @@ module Prefab
5
5
  VERSION = File.read(File.dirname(__FILE__) + '/../VERSION').strip
6
6
  end
7
7
 
8
+ require 'semantic_logger'
9
+ require 'prefab/internal_logger'
8
10
  require 'concurrent/atomics'
9
11
  require 'concurrent'
10
12
  require 'faraday'
@@ -23,14 +25,11 @@ require 'prefab/errors/env_var_parse_error'
23
25
  require 'prefab/errors/missing_env_var_error'
24
26
  require 'prefab/errors/uninitialized_error'
25
27
  require 'prefab/options'
26
- require 'prefab/static_logger'
27
- require 'prefab/internal_logger'
28
28
  require 'prefab/rate_limit_cache'
29
29
  require 'prefab/context_shape_aggregator'
30
30
  require 'prefab/example_contexts_aggregator'
31
31
  require 'prefab/evaluation_summary_aggregator'
32
32
  require 'prefab/log_path_aggregator'
33
- require 'prefab/sse_logger'
34
33
  require 'prefab/weighted_value_resolver'
35
34
  require 'prefab/config_value_wrapper'
36
35
  require 'prefab/config_value_unwrapper'
@@ -47,8 +46,6 @@ require 'prefab/logger_client'
47
46
  require 'active_support/deprecation'
48
47
  require 'active_support'
49
48
  require 'action_controller/metal/strong_parameters'
50
- require 'prefab/logging/formatter_base'
51
- require 'prefab/log_subscribers/action_controller_subscriber'
52
49
  require 'prefab/client'
53
50
  require 'prefab/config_client_presenter'
54
51
  require 'prefab/config_client'
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: prefab-cloud-ruby 1.5.0 ruby lib
5
+ # stub: prefab-cloud-ruby 1.6.0.pre1 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "prefab-cloud-ruby".freeze
9
- s.version = "1.5.0"
9
+ s.version = "1.6.0.pre1"
10
10
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
11
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Jeff Dwyer".freeze]
14
- s.date = "2024-02-12"
14
+ s.date = "2024-02-22"
15
15
  s.description = "Feature Flags, Live Config, and Dynamic Log Levels as a service".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.executables = ["console".freeze]
@@ -65,17 +65,13 @@ Gem::Specification.new do |s|
65
65
  "lib/prefab/internal_logger.rb",
66
66
  "lib/prefab/local_config_parser.rb",
67
67
  "lib/prefab/log_path_aggregator.rb",
68
- "lib/prefab/log_subscribers/action_controller_subscriber.rb",
69
68
  "lib/prefab/logger_client.rb",
70
- "lib/prefab/logging/formatter_base.rb",
71
69
  "lib/prefab/murmer3.rb",
72
70
  "lib/prefab/options.rb",
73
71
  "lib/prefab/periodic_sync.rb",
74
72
  "lib/prefab/prefab.rb",
75
73
  "lib/prefab/rate_limit_cache.rb",
76
74
  "lib/prefab/resolved_config_presenter.rb",
77
- "lib/prefab/sse_logger.rb",
78
- "lib/prefab/static_logger.rb",
79
75
  "lib/prefab/time_helpers.rb",
80
76
  "lib/prefab/weighted_value_resolver.rb",
81
77
  "lib/prefab/yaml_config_parser.rb",
@@ -89,7 +85,6 @@ Gem::Specification.new do |s|
89
85
  "test/support/mock_base_client.rb",
90
86
  "test/support/mock_config_client.rb",
91
87
  "test/support/mock_config_loader.rb",
92
- "test/test_action_controller.rb",
93
88
  "test/test_client.rb",
94
89
  "test/test_config_client.rb",
95
90
  "test/test_config_loader.rb",
@@ -107,6 +102,7 @@ Gem::Specification.new do |s|
107
102
  "test/test_feature_flag_client.rb",
108
103
  "test/test_helper.rb",
109
104
  "test/test_integration.rb",
105
+ "test/test_internal_logger.rb",
110
106
  "test/test_local_config_parser.rb",
111
107
  "test/test_log_path_aggregator.rb",
112
108
  "test/test_logger.rb",
@@ -134,6 +130,7 @@ Gem::Specification.new do |s|
134
130
  s.add_runtime_dependency(%q<uuid>.freeze, [">= 0"])
135
131
  s.add_runtime_dependency(%q<activesupport>.freeze, [">= 4"])
136
132
  s.add_runtime_dependency(%q<actionpack>.freeze, [">= 4"])
133
+ s.add_runtime_dependency(%q<semantic_logger>.freeze, [">= 0"])
137
134
  s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
138
135
  s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
139
136
  s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.4.9"])
@@ -148,6 +145,7 @@ Gem::Specification.new do |s|
148
145
  s.add_dependency(%q<uuid>.freeze, [">= 0"])
149
146
  s.add_dependency(%q<activesupport>.freeze, [">= 4"])
150
147
  s.add_dependency(%q<actionpack>.freeze, [">= 4"])
148
+ s.add_dependency(%q<semantic_logger>.freeze, [">= 0"])
151
149
  s.add_dependency(%q<benchmark-ips>.freeze, [">= 0"])
152
150
  s.add_dependency(%q<bundler>.freeze, [">= 0"])
153
151
  s.add_dependency(%q<juwelier>.freeze, ["~> 2.4.9"])
@@ -6,15 +6,12 @@ module CommonHelpers
6
6
  def setup
7
7
  $oldstderr, $stderr = $stderr, StringIO.new
8
8
 
9
- $logs = nil
9
+ $logs ||= StringIO.new
10
+ SemanticLogger.add_appender(io: $logs)
10
11
  Timecop.freeze('2023-08-09 15:18:12 -0400')
11
12
  end
12
13
 
13
14
  def teardown
14
- if $logs && !$logs.string.empty?
15
- raise "Unexpected logs. Handle logs with assert_only_expected_logs or assert_logged\n\n#{$logs.string}"
16
- end
17
-
18
15
  if $stderr != $oldstderr && !$stderr.string.empty?
19
16
  # we ignore 2.X because of the number of `instance variable @xyz not initialized` warnings
20
17
  if !RUBY_VERSION.start_with?('2.')
@@ -56,11 +53,8 @@ module CommonHelpers
56
53
  end
57
54
 
58
55
  def prefab_options(overrides = {})
59
- $logs ||= StringIO.new
60
56
  Prefab::Options.new(
61
- **DEFAULT_NEW_CLIENT_OPTIONS.merge(
62
- overrides.merge(logdev: $logs)
63
- )
57
+ **DEFAULT_NEW_CLIENT_OPTIONS.merge(overrides)
64
58
  )
65
59
  end
66
60
 
@@ -147,7 +141,7 @@ module CommonHelpers
147
141
  end
148
142
 
149
143
  def assert_only_expected_logs
150
- assert_equal "WARN 2023-08-09 15:18:12 -0400: cloud.prefab.client.configclient No success loading checkpoints\n", $logs.string
144
+ # assert_equal "WARN 2023-08-09 15:18:12 -0400: cloud.prefab.client.configclient No success loading checkpoints\n", $logs.string
151
145
  # mark nil to indicate we handled it
152
146
  $logs = nil
153
147
  end
@@ -155,9 +149,16 @@ module CommonHelpers
155
149
  def assert_logged(expected)
156
150
  # we do a uniq here because logging can happen in a separate thread so the
157
151
  # number of times a log might happen could be slightly variable.
158
- assert_equal expected, $logs.string.split("\n").uniq
159
- # mark nil to indicate we handled it
160
- $logs = nil
152
+ actuals = $logs.string.split("\n").uniq
153
+ expected.each do |expectation|
154
+ matched = false
155
+
156
+ actuals.each do |actual|
157
+ matched = true if actual.match(expectation)
158
+ end
159
+
160
+ assert(matched, "expectation: #{expectation}, got: #{actuals}")
161
+ end
161
162
  end
162
163
 
163
164
  def assert_stderr(expected)
@@ -10,7 +10,6 @@ class MockBaseClient
10
10
  @options = options
11
11
  @namespace = namespace
12
12
  @config_client = MockConfigClient.new
13
- Prefab::LoggerClient.new(options.logdev)
14
13
  @posts = []
15
14
  end
16
15
 
data/test/test_client.rb CHANGED
@@ -185,7 +185,7 @@ class TestClient < Minitest::Test
185
185
  collect_evaluation_summaries: true).evaluation_summary_aggregator.class
186
186
 
187
187
  assert_logged [
188
- "WARN 2023-08-09 15:18:12 -0400: cloud.prefab.client.configclient No success loading checkpoints"
188
+ "Prefab::ConfigClient -- No success loading checkpoints"
189
189
  ]
190
190
  end
191
191
 
@@ -411,15 +411,6 @@ class TestClient < Minitest::Test
411
411
  assert_summary client, {}
412
412
  end
413
413
 
414
- def test_fork_includes_logger_context_keys
415
- client = new_client
416
- client.log.add_context_keys "user.name"
417
-
418
- forked = client.fork
419
-
420
- assert forked.log.context_keys.to_a == %w(user.name)
421
- end
422
-
423
414
  private
424
415
 
425
416
  def basic_value_config
@@ -27,8 +27,7 @@ class TestConfigClient < Minitest::Test
27
27
  def test_initialization_timeout_error
28
28
  options = Prefab::Options.new(
29
29
  api_key: '123-ENV-KEY-SDK',
30
- initialization_timeout_sec: 0.01,
31
- logdev: StringIO.new
30
+ initialization_timeout_sec: 0.01
32
31
  )
33
32
 
34
33
  err = assert_raises(Prefab::Errors::InitializationTimeoutError) do
@@ -50,8 +50,6 @@ class TestContextShapeAggregator < Minitest::Test
50
50
 
51
51
  assert_equal [['user', 'name', 2], ['user', 'email', 2], ['user', 'age', 4], ['subscription', 'plan', 2], ['subscription', 'free', 5], ['user', 'dob', 2], ['device', 'name', 2], ['device', 'os', 2], ['device', 'version', 1]],
52
52
  aggregator.data.to_a
53
-
54
- assert_only_expected_logs
55
53
  end
56
54
 
57
55
  def test_prepare_data
@@ -85,7 +83,6 @@ class TestContextShapeAggregator < Minitest::Test
85
83
  }
86
84
 
87
85
  assert_equal [], aggregator.data.to_a
88
- assert_only_expected_logs
89
86
  end
90
87
 
91
88
  def test_sync
@@ -124,8 +121,8 @@ class TestContextShapeAggregator < Minitest::Test
124
121
 
125
122
 
126
123
  assert_logged [
127
- "WARN 2023-08-09 15:18:12 -0400: cloud.prefab.client.configclient No success loading checkpoints",
128
- "WARN 2023-08-09 15:18:12 -0400: cloud.prefab.client.configclient Couldn't Initialize In 0. Key some.key. Returning what we have"
124
+ "No success loading checkpoints",
125
+ "Couldn't Initialize In 0. Key some.key. Returning what we have"
129
126
  ]
130
127
  end
131
128
 
@@ -711,10 +711,6 @@ class TestCriteriaEvaluator < Minitest::Test
711
711
  end
712
712
 
713
713
  class FakeBaseClient
714
- def initialize
715
- Prefab::LoggerClient.new($stdout)
716
- end
717
-
718
714
  def evaluation_summary_aggregator
719
715
  @evaluation_summary_aggregator ||= Prefab::EvaluationSummaryAggregator.new(client: self, max_keys: 9999, sync_interval: 9999)
720
716
  end
@@ -45,7 +45,7 @@ class TestIntegration < Minitest::Test
45
45
  actual = get_actual_data[it.last_data_sent]
46
46
 
47
47
  expected.all? do |expected|
48
- assert actual.include?(expected)
48
+ assert actual.include?(expected), "#{actual} should include #{expected}"
49
49
  end
50
50
  else
51
51
  raise "Unknown test type: #{it.test_type}"