prefab-cloud-ruby 1.0.1 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/VERSION +1 -1
- data/lib/prefab/client.rb +4 -4
- data/lib/prefab/config_client.rb +27 -8
- data/lib/prefab/config_client_presenter.rb +18 -0
- data/lib/prefab/config_resolver.rb +5 -1
- data/lib/prefab/context.rb +8 -0
- data/lib/prefab/context_shape_aggregator.rb +1 -1
- data/lib/prefab/evaluation_summary_aggregator.rb +1 -1
- data/lib/prefab/example_contexts_aggregator.rb +1 -1
- data/lib/prefab/log_path_aggregator.rb +4 -1
- data/lib/prefab/logger_client.rb +25 -26
- data/lib/prefab/options.rb +16 -10
- data/lib/prefab/periodic_sync.rb +4 -0
- data/lib/prefab-cloud-ruby.rb +1 -0
- data/lib/prefab_pb.rb +3 -1
- data/prefab-cloud-ruby.gemspec +4 -3
- data/test/integration_test.rb +54 -4
- data/test/integration_test_helpers.rb +113 -0
- data/test/support/common_helpers.rb +11 -7
- data/test/test_integration.rb +14 -11
- data/test/test_logger.rb +40 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4207ba2ec83b02534caa1d8f23b75c2120c8d277253312a5bd98898c38baf156
|
4
|
+
data.tar.gz: 8698e869c65017759a56c01f3ff57bc16b9597cc4d1edc219fc282f0ae371e0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31eb4a0e5e132dd3136a48f9afa5f7d7decb73eccb43cc74329e9fc2b3c5a5b7109bc53a3c468e8272ae0d4ad04e3f85fb516eb16b6590325e23046e6f1c9d7b
|
7
|
+
data.tar.gz: 9ea6c49f4ffe05d15654143c98dc7f74d405ac00bd919d3ae43547d9aa3ba4c3adcfa54626a0c393fa766cb420af29231032f07dd4da1c53d71c12da2cfc273a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.1.1 - 2023-10-11
|
4
|
+
|
5
|
+
- Migrate happy-path client-initialization logging to `DEBUG` level rather than `INFO` (#144)
|
6
|
+
- Add `ConfigClientPresenter` for logging out stats upon successful client initialization (#144)
|
7
|
+
- Add support for default context (#146)
|
8
|
+
|
9
|
+
## 1.1.0 - 2023-09-18
|
10
|
+
|
11
|
+
- Add support for structured logging (#143)
|
12
|
+
- Ability to pass a hash of key/value context pairs to any of the user-facing log methods
|
13
|
+
|
3
14
|
## 1.0.1 - 2023-08-17
|
4
15
|
|
5
16
|
- Bug fix for StringList w/ ExampleContextsAggregator (#141)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.1.1
|
data/lib/prefab/client.rb
CHANGED
@@ -16,13 +16,13 @@ module Prefab
|
|
16
16
|
@instance_hash = UUID.new.generate
|
17
17
|
|
18
18
|
if @options.local_only?
|
19
|
-
log_internal ::Logger::
|
19
|
+
log_internal ::Logger::DEBUG, 'Prefab Running in Local Mode'
|
20
20
|
else
|
21
21
|
@api_key = @options.api_key
|
22
22
|
raise Prefab::Errors::InvalidApiKeyError, @api_key if @api_key.nil? || @api_key.empty? || api_key.count('-') < 1
|
23
23
|
|
24
24
|
@prefab_api_url = @options.prefab_api_url
|
25
|
-
log_internal ::Logger::
|
25
|
+
log_internal ::Logger::DEBUG, "Prefab Connecting to: #{@prefab_api_url}"
|
26
26
|
end
|
27
27
|
|
28
28
|
context.clear
|
@@ -99,8 +99,8 @@ module Prefab
|
|
99
99
|
resolver.on_update(&block)
|
100
100
|
end
|
101
101
|
|
102
|
-
def log_internal(level, msg, path = nil)
|
103
|
-
log.log_internal msg, path, nil, level
|
102
|
+
def log_internal(level, msg, path = nil, **tags)
|
103
|
+
log.log_internal msg, path, nil, level, tags
|
104
104
|
end
|
105
105
|
|
106
106
|
def enabled?(feature_name, jit_context = NO_DEFAULT_PROVIDED)
|
data/lib/prefab/config_client.rb
CHANGED
@@ -28,7 +28,7 @@ module Prefab
|
|
28
28
|
@initialized_future = Concurrent::Future.execute { @initialization_lock.acquire_read_lock }
|
29
29
|
|
30
30
|
if @options.local_only?
|
31
|
-
finish_init!(:local_only)
|
31
|
+
finish_init!(:local_only, nil)
|
32
32
|
else
|
33
33
|
load_checkpoint
|
34
34
|
start_checkpointing_thread
|
@@ -146,18 +146,29 @@ module Prefab
|
|
146
146
|
@config_resolver.project_env_id = project_env_id
|
147
147
|
starting_highwater_mark = @config_loader.highwater_mark
|
148
148
|
|
149
|
+
default_contexts = configs.default_context&.contexts&.map do |context|
|
150
|
+
[
|
151
|
+
context.type,
|
152
|
+
context.values.keys.map do |k|
|
153
|
+
[k, Prefab::ConfigValueUnwrapper.new(context.values[k]).unwrap]
|
154
|
+
end.to_h
|
155
|
+
]
|
156
|
+
end.to_h
|
157
|
+
|
158
|
+
@config_resolver.default_context = default_contexts || {}
|
159
|
+
|
149
160
|
configs.configs.each do |config|
|
150
161
|
@config_loader.set(config, source)
|
151
162
|
end
|
152
163
|
if @config_loader.highwater_mark > starting_highwater_mark
|
153
|
-
@base_client.log_internal ::Logger::
|
164
|
+
@base_client.log_internal ::Logger::DEBUG,
|
154
165
|
"Found new checkpoint with highwater id #{@config_loader.highwater_mark} from #{source} in project #{project_id} environment: #{project_env_id} and namespace: '#{@namespace}'"
|
155
166
|
else
|
156
167
|
@base_client.log_internal ::Logger::DEBUG,
|
157
168
|
"Checkpoint with highwater id #{@config_loader.highwater_mark} from #{source}. No changes.", 'load_configs'
|
158
169
|
end
|
159
170
|
@config_resolver.update
|
160
|
-
finish_init!(source)
|
171
|
+
finish_init!(source, project_id)
|
161
172
|
end
|
162
173
|
|
163
174
|
# A thread that checks for a checkpoint
|
@@ -170,18 +181,26 @@ module Prefab
|
|
170
181
|
delta = @checkpoint_freq_secs - (Time.now - started_at)
|
171
182
|
sleep(delta) if delta > 0
|
172
183
|
rescue StandardError => e
|
173
|
-
@base_client.log_internal ::Logger::
|
184
|
+
@base_client.log_internal ::Logger::DEBUG, "Issue Checkpointing #{e.message}"
|
174
185
|
end
|
175
186
|
end
|
176
187
|
end
|
177
188
|
|
178
|
-
def finish_init!(source)
|
189
|
+
def finish_init!(source, project_id)
|
179
190
|
return unless @initialization_lock.write_locked?
|
180
191
|
|
181
|
-
@base_client.log_internal ::Logger::
|
192
|
+
@base_client.log_internal ::Logger::DEBUG, "Unlocked Config via #{source}"
|
182
193
|
@initialization_lock.release_write_lock
|
183
194
|
@base_client.log.config_client = self
|
184
|
-
|
195
|
+
presenter = Prefab::ConfigClientPresenter.new(
|
196
|
+
size: @config_resolver.local_store.size,
|
197
|
+
source: source,
|
198
|
+
project_id: project_id,
|
199
|
+
project_env_id: @config_resolver.project_env_id,
|
200
|
+
api_key: @base_client.options.api_key
|
201
|
+
)
|
202
|
+
@base_client.log_internal ::Logger::INFO, presenter.to_s
|
203
|
+
@base_client.log_internal ::Logger::DEBUG, to_s
|
185
204
|
end
|
186
205
|
|
187
206
|
def start_sse_streaming_connection_thread(start_at_id)
|
@@ -193,7 +212,7 @@ module Prefab
|
|
193
212
|
'X-PrefabCloud-Client-Version' => "prefab-cloud-ruby-#{Prefab::VERSION}"
|
194
213
|
}
|
195
214
|
url = "#{@base_client.prefab_api_url}/api/v1/sse/config"
|
196
|
-
@base_client.log_internal ::Logger::
|
215
|
+
@base_client.log_internal ::Logger::DEBUG, "SSE Streaming Connect to #{url} start_at #{start_at_id}"
|
197
216
|
@streaming_thread = SSE::Client.new(url,
|
198
217
|
headers: headers,
|
199
218
|
read_timeout: SSE_READ_TIMEOUT,
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prefab
|
4
|
+
class ConfigClientPresenter
|
5
|
+
def initialize(size:, source:, project_id:, project_env_id:, api_key:)
|
6
|
+
@size = size
|
7
|
+
@source = source
|
8
|
+
@project_id = project_id
|
9
|
+
@project_env_id = project_env_id
|
10
|
+
@api_key_id = api_key&.split("-")&.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"Configuration Loaded count=#{@size} source=#{@source} project=#{@project_id} project-env=#{@project_env_id} prefab.api-key-id=#{@api_key_id}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -3,6 +3,9 @@
|
|
3
3
|
module Prefab
|
4
4
|
class ConfigResolver
|
5
5
|
attr_accessor :project_env_id # this will be set by the config_client when it gets an API response
|
6
|
+
attr_reader :local_store
|
7
|
+
|
8
|
+
attr_accessor :default_context
|
6
9
|
|
7
10
|
def initialize(base_client, config_loader)
|
8
11
|
@lock = Concurrent::ReadWriteLock.new
|
@@ -11,6 +14,7 @@ module Prefab
|
|
11
14
|
@project_env_id = 0 # we don't know this yet, it is set from the API results
|
12
15
|
@base_client = base_client
|
13
16
|
@on_update = nil
|
17
|
+
@default_context = {}
|
14
18
|
make_local
|
15
19
|
end
|
16
20
|
|
@@ -61,7 +65,7 @@ module Prefab
|
|
61
65
|
properties
|
62
66
|
else
|
63
67
|
Context.merge_with_current(properties)
|
64
|
-
end
|
68
|
+
end.merge_default(default_context || {})
|
65
69
|
end
|
66
70
|
|
67
71
|
private
|
data/lib/prefab/context.rb
CHANGED
@@ -122,6 +122,14 @@ module Prefab
|
|
122
122
|
contexts[name.to_s] || NamedContext.new(name, {})
|
123
123
|
end
|
124
124
|
|
125
|
+
def merge_default(defaults)
|
126
|
+
defaults.keys.each do |name|
|
127
|
+
set(name, context(name).merge!(defaults[name]))
|
128
|
+
end
|
129
|
+
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
125
133
|
def to_proto(namespace)
|
126
134
|
prefab_context = {
|
127
135
|
'current-time' => ConfigValueWrapper.wrap(Prefab::TimeHelpers.now_in_ms)
|
@@ -55,7 +55,7 @@ module Prefab
|
|
55
55
|
summaries: summaries(to_ship)
|
56
56
|
)
|
57
57
|
|
58
|
-
result =
|
58
|
+
result = post('/api/v1/telemetry', events(summaries_proto))
|
59
59
|
|
60
60
|
log_internal "Uploaded #{to_ship.size} summaries: #{result.status}"
|
61
61
|
end
|
@@ -45,7 +45,7 @@ module Prefab
|
|
45
45
|
pool.post do
|
46
46
|
log_internal "Flushing #{to_ship.size} examples"
|
47
47
|
|
48
|
-
result =
|
48
|
+
result = post('/api/v1/telemetry', events(to_ship))
|
49
49
|
|
50
50
|
log_internal "Uploaded #{to_ship.size} examples: #{result.status}"
|
51
51
|
end
|
@@ -25,6 +25,9 @@ module Prefab
|
|
25
25
|
|
26
26
|
@data = Concurrent::Map.new
|
27
27
|
|
28
|
+
@last_data_sent = nil
|
29
|
+
@last_request = nil
|
30
|
+
|
28
31
|
start_periodic_sync(sync_interval)
|
29
32
|
end
|
30
33
|
|
@@ -55,7 +58,7 @@ module Prefab
|
|
55
58
|
namespace: @client.namespace
|
56
59
|
)
|
57
60
|
|
58
|
-
result =
|
61
|
+
result = post('/api/v1/known-loggers', loggers)
|
59
62
|
|
60
63
|
log_internal "Uploaded #{to_ship.size} paths: #{result.status}"
|
61
64
|
end
|
data/lib/prefab/logger_client.rb
CHANGED
@@ -27,26 +27,26 @@ module Prefab
|
|
27
27
|
@log_path_aggregator = log_path_aggregator
|
28
28
|
end
|
29
29
|
|
30
|
-
def add_internal(severity, message, progname, loc, &block)
|
30
|
+
def add_internal(severity, message, progname, loc, log_context={}, &block)
|
31
31
|
path_loc = get_loc_path(loc)
|
32
32
|
path = @prefix + path_loc
|
33
33
|
|
34
34
|
@log_path_aggregator&.push(path_loc, severity)
|
35
35
|
|
36
|
-
log(message, path, progname, severity, &block)
|
36
|
+
log(message, path, progname, severity, log_context, &block)
|
37
37
|
end
|
38
38
|
|
39
|
-
def log_internal(message, path, progname, severity, &block)
|
39
|
+
def log_internal(message, path, progname, severity, log_context={}, &block)
|
40
40
|
path = if path
|
41
41
|
"#{INTERNAL_PREFIX}.#{path}"
|
42
42
|
else
|
43
43
|
INTERNAL_PREFIX
|
44
44
|
end
|
45
45
|
|
46
|
-
log(message, path, progname, severity, &block)
|
46
|
+
log(message, path, progname, severity, log_context, &block)
|
47
47
|
end
|
48
48
|
|
49
|
-
def log(message, path, progname, severity)
|
49
|
+
def log(message, path, progname, severity, log_context={})
|
50
50
|
severity ||= ::Logger::UNKNOWN
|
51
51
|
|
52
52
|
return true if @logdev.nil? || severity < level_of(path) || @silences[local_log_id]
|
@@ -63,29 +63,29 @@ module Prefab
|
|
63
63
|
end
|
64
64
|
|
65
65
|
@logdev.write(
|
66
|
-
format_message(format_severity(severity), Time.now, progname, message, path)
|
66
|
+
format_message(format_severity(severity), Time.now, progname, message, path, log_context)
|
67
67
|
)
|
68
68
|
true
|
69
69
|
end
|
70
70
|
|
71
|
-
def debug(progname = nil, &block)
|
72
|
-
add_internal(DEBUG, nil, progname, caller_locations(1, 1)[0], &block)
|
71
|
+
def debug(progname = nil, **log_context, &block)
|
72
|
+
add_internal(DEBUG, nil, progname, caller_locations(1, 1)[0], log_context, &block)
|
73
73
|
end
|
74
74
|
|
75
|
-
def info(progname = nil, &block)
|
76
|
-
add_internal(INFO, nil, progname, caller_locations(1, 1)[0], &block)
|
75
|
+
def info(progname = nil, **log_context, &block)
|
76
|
+
add_internal(INFO, nil, progname, caller_locations(1, 1)[0], log_context, &block)
|
77
77
|
end
|
78
78
|
|
79
|
-
def warn(progname = nil, &block)
|
80
|
-
add_internal(WARN, nil, progname, caller_locations(1, 1)[0], &block)
|
79
|
+
def warn(progname = nil, **log_context, &block)
|
80
|
+
add_internal(WARN, nil, progname, caller_locations(1, 1)[0], log_context, &block)
|
81
81
|
end
|
82
82
|
|
83
|
-
def error(progname = nil, &block)
|
84
|
-
add_internal(ERROR, nil, progname, caller_locations(1, 1)[0], &block)
|
83
|
+
def error(progname = nil, **log_context, &block)
|
84
|
+
add_internal(ERROR, nil, progname, caller_locations(1, 1)[0], log_context, &block)
|
85
85
|
end
|
86
86
|
|
87
|
-
def fatal(progname = nil, &block)
|
88
|
-
add_internal(FATAL, nil, progname, caller_locations(1, 1)[0], &block)
|
87
|
+
def fatal(progname = nil, **log_context, &block)
|
88
|
+
add_internal(FATAL, nil, progname, caller_locations(1, 1)[0], log_context, &block)
|
89
89
|
end
|
90
90
|
|
91
91
|
def debug?
|
@@ -168,18 +168,17 @@ module Prefab
|
|
168
168
|
path
|
169
169
|
end
|
170
170
|
|
171
|
-
def format_message(severity, datetime, progname, msg, path = nil)
|
171
|
+
def format_message(severity, datetime, progname, msg, path = nil, log_context={})
|
172
172
|
formatter = (@formatter || @default_formatter)
|
173
173
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
(progname.nil? || progname.empty?) ? path : "#{progname}: #{path}"
|
174
|
+
formatter.call(
|
175
|
+
severity: severity,
|
176
|
+
datetime: datetime,
|
177
|
+
progname: progname,
|
178
|
+
path: path,
|
179
|
+
message: msg,
|
180
|
+
log_context: log_context
|
181
|
+
)
|
183
182
|
end
|
184
183
|
end
|
185
184
|
|
data/lib/prefab/options.rb
CHANGED
@@ -17,17 +17,23 @@ module Prefab
|
|
17
17
|
attr_reader :prefab_envs
|
18
18
|
attr_reader :collect_sync_interval
|
19
19
|
|
20
|
-
DEFAULT_LOG_FORMATTER = proc { |
|
21
|
-
|
20
|
+
DEFAULT_LOG_FORMATTER = proc { |data|
|
21
|
+
severity = data[:severity]
|
22
|
+
datetime = data[:datetime]
|
23
|
+
progname = data[:progname]
|
24
|
+
path = data[:path]
|
25
|
+
msg = data[:message]
|
26
|
+
log_context = data[:log_context]
|
27
|
+
|
28
|
+
progname = (progname.nil? || progname.empty?) ? path : "#{progname}: #{path}"
|
29
|
+
|
30
|
+
formatted_log_context = log_context.sort.map{|k, v| "#{k}=#{v}" }.join(" ")
|
31
|
+
"#{severity.ljust(5)} #{datetime}:#{' ' if progname}#{progname} #{msg}#{log_context.any? ? " " + formatted_log_context : ""}\n"
|
22
32
|
}
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
progname: progname,
|
28
|
-
message: msg,
|
29
|
-
path: path
|
30
|
-
}.compact.to_json << "\n"
|
33
|
+
|
34
|
+
JSON_LOG_FORMATTER = proc { |data|
|
35
|
+
log_context = data.delete(:log_context)
|
36
|
+
data.merge(log_context).compact.to_json << "\n"
|
31
37
|
}
|
32
38
|
|
33
39
|
module ON_INITIALIZATION_FAILURE
|
data/lib/prefab/periodic_sync.rb
CHANGED
data/lib/prefab-cloud-ruby.rb
CHANGED
@@ -40,6 +40,7 @@ require 'prefab/http_connection'
|
|
40
40
|
require 'prefab/context'
|
41
41
|
require 'prefab/logger_client'
|
42
42
|
require 'prefab/client'
|
43
|
+
require 'prefab/config_client_presenter'
|
43
44
|
require 'prefab/config_client'
|
44
45
|
require 'prefab/feature_flag_client'
|
45
46
|
require 'prefab/murmer3'
|
data/lib/prefab_pb.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
require 'google/protobuf'
|
6
6
|
|
7
7
|
|
8
|
-
descriptor_data = "\n\x0cprefab.proto\x12\x06prefab\"W\n\x14\x43onfigServicePointer\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x13\n\x0bstart_at_id\x18\x02 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x03 \x01(\x03\"\xca\x02\n\x0b\x43onfigValue\x12\r\n\x03int\x18\x01 \x01(\x03H\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x03 \x01(\x0cH\x00\x12\x10\n\x06\x64ouble\x18\x04 \x01(\x01H\x00\x12\x0e\n\x04\x62ool\x18\x05 \x01(\x08H\x00\x12\x31\n\x0fweighted_values\x18\x06 \x01(\x0b\x32\x16.prefab.WeightedValuesH\x00\x12\x33\n\x10limit_definition\x18\x07 \x01(\x0b\x32\x17.prefab.LimitDefinitionH\x00\x12%\n\tlog_level\x18\t \x01(\x0e\x32\x10.prefab.LogLevelH\x00\x12)\n\x0bstring_list\x18\n \x01(\x0b\x32\x12.prefab.StringListH\x00\x12%\n\tint_range\x18\x0b \x01(\x0b\x32\x10.prefab.IntRangeH\x00\x42\x06\n\x04type\"B\n\x08IntRange\x12\x12\n\x05start\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x10\n\x03\x65nd\x18\x02 \x01(\x03H\x01\x88\x01\x01\x42\x08\n\x06_startB\x06\n\x04_end\"\x1c\n\nStringList\x12\x0e\n\x06values\x18\x01 \x03(\t\"C\n\rWeightedValue\x12\x0e\n\x06weight\x18\x01 \x01(\x05\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue\"~\n\x0eWeightedValues\x12.\n\x0fweighted_values\x18\x01 \x03(\x0b\x32\x15.prefab.WeightedValue\x12\"\n\x15hash_by_property_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x18\n\x16_hash_by_property_name\"h\n\x07\x43onfigs\x12\x1f\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x0e.prefab.Config\x12<\n\x16\x63onfig_service_pointer\x18\x02 \x01(\x0b\x32\x1c.prefab.ConfigServicePointer\"\xf7\x01\n\x06\x43onfig\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x12\n\nproject_id\x18\x02 \x01(\x03\x12\x0b\n\x03key\x18\x03 \x01(\t\x12%\n\nchanged_by\x18\x04 \x01(\x0b\x32\x11.prefab.ChangedBy\x12\x1f\n\x04rows\x18\x05 \x03(\x0b\x32\x11.prefab.ConfigRow\x12-\n\x10\x61llowable_values\x18\x06 \x03(\x0b\x32\x13.prefab.ConfigValue\x12\'\n\x0b\x63onfig_type\x18\x07 \x01(\x0e\x32\x12.prefab.ConfigType\x12\x14\n\x07\x64raftId\x18\x08 \x01(\x03H\x00\x88\x01\x01\x42\n\n\x08_draftId\"+\n\tChangedBy\x12\x0f\n\x07user_id\x18\x01 \x01(\x03\x12\r\n\x05\x65mail\x18\x02 \x01(\t\"\xe4\x01\n\tConfigRow\x12\x1b\n\x0eproject_env_id\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12(\n\x06values\x18\x02 \x03(\x0b\x32\x18.prefab.ConditionalValue\x12\x35\n\nproperties\x18\x03 \x03(\x0b\x32!.prefab.ConfigRow.PropertiesEntry\x1a\x46\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue:\x02\x38\x01\x42\x11\n\x0f_project_env_id\"[\n\x10\x43onditionalValue\x12#\n\x08\x63riteria\x18\x01 \x03(\x0b\x32\x11.prefab.Criterion\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue\"\x94\x03\n\tCriterion\x12\x15\n\rproperty_name\x18\x01 \x01(\t\x12\x35\n\x08operator\x18\x02 \x01(\x0e\x32#.prefab.Criterion.CriterionOperator\x12+\n\x0evalue_to_match\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValue\"\x8b\x02\n\x11\x43riterionOperator\x12\x0b\n\x07NOT_SET\x10\x00\x12\x11\n\rLOOKUP_KEY_IN\x10\x01\x12\x15\n\x11LOOKUP_KEY_NOT_IN\x10\x02\x12\n\n\x06IN_SEG\x10\x03\x12\x0e\n\nNOT_IN_SEG\x10\x04\x12\x0f\n\x0b\x41LWAYS_TRUE\x10\x05\x12\x12\n\x0ePROP_IS_ONE_OF\x10\x06\x12\x16\n\x12PROP_IS_NOT_ONE_OF\x10\x07\x12\x19\n\x15PROP_ENDS_WITH_ONE_OF\x10\x08\x12!\n\x1dPROP_DOES_NOT_END_WITH_ONE_OF\x10\t\x12\x16\n\x12HIERARCHICAL_MATCH\x10\n\x12\x10\n\x0cIN_INT_RANGE\x10\x0b\"\x89\x01\n\x07Loggers\x12\x1f\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.Logger\x12\x10\n\x08start_at\x18\x02 \x01(\x03\x12\x0e\n\x06\x65nd_at\x18\x03 \x01(\x03\x12\x15\n\rinstance_hash\x18\x04 \x01(\t\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"\xd9\x01\n\x06Logger\x12\x13\n\x0blogger_name\x18\x01 \x01(\t\x12\x13\n\x06traces\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\x13\n\x06\x64\x65\x62ugs\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x12\n\x05infos\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12\x12\n\x05warns\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x13\n\x06\x65rrors\x18\x06 \x01(\x03H\x04\x88\x01\x01\x12\x13\n\x06\x66\x61tals\x18\x07 \x01(\x03H\x05\x88\x01\x01\x42\t\n\x07_tracesB\t\n\x07_debugsB\x08\n\x06_infosB\x08\n\x06_warnsB\t\n\x07_errorsB\t\n\x07_fatals\"\x16\n\x14LoggerReportResponse\"\xdb\x03\n\rLimitResponse\x12\x0e\n\x06passed\x18\x01 \x01(\x08\x12\x12\n\nexpires_at\x18\x02 \x01(\x03\x12\x16\n\x0e\x65nforced_group\x18\x03 \x01(\t\x12\x16\n\x0e\x63urrent_bucket\x18\x04 \x01(\x03\x12\x14\n\x0cpolicy_group\x18\x05 \x01(\t\x12;\n\x0bpolicy_name\x18\x06 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNames\x12\x14\n\x0cpolicy_limit\x18\x07 \x01(\x05\x12\x0e\n\x06\x61mount\x18\x08 \x01(\x03\x12\x16\n\x0elimit_reset_at\x18\t \x01(\x03\x12\x39\n\x0csafety_level\x18\n \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"\xa9\x01\n\x10LimitPolicyNames\x12\x0b\n\x07NOT_SET\x10\x00\x12\x14\n\x10SECONDLY_ROLLING\x10\x01\x12\x14\n\x10MINUTELY_ROLLING\x10\x03\x12\x12\n\x0eHOURLY_ROLLING\x10\x05\x12\x11\n\rDAILY_ROLLING\x10\x07\x12\x13\n\x0fMONTHLY_ROLLING\x10\x08\x12\x0c\n\x08INFINITE\x10\t\x12\x12\n\x0eYEARLY_ROLLING\x10\n\"\x99\x02\n\x0cLimitRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x16\n\x0e\x61\x63quire_amount\x18\x02 \x01(\x05\x12\x0e\n\x06groups\x18\x03 \x03(\t\x12:\n\x0elimit_combiner\x18\x04 \x01(\x0e\x32\".prefab.LimitRequest.LimitCombiner\x12\x1e\n\x16\x61llow_partial_response\x18\x05 \x01(\x08\x12\x39\n\x0csafety_level\x18\x06 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"6\n\rLimitCombiner\x12\x0b\n\x07NOT_SET\x10\x00\x12\x0b\n\x07MINIMUM\x10\x01\x12\x0b\n\x07MAXIMUM\x10\x02\"/\n\nContextSet\x12!\n\x08\x63ontexts\x18\x01 \x03(\x0b\x32\x0f.prefab.Context\"\x96\x01\n\x07\x43ontext\x12\x11\n\x04type\x18\x01 \x01(\tH\x00\x88\x01\x01\x12+\n\x06values\x18\x02 \x03(\x0b\x32\x1b.prefab.Context.ValuesEntry\x1a\x42\n\x0bValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue:\x02\x38\x01\x42\x07\n\x05_type\"\x93\x01\n\x08Identity\x12\x13\n\x06lookup\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x34\n\nattributes\x18\x02 \x03(\x0b\x32 .prefab.Identity.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07_lookup\"\xc1\x01\n\x11\x43lientConfigValue\x12\x10\n\x03int\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x13\n\x06string\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x13\n\x06\x64ouble\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x11\n\x04\x62ool\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12(\n\tlog_level\x18\x05 \x01(\x0e\x32\x10.prefab.LogLevelH\x04\x88\x01\x01\x42\x06\n\x04_intB\t\n\x07_stringB\t\n\x07_doubleB\x07\n\x05_boolB\x0c\n\n_log_level\"\x94\x01\n\x11\x43onfigEvaluations\x12\x35\n\x06values\x18\x01 \x03(\x0b\x32%.prefab.ConfigEvaluations.ValuesEntry\x1aH\n\x0bValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.prefab.ClientConfigValue:\x02\x38\x01\"\xa8\x02\n\x0fLimitDefinition\x12;\n\x0bpolicy_name\x18\x02 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNames\x12\r\n\x05limit\x18\x03 \x01(\x05\x12\r\n\x05\x62urst\x18\x04 \x01(\x05\x12\x12\n\naccount_id\x18\x05 \x01(\x03\x12\x15\n\rlast_modified\x18\x06 \x01(\x03\x12\x12\n\nreturnable\x18\x07 \x01(\x08\x12\x39\n\x0csafety_level\x18\x08 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"@\n\x0bSafetyLevel\x12\x0b\n\x07NOT_SET\x10\x00\x12\x12\n\x0eL4_BEST_EFFORT\x10\x04\x12\x10\n\x0cL5_BOMBPROOF\x10\x05\"@\n\x10LimitDefinitions\x12,\n\x0b\x64\x65\x66initions\x18\x01 \x03(\x0b\x32\x17.prefab.LimitDefinition\"\x8a\x01\n\x0f\x42ufferedRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x0e\n\x06method\x18\x02 \x01(\t\x12\x0b\n\x03uri\x18\x03 \x01(\t\x12\x0c\n\x04\x62ody\x18\x04 \x01(\t\x12\x14\n\x0climit_groups\x18\x05 \x03(\t\x12\x14\n\x0c\x63ontent_type\x18\x06 \x01(\t\x12\x0c\n\x04\x66ifo\x18\x07 \x01(\x08\"\x94\x01\n\x0c\x42\x61tchRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x0e\n\x06method\x18\x02 \x01(\t\x12\x0b\n\x03uri\x18\x03 \x01(\t\x12\x0c\n\x04\x62ody\x18\x04 \x01(\t\x12\x14\n\x0climit_groups\x18\x05 \x03(\t\x12\x16\n\x0e\x62\x61tch_template\x18\x06 \x01(\t\x12\x17\n\x0f\x62\x61tch_separator\x18\x07 \x01(\t\" \n\rBasicResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"3\n\x10\x43reationResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0e\n\x06new_id\x18\x02 \x01(\x03\"h\n\x07IdBlock\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x02 \x01(\x03\x12\x15\n\rsequence_name\x18\x03 \x01(\t\x12\r\n\x05start\x18\x04 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x05 \x01(\x03\"a\n\x0eIdBlockRequest\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x02 \x01(\x03\x12\x15\n\rsequence_name\x18\x03 \x01(\t\x12\x0c\n\x04size\x18\x04 \x01(\x03\"\x8a\x01\n\x0c\x43ontextShape\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x39\n\x0b\x66ield_types\x18\x02 \x03(\x0b\x32$.prefab.ContextShape.FieldTypesEntry\x1a\x31\n\x0f\x46ieldTypesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"[\n\rContextShapes\x12$\n\x06shapes\x18\x01 \x03(\x0b\x32\x14.prefab.ContextShape\x12\x16\n\tnamespace\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"C\n\rEvaluatedKeys\x12\x0c\n\x04keys\x18\x01 \x03(\t\x12\x16\n\tnamespace\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"\x93\x01\n\x0f\x45valuatedConfig\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x16\n\x0e\x63onfig_version\x18\x02 \x01(\x03\x12#\n\x06result\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValue\x12#\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSet\x12\x11\n\ttimestamp\x18\x05 \x01(\x03\"<\n\x10\x45valuatedConfigs\x12(\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x17.prefab.EvaluatedConfig\"\xb1\x03\n\x17\x43onfigEvaluationCounter\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x11\n\tconfig_id\x18\x02 \x01(\x03\x12\x1b\n\x0eselected_index\x18\x03 \x01(\rH\x00\x88\x01\x01\x12\x30\n\x0eselected_value\x18\x04 \x01(\x0b\x32\x13.prefab.ConfigValueH\x01\x88\x01\x01\x12\x1d\n\x10\x63onfig_row_index\x18\x05 \x01(\rH\x02\x88\x01\x01\x12$\n\x17\x63onditional_value_index\x18\x06 \x01(\rH\x03\x88\x01\x01\x12!\n\x14weighted_value_index\x18\x07 \x01(\rH\x04\x88\x01\x01\x12\x36\n\x06reason\x18\x08 \x01(\x0e\x32&.prefab.ConfigEvaluationCounter.Reason\"\x15\n\x06Reason\x12\x0b\n\x07UNKNOWN\x10\x00\x42\x11\n\x0f_selected_indexB\x11\n\x0f_selected_valueB\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_index\"{\n\x17\x43onfigEvaluationSummary\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x04type\x18\x02 \x01(\x0e\x32\x12.prefab.ConfigType\x12\x31\n\x08\x63ounters\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationCounter\"k\n\x19\x43onfigEvaluationSummaries\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x32\n\tsummaries\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationSummary\"\xb5\x01\n\x0eTelemetryEvent\x12\x36\n\tsummaries\x18\x02 \x01(\x0b\x32!.prefab.ConfigEvaluationSummariesH\x00\x12\x33\n\x10\x65xample_contexts\x18\x03 \x01(\x0b\x32\x17.prefab.ExampleContextsH\x00\x12+\n\x0c\x63lient_stats\x18\x04 \x01(\x0b\x32\x13.prefab.ClientStatsH\x00\x42\t\n\x07payload\"P\n\x0fTelemetryEvents\x12\x15\n\rinstance_hash\x18\x01 \x01(\t\x12&\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x16.prefab.TelemetryEvent\"*\n\x17TelemetryEventsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\";\n\x0f\x45xampleContexts\x12(\n\x08\x65xamples\x18\x01 \x03(\x0b\x32\x16.prefab.ExampleContext\"K\n\x0e\x45xampleContext\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12&\n\ncontextSet\x18\x02 \x01(\x0b\x32\x12.prefab.ContextSet\"F\n\x0b\x43lientStats\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x1b\n\x13\x64ropped_event_count\x18\x03 \x01(\x04*u\n\nConfigType\x12\x17\n\x13NOT_SET_CONFIG_TYPE\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\x10\n\x0c\x46\x45\x41TURE_FLAG\x10\x02\x12\r\n\tLOG_LEVEL\x10\x03\x12\x0b\n\x07SEGMENT\x10\x04\x12\x14\n\x10LIMIT_DEFINITION\x10\x05*a\n\x08LogLevel\x12\x15\n\x11NOT_SET_LOG_LEVEL\x10\x00\x12\t\n\x05TRACE\x10\x01\x12\t\n\x05\x44\x45\x42UG\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\x08\n\x04WARN\x10\x05\x12\t\n\x05\x45RROR\x10\x06\x12\t\n\x05\x46\x41TAL\x10\t*G\n\tOnFailure\x12\x0b\n\x07NOT_SET\x10\x00\x12\x10\n\x0cLOG_AND_PASS\x10\x01\x12\x10\n\x0cLOG_AND_FAIL\x10\x02\x12\t\n\x05THROW\x10\x03\x42\x1d\n\x13\x63loud.prefab.domainB\x06Prefabb\x06proto3"
|
8
|
+
descriptor_data = "\n\x0cprefab.proto\x12\x06prefab\"W\n\x14\x43onfigServicePointer\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x13\n\x0bstart_at_id\x18\x02 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x03 \x01(\x03\"\xca\x02\n\x0b\x43onfigValue\x12\r\n\x03int\x18\x01 \x01(\x03H\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x03 \x01(\x0cH\x00\x12\x10\n\x06\x64ouble\x18\x04 \x01(\x01H\x00\x12\x0e\n\x04\x62ool\x18\x05 \x01(\x08H\x00\x12\x31\n\x0fweighted_values\x18\x06 \x01(\x0b\x32\x16.prefab.WeightedValuesH\x00\x12\x33\n\x10limit_definition\x18\x07 \x01(\x0b\x32\x17.prefab.LimitDefinitionH\x00\x12%\n\tlog_level\x18\t \x01(\x0e\x32\x10.prefab.LogLevelH\x00\x12)\n\x0bstring_list\x18\n \x01(\x0b\x32\x12.prefab.StringListH\x00\x12%\n\tint_range\x18\x0b \x01(\x0b\x32\x10.prefab.IntRangeH\x00\x42\x06\n\x04type\"B\n\x08IntRange\x12\x12\n\x05start\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x10\n\x03\x65nd\x18\x02 \x01(\x03H\x01\x88\x01\x01\x42\x08\n\x06_startB\x06\n\x04_end\"\x1c\n\nStringList\x12\x0e\n\x06values\x18\x01 \x03(\t\"C\n\rWeightedValue\x12\x0e\n\x06weight\x18\x01 \x01(\x05\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue\"~\n\x0eWeightedValues\x12.\n\x0fweighted_values\x18\x01 \x03(\x0b\x32\x15.prefab.WeightedValue\x12\"\n\x15hash_by_property_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x18\n\x16_hash_by_property_name\"X\n\x0e\x41piKeyMetadata\x12\x13\n\x06key_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07user_id\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_key_idB\n\n\x08_user_idJ\x04\x08\x02\x10\x03\"\xf8\x01\n\x07\x43onfigs\x12\x1f\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x0e.prefab.Config\x12<\n\x16\x63onfig_service_pointer\x18\x02 \x01(\x0b\x32\x1c.prefab.ConfigServicePointer\x12\x34\n\x0f\x61pikey_metadata\x18\x03 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00\x88\x01\x01\x12\x30\n\x0f\x64\x65\x66\x61ult_context\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSetH\x01\x88\x01\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_context\"\xf7\x01\n\x06\x43onfig\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x12\n\nproject_id\x18\x02 \x01(\x03\x12\x0b\n\x03key\x18\x03 \x01(\t\x12%\n\nchanged_by\x18\x04 \x01(\x0b\x32\x11.prefab.ChangedBy\x12\x1f\n\x04rows\x18\x05 \x03(\x0b\x32\x11.prefab.ConfigRow\x12-\n\x10\x61llowable_values\x18\x06 \x03(\x0b\x32\x13.prefab.ConfigValue\x12\'\n\x0b\x63onfig_type\x18\x07 \x01(\x0e\x32\x12.prefab.ConfigType\x12\x14\n\x07\x64raftId\x18\x08 \x01(\x03H\x00\x88\x01\x01\x42\n\n\x08_draftId\"?\n\tChangedBy\x12\x0f\n\x07user_id\x18\x01 \x01(\x03\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x12\n\napi_key_id\x18\x03 \x01(\t\"\xe4\x01\n\tConfigRow\x12\x1b\n\x0eproject_env_id\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12(\n\x06values\x18\x02 \x03(\x0b\x32\x18.prefab.ConditionalValue\x12\x35\n\nproperties\x18\x03 \x03(\x0b\x32!.prefab.ConfigRow.PropertiesEntry\x1a\x46\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue:\x02\x38\x01\x42\x11\n\x0f_project_env_id\"[\n\x10\x43onditionalValue\x12#\n\x08\x63riteria\x18\x01 \x03(\x0b\x32\x11.prefab.Criterion\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue\"\x94\x03\n\tCriterion\x12\x15\n\rproperty_name\x18\x01 \x01(\t\x12\x35\n\x08operator\x18\x02 \x01(\x0e\x32#.prefab.Criterion.CriterionOperator\x12+\n\x0evalue_to_match\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValue\"\x8b\x02\n\x11\x43riterionOperator\x12\x0b\n\x07NOT_SET\x10\x00\x12\x11\n\rLOOKUP_KEY_IN\x10\x01\x12\x15\n\x11LOOKUP_KEY_NOT_IN\x10\x02\x12\n\n\x06IN_SEG\x10\x03\x12\x0e\n\nNOT_IN_SEG\x10\x04\x12\x0f\n\x0b\x41LWAYS_TRUE\x10\x05\x12\x12\n\x0ePROP_IS_ONE_OF\x10\x06\x12\x16\n\x12PROP_IS_NOT_ONE_OF\x10\x07\x12\x19\n\x15PROP_ENDS_WITH_ONE_OF\x10\x08\x12!\n\x1dPROP_DOES_NOT_END_WITH_ONE_OF\x10\t\x12\x16\n\x12HIERARCHICAL_MATCH\x10\n\x12\x10\n\x0cIN_INT_RANGE\x10\x0b\"\x89\x01\n\x07Loggers\x12\x1f\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.Logger\x12\x10\n\x08start_at\x18\x02 \x01(\x03\x12\x0e\n\x06\x65nd_at\x18\x03 \x01(\x03\x12\x15\n\rinstance_hash\x18\x04 \x01(\t\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"\xd9\x01\n\x06Logger\x12\x13\n\x0blogger_name\x18\x01 \x01(\t\x12\x13\n\x06traces\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\x13\n\x06\x64\x65\x62ugs\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x12\n\x05infos\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12\x12\n\x05warns\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x13\n\x06\x65rrors\x18\x06 \x01(\x03H\x04\x88\x01\x01\x12\x13\n\x06\x66\x61tals\x18\x07 \x01(\x03H\x05\x88\x01\x01\x42\t\n\x07_tracesB\t\n\x07_debugsB\x08\n\x06_infosB\x08\n\x06_warnsB\t\n\x07_errorsB\t\n\x07_fatals\"\x16\n\x14LoggerReportResponse\"\xdb\x03\n\rLimitResponse\x12\x0e\n\x06passed\x18\x01 \x01(\x08\x12\x12\n\nexpires_at\x18\x02 \x01(\x03\x12\x16\n\x0e\x65nforced_group\x18\x03 \x01(\t\x12\x16\n\x0e\x63urrent_bucket\x18\x04 \x01(\x03\x12\x14\n\x0cpolicy_group\x18\x05 \x01(\t\x12;\n\x0bpolicy_name\x18\x06 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNames\x12\x14\n\x0cpolicy_limit\x18\x07 \x01(\x05\x12\x0e\n\x06\x61mount\x18\x08 \x01(\x03\x12\x16\n\x0elimit_reset_at\x18\t \x01(\x03\x12\x39\n\x0csafety_level\x18\n \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"\xa9\x01\n\x10LimitPolicyNames\x12\x0b\n\x07NOT_SET\x10\x00\x12\x14\n\x10SECONDLY_ROLLING\x10\x01\x12\x14\n\x10MINUTELY_ROLLING\x10\x03\x12\x12\n\x0eHOURLY_ROLLING\x10\x05\x12\x11\n\rDAILY_ROLLING\x10\x07\x12\x13\n\x0fMONTHLY_ROLLING\x10\x08\x12\x0c\n\x08INFINITE\x10\t\x12\x12\n\x0eYEARLY_ROLLING\x10\n\"\x99\x02\n\x0cLimitRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x16\n\x0e\x61\x63quire_amount\x18\x02 \x01(\x05\x12\x0e\n\x06groups\x18\x03 \x03(\t\x12:\n\x0elimit_combiner\x18\x04 \x01(\x0e\x32\".prefab.LimitRequest.LimitCombiner\x12\x1e\n\x16\x61llow_partial_response\x18\x05 \x01(\x08\x12\x39\n\x0csafety_level\x18\x06 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"6\n\rLimitCombiner\x12\x0b\n\x07NOT_SET\x10\x00\x12\x0b\n\x07MINIMUM\x10\x01\x12\x0b\n\x07MAXIMUM\x10\x02\"/\n\nContextSet\x12!\n\x08\x63ontexts\x18\x01 \x03(\x0b\x32\x0f.prefab.Context\"\x96\x01\n\x07\x43ontext\x12\x11\n\x04type\x18\x01 \x01(\tH\x00\x88\x01\x01\x12+\n\x06values\x18\x02 \x03(\x0b\x32\x1b.prefab.Context.ValuesEntry\x1a\x42\n\x0bValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue:\x02\x38\x01\x42\x07\n\x05_type\"\x93\x01\n\x08Identity\x12\x13\n\x06lookup\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x34\n\nattributes\x18\x02 \x03(\x0b\x32 .prefab.Identity.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07_lookup\"\xc1\x01\n\x11\x43lientConfigValue\x12\x10\n\x03int\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x13\n\x06string\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x13\n\x06\x64ouble\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x11\n\x04\x62ool\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12(\n\tlog_level\x18\x05 \x01(\x0e\x32\x10.prefab.LogLevelH\x04\x88\x01\x01\x42\x06\n\x04_intB\t\n\x07_stringB\t\n\x07_doubleB\x07\n\x05_boolB\x0c\n\n_log_level\"\xa4\x02\n\x11\x43onfigEvaluations\x12\x35\n\x06values\x18\x01 \x03(\x0b\x32%.prefab.ConfigEvaluations.ValuesEntry\x12\x34\n\x0f\x61pikey_metadata\x18\x02 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00\x88\x01\x01\x12\x30\n\x0f\x64\x65\x66\x61ult_context\x18\x03 \x01(\x0b\x32\x12.prefab.ContextSetH\x01\x88\x01\x01\x1aH\n\x0bValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.prefab.ClientConfigValue:\x02\x38\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_context\"\xa8\x02\n\x0fLimitDefinition\x12;\n\x0bpolicy_name\x18\x02 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNames\x12\r\n\x05limit\x18\x03 \x01(\x05\x12\r\n\x05\x62urst\x18\x04 \x01(\x05\x12\x12\n\naccount_id\x18\x05 \x01(\x03\x12\x15\n\rlast_modified\x18\x06 \x01(\x03\x12\x12\n\nreturnable\x18\x07 \x01(\x08\x12\x39\n\x0csafety_level\x18\x08 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"@\n\x0bSafetyLevel\x12\x0b\n\x07NOT_SET\x10\x00\x12\x12\n\x0eL4_BEST_EFFORT\x10\x04\x12\x10\n\x0cL5_BOMBPROOF\x10\x05\"@\n\x10LimitDefinitions\x12,\n\x0b\x64\x65\x66initions\x18\x01 \x03(\x0b\x32\x17.prefab.LimitDefinition\"\x8a\x01\n\x0f\x42ufferedRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x0e\n\x06method\x18\x02 \x01(\t\x12\x0b\n\x03uri\x18\x03 \x01(\t\x12\x0c\n\x04\x62ody\x18\x04 \x01(\t\x12\x14\n\x0climit_groups\x18\x05 \x03(\t\x12\x14\n\x0c\x63ontent_type\x18\x06 \x01(\t\x12\x0c\n\x04\x66ifo\x18\x07 \x01(\x08\"\x94\x01\n\x0c\x42\x61tchRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x0e\n\x06method\x18\x02 \x01(\t\x12\x0b\n\x03uri\x18\x03 \x01(\t\x12\x0c\n\x04\x62ody\x18\x04 \x01(\t\x12\x14\n\x0climit_groups\x18\x05 \x03(\t\x12\x16\n\x0e\x62\x61tch_template\x18\x06 \x01(\t\x12\x17\n\x0f\x62\x61tch_separator\x18\x07 \x01(\t\" \n\rBasicResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"3\n\x10\x43reationResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0e\n\x06new_id\x18\x02 \x01(\x03\"h\n\x07IdBlock\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x02 \x01(\x03\x12\x15\n\rsequence_name\x18\x03 \x01(\t\x12\r\n\x05start\x18\x04 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x05 \x01(\x03\"a\n\x0eIdBlockRequest\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x02 \x01(\x03\x12\x15\n\rsequence_name\x18\x03 \x01(\t\x12\x0c\n\x04size\x18\x04 \x01(\x03\"\x8a\x01\n\x0c\x43ontextShape\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x39\n\x0b\x66ield_types\x18\x02 \x03(\x0b\x32$.prefab.ContextShape.FieldTypesEntry\x1a\x31\n\x0f\x46ieldTypesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"[\n\rContextShapes\x12$\n\x06shapes\x18\x01 \x03(\x0b\x32\x14.prefab.ContextShape\x12\x16\n\tnamespace\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"C\n\rEvaluatedKeys\x12\x0c\n\x04keys\x18\x01 \x03(\t\x12\x16\n\tnamespace\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"\x93\x01\n\x0f\x45valuatedConfig\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x16\n\x0e\x63onfig_version\x18\x02 \x01(\x03\x12#\n\x06result\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValue\x12#\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSet\x12\x11\n\ttimestamp\x18\x05 \x01(\x03\"<\n\x10\x45valuatedConfigs\x12(\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x17.prefab.EvaluatedConfig\"\xc4\x03\n\x17\x43onfigEvaluationCounter\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x16\n\tconfig_id\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\x1b\n\x0eselected_index\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x30\n\x0eselected_value\x18\x04 \x01(\x0b\x32\x13.prefab.ConfigValueH\x02\x88\x01\x01\x12\x1d\n\x10\x63onfig_row_index\x18\x05 \x01(\rH\x03\x88\x01\x01\x12$\n\x17\x63onditional_value_index\x18\x06 \x01(\rH\x04\x88\x01\x01\x12!\n\x14weighted_value_index\x18\x07 \x01(\rH\x05\x88\x01\x01\x12\x36\n\x06reason\x18\x08 \x01(\x0e\x32&.prefab.ConfigEvaluationCounter.Reason\"\x15\n\x06Reason\x12\x0b\n\x07UNKNOWN\x10\x00\x42\x0c\n\n_config_idB\x11\n\x0f_selected_indexB\x11\n\x0f_selected_valueB\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_index\"{\n\x17\x43onfigEvaluationSummary\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x04type\x18\x02 \x01(\x0e\x32\x12.prefab.ConfigType\x12\x31\n\x08\x63ounters\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationCounter\"k\n\x19\x43onfigEvaluationSummaries\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x32\n\tsummaries\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationSummary\"Z\n\x15LoggersTelemetryEvent\x12\x1f\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.Logger\x12\x10\n\x08start_at\x18\x02 \x01(\x03\x12\x0e\n\x06\x65nd_at\x18\x03 \x01(\x03\"\xe7\x01\n\x0eTelemetryEvent\x12\x36\n\tsummaries\x18\x02 \x01(\x0b\x32!.prefab.ConfigEvaluationSummariesH\x00\x12\x33\n\x10\x65xample_contexts\x18\x03 \x01(\x0b\x32\x17.prefab.ExampleContextsH\x00\x12+\n\x0c\x63lient_stats\x18\x04 \x01(\x0b\x32\x13.prefab.ClientStatsH\x00\x12\x30\n\x07loggers\x18\x05 \x01(\x0b\x32\x1d.prefab.LoggersTelemetryEventH\x00\x42\t\n\x07payload\"P\n\x0fTelemetryEvents\x12\x15\n\rinstance_hash\x18\x01 \x01(\t\x12&\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x16.prefab.TelemetryEvent\"*\n\x17TelemetryEventsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\";\n\x0f\x45xampleContexts\x12(\n\x08\x65xamples\x18\x01 \x03(\x0b\x32\x16.prefab.ExampleContext\"K\n\x0e\x45xampleContext\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12&\n\ncontextSet\x18\x02 \x01(\x0b\x32\x12.prefab.ContextSet\"F\n\x0b\x43lientStats\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x1b\n\x13\x64ropped_event_count\x18\x03 \x01(\x04*\x82\x01\n\nConfigType\x12\x17\n\x13NOT_SET_CONFIG_TYPE\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\x10\n\x0c\x46\x45\x41TURE_FLAG\x10\x02\x12\r\n\tLOG_LEVEL\x10\x03\x12\x0b\n\x07SEGMENT\x10\x04\x12\x14\n\x10LIMIT_DEFINITION\x10\x05\x12\x0b\n\x07\x44\x45LETED\x10\x06*a\n\x08LogLevel\x12\x15\n\x11NOT_SET_LOG_LEVEL\x10\x00\x12\t\n\x05TRACE\x10\x01\x12\t\n\x05\x44\x45\x42UG\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\x08\n\x04WARN\x10\x05\x12\t\n\x05\x45RROR\x10\x06\x12\t\n\x05\x46\x41TAL\x10\t*G\n\tOnFailure\x12\x0b\n\x07NOT_SET\x10\x00\x12\x10\n\x0cLOG_AND_PASS\x10\x01\x12\x10\n\x0cLOG_AND_FAIL\x10\x02\x12\t\n\x05THROW\x10\x03\x42\x1d\n\x13\x63loud.prefab.domainB\x06Prefabb\x06proto3"
|
9
9
|
|
10
10
|
pool = Google::Protobuf::DescriptorPool.generated_pool
|
11
11
|
|
@@ -38,6 +38,7 @@ module PrefabProto
|
|
38
38
|
StringList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.StringList").msgclass
|
39
39
|
WeightedValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.WeightedValue").msgclass
|
40
40
|
WeightedValues = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.WeightedValues").msgclass
|
41
|
+
ApiKeyMetadata = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ApiKeyMetadata").msgclass
|
41
42
|
Configs = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Configs").msgclass
|
42
43
|
Config = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Config").msgclass
|
43
44
|
ChangedBy = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ChangedBy").msgclass
|
@@ -75,6 +76,7 @@ module PrefabProto
|
|
75
76
|
ConfigEvaluationCounter::Reason = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationCounter.Reason").enummodule
|
76
77
|
ConfigEvaluationSummary = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationSummary").msgclass
|
77
78
|
ConfigEvaluationSummaries = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationSummaries").msgclass
|
79
|
+
LoggersTelemetryEvent = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LoggersTelemetryEvent").msgclass
|
78
80
|
TelemetryEvent = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.TelemetryEvent").msgclass
|
79
81
|
TelemetryEvents = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.TelemetryEvents").msgclass
|
80
82
|
TelemetryEventsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.TelemetryEventsResponse").msgclass
|
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.1.1 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.1.1"
|
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-10-11"
|
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]
|
@@ -40,6 +40,7 @@ Gem::Specification.new do |s|
|
|
40
40
|
"lib/prefab-cloud-ruby.rb",
|
41
41
|
"lib/prefab/client.rb",
|
42
42
|
"lib/prefab/config_client.rb",
|
43
|
+
"lib/prefab/config_client_presenter.rb",
|
43
44
|
"lib/prefab/config_loader.rb",
|
44
45
|
"lib/prefab/config_resolver.rb",
|
45
46
|
"lib/prefab/config_value_unwrapper.rb",
|
data/test/integration_test.rb
CHANGED
@@ -1,18 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class IntegrationTest
|
4
|
-
attr_reader :func, :input, :expected, :test_client
|
4
|
+
attr_reader :func, :input, :expected, :data, :expected_data, :aggregator, :endpoint, :test_client
|
5
5
|
|
6
6
|
def initialize(test_data)
|
7
7
|
@client_overrides = parse_client_overrides(test_data['client_overrides'])
|
8
8
|
@func = parse_function(test_data['function'])
|
9
9
|
@input = parse_input(test_data['input'])
|
10
10
|
@expected = parse_expected(test_data['expected'])
|
11
|
-
@
|
11
|
+
@data = test_data['data']
|
12
|
+
@expected_data = test_data['expected_data']
|
13
|
+
@aggregator = test_data['aggregator']
|
14
|
+
@endpoint = test_data['endpoint']
|
15
|
+
@test_client = capture_telemetry(base_client)
|
12
16
|
end
|
13
17
|
|
14
18
|
def test_type
|
15
|
-
if @
|
19
|
+
if @data
|
20
|
+
:telemetry
|
21
|
+
elsif @input[0] && @input[0].start_with?('log-level.')
|
16
22
|
:log_level
|
17
23
|
elsif @expected[:status] == 'raise'
|
18
24
|
:raise
|
@@ -23,6 +29,18 @@ class IntegrationTest
|
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
32
|
+
def last_data_sent
|
33
|
+
test_client.last_data_sent
|
34
|
+
end
|
35
|
+
|
36
|
+
def last_post_result
|
37
|
+
test_client.last_post_result
|
38
|
+
end
|
39
|
+
|
40
|
+
def last_post_endpoint
|
41
|
+
test_client.last_post_endpoint
|
42
|
+
end
|
43
|
+
|
26
44
|
private
|
27
45
|
|
28
46
|
def parse_client_overrides(overrides)
|
@@ -42,6 +60,8 @@ class IntegrationTest
|
|
42
60
|
end
|
43
61
|
|
44
62
|
def parse_input(input)
|
63
|
+
return nil if input.nil?
|
64
|
+
|
45
65
|
if input['key']
|
46
66
|
parse_config_input(input)
|
47
67
|
elsif input['flag']
|
@@ -62,6 +82,8 @@ class IntegrationTest
|
|
62
82
|
end
|
63
83
|
|
64
84
|
def parse_expected(expected)
|
85
|
+
return {} if expected.nil?
|
86
|
+
|
65
87
|
{
|
66
88
|
status: expected['status'],
|
67
89
|
error: parse_error_type(expected['error']),
|
@@ -73,6 +95,7 @@ class IntegrationTest
|
|
73
95
|
def parse_error_type(error_type)
|
74
96
|
case error_type
|
75
97
|
when 'missing_default' then Prefab::Errors::MissingDefaultError
|
98
|
+
when 'initialization_timeout' then Prefab::Errors::InitializationTimeoutError
|
76
99
|
end
|
77
100
|
end
|
78
101
|
|
@@ -87,7 +110,34 @@ class IntegrationTest
|
|
87
110
|
prefab_envs: ['unit_tests'],
|
88
111
|
prefab_datasources: Prefab::Options::DATASOURCES::ALL,
|
89
112
|
api_key: ENV['PREFAB_INTEGRATION_TEST_API_KEY'],
|
90
|
-
prefab_api_url: 'https://api.staging-prefab.cloud'
|
113
|
+
prefab_api_url: 'https://api.staging-prefab.cloud',
|
91
114
|
}.merge(@client_overrides))
|
92
115
|
end
|
116
|
+
|
117
|
+
def capture_telemetry(client)
|
118
|
+
client.define_singleton_method(:post) do |url, data|
|
119
|
+
client.instance_variable_set(:@last_data_sent, data)
|
120
|
+
client.instance_variable_set(:@last_post_endpoint, url)
|
121
|
+
|
122
|
+
result = super(url, data)
|
123
|
+
|
124
|
+
client.instance_variable_set(:@last_post_result, result)
|
125
|
+
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
client.define_singleton_method(:last_data_sent) do
|
130
|
+
client.instance_variable_get(:@last_data_sent)
|
131
|
+
end
|
132
|
+
|
133
|
+
client.define_singleton_method(:last_post_endpoint) do
|
134
|
+
client.instance_variable_get(:@last_post_endpoint)
|
135
|
+
end
|
136
|
+
|
137
|
+
client.define_singleton_method(:last_post_result) do
|
138
|
+
client.instance_variable_get(:@last_post_result)
|
139
|
+
end
|
140
|
+
|
141
|
+
client
|
142
|
+
end
|
93
143
|
end
|
@@ -33,4 +33,117 @@ module IntegrationTestHelpers
|
|
33
33
|
.select { |file| file =~ /\.ya?ml$/ }
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
def self.prepare_post_data(it)
|
38
|
+
case it.aggregator
|
39
|
+
when "log_path"
|
40
|
+
aggregator = it.test_client.log_path_aggregator
|
41
|
+
|
42
|
+
it.data.each do |(path, data)|
|
43
|
+
data.each_with_index do |count, severity|
|
44
|
+
count.times { aggregator.push(path, severity) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
expected_loggers = Hash.new { |h, k| h[k] = PrefabProto::Logger.new }
|
49
|
+
|
50
|
+
it.expected_data.each do |data|
|
51
|
+
data["counts"].each do |(severity, count)|
|
52
|
+
expected_loggers[data["logger_name"]][severity] = count
|
53
|
+
expected_loggers[data["logger_name"]]["logger_name"] = data["logger_name"]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
[aggregator, ->(data) { data.loggers }, expected_loggers.values]
|
58
|
+
when "context_shape"
|
59
|
+
aggregator = it.test_client.context_shape_aggregator
|
60
|
+
|
61
|
+
context = Prefab::Context.new(it.data)
|
62
|
+
|
63
|
+
aggregator.push(context)
|
64
|
+
|
65
|
+
expected = it.expected_data.map do |data|
|
66
|
+
PrefabProto::ContextShape.new(
|
67
|
+
name: data["name"],
|
68
|
+
field_types: data["field_types"]
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
[aggregator, ->(data) { data.shapes }, expected]
|
73
|
+
when "evaluation_summary"
|
74
|
+
aggregator = it.test_client.evaluation_summary_aggregator
|
75
|
+
|
76
|
+
aggregator.instance_variable_set("@data", Concurrent::Hash.new)
|
77
|
+
|
78
|
+
it.data.each do |key|
|
79
|
+
it.test_client.get(key)
|
80
|
+
end
|
81
|
+
|
82
|
+
expected_data = []
|
83
|
+
it.expected_data.each do |data|
|
84
|
+
value = if data["value_type"] == "string_list"
|
85
|
+
PrefabProto::StringList.new(values: data["value"])
|
86
|
+
else
|
87
|
+
data["value"]
|
88
|
+
end
|
89
|
+
expected_data << PrefabProto::ConfigEvaluationSummary.new(
|
90
|
+
key: data["key"],
|
91
|
+
type: data["type"].to_sym,
|
92
|
+
counters: [
|
93
|
+
PrefabProto::ConfigEvaluationCounter.new(
|
94
|
+
count: data["count"],
|
95
|
+
config_id: 0,
|
96
|
+
selected_value: PrefabProto::ConfigValue.new(data["value_type"] => value),
|
97
|
+
config_row_index: data["summary"]["config_row_index"],
|
98
|
+
conditional_value_index: data["summary"]["conditional_value_index"] || 0,
|
99
|
+
weighted_value_index: data["summary"]["weighted_value_index"],
|
100
|
+
reason: :UNKNOWN
|
101
|
+
)
|
102
|
+
]
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
[aggregator, ->(data) {
|
107
|
+
data.events[0].summaries.summaries.each { |e|
|
108
|
+
e.counters.each { |c|
|
109
|
+
c.config_id = 0
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}, expected_data]
|
113
|
+
when "example_contexts"
|
114
|
+
aggregator = it.test_client.example_contexts_aggregator
|
115
|
+
|
116
|
+
it.data.each do |hash|
|
117
|
+
aggregator.record(Prefab::Context.new(hash))
|
118
|
+
end
|
119
|
+
|
120
|
+
expected_data = []
|
121
|
+
it.expected_data.each do |data|
|
122
|
+
expected_data << PrefabProto::ExampleContext.new(
|
123
|
+
timestamp: 0,
|
124
|
+
contextSet: PrefabProto::ContextSet.new(
|
125
|
+
contexts: data.map do |(k, vs)|
|
126
|
+
PrefabProto::Context.new(
|
127
|
+
type: k,
|
128
|
+
values: vs.map do |v|
|
129
|
+
[v["key"], PrefabProto::ConfigValue.new(v["value_type"] => v["value"])]
|
130
|
+
end.to_h
|
131
|
+
)
|
132
|
+
end
|
133
|
+
)
|
134
|
+
)
|
135
|
+
end
|
136
|
+
[aggregator, ->(data) { data.events[0].example_contexts.examples.each { |e| e.timestamp = 0 } }, expected_data]
|
137
|
+
else
|
138
|
+
puts "unknown aggregator #{it.aggregator}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.with_parent_context_maybe(context, &block)
|
143
|
+
if context
|
144
|
+
Prefab::Context.with_context(context, &block)
|
145
|
+
else
|
146
|
+
yield
|
147
|
+
end
|
148
|
+
end
|
36
149
|
end
|
@@ -82,6 +82,16 @@ module CommonHelpers
|
|
82
82
|
|
83
83
|
FakeResponse = Struct.new(:status, :body)
|
84
84
|
|
85
|
+
def wait_for(condition, max_wait: 2, sleep_time: 0.01)
|
86
|
+
wait_time = 0
|
87
|
+
while !condition.call
|
88
|
+
wait_time += sleep_time
|
89
|
+
sleep sleep_time
|
90
|
+
|
91
|
+
raise "Waited #{max_wait} seconds for the condition to be true, but it never was" if wait_time > max_wait
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
85
95
|
def wait_for_post_requests(client, max_wait: 2, sleep_time: 0.01)
|
86
96
|
# we use ivars to avoid re-mocking the post method on subsequent calls
|
87
97
|
client.instance_variable_set("@_requests", [])
|
@@ -99,13 +109,7 @@ module CommonHelpers
|
|
99
109
|
yield
|
100
110
|
|
101
111
|
# let the flush thread run
|
102
|
-
|
103
|
-
while client.instance_variable_get("@_requests").empty?
|
104
|
-
wait_time += sleep_time
|
105
|
-
sleep sleep_time
|
106
|
-
|
107
|
-
raise "Waited #{max_wait} seconds for the flush thread to run, but it never did" if wait_time > max_wait
|
108
|
-
end
|
112
|
+
wait_for -> { client.instance_variable_get("@_requests").size > 0 }, max_wait: max_wait, sleep_time: sleep_time
|
109
113
|
|
110
114
|
client.instance_variable_get("@_requests")
|
111
115
|
end
|
data/test/test_integration.rb
CHANGED
@@ -16,7 +16,7 @@ class TestIntegration < Minitest::Test
|
|
16
16
|
define_method(:"test_#{test['name']}_#{test_case['name']}") do
|
17
17
|
it = IntegrationTest.new(test_case)
|
18
18
|
|
19
|
-
with_parent_context_maybe(parent_context) do
|
19
|
+
IntegrationTestHelpers.with_parent_context_maybe(parent_context) do
|
20
20
|
case it.test_type
|
21
21
|
when :raise
|
22
22
|
err = assert_raises(it.expected[:error]) do
|
@@ -34,6 +34,19 @@ class TestIntegration < Minitest::Test
|
|
34
34
|
end
|
35
35
|
when :log_level
|
36
36
|
assert_equal it.expected[:value].to_sym, it.test_client.send(it.func, *it.input)
|
37
|
+
when :telemetry
|
38
|
+
aggregator, get_actual_data, expected = IntegrationTestHelpers.prepare_post_data(it)
|
39
|
+
aggregator.sync
|
40
|
+
|
41
|
+
wait_for -> { it.last_post_result&.status == 200 }
|
42
|
+
|
43
|
+
assert it.endpoint == it.last_post_endpoint
|
44
|
+
|
45
|
+
actual = get_actual_data[it.last_data_sent]
|
46
|
+
|
47
|
+
expected.all? do |expected|
|
48
|
+
assert actual.include?(expected)
|
49
|
+
end
|
37
50
|
else
|
38
51
|
raise "Unknown test type: #{it.test_type}"
|
39
52
|
end
|
@@ -42,14 +55,4 @@ class TestIntegration < Minitest::Test
|
|
42
55
|
end
|
43
56
|
end
|
44
57
|
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def with_parent_context_maybe(context, &block)
|
49
|
-
if context
|
50
|
-
Prefab::Context.with_context(context, &block)
|
51
|
-
else
|
52
|
-
yield
|
53
|
-
end
|
54
|
-
end
|
55
58
|
end
|
data/test/test_logger.rb
CHANGED
@@ -404,6 +404,46 @@ class TestLogger < Minitest::Test
|
|
404
404
|
assert_logged io, 'ERROR', 'test.test_logger.test_logging_with_a_block', message
|
405
405
|
end
|
406
406
|
|
407
|
+
def test_structured_logging
|
408
|
+
prefab, io = captured_logger
|
409
|
+
message = 'HELLO'
|
410
|
+
|
411
|
+
prefab.log.error message, user: "michael", id: 123
|
412
|
+
|
413
|
+
assert_logged io, 'ERROR', 'test.test_logger.test_structured_logging', "#{message} id=123 user=michael"
|
414
|
+
end
|
415
|
+
|
416
|
+
def test_structured_json_logging
|
417
|
+
prefab, io = captured_logger(log_formatter: Prefab::Options::JSON_LOG_FORMATTER)
|
418
|
+
message = 'HELLO'
|
419
|
+
|
420
|
+
prefab.log.error message, user: "michael", id: 123
|
421
|
+
|
422
|
+
log_data = JSON.parse(io.string)
|
423
|
+
assert log_data["message"] == message
|
424
|
+
assert log_data["user"] == "michael"
|
425
|
+
assert log_data["id"] == 123
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_structured_internal_logging
|
429
|
+
prefab, io = captured_logger
|
430
|
+
|
431
|
+
prefab.log.log_internal('test', 'test.path', '', ::Logger::WARN, user: "michael")
|
432
|
+
|
433
|
+
assert_logged io, 'WARN', 'cloud.prefab.client.test.path', "test user=michael"
|
434
|
+
end
|
435
|
+
|
436
|
+
def test_structured_block_logger
|
437
|
+
prefab, io = captured_logger
|
438
|
+
message = 'MY MESSAGE'
|
439
|
+
|
440
|
+
prefab.log.error user: "michael" do
|
441
|
+
message
|
442
|
+
end
|
443
|
+
|
444
|
+
assert_logged io, 'ERROR', 'test.test_logger.test_structured_block_logger', "#{message} user=michael"
|
445
|
+
end
|
446
|
+
|
407
447
|
private
|
408
448
|
|
409
449
|
def assert_logged(logged_io, level, path, message)
|
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: 1.
|
4
|
+
version: 1.1.1
|
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-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -199,6 +199,7 @@ files:
|
|
199
199
|
- lib/prefab-cloud-ruby.rb
|
200
200
|
- lib/prefab/client.rb
|
201
201
|
- lib/prefab/config_client.rb
|
202
|
+
- lib/prefab/config_client_presenter.rb
|
202
203
|
- lib/prefab/config_loader.rb
|
203
204
|
- lib/prefab/config_resolver.rb
|
204
205
|
- lib/prefab/config_value_unwrapper.rb
|