prefab-cloud-ruby 0.24.4 → 0.24.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -1
- data/VERSION +1 -1
- data/compile_protos.sh +7 -0
- data/lib/prefab/client.rb +17 -4
- data/lib/prefab/config_client.rb +10 -10
- data/lib/prefab/config_value_unwrapper.rb +20 -9
- data/lib/prefab/context.rb +39 -7
- data/lib/prefab/context_shape_aggregator.rb +1 -1
- data/lib/prefab/criteria_evaluator.rb +24 -16
- data/lib/prefab/evaluated_keys_aggregator.rb +1 -1
- data/lib/prefab/evaluation.rb +48 -0
- data/lib/prefab/evaluation_summary_aggregator.rb +85 -0
- data/lib/prefab/example_contexts_aggregator.rb +76 -0
- data/lib/prefab/exponential_backoff.rb +5 -0
- data/lib/prefab/http_connection.rb +5 -1
- data/lib/prefab/log_path_aggregator.rb +1 -1
- data/lib/prefab/logger_client.rb +12 -13
- data/lib/prefab/options.rb +27 -14
- data/lib/prefab/periodic_sync.rb +30 -13
- data/lib/prefab/rate_limit_cache.rb +41 -0
- data/lib/prefab/resolved_config_presenter.rb +2 -4
- data/lib/prefab/weighted_value_resolver.rb +1 -1
- data/lib/prefab-cloud-ruby.rb +6 -3
- data/lib/prefab_pb.rb +11 -1
- data/prefab-cloud-ruby.gemspec +14 -5
- data/test/support/common_helpers.rb +105 -0
- data/test/support/mock_base_client.rb +44 -0
- data/test/support/mock_config_client.rb +19 -0
- data/test/support/mock_config_loader.rb +1 -0
- data/test/test_client.rb +257 -2
- data/test/test_config_resolver.rb +25 -24
- data/test/test_config_value_unwrapper.rb +22 -32
- data/test/test_context_shape_aggregator.rb +0 -1
- data/test/test_criteria_evaluator.rb +179 -133
- data/test/test_evaluation_summary_aggregator.rb +162 -0
- data/test/test_example_contexts_aggregator.rb +238 -0
- data/test/test_helper.rb +5 -131
- data/test/test_local_config_parser.rb +2 -2
- data/test/test_logger.rb +5 -5
- data/test/test_options.rb +8 -0
- data/test/test_rate_limit_cache.rb +44 -0
- data/test/test_weighted_value_resolver.rb +13 -7
- metadata +13 -4
- data/lib/prefab/evaluated_configs_aggregator.rb +0 -60
- data/test/test_evaluated_configs_aggregator.rb +0 -254
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36d1b27d1c03aef56882735b73835b65b508b5eef821f65e89ab5ba77f54a8ab
|
4
|
+
data.tar.gz: 00a336ac664ab495ce1c5fff4b5ab6972169a095087887958c3a0881016ba273
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0dc48a30fd50f53e9709e138afd408bfc2e91e6badb473c1d141db56c7cdfa507aef81db0f06674b8d640dec2a7ac147654def0cdd7e7bcebdd3b0eb2a79854
|
7
|
+
data.tar.gz: a3bd2f91776a25d646f1ab28d54d395bd24283e16dbca2f0bc7a1d1f77c9bb063488e9f62e00030a8acc84b2ecb8b07791bf84c1893e091f40edbb75e55870ca
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
##
|
3
|
+
## 0.24.6 - 2023-07-31
|
4
|
+
|
5
|
+
- Logger Client compatibility (#129)
|
6
|
+
- Replace EvaluatedConfigs with ExampleContexts (#128)
|
7
|
+
- Add ConfigEvaluationSummaries (opt-in for now) (#123)
|
8
|
+
|
9
|
+
## 0.24.5 - 2023-07-10
|
10
|
+
|
11
|
+
- Report Client Version (#121)
|
4
12
|
|
5
13
|
## [0.24.4] - 2023-07-06
|
6
14
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.24.
|
1
|
+
0.24.6
|
data/compile_protos.sh
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
|
3
|
+
set -e
|
4
|
+
|
3
5
|
gem install grpc-tools
|
4
6
|
|
7
|
+
(
|
8
|
+
cd ../prefab-cloud
|
9
|
+
git pull --rebase
|
10
|
+
)
|
11
|
+
|
5
12
|
grpc_tools_ruby_protoc -I ../prefab-cloud/ --ruby_out=lib --grpc_out=lib prefab.proto
|
6
13
|
|
7
14
|
gsed -i 's/^module Prefab$/module PrefabProto/g' lib/prefab_pb.rb
|
data/lib/prefab/client.rb
CHANGED
@@ -80,11 +80,24 @@ module Prefab
|
|
80
80
|
sync_interval: @options.collect_sync_interval)
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
84
|
-
return nil if @options.
|
83
|
+
def example_contexts_aggregator
|
84
|
+
return nil if @options.collect_max_example_contexts <= 0
|
85
85
|
|
86
|
-
@
|
87
|
-
|
86
|
+
@example_contexts_aggregator ||= ExampleContextsAggregator.new(
|
87
|
+
client: self,
|
88
|
+
max_contexts: @options.collect_max_example_contexts,
|
89
|
+
sync_interval: @options.collect_sync_interval
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
def evaluation_summary_aggregator
|
94
|
+
return nil if @options.collect_max_evaluation_summaries <= 0
|
95
|
+
|
96
|
+
@evaluation_summary_aggregator ||= EvaluationSummaryAggregator.new(
|
97
|
+
client: self,
|
98
|
+
max_keys: @options.collect_max_evaluation_summaries,
|
99
|
+
sync_interval: @options.collect_sync_interval
|
100
|
+
)
|
88
101
|
end
|
89
102
|
|
90
103
|
def set_rails_loggers
|
data/lib/prefab/config_client.rb
CHANGED
@@ -58,18 +58,17 @@ module Prefab
|
|
58
58
|
def get(key, default = NO_DEFAULT_PROVIDED, properties = NO_DEFAULT_PROVIDED)
|
59
59
|
context = @config_resolver.make_context(properties)
|
60
60
|
|
61
|
-
|
61
|
+
if properties != NO_DEFAULT_PROVIDED && @base_client.example_contexts_aggregator
|
62
|
+
@base_client.example_contexts_aggregator.record(context)
|
63
|
+
end
|
64
|
+
|
65
|
+
evaluation = _get(key, context)
|
62
66
|
|
63
67
|
@base_client.context_shape_aggregator&.push(context)
|
64
68
|
@base_client.evaluated_keys_aggregator&.push(key)
|
65
69
|
|
66
|
-
if
|
67
|
-
|
68
|
-
if @base_client.evaluated_configs_aggregator && key != Prefab::LoggerClient::BASE_KEY && !key.start_with?(LOGGING_KEY_PREFIX)
|
69
|
-
@base_client.evaluated_configs_aggregator.push([raw(key), value, context])
|
70
|
-
end
|
71
|
-
|
72
|
-
Prefab::ConfigValueUnwrapper.unwrap(value, key, context)
|
70
|
+
if evaluation
|
71
|
+
evaluation.report_and_return(@base_client.evaluation_summary_aggregator)
|
73
72
|
else
|
74
73
|
handle_default(key, default)
|
75
74
|
end
|
@@ -183,7 +182,7 @@ module Prefab
|
|
183
182
|
|
184
183
|
@base_client.log_internal ::Logger::INFO, "Unlocked Config via #{source}"
|
185
184
|
@initialization_lock.release_write_lock
|
186
|
-
@base_client.log.
|
185
|
+
@base_client.log.config_client = self
|
187
186
|
@base_client.log_internal ::Logger::INFO, to_s
|
188
187
|
end
|
189
188
|
|
@@ -192,7 +191,8 @@ module Prefab
|
|
192
191
|
auth_string = Base64.strict_encode64(auth)
|
193
192
|
headers = {
|
194
193
|
'x-prefab-start-at-id' => start_at_id,
|
195
|
-
'Authorization' => "Basic #{auth_string}"
|
194
|
+
'Authorization' => "Basic #{auth_string}",
|
195
|
+
'X-PrefabCloud-Client-Version' => "prefab-cloud-ruby-#{Prefab::VERSION}"
|
196
196
|
}
|
197
197
|
url = "#{@base_client.prefab_api_url}/api/v1/sse/config"
|
198
198
|
@base_client.log_internal ::Logger::INFO, "SSE Streaming Connect to #{url} start_at #{start_at_id}"
|
@@ -2,24 +2,35 @@
|
|
2
2
|
|
3
3
|
module Prefab
|
4
4
|
class ConfigValueUnwrapper
|
5
|
-
|
6
|
-
return nil unless config_value
|
5
|
+
attr_reader :value, :weighted_value_index
|
7
6
|
|
8
|
-
|
7
|
+
def initialize(value, weighted_value_index = nil)
|
8
|
+
@value = value
|
9
|
+
@weighted_value_index = weighted_value_index
|
10
|
+
end
|
11
|
+
|
12
|
+
def unwrap
|
13
|
+
case value.type
|
9
14
|
when :int, :string, :double, :bool, :log_level
|
10
|
-
|
15
|
+
value.public_send(value.type)
|
11
16
|
when :string_list
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
value.string_list.values
|
18
|
+
else
|
19
|
+
raise "Unknown type: #{config_value.type}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.deepest_value(config_value, config_key, context)
|
24
|
+
if config_value&.type == :weighted_values
|
25
|
+
value, index = Prefab::WeightedValueResolver.new(
|
15
26
|
config_value.weighted_values.weighted_values,
|
16
27
|
config_key,
|
17
28
|
context.get(config_value.weighted_values.hash_by_property_name)
|
18
29
|
).resolve
|
19
30
|
|
20
|
-
|
31
|
+
new(deepest_value(value.value, config_key, context).value, index)
|
21
32
|
else
|
22
|
-
|
33
|
+
new(config_value)
|
23
34
|
end
|
24
35
|
end
|
25
36
|
end
|
data/lib/prefab/context.rb
CHANGED
@@ -25,10 +25,23 @@ module Prefab
|
|
25
25
|
def to_h
|
26
26
|
@hash
|
27
27
|
end
|
28
|
+
|
29
|
+
def key
|
30
|
+
"#{@name}:#{get('key')}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_proto
|
34
|
+
PrefabProto::Context.new(
|
35
|
+
type: name,
|
36
|
+
values: to_h.transform_values do |value|
|
37
|
+
ConfigValueWrapper.wrap(value)
|
38
|
+
end
|
39
|
+
)
|
40
|
+
end
|
28
41
|
end
|
29
42
|
|
30
43
|
THREAD_KEY = :prefab_context
|
31
|
-
attr_reader :contexts
|
44
|
+
attr_reader :contexts, :seen_at
|
32
45
|
|
33
46
|
class << self
|
34
47
|
def current=(context)
|
@@ -58,6 +71,7 @@ module Prefab
|
|
58
71
|
|
59
72
|
def initialize(context = {})
|
60
73
|
@contexts = {}
|
74
|
+
@seen_at = Time.now.utc.to_i
|
61
75
|
|
62
76
|
if context.is_a?(NamedContext)
|
63
77
|
@contexts[context.name] = context
|
@@ -113,15 +127,33 @@ module Prefab
|
|
113
127
|
|
114
128
|
PrefabProto::ContextSet.new(
|
115
129
|
contexts: contexts.map do |name, context|
|
116
|
-
|
117
|
-
type: name,
|
118
|
-
values: context.to_h.transform_values do |value|
|
119
|
-
ConfigValueWrapper.wrap(value)
|
120
|
-
end
|
121
|
-
)
|
130
|
+
context.to_proto
|
122
131
|
end.concat([PrefabProto::Context.new(type: 'prefab',
|
123
132
|
values: prefab_context)])
|
124
133
|
)
|
125
134
|
end
|
135
|
+
|
136
|
+
def slim_proto
|
137
|
+
PrefabProto::ContextSet.new(
|
138
|
+
contexts: contexts.map do |_, context|
|
139
|
+
context.to_proto
|
140
|
+
end
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
def grouped_key
|
145
|
+
contexts.map do |_, context|
|
146
|
+
context.key
|
147
|
+
end.sort.join('|')
|
148
|
+
end
|
149
|
+
|
150
|
+
include Comparable
|
151
|
+
def <=>(other)
|
152
|
+
if other.is_a?(Prefab::Context)
|
153
|
+
to_h <=> other.to_h
|
154
|
+
else
|
155
|
+
super
|
156
|
+
end
|
157
|
+
end
|
126
158
|
end
|
127
159
|
end
|
@@ -4,6 +4,8 @@
|
|
4
4
|
# We're intentionally keeping the UPCASED method names to match the protobuf
|
5
5
|
# and avoid wasting CPU cycles lowercasing things
|
6
6
|
module Prefab
|
7
|
+
# This class evaluates a config's criteria. `evaluate` returns the value of
|
8
|
+
# the first match based on the provided properties.
|
7
9
|
class CriteriaEvaluator
|
8
10
|
NAMESPACE_KEY = 'NAMESPACE'
|
9
11
|
NO_MATCHING_ROWS = [].freeze
|
@@ -17,15 +19,8 @@ module Prefab
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def evaluate(properties)
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
default_row_values.each do |conditional_value|
|
25
|
-
return conditional_value.value if all_criteria_match?(conditional_value, properties)
|
26
|
-
end
|
27
|
-
|
28
|
-
nil
|
22
|
+
evaluate_for_env(@project_env_id, properties) ||
|
23
|
+
evaluate_for_env(0, properties)
|
29
24
|
end
|
30
25
|
|
31
26
|
def all_criteria_match?(conditional_value, props)
|
@@ -83,12 +78,24 @@ module Prefab
|
|
83
78
|
|
84
79
|
private
|
85
80
|
|
86
|
-
def
|
87
|
-
@config.rows.
|
88
|
-
|
81
|
+
def evaluate_for_env(env_id, properties)
|
82
|
+
@config.rows.each_with_index do |row, index|
|
83
|
+
next unless row.project_env_id == env_id
|
84
|
+
|
85
|
+
row.values.each_with_index do |conditional_value, value_index|
|
86
|
+
next unless all_criteria_match?(conditional_value, properties)
|
87
|
+
|
88
|
+
return Prefab::Evaluation.new(
|
89
|
+
config: @config,
|
90
|
+
value: conditional_value.value,
|
91
|
+
value_index: value_index,
|
92
|
+
config_row_index: index,
|
93
|
+
context: properties
|
94
|
+
)
|
95
|
+
end
|
96
|
+
end
|
89
97
|
|
90
|
-
|
91
|
-
@config.rows.find { |row| row.project_env_id != @project_env_id }&.values || NO_MATCHING_ROWS
|
98
|
+
nil
|
92
99
|
end
|
93
100
|
|
94
101
|
def in_segment?(criterion, properties)
|
@@ -96,11 +103,12 @@ module Prefab
|
|
96
103
|
|
97
104
|
@base_client.log.info("Segment #{criterion.value_to_match.string} not found") unless segment
|
98
105
|
|
99
|
-
segment&.
|
106
|
+
segment&.report_and_return(@base_client.evaluation_summary_aggregator)
|
100
107
|
end
|
101
108
|
|
102
109
|
def matches?(criterion, value, properties)
|
103
|
-
criterion_value_or_values = Prefab::ConfigValueUnwrapper.
|
110
|
+
criterion_value_or_values = Prefab::ConfigValueUnwrapper.deepest_value(criterion.value_to_match, @config.key,
|
111
|
+
properties).unwrap
|
104
112
|
|
105
113
|
case criterion_value_or_values
|
106
114
|
when Google::Protobuf::RepeatedField
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prefab
|
4
|
+
# Records the result of evaluating a config's criteria and forensics for reporting
|
5
|
+
class Evaluation
|
6
|
+
attr_reader :value
|
7
|
+
|
8
|
+
def initialize(config:, value:, value_index:, config_row_index:, context:)
|
9
|
+
@config = config
|
10
|
+
@value = value
|
11
|
+
@value_index = value_index
|
12
|
+
@config_row_index = config_row_index
|
13
|
+
@context = context
|
14
|
+
end
|
15
|
+
|
16
|
+
def unwrapped_value
|
17
|
+
deepest_value.unwrap
|
18
|
+
end
|
19
|
+
|
20
|
+
def report_and_return(evaluation_summary_aggregator)
|
21
|
+
report(evaluation_summary_aggregator)
|
22
|
+
|
23
|
+
unwrapped_value
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def report(evaluation_summary_aggregator)
|
29
|
+
return if @config.config_type == :LOG_LEVEL
|
30
|
+
|
31
|
+
evaluation_summary_aggregator&.record(
|
32
|
+
config_key: @config.key,
|
33
|
+
config_type: @config.config_type,
|
34
|
+
counter: {
|
35
|
+
config_id: @config.id,
|
36
|
+
config_row_index: @config_row_index,
|
37
|
+
conditional_value_index: @value_index,
|
38
|
+
selected_value: deepest_value.value,
|
39
|
+
weighted_value_index: deepest_value.weighted_value_index,
|
40
|
+
selected_index: nil # TODO
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
def deepest_value
|
45
|
+
@deepest_value ||= Prefab::ConfigValueUnwrapper.deepest_value(@value, @config.key, @context)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'periodic_sync'
|
4
|
+
|
5
|
+
module Prefab
|
6
|
+
# This class aggregates the number of times each config is evaluated, and
|
7
|
+
# details about how the config is evaluated This data is reported to the
|
8
|
+
# server at a regular interval defined by `sync_interval`.
|
9
|
+
class EvaluationSummaryAggregator
|
10
|
+
include Prefab::PeriodicSync
|
11
|
+
|
12
|
+
attr_reader :data
|
13
|
+
|
14
|
+
def initialize(client:, max_keys:, sync_interval:)
|
15
|
+
@client = client
|
16
|
+
@max_keys = max_keys
|
17
|
+
@name = 'evaluation_summary_aggregator'
|
18
|
+
|
19
|
+
@data = Concurrent::Hash.new
|
20
|
+
|
21
|
+
start_periodic_sync(sync_interval)
|
22
|
+
end
|
23
|
+
|
24
|
+
def record(config_key:, config_type:, counter:)
|
25
|
+
return if @data.size >= @max_keys
|
26
|
+
|
27
|
+
key = [config_key, config_type]
|
28
|
+
@data[key] ||= Concurrent::Hash.new
|
29
|
+
|
30
|
+
@data[key][counter] ||= 0
|
31
|
+
@data[key][counter] += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def counter_proto(counter, count)
|
37
|
+
PrefabProto::ConfigEvaluationCounter.new(
|
38
|
+
config_id: counter[:config_id],
|
39
|
+
selected_index: counter[:selected_index],
|
40
|
+
config_row_index: counter[:config_row_index],
|
41
|
+
conditional_value_index: counter[:conditional_value_index],
|
42
|
+
weighted_value_index: counter[:weighted_value_index],
|
43
|
+
selected_value: counter[:selected_value],
|
44
|
+
count: count
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def flush(to_ship, start_at_was)
|
49
|
+
pool.post do
|
50
|
+
log_internal "Flushing #{to_ship.size} summaries"
|
51
|
+
|
52
|
+
summaries_proto = PrefabProto::ConfigEvaluationSummaries.new(
|
53
|
+
start: start_at_was,
|
54
|
+
end: Prefab::TimeHelpers.now_in_ms,
|
55
|
+
summaries: summaries(to_ship)
|
56
|
+
)
|
57
|
+
|
58
|
+
result = @client.post('/api/v1/telemetry', events(summaries_proto))
|
59
|
+
|
60
|
+
log_internal "Uploaded #{to_ship.size} summaries: #{result.status}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def events(summaries)
|
65
|
+
event = PrefabProto::TelemetryEvent.new(summaries: summaries)
|
66
|
+
|
67
|
+
PrefabProto::TelemetryEvents.new(
|
68
|
+
instance_hash: @client.instance_hash,
|
69
|
+
events: [event]
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
def summaries(data)
|
74
|
+
data.map do |(config_key, config_type), counters|
|
75
|
+
counter_protos = counters.map { |counter, count| counter_proto(counter, count) }
|
76
|
+
|
77
|
+
PrefabProto::ConfigEvaluationSummary.new(
|
78
|
+
key: config_key,
|
79
|
+
type: config_type,
|
80
|
+
counters: counter_protos
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'periodic_sync'
|
4
|
+
|
5
|
+
module Prefab
|
6
|
+
# This class aggregates example contexts. It dedupes based on the
|
7
|
+
# concatenation of the keys of the contexts.
|
8
|
+
#
|
9
|
+
# It shouldn't send the same context more than once per hour.
|
10
|
+
class ExampleContextsAggregator
|
11
|
+
include Prefab::PeriodicSync
|
12
|
+
|
13
|
+
attr_reader :data, :cache
|
14
|
+
|
15
|
+
ONE_HOUR = 60 * 60
|
16
|
+
|
17
|
+
def initialize(client:, max_contexts:, sync_interval:)
|
18
|
+
@client = client
|
19
|
+
@max_contexts = max_contexts
|
20
|
+
@name = 'example_contexts_aggregator'
|
21
|
+
|
22
|
+
@data = Concurrent::Array.new
|
23
|
+
@cache = Prefab::RateLimitCache.new(ONE_HOUR)
|
24
|
+
|
25
|
+
start_periodic_sync(sync_interval)
|
26
|
+
end
|
27
|
+
|
28
|
+
def record(contexts)
|
29
|
+
key = contexts.grouped_key
|
30
|
+
|
31
|
+
return unless @data.size < @max_contexts && !@cache.fresh?(key)
|
32
|
+
|
33
|
+
@cache.set(key)
|
34
|
+
|
35
|
+
@data.push(contexts)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def on_prepare_data
|
41
|
+
@cache.prune
|
42
|
+
end
|
43
|
+
|
44
|
+
def flush(to_ship, _)
|
45
|
+
pool.post do
|
46
|
+
log_internal "Flushing #{to_ship.size} examples"
|
47
|
+
|
48
|
+
result = @client.post('/api/v1/telemetry', events(to_ship))
|
49
|
+
|
50
|
+
log_internal "Uploaded #{to_ship.size} examples: #{result.status}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def example_contexts(to_ship)
|
55
|
+
to_ship.map do |contexts|
|
56
|
+
PrefabProto::ExampleContext.new(
|
57
|
+
timestamp: contexts.seen_at * 1000,
|
58
|
+
contextSet: contexts.slim_proto
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def events(to_ship)
|
64
|
+
event = PrefabProto::TelemetryEvent.new(
|
65
|
+
example_contexts: PrefabProto::ExampleContexts.new(
|
66
|
+
examples: example_contexts(to_ship)
|
67
|
+
)
|
68
|
+
)
|
69
|
+
|
70
|
+
PrefabProto::TelemetryEvents.new(
|
71
|
+
instance_hash: @client.instance_hash,
|
72
|
+
events: [event]
|
73
|
+
)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,4 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Prefab
|
4
|
+
# This class implements exponential backoff with a maximum delay.
|
5
|
+
#
|
6
|
+
# This is the default sync interval for aggregators.
|
2
7
|
class ExponentialBackoff
|
3
8
|
def initialize(max_delay:, initial_delay: 2, multiplier: 2)
|
4
9
|
@initial_delay = initial_delay
|
@@ -3,7 +3,11 @@
|
|
3
3
|
module Prefab
|
4
4
|
class HttpConnection
|
5
5
|
AUTH_USER = 'authuser'
|
6
|
-
PROTO_HEADERS = {
|
6
|
+
PROTO_HEADERS = {
|
7
|
+
'Content-Type' => 'application/x-protobuf',
|
8
|
+
'Accept' => 'application/x-protobuf',
|
9
|
+
'X-PrefabCloud-Client-Version' => "prefab-cloud-ruby-#{Prefab::VERSION}"
|
10
|
+
}.freeze
|
7
11
|
|
8
12
|
def initialize(api_root, api_key)
|
9
13
|
@api_root = api_root
|
data/lib/prefab/logger_client.rb
CHANGED
@@ -15,7 +15,7 @@ module Prefab
|
|
15
15
|
PrefabProto::LogLevel::WARN => ::Logger::WARN,
|
16
16
|
PrefabProto::LogLevel::ERROR => ::Logger::ERROR,
|
17
17
|
PrefabProto::LogLevel::FATAL => ::Logger::FATAL
|
18
|
-
}
|
18
|
+
}.freeze
|
19
19
|
|
20
20
|
def initialize(logdev, log_path_aggregator: nil, formatter: nil, prefix: nil)
|
21
21
|
super(logdev)
|
@@ -27,7 +27,7 @@ module Prefab
|
|
27
27
|
@log_path_aggregator = log_path_aggregator
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def add_internal(severity, message, progname, loc, &block)
|
31
31
|
path_loc = get_loc_path(loc)
|
32
32
|
path = @prefix + path_loc
|
33
33
|
|
@@ -36,7 +36,7 @@ module Prefab
|
|
36
36
|
log(message, path, progname, severity, &block)
|
37
37
|
end
|
38
38
|
|
39
|
-
def log_internal(message, path
|
39
|
+
def log_internal(message, path, progname, severity, &block)
|
40
40
|
path = if path
|
41
41
|
"#{INTERNAL_PREFIX}.#{path}"
|
42
42
|
else
|
@@ -51,9 +51,8 @@ module Prefab
|
|
51
51
|
|
52
52
|
return true if @logdev.nil? || severity < level_of(path) || @silences[local_log_id]
|
53
53
|
|
54
|
-
if progname.nil?
|
55
|
-
|
56
|
-
end
|
54
|
+
progname = @progname if progname.nil?
|
55
|
+
|
57
56
|
if message.nil?
|
58
57
|
if block_given?
|
59
58
|
message = yield
|
@@ -70,23 +69,23 @@ module Prefab
|
|
70
69
|
end
|
71
70
|
|
72
71
|
def debug(progname = nil, &block)
|
73
|
-
|
72
|
+
add_internal(DEBUG, nil, progname, caller_locations(1, 1)[0], &block)
|
74
73
|
end
|
75
74
|
|
76
75
|
def info(progname = nil, &block)
|
77
|
-
|
76
|
+
add_internal(INFO, nil, progname, caller_locations(1, 1)[0], &block)
|
78
77
|
end
|
79
78
|
|
80
79
|
def warn(progname = nil, &block)
|
81
|
-
|
80
|
+
add_internal(WARN, nil, progname, caller_locations(1, 1)[0], &block)
|
82
81
|
end
|
83
82
|
|
84
83
|
def error(progname = nil, &block)
|
85
|
-
|
84
|
+
add_internal(ERROR, nil, progname, caller_locations(1, 1)[0], &block)
|
86
85
|
end
|
87
86
|
|
88
87
|
def fatal(progname = nil, &block)
|
89
|
-
|
88
|
+
add_internal(FATAL, nil, progname, caller_locations(1, 1)[0], &block)
|
90
89
|
end
|
91
90
|
|
92
91
|
def debug?
|
@@ -113,7 +112,7 @@ module Prefab
|
|
113
112
|
DEBUG
|
114
113
|
end
|
115
114
|
|
116
|
-
def
|
115
|
+
def config_client=(config_client)
|
117
116
|
@config_client = config_client
|
118
117
|
end
|
119
118
|
|
@@ -169,7 +168,7 @@ module Prefab
|
|
169
168
|
path
|
170
169
|
end
|
171
170
|
|
172
|
-
def format_message(severity, datetime, progname, msg, path)
|
171
|
+
def format_message(severity, datetime, progname, msg, path = nil)
|
173
172
|
formatter = (@formatter || @default_formatter)
|
174
173
|
|
175
174
|
if formatter.arity == 5
|