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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +3 -0
- data/README.md +24 -15
- data/VERSION +1 -1
- data/lib/prefab/client.rb +2 -7
- data/lib/prefab/config_client.rb +12 -16
- data/lib/prefab/config_loader.rb +1 -1
- data/lib/prefab/config_value_unwrapper.rb +1 -1
- data/lib/prefab/context_shape_aggregator.rb +1 -2
- data/lib/prefab/criteria_evaluator.rb +3 -3
- data/lib/prefab/evaluation_summary_aggregator.rb +1 -2
- data/lib/prefab/example_contexts_aggregator.rb +1 -2
- data/lib/prefab/feature_flag_client.rb +2 -1
- data/lib/prefab/internal_logger.rb +36 -10
- data/lib/prefab/log_path_aggregator.rb +1 -2
- data/lib/prefab/logger_client.rb +34 -213
- data/lib/prefab/options.rb +0 -42
- data/lib/prefab/periodic_sync.rb +2 -1
- data/lib/prefab/prefab.rb +23 -1
- data/lib/prefab/yaml_config_parser.rb +1 -1
- data/lib/prefab-cloud-ruby.rb +2 -5
- data/prefab-cloud-ruby.gemspec +7 -9
- data/test/support/common_helpers.rb +14 -13
- data/test/support/mock_base_client.rb +0 -1
- data/test/test_client.rb +1 -10
- data/test/test_config_client.rb +1 -2
- data/test/test_context_shape_aggregator.rb +2 -5
- data/test/test_criteria_evaluator.rb +0 -4
- data/test/test_integration.rb +1 -1
- data/test/test_internal_logger.rb +25 -0
- data/test/test_log_path_aggregator.rb +5 -10
- data/test/test_logger.rb +57 -453
- data/test/test_logger_initialization.rb +1 -1
- metadata +19 -9
- data/lib/prefab/log_subscribers/action_controller_subscriber.rb +0 -55
- data/lib/prefab/logging/formatter_base.rb +0 -21
- data/lib/prefab/sse_logger.rb +0 -14
- data/lib/prefab/static_logger.rb +0 -29
- data/test/test_action_controller.rb +0 -81
data/lib/prefab/logger_client.rb
CHANGED
@@ -1,99 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Prefab
|
4
|
-
class LoggerClient
|
4
|
+
class LoggerClient
|
5
5
|
SEP = '.'
|
6
6
|
BASE_KEY = 'log-level'
|
7
|
-
|
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 =>
|
13
|
-
PrefabProto::LogLevel::TRACE =>
|
14
|
-
PrefabProto::LogLevel::DEBUG =>
|
15
|
-
PrefabProto::LogLevel::INFO =>
|
16
|
-
PrefabProto::LogLevel::WARN =>
|
17
|
-
PrefabProto::LogLevel::ERROR =>
|
18
|
-
PrefabProto::LogLevel::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
|
22
|
-
|
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
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
200
|
-
|
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
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
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
|
data/lib/prefab/options.rb
CHANGED
@@ -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
|
data/lib/prefab/periodic_sync.rb
CHANGED
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
|
-
|
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)
|
data/lib/prefab-cloud-ruby.rb
CHANGED
@@ -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'
|
data/prefab-cloud-ruby.gemspec
CHANGED
@@ -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
|
+
# 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.
|
9
|
+
s.version = "1.6.0.pre1"
|
10
10
|
|
11
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
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-
|
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
|
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
|
-
|
159
|
-
|
160
|
-
|
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)
|
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
|
-
"
|
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
|
data/test/test_config_client.rb
CHANGED
@@ -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
|
-
"
|
128
|
-
"
|
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
|
data/test/test_integration.rb
CHANGED
@@ -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}"
|