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
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
|