prefab-cloud-ruby 0.21.0 → 0.22.0
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/.github/workflows/ruby.yml +1 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +8 -0
- data/README.md +11 -9
- data/VERSION +1 -1
- data/lib/prefab/cancellable_interceptor.rb +3 -3
- data/lib/prefab/client.rb +23 -7
- data/lib/prefab/config_client.rb +16 -16
- data/lib/prefab/config_loader.rb +1 -1
- data/lib/prefab/internal_logger.rb +1 -1
- data/lib/prefab/log_path_collector.rb +98 -0
- data/lib/prefab/logger_client.rb +20 -13
- data/lib/prefab/options.rb +22 -3
- data/lib/prefab/yaml_config_parser.rb +2 -2
- data/lib/prefab_pb.rb +21 -0
- data/lib/prefab_services_pb.rb +14 -0
- data/prefab-cloud-ruby.gemspec +8 -3
- data/test/test_client.rb +24 -0
- data/test/test_log_path_collector.rb +56 -0
- data/test/test_logger.rb +13 -13
- data/test/test_options.rb +32 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5df09f0991b0d46c29ce33bc010116733960a5004ede7dd5a0df868b15e4a29
|
4
|
+
data.tar.gz: ded97aa4f8e2dc37e7581ee5d29c7bcb3eff88e7aa8f72fedb7bd9710050bfec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e44b86fabd88830aed86910f4ff9175df14a06dc30b19821c741c691a9637bcff69870de0d816c2348a650dc9eb5b3a3c54a4452f71039aaab2f042086c3536
|
7
|
+
data.tar.gz: d81cf8af71e9aa189e7ba8b7078af6472df4dc6e3b08a33771163363424986d8b194c0ed88fa961217758ee9e5d21ca5604810f96db53a80366d72df606cb6d7
|
data/.github/workflows/ruby.yml
CHANGED
data/Gemfile
CHANGED
@@ -6,6 +6,7 @@ gem 'googleapis-common-protos-types', platforms: :ruby
|
|
6
6
|
gem 'google-protobuf', platforms: :ruby
|
7
7
|
gem 'grpc', platforms: :ruby
|
8
8
|
gem 'ld-eventsource'
|
9
|
+
gem 'uuid'
|
9
10
|
|
10
11
|
group :development do
|
11
12
|
gem 'benchmark-ips'
|
@@ -20,4 +21,5 @@ group :test do
|
|
20
21
|
gem 'minitest'
|
21
22
|
gem 'minitest-focus'
|
22
23
|
gem 'minitest-reporters'
|
24
|
+
gem 'timecop'
|
23
25
|
end
|
data/Gemfile.lock
CHANGED
@@ -68,6 +68,8 @@ GEM
|
|
68
68
|
llhttp-ffi (0.3.1)
|
69
69
|
ffi-compiler (~> 1.0)
|
70
70
|
rake (~> 13.0)
|
71
|
+
macaddr (1.7.2)
|
72
|
+
systemu (~> 2.6.5)
|
71
73
|
mini_portile2 (2.8.0)
|
72
74
|
minitest (5.16.2)
|
73
75
|
minitest-focus (1.3.1)
|
@@ -103,10 +105,14 @@ GEM
|
|
103
105
|
docile (~> 1.1)
|
104
106
|
simplecov-html (~> 0.11)
|
105
107
|
simplecov-html (0.12.3)
|
108
|
+
systemu (2.6.5)
|
106
109
|
thread_safe (0.3.6)
|
110
|
+
timecop (0.9.4)
|
107
111
|
unf (0.1.4)
|
108
112
|
unf_ext
|
109
113
|
unf_ext (0.0.8)
|
114
|
+
uuid (2.3.9)
|
115
|
+
macaddr (~> 1.0)
|
110
116
|
|
111
117
|
PLATFORMS
|
112
118
|
ruby
|
@@ -127,6 +133,8 @@ DEPENDENCIES
|
|
127
133
|
minitest-reporters
|
128
134
|
rdoc
|
129
135
|
simplecov
|
136
|
+
timecop
|
137
|
+
uuid
|
130
138
|
|
131
139
|
BUNDLED WITH
|
132
140
|
2.3.5
|
data/README.md
CHANGED
@@ -3,18 +3,20 @@ Ruby Client for Prefab FeatureFlags, Config as a Service: https://www.prefab.clo
|
|
3
3
|
|
4
4
|
```ruby
|
5
5
|
client = Prefab::Client.new
|
6
|
-
@feature_flags = client.feature_flag_client
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
lookup_key = "user-123"
|
8
|
+
identity_attributes = {
|
9
|
+
team_id: 432,
|
10
|
+
user_id: 123,
|
11
|
+
subscription_level: 'pro',
|
12
|
+
email: "alice@example.com"
|
13
|
+
}
|
10
14
|
|
11
|
-
|
12
|
-
puts @feature_flags.feature_is_on? "MyFeature" # returns yes 10 pct of the time
|
15
|
+
result = client.enabled? "my-first-feature-flag", lookup_key, identity_attributes
|
13
16
|
|
14
|
-
|
15
|
-
puts @feature_flags.feature_is_on? "MyFeature", "user:1123"
|
17
|
+
puts "my-first-feature-flag is: #{result} for #{lookup_key}"
|
16
18
|
```
|
17
|
-
See full documentation https://
|
19
|
+
See full documentation https://docs.prefab.cloud/docs/ruby-sdk/ruby
|
18
20
|
|
19
21
|
## Supports
|
20
22
|
|
@@ -74,5 +76,5 @@ REMOTE_BRANCH=main LOCAL_BRANCH=main bundle exec rake release
|
|
74
76
|
|
75
77
|
## Copyright
|
76
78
|
|
77
|
-
Copyright (c)
|
79
|
+
Copyright (c) 2023 Jeff Dwyer. See LICENSE.txt for
|
78
80
|
further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.22.0
|
@@ -13,16 +13,16 @@ module Prefab
|
|
13
13
|
i = 0
|
14
14
|
while i < WAIT_SEC
|
15
15
|
if @call.instance_variable_get('@wrapped').cancelled?
|
16
|
-
@base_client.log_internal Logger::DEBUG, 'Cancelled streaming.'
|
16
|
+
@base_client.log_internal ::Logger::DEBUG, 'Cancelled streaming.'
|
17
17
|
return
|
18
18
|
else
|
19
|
-
@base_client.log_internal Logger::DEBUG, 'Unable to cancel streaming. Trying again'
|
19
|
+
@base_client.log_internal ::Logger::DEBUG, 'Unable to cancel streaming. Trying again'
|
20
20
|
@call.instance_variable_get('@wrapped').instance_variable_get('@call').cancel
|
21
21
|
i += 1
|
22
22
|
sleep(1)
|
23
23
|
end
|
24
24
|
end
|
25
|
-
@base_client.log_internal Logger::INFO, 'Unable to cancel streaming.'
|
25
|
+
@base_client.log_internal ::Logger::INFO, 'Unable to cancel streaming.'
|
26
26
|
end
|
27
27
|
|
28
28
|
def request_response(request:, call:, method:, metadata:, &block)
|
data/lib/prefab/client.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'uuid'
|
4
|
+
|
3
5
|
module Prefab
|
4
6
|
class Client
|
5
7
|
MAX_SLEEP_SEC = 10
|
@@ -13,16 +15,18 @@ module Prefab
|
|
13
15
|
attr_reader :api_key
|
14
16
|
attr_reader :prefab_api_url
|
15
17
|
attr_reader :options
|
18
|
+
attr_reader :instance_hash
|
16
19
|
|
17
20
|
def initialize(options = Prefab::Options.new)
|
18
|
-
@options = options
|
21
|
+
@options = options.is_a?(Prefab::Options) ? options : Prefab::Options.new(options)
|
19
22
|
@shared_cache = @options.shared_cache
|
20
23
|
@stats = @options.stats
|
21
24
|
@namespace = @options.namespace
|
22
25
|
@stubs = {}
|
26
|
+
@instance_hash = UUID.new.generate
|
23
27
|
|
24
28
|
if @options.local_only?
|
25
|
-
log_internal Logger::INFO, 'Prefab Running in Local Mode'
|
29
|
+
log_internal ::Logger::INFO, 'Prefab Running in Local Mode'
|
26
30
|
else
|
27
31
|
@api_key = @options.api_key
|
28
32
|
raise Prefab::Errors::InvalidApiKeyError, @api_key if @api_key.nil? || @api_key.empty? || api_key.count('-') < 1
|
@@ -30,7 +34,7 @@ module Prefab
|
|
30
34
|
@interceptor = Prefab::AuthInterceptor.new(@api_key)
|
31
35
|
@prefab_api_url = @options.prefab_api_url
|
32
36
|
@prefab_grpc_url = @options.prefab_grpc_url
|
33
|
-
log_internal Logger::INFO,
|
37
|
+
log_internal ::Logger::INFO,
|
34
38
|
"Prefab Connecting to: #{@prefab_api_url} and #{@prefab_grpc_url} Secure: #{http_secure?}"
|
35
39
|
at_exit do
|
36
40
|
channel.destroy
|
@@ -55,9 +59,17 @@ module Prefab
|
|
55
59
|
@feature_flag_client ||= Prefab::FeatureFlagClient.new(self)
|
56
60
|
end
|
57
61
|
|
62
|
+
def log_path_collector
|
63
|
+
return nil if @options.collect_max_paths <= 0
|
64
|
+
|
65
|
+
@log_path_collector ||= LogPathCollector.new(client: self, max_paths: @options.collect_max_paths,
|
66
|
+
sync_interval: @options.collect_sync_interval)
|
67
|
+
end
|
68
|
+
|
58
69
|
def log
|
59
70
|
@logger_client ||= Prefab::LoggerClient.new(@options.logdev, formatter: @options.log_formatter,
|
60
|
-
prefix: @options.log_prefix
|
71
|
+
prefix: @options.log_prefix,
|
72
|
+
log_path_collector: log_path_collector)
|
61
73
|
end
|
62
74
|
|
63
75
|
def log_internal(level, msg, path = nil)
|
@@ -65,6 +77,9 @@ module Prefab
|
|
65
77
|
end
|
66
78
|
|
67
79
|
def request(service, method, req_options: {}, params: {})
|
80
|
+
# Future-proofing since we previously bumped into a conflict with a service with a `send` method
|
81
|
+
raise ArgumentError, 'Cannot call public_send on an grpc service in Ruby' if method.to_s == 'public_send'
|
82
|
+
|
68
83
|
opts = { timeout: 10 }.merge(req_options)
|
69
84
|
|
70
85
|
attempts = 0
|
@@ -72,16 +87,17 @@ module Prefab
|
|
72
87
|
|
73
88
|
begin
|
74
89
|
attempts += 1
|
75
|
-
|
90
|
+
|
91
|
+
stub_for(service, opts[:timeout]).public_send(method, *params)
|
76
92
|
rescue StandardError => e
|
77
|
-
log_internal Logger::WARN, e
|
93
|
+
log_internal ::Logger::WARN, e
|
78
94
|
|
79
95
|
raise e if Time.now - start_time > opts[:timeout]
|
80
96
|
|
81
97
|
sleep_seconds = [BASE_SLEEP_SEC * (2**(attempts - 1)), MAX_SLEEP_SEC].min
|
82
98
|
sleep_seconds *= (0.5 * (1 + rand))
|
83
99
|
sleep_seconds = [BASE_SLEEP_SEC, sleep_seconds].max
|
84
|
-
log_internal Logger::INFO, "Sleep #{sleep_seconds} and Reset #{service} #{method}"
|
100
|
+
log_internal ::Logger::INFO, "Sleep #{sleep_seconds} and Reset #{service} #{method}"
|
85
101
|
sleep sleep_seconds
|
86
102
|
reset!
|
87
103
|
retry
|
data/lib/prefab/config_client.rb
CHANGED
@@ -10,7 +10,7 @@ module Prefab
|
|
10
10
|
def initialize(base_client, timeout)
|
11
11
|
@base_client = base_client
|
12
12
|
@options = base_client.options
|
13
|
-
@base_client.log_internal Logger::DEBUG, 'Initialize ConfigClient'
|
13
|
+
@base_client.log_internal ::Logger::DEBUG, 'Initialize ConfigClient'
|
14
14
|
@timeout = timeout
|
15
15
|
|
16
16
|
@stream_lock = Concurrent::ReadWriteLock.new
|
@@ -21,9 +21,9 @@ module Prefab
|
|
21
21
|
@config_resolver = Prefab::ConfigResolver.new(@base_client, @config_loader)
|
22
22
|
|
23
23
|
@initialization_lock = Concurrent::ReadWriteLock.new
|
24
|
-
@base_client.log_internal Logger::DEBUG, 'Initialize ConfigClient: AcquireWriteLock'
|
24
|
+
@base_client.log_internal ::Logger::DEBUG, 'Initialize ConfigClient: AcquireWriteLock'
|
25
25
|
@initialization_lock.acquire_write_lock
|
26
|
-
@base_client.log_internal Logger::DEBUG, 'Initialize ConfigClient: AcquiredWriteLock'
|
26
|
+
@base_client.log_internal ::Logger::DEBUG, 'Initialize ConfigClient: AcquiredWriteLock'
|
27
27
|
@initialized_future = Concurrent::Future.execute { @initialization_lock.acquire_read_lock }
|
28
28
|
|
29
29
|
@cancellable_interceptor = Prefab::CancellableInterceptor.new(@base_client)
|
@@ -99,7 +99,7 @@ module Prefab
|
|
99
99
|
raise Prefab::Errors::InitializationTimeoutError.new(@options.initialization_timeout_sec, key)
|
100
100
|
end
|
101
101
|
|
102
|
-
@base_client.log_internal Logger::WARN,
|
102
|
+
@base_client.log_internal ::Logger::WARN,
|
103
103
|
"Couldn't Initialize In #{@options.initialization_timeout_sec}. Key #{key}. Returning what we have"
|
104
104
|
@initialization_lock.release_write_lock
|
105
105
|
|
@@ -119,13 +119,13 @@ module Prefab
|
|
119
119
|
|
120
120
|
return if success
|
121
121
|
|
122
|
-
@base_client.log_internal Logger::INFO, 'LoadCheckpoint: Fallback to GRPC API'
|
122
|
+
@base_client.log_internal ::Logger::INFO, 'LoadCheckpoint: Fallback to GRPC API'
|
123
123
|
|
124
124
|
success = load_checkpoint_from_grpc_api
|
125
125
|
|
126
126
|
return if success
|
127
127
|
|
128
|
-
@base_client.log_internal Logger::WARN, 'No success loading checkpoints'
|
128
|
+
@base_client.log_internal ::Logger::WARN, 'No success loading checkpoints'
|
129
129
|
end
|
130
130
|
|
131
131
|
def load_checkpoint_from_grpc_api
|
@@ -135,9 +135,9 @@ module Prefab
|
|
135
135
|
load_configs(resp, :remote_api_grpc)
|
136
136
|
true
|
137
137
|
rescue GRPC::Unauthenticated
|
138
|
-
@base_client.log_internal Logger::WARN, 'Unauthenticated'
|
138
|
+
@base_client.log_internal ::Logger::WARN, 'Unauthenticated'
|
139
139
|
rescue StandardError => e
|
140
|
-
@base_client.log_internal Logger::WARN, "Unexpected grpc_api problem loading checkpoint #{e}"
|
140
|
+
@base_client.log_internal ::Logger::WARN, "Unexpected grpc_api problem loading checkpoint #{e}"
|
141
141
|
false
|
142
142
|
end
|
143
143
|
|
@@ -162,11 +162,11 @@ module Prefab
|
|
162
162
|
load_configs(configs, source)
|
163
163
|
true
|
164
164
|
else
|
165
|
-
@base_client.log_internal Logger::INFO, "Checkpoint #{source} failed to load. Response #{resp.status}"
|
165
|
+
@base_client.log_internal ::Logger::INFO, "Checkpoint #{source} failed to load. Response #{resp.status}"
|
166
166
|
false
|
167
167
|
end
|
168
168
|
rescue StandardError => e
|
169
|
-
@base_client.log_internal Logger::WARN, "Unexpected #{source} problem loading checkpoint #{e} #{conn}"
|
169
|
+
@base_client.log_internal ::Logger::WARN, "Unexpected #{source} problem loading checkpoint #{e} #{conn}"
|
170
170
|
false
|
171
171
|
end
|
172
172
|
|
@@ -180,10 +180,10 @@ module Prefab
|
|
180
180
|
@config_loader.set(config, source)
|
181
181
|
end
|
182
182
|
if @config_loader.highwater_mark > starting_highwater_mark
|
183
|
-
@base_client.log_internal Logger::INFO,
|
183
|
+
@base_client.log_internal ::Logger::INFO,
|
184
184
|
"Found new checkpoint with highwater id #{@config_loader.highwater_mark} from #{source} in project #{project_id} environment: #{project_env_id} and namespace: '#{@namespace}'"
|
185
185
|
else
|
186
|
-
@base_client.log_internal Logger::DEBUG,
|
186
|
+
@base_client.log_internal ::Logger::DEBUG,
|
187
187
|
"Checkpoint with highwater id #{@config_loader.highwater_mark} from #{source}. No changes.", 'load_configs'
|
188
188
|
end
|
189
189
|
@base_client.stats.increment('prefab.config.checkpoint.load')
|
@@ -201,7 +201,7 @@ module Prefab
|
|
201
201
|
delta = @checkpoint_freq_secs - (Time.now - started_at)
|
202
202
|
sleep(delta) if delta > 0
|
203
203
|
rescue StandardError => e
|
204
|
-
@base_client.log_internal Logger::INFO, "Issue Checkpointing #{e.message}"
|
204
|
+
@base_client.log_internal ::Logger::INFO, "Issue Checkpointing #{e.message}"
|
205
205
|
end
|
206
206
|
end
|
207
207
|
end
|
@@ -209,10 +209,10 @@ module Prefab
|
|
209
209
|
def finish_init!(source)
|
210
210
|
return unless @initialization_lock.write_locked?
|
211
211
|
|
212
|
-
@base_client.log_internal Logger::INFO, "Unlocked Config via #{source}"
|
212
|
+
@base_client.log_internal ::Logger::INFO, "Unlocked Config via #{source}"
|
213
213
|
@initialization_lock.release_write_lock
|
214
214
|
@base_client.log.set_config_client(self)
|
215
|
-
@base_client.log_internal Logger::INFO, to_s
|
215
|
+
@base_client.log_internal ::Logger::INFO, to_s
|
216
216
|
end
|
217
217
|
|
218
218
|
def start_sse_streaming_connection_thread(start_at_id)
|
@@ -223,7 +223,7 @@ module Prefab
|
|
223
223
|
"Authorization": "Basic #{auth_string}"
|
224
224
|
}
|
225
225
|
url = "#{@base_client.prefab_api_url}/api/v1/sse/config"
|
226
|
-
@base_client.log_internal Logger::INFO, "SSE Streaming Connect to #{url} start_at #{start_at_id}"
|
226
|
+
@base_client.log_internal ::Logger::INFO, "SSE Streaming Connect to #{url} start_at #{start_at_id}"
|
227
227
|
@streaming_thread = SSE::Client.new(url,
|
228
228
|
headers: headers,
|
229
229
|
read_timeout: SSE_READ_TIMEOUT,
|
data/lib/prefab/config_loader.rb
CHANGED
@@ -29,7 +29,7 @@ module Prefab
|
|
29
29
|
@api_config.delete(config.key)
|
30
30
|
else
|
31
31
|
if @api_config[config.key]
|
32
|
-
@base_client.log_internal Logger::DEBUG,
|
32
|
+
@base_client.log_internal ::Logger::DEBUG,
|
33
33
|
"Replace #{config.key} with value from #{source} #{@api_config[config.key][:config].id} -> #{config.id}"
|
34
34
|
end
|
35
35
|
@api_config[config.key] = { source: source, config: config }
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prefab
|
4
|
+
class LogPathCollector
|
5
|
+
INCREMENT = ->(count) { (count || 0) + 1 }
|
6
|
+
|
7
|
+
SEVERITY_KEY = {
|
8
|
+
::Logger::DEBUG => 'debugs',
|
9
|
+
::Logger::INFO => 'infos',
|
10
|
+
::Logger::WARN => 'warns',
|
11
|
+
::Logger::ERROR => 'errors',
|
12
|
+
::Logger::FATAL => 'fatals'
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
def initialize(client:, max_paths:, sync_interval:)
|
16
|
+
@max_paths = max_paths
|
17
|
+
@sync_interval = sync_interval
|
18
|
+
@client = client
|
19
|
+
@start_at = now
|
20
|
+
|
21
|
+
@pool = Concurrent::ThreadPoolExecutor.new(
|
22
|
+
fallback_policy: :discard,
|
23
|
+
max_queue: 5,
|
24
|
+
max_threads: 4,
|
25
|
+
min_threads: 1,
|
26
|
+
name: 'prefab-log-paths'
|
27
|
+
)
|
28
|
+
|
29
|
+
@paths = Concurrent::Map.new
|
30
|
+
|
31
|
+
start_periodic_sync
|
32
|
+
end
|
33
|
+
|
34
|
+
def push(path, severity)
|
35
|
+
return unless @paths.size < @max_paths
|
36
|
+
|
37
|
+
@paths.compute([path, severity], &INCREMENT)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def sync
|
43
|
+
return if @paths.size.zero?
|
44
|
+
|
45
|
+
log_internal "Syncing #{@paths.size} paths"
|
46
|
+
|
47
|
+
flush
|
48
|
+
end
|
49
|
+
|
50
|
+
def flush
|
51
|
+
to_ship = @paths.dup
|
52
|
+
@paths.clear
|
53
|
+
|
54
|
+
start_at_was = @start_at
|
55
|
+
@start_at = now
|
56
|
+
|
57
|
+
@pool.post do
|
58
|
+
log_internal "Uploading stats for #{to_ship.size} paths"
|
59
|
+
|
60
|
+
aggregate = Hash.new { |h, k| h[k] = Prefab::Logger.new }
|
61
|
+
|
62
|
+
to_ship.each do |(path, severity), count|
|
63
|
+
aggregate[path][SEVERITY_KEY[severity]] = count
|
64
|
+
aggregate[path]['logger_name'] = path
|
65
|
+
end
|
66
|
+
|
67
|
+
loggers = Prefab::Loggers.new(
|
68
|
+
loggers: aggregate.values,
|
69
|
+
start_at: start_at_was,
|
70
|
+
end_at: now,
|
71
|
+
instance_hash: @client.instance_hash,
|
72
|
+
namespace: @client.namespace
|
73
|
+
)
|
74
|
+
|
75
|
+
@client.request Prefab::LoggerReportingService, :send, req_options: {}, params: loggers
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def start_periodic_sync
|
80
|
+
Thread.new do
|
81
|
+
log_internal "Initialized log path collector instance_hash=#{@client.instance_hash} max_paths=#{@max_paths} sync_interval=#{@sync_interval}"
|
82
|
+
|
83
|
+
loop do
|
84
|
+
sleep @sync_interval
|
85
|
+
sync
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def log_internal(message)
|
91
|
+
@client.log.log_internal message, 'log_path_collector', nil, ::Logger::INFO
|
92
|
+
end
|
93
|
+
|
94
|
+
def now
|
95
|
+
(Time.now.utc.to_f * 1000).to_i
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/prefab/logger_client.rb
CHANGED
@@ -1,33 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'prefab/log_path_collector'
|
4
|
+
|
3
5
|
module Prefab
|
4
|
-
class LoggerClient < Logger
|
6
|
+
class LoggerClient < ::Logger
|
5
7
|
SEP = '.'
|
6
8
|
BASE_KEY = 'log-level'
|
7
9
|
UNKNOWN_PATH = 'unknown.'
|
8
10
|
INTERNAL_PREFIX = 'cloud.prefab.client'
|
9
11
|
|
10
12
|
LOG_LEVEL_LOOKUPS = {
|
11
|
-
Prefab::LogLevel::NOT_SET_LOG_LEVEL => Logger::DEBUG,
|
12
|
-
Prefab::LogLevel::TRACE => Logger::DEBUG,
|
13
|
-
Prefab::LogLevel::DEBUG => Logger::DEBUG,
|
14
|
-
Prefab::LogLevel::INFO => Logger::INFO,
|
15
|
-
Prefab::LogLevel::WARN => Logger::WARN,
|
16
|
-
Prefab::LogLevel::ERROR => Logger::ERROR,
|
17
|
-
Prefab::LogLevel::FATAL => Logger::FATAL
|
13
|
+
Prefab::LogLevel::NOT_SET_LOG_LEVEL => ::Logger::DEBUG,
|
14
|
+
Prefab::LogLevel::TRACE => ::Logger::DEBUG,
|
15
|
+
Prefab::LogLevel::DEBUG => ::Logger::DEBUG,
|
16
|
+
Prefab::LogLevel::INFO => ::Logger::INFO,
|
17
|
+
Prefab::LogLevel::WARN => ::Logger::WARN,
|
18
|
+
Prefab::LogLevel::ERROR => ::Logger::ERROR,
|
19
|
+
Prefab::LogLevel::FATAL => ::Logger::FATAL
|
18
20
|
}
|
19
21
|
|
20
|
-
def initialize(logdev, formatter: nil, prefix: nil)
|
22
|
+
def initialize(logdev, log_path_collector: nil, formatter: nil, prefix: nil)
|
21
23
|
super(logdev)
|
22
24
|
self.formatter = formatter
|
23
25
|
@config_client = BootstrappingConfigClient.new
|
24
26
|
@silences = Concurrent::Map.new(initial_capacity: 2)
|
25
|
-
@prefix = prefix
|
27
|
+
@prefix = "#{prefix}#{prefix && '.'}"
|
28
|
+
|
29
|
+
@log_path_collector = log_path_collector
|
26
30
|
end
|
27
31
|
|
28
32
|
def add(severity, message = nil, progname = nil, loc, &block)
|
29
|
-
|
30
|
-
path =
|
33
|
+
path_loc = get_loc_path(loc)
|
34
|
+
path = @prefix + path_loc
|
35
|
+
|
36
|
+
@log_path_collector&.push(path_loc, severity)
|
31
37
|
|
32
38
|
log(message, path, progname, severity, &block)
|
33
39
|
end
|
@@ -43,7 +49,8 @@ module Prefab
|
|
43
49
|
end
|
44
50
|
|
45
51
|
def log(message, path, progname, severity)
|
46
|
-
severity ||= Logger::UNKNOWN
|
52
|
+
severity ||= ::Logger::UNKNOWN
|
53
|
+
|
47
54
|
return true if @logdev.nil? || severity < level_of(path) || @silences[local_log_id]
|
48
55
|
|
49
56
|
progname = "#{path}: #{progname || @progname}"
|
data/lib/prefab/options.rb
CHANGED
@@ -17,6 +17,7 @@ module Prefab
|
|
17
17
|
attr_reader :prefab_config_override_dir
|
18
18
|
attr_reader :prefab_config_classpath_dir
|
19
19
|
attr_reader :prefab_envs
|
20
|
+
attr_reader :collect_sync_interval
|
20
21
|
|
21
22
|
DEFAULT_LOG_FORMATTER = proc { |severity, datetime, progname, msg|
|
22
23
|
"#{severity.ljust(5)} #{datetime}:#{' ' if progname}#{progname} #{msg}\n"
|
@@ -37,7 +38,10 @@ module Prefab
|
|
37
38
|
LOCAL_ONLY = 2
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
+
DEFAULT_MAX_PATHS = 1_000
|
42
|
+
DEFAULT_SYNC_INTERVAL = 60
|
43
|
+
|
44
|
+
private def init(
|
41
45
|
api_key: ENV['PREFAB_API_KEY'],
|
42
46
|
logdev: $stdout,
|
43
47
|
stats: NoopStats.new, # receives increment("prefab.limitcheck", {:tags=>["policy_group:page_view", "pass:true"]})
|
@@ -55,9 +59,11 @@ module Prefab
|
|
55
59
|
prefab_datasources: ENV['PREFAB_DATASOURCES'] == 'LOCAL_ONLY' ? DATASOURCES::LOCAL_ONLY : DATASOURCES::ALL,
|
56
60
|
prefab_config_override_dir: Dir.home,
|
57
61
|
prefab_config_classpath_dir: '.',
|
58
|
-
prefab_envs: ENV['PREFAB_ENVS'].nil? ? [] : ENV['PREFAB_ENVS'].split(',')
|
62
|
+
prefab_envs: ENV['PREFAB_ENVS'].nil? ? [] : ENV['PREFAB_ENVS'].split(','),
|
63
|
+
collect_logs: true,
|
64
|
+
collect_max_paths: DEFAULT_MAX_PATHS,
|
65
|
+
collect_sync_interval: DEFAULT_SYNC_INTERVAL
|
59
66
|
)
|
60
|
-
# debugger
|
61
67
|
@api_key = api_key
|
62
68
|
@logdev = logdev
|
63
69
|
@stats = stats
|
@@ -74,12 +80,25 @@ module Prefab
|
|
74
80
|
@prefab_config_classpath_dir = prefab_config_classpath_dir
|
75
81
|
@prefab_config_override_dir = prefab_config_override_dir
|
76
82
|
@prefab_envs = Array(prefab_envs)
|
83
|
+
@collect_logs = collect_logs
|
84
|
+
@collect_max_paths = collect_max_paths
|
85
|
+
@collect_sync_interval = collect_sync_interval
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(options = {})
|
89
|
+
init(**options)
|
77
90
|
end
|
78
91
|
|
79
92
|
def local_only?
|
80
93
|
@prefab_datasources == DATASOURCES::LOCAL_ONLY
|
81
94
|
end
|
82
95
|
|
96
|
+
def collect_max_paths
|
97
|
+
return 0 if !@collect_logs || local_only?
|
98
|
+
|
99
|
+
@collect_max_paths
|
100
|
+
end
|
101
|
+
|
83
102
|
# https://api.prefab.cloud -> https://api-prefab-cloud.global.ssl.fastly.net
|
84
103
|
def url_for_api_cdn
|
85
104
|
ENV['PREFAB_CDN_URL'] || "#{@prefab_api_url.gsub(/\./, '-')}.global.ssl.fastly.net"
|
@@ -21,10 +21,10 @@ module Prefab
|
|
21
21
|
|
22
22
|
def load
|
23
23
|
if File.exist?(@file)
|
24
|
-
@client.log_internal Logger::INFO, "Load #{@file}"
|
24
|
+
@client.log_internal ::Logger::INFO, "Load #{@file}"
|
25
25
|
YAML.load_file(@file)
|
26
26
|
else
|
27
|
-
@client.log_internal Logger::INFO, "No file #{@file}"
|
27
|
+
@client.log_internal ::Logger::INFO, "No file #{@file}"
|
28
28
|
{}
|
29
29
|
end
|
30
30
|
end
|
data/lib/prefab_pb.rb
CHANGED
@@ -181,6 +181,24 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
181
181
|
optional :sequence_name, :string, 3
|
182
182
|
optional :size, :int64, 4
|
183
183
|
end
|
184
|
+
add_message "prefab.Loggers" do
|
185
|
+
repeated :loggers, :message, 1, "prefab.Logger"
|
186
|
+
optional :start_at, :int64, 2
|
187
|
+
optional :end_at, :int64, 3
|
188
|
+
optional :instance_hash, :string, 4
|
189
|
+
proto3_optional :namespace, :string, 5
|
190
|
+
end
|
191
|
+
add_message "prefab.Logger" do
|
192
|
+
optional :logger_name, :string, 1
|
193
|
+
proto3_optional :traces, :int64, 2
|
194
|
+
proto3_optional :debugs, :int64, 3
|
195
|
+
proto3_optional :infos, :int64, 4
|
196
|
+
proto3_optional :warns, :int64, 5
|
197
|
+
proto3_optional :errors, :int64, 6
|
198
|
+
proto3_optional :fatals, :int64, 7
|
199
|
+
end
|
200
|
+
add_message "prefab.LoggerReportResponse" do
|
201
|
+
end
|
184
202
|
add_enum "prefab.ConfigType" do
|
185
203
|
value :NOT_SET_CONFIG_TYPE, 0
|
186
204
|
value :CONFIG, 1
|
@@ -236,6 +254,9 @@ module Prefab
|
|
236
254
|
CreationResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.CreationResponse").msgclass
|
237
255
|
IdBlock = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlock").msgclass
|
238
256
|
IdBlockRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlockRequest").msgclass
|
257
|
+
Loggers = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Loggers").msgclass
|
258
|
+
Logger = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Logger").msgclass
|
259
|
+
LoggerReportResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LoggerReportResponse").msgclass
|
239
260
|
ConfigType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigType").enummodule
|
240
261
|
LogLevel = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LogLevel").enummodule
|
241
262
|
OnFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.OnFailure").enummodule
|
data/lib/prefab_services_pb.rb
CHANGED
@@ -61,6 +61,20 @@ module Prefab
|
|
61
61
|
rpc :GetAll, ::Prefab::Identity, ::Prefab::ConfigEvaluations
|
62
62
|
end
|
63
63
|
|
64
|
+
Stub = Service.rpc_stub_class
|
65
|
+
end
|
66
|
+
module LoggerReportingService
|
67
|
+
class Service
|
68
|
+
|
69
|
+
include ::GRPC::GenericService
|
70
|
+
|
71
|
+
self.marshal_class_method = :encode
|
72
|
+
self.unmarshal_class_method = :decode
|
73
|
+
self.service_name = 'prefab.LoggerReportingService'
|
74
|
+
|
75
|
+
rpc :Send, ::Prefab::Loggers, ::Prefab::LoggerReportResponse
|
76
|
+
end
|
77
|
+
|
64
78
|
Stub = Service.rpc_stub_class
|
65
79
|
end
|
66
80
|
end
|
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 0.
|
5
|
+
# stub: prefab-cloud-ruby 0.22.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "prefab-cloud-ruby".freeze
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.22.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".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 = "2023-
|
14
|
+
s.date = "2023-03-15"
|
15
15
|
s.description = "RateLimits & Config as a service".freeze
|
16
16
|
s.email = "jdwyer@prefab.cloud".freeze
|
17
17
|
s.extra_rdoc_files = [
|
@@ -48,6 +48,7 @@ Gem::Specification.new do |s|
|
|
48
48
|
"lib/prefab/feature_flag_client.rb",
|
49
49
|
"lib/prefab/internal_logger.rb",
|
50
50
|
"lib/prefab/local_config_parser.rb",
|
51
|
+
"lib/prefab/log_path_collector.rb",
|
51
52
|
"lib/prefab/logger_client.rb",
|
52
53
|
"lib/prefab/murmer3.rb",
|
53
54
|
"lib/prefab/noop_cache.rb",
|
@@ -74,7 +75,9 @@ Gem::Specification.new do |s|
|
|
74
75
|
"test/test_helper.rb",
|
75
76
|
"test/test_integration.rb",
|
76
77
|
"test/test_local_config_parser.rb",
|
78
|
+
"test/test_log_path_collector.rb",
|
77
79
|
"test/test_logger.rb",
|
80
|
+
"test/test_options.rb",
|
78
81
|
"test/test_weighted_value_resolver.rb"
|
79
82
|
]
|
80
83
|
s.homepage = "http://github.com/prefab-cloud/prefab-cloud-ruby".freeze
|
@@ -93,6 +96,7 @@ Gem::Specification.new do |s|
|
|
93
96
|
s.add_runtime_dependency(%q<google-protobuf>.freeze, [">= 0"])
|
94
97
|
s.add_runtime_dependency(%q<grpc>.freeze, [">= 0"])
|
95
98
|
s.add_runtime_dependency(%q<ld-eventsource>.freeze, [">= 0"])
|
99
|
+
s.add_runtime_dependency(%q<uuid>.freeze, [">= 0"])
|
96
100
|
s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
97
101
|
s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
|
98
102
|
s.add_development_dependency(%q<grpc-tools>.freeze, [">= 0"])
|
@@ -106,6 +110,7 @@ Gem::Specification.new do |s|
|
|
106
110
|
s.add_dependency(%q<google-protobuf>.freeze, [">= 0"])
|
107
111
|
s.add_dependency(%q<grpc>.freeze, [">= 0"])
|
108
112
|
s.add_dependency(%q<ld-eventsource>.freeze, [">= 0"])
|
113
|
+
s.add_dependency(%q<uuid>.freeze, [">= 0"])
|
109
114
|
s.add_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
110
115
|
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
111
116
|
s.add_dependency(%q<grpc-tools>.freeze, [">= 0"])
|
data/test/test_client.rb
CHANGED
@@ -84,6 +84,30 @@ class TestClient < Minitest::Test
|
|
84
84
|
assert certs.length > 1
|
85
85
|
end
|
86
86
|
|
87
|
+
def test_initialization_with_an_options_object
|
88
|
+
options_hash = {
|
89
|
+
namespace: 'test-namespace',
|
90
|
+
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
|
91
|
+
}
|
92
|
+
|
93
|
+
options = Prefab::Options.new(options_hash)
|
94
|
+
|
95
|
+
client = Prefab::Client.new(options)
|
96
|
+
|
97
|
+
assert_equal client.namespace, 'test-namespace'
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_initialization_with_a_hash
|
101
|
+
options_hash = {
|
102
|
+
namespace: 'test-namespace',
|
103
|
+
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
|
104
|
+
}
|
105
|
+
|
106
|
+
client = Prefab::Client.new(options_hash)
|
107
|
+
|
108
|
+
assert_equal client.namespace, 'test-namespace'
|
109
|
+
end
|
110
|
+
|
87
111
|
private
|
88
112
|
|
89
113
|
def new_client(overrides = {})
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'timecop'
|
5
|
+
|
6
|
+
class TestLogPathCollector < Minitest::Test
|
7
|
+
def test_sync
|
8
|
+
Timecop.freeze do
|
9
|
+
client = new_client(namespace: 'this.is.a.namespace')
|
10
|
+
|
11
|
+
2.times { client.log.info('here is a message') }
|
12
|
+
3.times { client.log.error('here is a message') }
|
13
|
+
|
14
|
+
requests = []
|
15
|
+
|
16
|
+
client.define_singleton_method(:request) do |*params|
|
17
|
+
requests.push(params)
|
18
|
+
end
|
19
|
+
|
20
|
+
client.log_path_collector.send(:sync)
|
21
|
+
|
22
|
+
# let the flush thread run
|
23
|
+
sleep 0.01 while requests.length == 0
|
24
|
+
|
25
|
+
assert_equal requests, [[
|
26
|
+
Prefab::LoggerReportingService,
|
27
|
+
:send,
|
28
|
+
{
|
29
|
+
req_options: {},
|
30
|
+
params: Prefab::Loggers.new(
|
31
|
+
loggers: [Prefab::Logger.new(logger_name: 'test.test_log_path_collector.test_sync',
|
32
|
+
infos: 2, errors: 3)],
|
33
|
+
start_at: (Time.now.utc.to_f * 1000).to_i,
|
34
|
+
end_at: (Time.now.utc.to_f * 1000).to_i,
|
35
|
+
instance_hash: client.instance_hash,
|
36
|
+
namespace: 'this.is.a.namespace'
|
37
|
+
)
|
38
|
+
}
|
39
|
+
]]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def new_client(overrides = {})
|
46
|
+
options = Prefab::Options.new(**{
|
47
|
+
prefab_config_override_dir: 'none',
|
48
|
+
prefab_config_classpath_dir: 'test',
|
49
|
+
prefab_envs: ['unit_tests'],
|
50
|
+
api_key: '123-development-yourapikey-SDK',
|
51
|
+
collect_sync_interval: 1000 # we'll trigger sync manually in our test
|
52
|
+
}.merge(overrides))
|
53
|
+
|
54
|
+
Prefab::Client.new(options)
|
55
|
+
end
|
56
|
+
end
|
data/test/test_logger.rb
CHANGED
@@ -47,37 +47,37 @@ class TestCLogger < Minitest::Test
|
|
47
47
|
def test_level_of
|
48
48
|
with_env('PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL', 'info') do
|
49
49
|
# env var overrides the default level
|
50
|
-
assert_equal Logger::INFO,
|
50
|
+
assert_equal ::Logger::INFO,
|
51
51
|
@logger.level_of('app.models.user'), 'PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info'
|
52
52
|
|
53
53
|
@logger.set_config_client(MockConfigClient.new({}))
|
54
|
-
assert_equal Logger::WARN,
|
54
|
+
assert_equal ::Logger::WARN,
|
55
55
|
@logger.level_of('app.models.user'), 'default is warn'
|
56
56
|
|
57
57
|
@logger.set_config_client(MockConfigClient.new('log-level.app' => :INFO))
|
58
|
-
assert_equal Logger::INFO,
|
58
|
+
assert_equal ::Logger::INFO,
|
59
59
|
@logger.level_of('app.models.user')
|
60
60
|
|
61
61
|
@logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG))
|
62
|
-
assert_equal Logger::DEBUG,
|
62
|
+
assert_equal ::Logger::DEBUG,
|
63
63
|
@logger.level_of('app.models.user')
|
64
64
|
|
65
65
|
@logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG,
|
66
66
|
'log-level.app.models' => :ERROR))
|
67
|
-
assert_equal Logger::ERROR,
|
67
|
+
assert_equal ::Logger::ERROR,
|
68
68
|
@logger.level_of('app.models.user'), 'test leveling'
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
72
|
def test_log_internal
|
73
73
|
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : test message/)
|
74
|
-
logger.log_internal('test message', 'test.path', '', Logger::WARN)
|
74
|
+
logger.log_internal('test message', 'test.path', '', ::Logger::WARN)
|
75
75
|
mock_logdev.verify
|
76
76
|
end
|
77
77
|
|
78
78
|
def test_log_internal_unknown
|
79
79
|
logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- cloud.prefab.client.test.path: : test message/)
|
80
|
-
logger.log_internal('test message', 'test.path', '', Logger::UNKNOWN)
|
80
|
+
logger.log_internal('test message', 'test.path', '', ::Logger::UNKNOWN)
|
81
81
|
mock_logdev.verify
|
82
82
|
end
|
83
83
|
|
@@ -85,30 +85,30 @@ class TestCLogger < Minitest::Test
|
|
85
85
|
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : should log/,
|
86
86
|
calls: 2)
|
87
87
|
logger.silence do
|
88
|
-
logger.log_internal('should not log', 'test.path', '', Logger::WARN)
|
88
|
+
logger.log_internal('should not log', 'test.path', '', ::Logger::WARN)
|
89
89
|
end
|
90
|
-
logger.log_internal('should log', 'test.path', '', Logger::WARN)
|
90
|
+
logger.log_internal('should log', 'test.path', '', ::Logger::WARN)
|
91
91
|
mock_logdev.verify
|
92
92
|
end
|
93
93
|
|
94
94
|
def test_log
|
95
95
|
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : test message/)
|
96
|
-
logger.log('test message', 'test.path', '', Logger::WARN)
|
96
|
+
logger.log('test message', 'test.path', '', ::Logger::WARN)
|
97
97
|
mock_logdev.verify
|
98
98
|
end
|
99
99
|
|
100
100
|
def test_log_unknown
|
101
101
|
logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- test.path: : test message/)
|
102
|
-
logger.log('test message', 'test.path', '', Logger::UNKNOWN)
|
102
|
+
logger.log('test message', 'test.path', '', ::Logger::UNKNOWN)
|
103
103
|
mock_logdev.verify
|
104
104
|
end
|
105
105
|
|
106
106
|
def test_log_silencing
|
107
107
|
logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : should log/, calls: 2)
|
108
108
|
logger.silence do
|
109
|
-
logger.log('should not log', 'test.path', '', Logger::WARN)
|
109
|
+
logger.log('should not log', 'test.path', '', ::Logger::WARN)
|
110
110
|
end
|
111
|
-
logger.log('should log', 'test.path', '', Logger::WARN)
|
111
|
+
logger.log('should log', 'test.path', '', ::Logger::WARN)
|
112
112
|
mock_logdev.verify
|
113
113
|
end
|
114
114
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class TestOptions < Minitest::Test
|
6
|
+
API_KEY = 'abcdefg'
|
7
|
+
|
8
|
+
def test_works_with_named_arguments
|
9
|
+
assert_equal API_KEY, Prefab::Options.new(api_key: API_KEY).api_key
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_works_with_hash
|
13
|
+
assert_equal API_KEY, Prefab::Options.new({ api_key: API_KEY }).api_key
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_collect_max_paths
|
17
|
+
assert_equal 1000, Prefab::Options.new.collect_max_paths
|
18
|
+
assert_equal 100, Prefab::Options.new(collect_max_paths: 100).collect_max_paths
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_collect_max_paths_with_local_only
|
22
|
+
options = Prefab::Options.new(collect_max_paths: 100,
|
23
|
+
prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY)
|
24
|
+
assert_equal 0, options.collect_max_paths
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_collect_max_paths_with_collect_logs_false
|
28
|
+
options = Prefab::Options.new(collect_max_paths: 100,
|
29
|
+
collect_logs: false)
|
30
|
+
assert_equal 0, options.collect_max_paths
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prefab-cloud-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Dwyer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -100,6 +100,20 @@ dependencies:
|
|
100
100
|
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: uuid
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
103
117
|
- !ruby/object:Gem::Dependency
|
104
118
|
name: benchmark-ips
|
105
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -221,6 +235,7 @@ files:
|
|
221
235
|
- lib/prefab/feature_flag_client.rb
|
222
236
|
- lib/prefab/internal_logger.rb
|
223
237
|
- lib/prefab/local_config_parser.rb
|
238
|
+
- lib/prefab/log_path_collector.rb
|
224
239
|
- lib/prefab/logger_client.rb
|
225
240
|
- lib/prefab/murmer3.rb
|
226
241
|
- lib/prefab/noop_cache.rb
|
@@ -247,7 +262,9 @@ files:
|
|
247
262
|
- test/test_helper.rb
|
248
263
|
- test/test_integration.rb
|
249
264
|
- test/test_local_config_parser.rb
|
265
|
+
- test/test_log_path_collector.rb
|
250
266
|
- test/test_logger.rb
|
267
|
+
- test/test_options.rb
|
251
268
|
- test/test_weighted_value_resolver.rb
|
252
269
|
homepage: http://github.com/prefab-cloud/prefab-cloud-ruby
|
253
270
|
licenses:
|