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.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 216fce2170e0fc185a3a79d2f9b7ffa4830e966fc203dc97bcb9b69aa4d79fd0
|
4
|
+
data.tar.gz: c2e4ac474cd6b83b33042a9a0cc3ef95d3f96b3f2c3044884831215d4f3af418
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be331123d75a902d6a48a4fa0fb59eb3dbf74254d9671ab0f3b8d3507a6ac2958815e014494288c9e61c2469110dbfc8c374be7d958e3e7dd95142b7ced01cd1
|
7
|
+
data.tar.gz: c73394980ed15e9edf8e3b513bca62922bded72aacc3efc75f2a1915701c89c75aad7c70c534cc350c68bf25bfe77b123a819ea39e0bfc589d45eeca0bf9d209
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Unreleased
|
4
|
+
|
5
|
+
- Use semantic_logger for internal logging (#173)
|
6
|
+
- Remove Prefab::LoggerClient as a logger for end users (#173)
|
7
|
+
- Provide log_filter for end users (#173)
|
8
|
+
|
3
9
|
## 1.5.0 - 2024-02-12
|
4
10
|
|
5
11
|
- Fix potential inconsistent Context behavior (#172)
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -146,6 +146,8 @@ GEM
|
|
146
146
|
rdoc (6.3.3)
|
147
147
|
ruby-progressbar (1.11.0)
|
148
148
|
ruby2_keywords (0.0.4)
|
149
|
+
semantic_logger (4.15.0)
|
150
|
+
concurrent-ruby (~> 1.0)
|
149
151
|
semver2 (3.4.2)
|
150
152
|
simplecov (0.18.5)
|
151
153
|
docile (~> 1.1)
|
@@ -180,6 +182,7 @@ DEPENDENCIES
|
|
180
182
|
minitest-focus
|
181
183
|
minitest-reporters
|
182
184
|
rdoc
|
185
|
+
semantic_logger
|
183
186
|
simplecov
|
184
187
|
timecop
|
185
188
|
uuid
|
data/README.md
CHANGED
@@ -33,40 +33,49 @@ See full documentation https://docs.prefab.cloud/docs/ruby-sdk/ruby
|
|
33
33
|
Many ruby web servers fork. When the process is forked, the current realtime update stream is disconnected. If you're using Puma or Unicorn, do the following.
|
34
34
|
|
35
35
|
```ruby
|
36
|
-
#config/
|
37
|
-
|
38
|
-
$prefab.set_rails_loggers
|
36
|
+
#config/application.rb
|
37
|
+
Prefab.init # reads PREFAB_API_KEY env var
|
39
38
|
```
|
40
39
|
|
41
40
|
```ruby
|
42
41
|
#puma.rb
|
43
42
|
on_worker_boot do
|
44
|
-
|
45
|
-
$prefab.set_rails_loggers
|
43
|
+
Prefab.fork
|
46
44
|
end
|
47
45
|
```
|
48
46
|
|
49
47
|
```ruby
|
50
48
|
# unicorn.rb
|
51
49
|
after_fork do |server, worker|
|
52
|
-
|
53
|
-
$prefab.set_rails_loggers
|
50
|
+
Prefab.fork
|
54
51
|
end
|
55
52
|
```
|
56
53
|
|
57
54
|
## Logging & Debugging
|
58
55
|
|
59
|
-
|
56
|
+
To use dynamic logging. Install https://logger.rocketjob.io/rails.html and then add Prefab as a dynamic filter.
|
60
57
|
|
61
58
|
```
|
62
|
-
|
63
|
-
|
59
|
+
gem "amazing_print"
|
60
|
+
gem "rails_semantic_logger"
|
64
61
|
```
|
62
|
+
```ruby
|
63
|
+
#application.rb
|
64
|
+
SemanticLogger.default_level = :trace # Prefab will take over the filtering
|
65
|
+
SemanticLogger.add_appender(
|
66
|
+
io: $stdout,
|
67
|
+
formatter: Rails.env.development? ? :default : :json,
|
68
|
+
filter: Prefab.log_filter,
|
69
|
+
)
|
70
|
+
Prefab.init
|
71
|
+
````
|
65
72
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
```ruby
|
74
|
+
#puma.rb
|
75
|
+
on_worker_boot do
|
76
|
+
SemanticLogger.reopen
|
77
|
+
Prefab.fork
|
78
|
+
end
|
70
79
|
```
|
71
80
|
|
72
81
|
## Contributing to prefab-cloud-ruby
|
@@ -91,4 +100,4 @@ REMOTE_BRANCH=main LOCAL_BRANCH=main bundle exec rake release
|
|
91
100
|
|
92
101
|
## Copyright
|
93
102
|
|
94
|
-
Copyright (c)
|
103
|
+
Copyright (c) 2024 Prefab, Inc. See LICENSE.txt for further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0.pre1
|
data/lib/prefab/client.rb
CHANGED
@@ -4,9 +4,9 @@ require 'uuid'
|
|
4
4
|
|
5
5
|
module Prefab
|
6
6
|
class Client
|
7
|
+
LOG = Prefab::InternalLogger.new(self)
|
7
8
|
MAX_SLEEP_SEC = 10
|
8
9
|
BASE_SLEEP_SEC = 0.5
|
9
|
-
LOG = Prefab::InternalLogger.new(Client)
|
10
10
|
|
11
11
|
attr_reader :namespace, :interceptor, :api_key, :prefab_api_url, :options, :instance_hash
|
12
12
|
|
@@ -15,10 +15,6 @@ module Prefab
|
|
15
15
|
@namespace = @options.namespace
|
16
16
|
@stubs = {}
|
17
17
|
@instance_hash = UUID.new.generate
|
18
|
-
Prefab::LoggerClient.new(@options.logdev, formatter: @options.log_formatter,
|
19
|
-
prefix: @options.log_prefix,
|
20
|
-
log_path_aggregator: log_path_aggregator
|
21
|
-
)
|
22
18
|
|
23
19
|
if @options.local_only?
|
24
20
|
LOG.debug 'Prefab Running in Local Mode'
|
@@ -55,13 +51,12 @@ module Prefab
|
|
55
51
|
|
56
52
|
def log_path_aggregator
|
57
53
|
return nil if @options.collect_max_paths <= 0
|
58
|
-
|
59
54
|
@log_path_aggregator ||= LogPathAggregator.new(client: self, max_paths: @options.collect_max_paths,
|
60
55
|
sync_interval: @options.collect_sync_interval)
|
61
56
|
end
|
62
57
|
|
63
58
|
def log
|
64
|
-
Prefab::LoggerClient.
|
59
|
+
@log ||= Prefab::LoggerClient.new(client: self, log_path_aggregator: log_path_aggregator)
|
65
60
|
end
|
66
61
|
|
67
62
|
def context_shape_aggregator
|
data/lib/prefab/config_client.rb
CHANGED
@@ -2,14 +2,12 @@
|
|
2
2
|
|
3
3
|
module Prefab
|
4
4
|
class ConfigClient
|
5
|
+
LOG = Prefab::InternalLogger.new(self)
|
5
6
|
RECONNECT_WAIT = 5
|
6
7
|
DEFAULT_CHECKPOINT_FREQ_SEC = 60
|
7
8
|
SSE_READ_TIMEOUT = 300
|
8
9
|
STALE_CACHE_WARN_HOURS = 5
|
9
10
|
AUTH_USER = 'authuser'
|
10
|
-
LOGGING_KEY_PREFIX = "#{Prefab::LoggerClient::BASE_KEY}#{Prefab::LoggerClient::SEP}".freeze
|
11
|
-
LOG = Prefab::InternalLogger.new(ConfigClient)
|
12
|
-
|
13
11
|
def initialize(base_client, timeout)
|
14
12
|
@base_client = base_client
|
15
13
|
@options = base_client.options
|
@@ -23,11 +21,7 @@ module Prefab
|
|
23
21
|
@config_loader = Prefab::ConfigLoader.new(@base_client)
|
24
22
|
@config_resolver = Prefab::ConfigResolver.new(@base_client, @config_loader)
|
25
23
|
|
26
|
-
@initialization_lock = Concurrent::
|
27
|
-
LOG.debug 'Initialize ConfigClient: AcquireWriteLock'
|
28
|
-
@initialization_lock.acquire_write_lock
|
29
|
-
LOG.debug 'Initialize ConfigClient: AcquiredWriteLock'
|
30
|
-
@initialized_future = Concurrent::Future.execute { @initialization_lock.acquire_read_lock }
|
24
|
+
@initialization_lock = Concurrent::CountDownLatch.new(1)
|
31
25
|
|
32
26
|
if @options.local_only?
|
33
27
|
finish_init!(:local_only, nil)
|
@@ -77,6 +71,10 @@ module Prefab
|
|
77
71
|
end
|
78
72
|
end
|
79
73
|
|
74
|
+
def initialized?
|
75
|
+
@initialization_lock.count <= 0
|
76
|
+
end
|
77
|
+
|
80
78
|
private
|
81
79
|
|
82
80
|
def raw(key)
|
@@ -93,14 +91,13 @@ module Prefab
|
|
93
91
|
|
94
92
|
def _get(key, properties)
|
95
93
|
# wait timeout sec for the initialization to be complete
|
96
|
-
@
|
97
|
-
if
|
94
|
+
success = @initialization_lock.wait(@options.initialization_timeout_sec)
|
95
|
+
if !success
|
98
96
|
unless @options.on_init_failure == Prefab::Options::ON_INITIALIZATION_FAILURE::RETURN
|
99
97
|
raise Prefab::Errors::InitializationTimeoutError.new(@options.initialization_timeout_sec, key)
|
100
98
|
end
|
101
99
|
|
102
100
|
LOG.warn("Couldn't Initialize In #{@options.initialization_timeout_sec}. Key #{key}. Returning what we have")
|
103
|
-
@initialization_lock.release_write_lock
|
104
101
|
end
|
105
102
|
|
106
103
|
@config_resolver.get key, properties
|
@@ -144,7 +141,7 @@ module Prefab
|
|
144
141
|
false
|
145
142
|
end
|
146
143
|
rescue Faraday::ConnectionFailed => e
|
147
|
-
if
|
144
|
+
if !initialized?
|
148
145
|
LOG.warn "Connection Fail loading #{source} checkpoint."
|
149
146
|
else
|
150
147
|
LOG.debug "Connection Fail loading #{source} checkpoint."
|
@@ -251,12 +248,11 @@ module Prefab
|
|
251
248
|
end
|
252
249
|
|
253
250
|
def finish_init!(source, project_id)
|
254
|
-
return
|
251
|
+
return if initialized?
|
255
252
|
|
256
253
|
LOG.debug "Unlocked Config via #{source}"
|
257
|
-
@initialization_lock.
|
254
|
+
@initialization_lock.count_down
|
258
255
|
|
259
|
-
Prefab::LoggerClient.instance.config_client = self
|
260
256
|
presenter = Prefab::ConfigClientPresenter.new(
|
261
257
|
size: @config_resolver.local_store.size,
|
262
258
|
source: source,
|
@@ -281,7 +277,7 @@ module Prefab
|
|
281
277
|
@streaming_thread = SSE::Client.new(url,
|
282
278
|
headers: headers,
|
283
279
|
read_timeout: SSE_READ_TIMEOUT,
|
284
|
-
logger: Prefab::
|
280
|
+
logger: Prefab::InternalLogger.new(SSE::Client)) do |client|
|
285
281
|
client.on_event do |event|
|
286
282
|
configs = PrefabProto::Configs.decode(Base64.decode64(event.data))
|
287
283
|
load_configs(configs, :sse)
|
data/lib/prefab/config_loader.rb
CHANGED
@@ -7,7 +7,7 @@ module Prefab
|
|
7
7
|
# This class evaluates a config's criteria. `evaluate` returns the value of
|
8
8
|
# the first match based on the provided properties.
|
9
9
|
class CriteriaEvaluator
|
10
|
-
LOG = Prefab::InternalLogger.new(
|
10
|
+
LOG = Prefab::InternalLogger.new(self)
|
11
11
|
NAMESPACE_KEY = 'NAMESPACE'
|
12
12
|
NO_MATCHING_ROWS = [].freeze
|
13
13
|
|
@@ -22,7 +22,7 @@ module Prefab
|
|
22
22
|
def evaluate(properties)
|
23
23
|
rtn = evaluate_for_env(@project_env_id, properties) ||
|
24
24
|
evaluate_for_env(0, properties)
|
25
|
-
LOG.
|
25
|
+
LOG.trace "Eval Key #{@config.key} Result #{rtn&.reportable_value} with #{properties.to_h}" unless @config.config_type == :LOG_LEVEL
|
26
26
|
rtn
|
27
27
|
end
|
28
28
|
|
@@ -105,7 +105,7 @@ module Prefab
|
|
105
105
|
def in_segment?(criterion, properties)
|
106
106
|
segment = @resolver.get(criterion.value_to_match.string, properties)
|
107
107
|
|
108
|
-
|
108
|
+
LOG.info("Segment #{criterion.value_to_match.string} not found") unless segment
|
109
109
|
|
110
110
|
segment&.report_and_return(@base_client.evaluation_summary_aggregator)
|
111
111
|
end
|
@@ -8,8 +8,7 @@ module Prefab
|
|
8
8
|
# server at a regular interval defined by `sync_interval`.
|
9
9
|
class EvaluationSummaryAggregator
|
10
10
|
include Prefab::PeriodicSync
|
11
|
-
|
12
|
-
LOG = Prefab::InternalLogger.new(EvaluationSummaryAggregator)
|
11
|
+
LOG = Prefab::InternalLogger.new(self)
|
13
12
|
|
14
13
|
attr_reader :data
|
15
14
|
|
@@ -9,8 +9,7 @@ module Prefab
|
|
9
9
|
# It shouldn't send the same context more than once per hour.
|
10
10
|
class ExampleContextsAggregator
|
11
11
|
include Prefab::PeriodicSync
|
12
|
-
|
13
|
-
LOG = Prefab::InternalLogger.new(ExampleContextsAggregator)
|
12
|
+
LOG = Prefab::InternalLogger.new(self)
|
14
13
|
|
15
14
|
attr_reader :data, :cache
|
16
15
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module Prefab
|
4
4
|
class FeatureFlagClient
|
5
|
+
LOG = Prefab::InternalLogger.new(self)
|
5
6
|
def initialize(base_client)
|
6
7
|
@base_client = base_client
|
7
8
|
end
|
@@ -35,7 +36,7 @@ module Prefab
|
|
35
36
|
|
36
37
|
variant.bool
|
37
38
|
rescue StandardError
|
38
|
-
|
39
|
+
LOG.info("is_on? methods only work for boolean feature flags variants. This feature flags variant is '#{variant}'. Returning false")
|
39
40
|
false
|
40
41
|
end
|
41
42
|
end
|
@@ -1,16 +1,42 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Prefab
|
4
|
-
class InternalLogger <
|
5
|
-
|
2
|
+
class InternalLogger < SemanticLogger::Logger
|
3
|
+
|
4
|
+
def initialize(klass)
|
5
|
+
super(klass, :warn)
|
6
|
+
instances << self
|
7
|
+
end
|
6
8
|
|
7
|
-
def
|
8
|
-
if
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def log(log, message = nil, progname = nil, &block)
|
10
|
+
return if recurse_check[local_log_id]
|
11
|
+
recurse_check[local_log_id] = true
|
12
|
+
begin
|
13
|
+
super(log, message, progname, &block)
|
14
|
+
ensure
|
15
|
+
recurse_check[local_log_id] = false
|
12
16
|
end
|
13
|
-
|
17
|
+
end
|
18
|
+
|
19
|
+
def local_log_id
|
20
|
+
Thread.current.__id__
|
21
|
+
end
|
22
|
+
|
23
|
+
# Our client outputs debug logging,
|
24
|
+
# but if you aren't using Prefab logging this could be too chatty.
|
25
|
+
# If you aren't using prefab log filter, only log warn level and above
|
26
|
+
def self.using_prefab_log_filter!
|
27
|
+
@@instances.each do |l|
|
28
|
+
l.level = :trace
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def instances
|
35
|
+
@@instances ||= []
|
36
|
+
end
|
37
|
+
|
38
|
+
def recurse_check
|
39
|
+
@recurse_check ||=Concurrent::Map.new(initial_capacity: 2)
|
14
40
|
end
|
15
41
|
end
|
16
42
|
end
|