prefab-cloud-ruby 1.5.0 → 1.6.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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}"