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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/VERSION +1 -1
  4. data/compile_protos.sh +7 -0
  5. data/lib/prefab/client.rb +17 -4
  6. data/lib/prefab/config_client.rb +10 -10
  7. data/lib/prefab/config_value_unwrapper.rb +20 -9
  8. data/lib/prefab/context.rb +39 -7
  9. data/lib/prefab/context_shape_aggregator.rb +1 -1
  10. data/lib/prefab/criteria_evaluator.rb +24 -16
  11. data/lib/prefab/evaluated_keys_aggregator.rb +1 -1
  12. data/lib/prefab/evaluation.rb +48 -0
  13. data/lib/prefab/evaluation_summary_aggregator.rb +85 -0
  14. data/lib/prefab/example_contexts_aggregator.rb +76 -0
  15. data/lib/prefab/exponential_backoff.rb +5 -0
  16. data/lib/prefab/http_connection.rb +5 -1
  17. data/lib/prefab/log_path_aggregator.rb +1 -1
  18. data/lib/prefab/logger_client.rb +12 -13
  19. data/lib/prefab/options.rb +27 -14
  20. data/lib/prefab/periodic_sync.rb +30 -13
  21. data/lib/prefab/rate_limit_cache.rb +41 -0
  22. data/lib/prefab/resolved_config_presenter.rb +2 -4
  23. data/lib/prefab/weighted_value_resolver.rb +1 -1
  24. data/lib/prefab-cloud-ruby.rb +6 -3
  25. data/lib/prefab_pb.rb +11 -1
  26. data/prefab-cloud-ruby.gemspec +14 -5
  27. data/test/support/common_helpers.rb +105 -0
  28. data/test/support/mock_base_client.rb +44 -0
  29. data/test/support/mock_config_client.rb +19 -0
  30. data/test/support/mock_config_loader.rb +1 -0
  31. data/test/test_client.rb +257 -2
  32. data/test/test_config_resolver.rb +25 -24
  33. data/test/test_config_value_unwrapper.rb +22 -32
  34. data/test/test_context_shape_aggregator.rb +0 -1
  35. data/test/test_criteria_evaluator.rb +179 -133
  36. data/test/test_evaluation_summary_aggregator.rb +162 -0
  37. data/test/test_example_contexts_aggregator.rb +238 -0
  38. data/test/test_helper.rb +5 -131
  39. data/test/test_local_config_parser.rb +2 -2
  40. data/test/test_logger.rb +5 -5
  41. data/test/test_options.rb +8 -0
  42. data/test/test_rate_limit_cache.rb +44 -0
  43. data/test/test_weighted_value_resolver.rb +13 -7
  44. metadata +13 -4
  45. data/lib/prefab/evaluated_configs_aggregator.rb +0 -60
  46. data/test/test_evaluated_configs_aggregator.rb +0 -254
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a88b7d4c3a88af4b66a623208ec2673453ce763660d2cca7993e0623c39e35e5
4
- data.tar.gz: 125b830fb204a7085fa6a3e5b365646f27d8bc4bcf42df0c2a6f2f0e0925dcd9
3
+ metadata.gz: 36d1b27d1c03aef56882735b73835b65b508b5eef821f65e89ab5ba77f54a8ab
4
+ data.tar.gz: 00a336ac664ab495ce1c5fff4b5ab6972169a095087887958c3a0881016ba273
5
5
  SHA512:
6
- metadata.gz: 7a73efdcad8211cd709f0b074db0bf46ae448362387ba6215c94314050087988909d3993a8377422a6a6ef5e09da703f3f40b017b751025d6dbbcbaffd35d012
7
- data.tar.gz: 3e2b3e9cbf7686843abfc13f948a87840da068a823c9740eb0ceba7ea13a24502f249aebb1d1fa1931a735b2042ee989b291b8d513e1504ba534df30ab5658ea
6
+ metadata.gz: b0dc48a30fd50f53e9709e138afd408bfc2e91e6badb473c1d141db56c7cdfa507aef81db0f06674b8d640dec2a7ac147654def0cdd7e7bcebdd3b0eb2a79854
7
+ data.tar.gz: a3bd2f91776a25d646f1ab28d54d395bd24283e16dbca2f0bc7a1d1f77c9bb063488e9f62e00030a8acc84b2ecb8b07791bf84c1893e091f40edbb75e55870ca
data/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
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.4
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 evaluated_configs_aggregator
84
- return nil if @options.collect_max_evaluations <= 0
83
+ def example_contexts_aggregator
84
+ return nil if @options.collect_max_example_contexts <= 0
85
85
 
86
- @evaluated_configs_aggregator ||= EvaluatedConfigsAggregator.new(client: self, max_configs: @options.collect_max_evaluations,
87
- sync_interval: @options.collect_sync_interval)
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
@@ -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
- value = _get(key, context)
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 value
67
- # NOTE: we don't &.push here because some of the args aren't already available
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.set_config_client(self)
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
- def self.unwrap(config_value, config_key, context)
6
- return nil unless config_value
5
+ attr_reader :value, :weighted_value_index
7
6
 
8
- case config_value.type
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
- config_value.public_send(config_value.type)
15
+ value.public_send(value.type)
11
16
  when :string_list
12
- config_value.string_list.values
13
- when :weighted_values
14
- value = Prefab::WeightedValueResolver.new(
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
- unwrap(value.value, config_key, context)
31
+ new(deepest_value(value.value, config_key, context).value, index)
21
32
  else
22
- raise "Unknown type: #{config_value.type}"
33
+ new(config_value)
23
34
  end
24
35
  end
25
36
  end
@@ -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
- PrefabProto::Context.new(
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
@@ -42,7 +42,7 @@ module Prefab
42
42
  private
43
43
 
44
44
  def flush(to_ship, _)
45
- @pool.post do
45
+ pool.post do
46
46
  log_internal "Uploading context shapes for #{to_ship.values.size}"
47
47
 
48
48
  shapes = PrefabProto::ContextShapes.new(
@@ -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
- matching_environment_row_values.each do |conditional_value|
21
- return conditional_value.value if all_criteria_match?(conditional_value, properties)
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 matching_environment_row_values
87
- @config.rows.find { |row| row.project_env_id == @project_env_id }&.values || NO_MATCHING_ROWS
88
- end
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
- def default_row_values
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&.bool
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.unwrap(criterion.value_to_match, @config.key, properties)
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
@@ -27,7 +27,7 @@ module Prefab
27
27
  private
28
28
 
29
29
  def flush(to_ship, _)
30
- @pool.post do
30
+ pool.post do
31
31
  log_internal "Uploading evaluated keys for #{to_ship.size}"
32
32
 
33
33
  keys = PrefabProto::EvaluatedKeys.new(keys: to_ship.to_a, namespace: @client.namespace)
@@ -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 = { 'Content-Type' => 'application/x-protobuf', 'Accept' => 'application/x-protobuf' }.freeze
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
@@ -37,7 +37,7 @@ module Prefab
37
37
  private
38
38
 
39
39
  def flush(to_ship, start_at_was)
40
- @pool.post do
40
+ pool.post do
41
41
  log_internal "Uploading stats for #{to_ship.size} paths"
42
42
 
43
43
  aggregate = Hash.new { |h, k| h[k] = PrefabProto::Logger.new }
@@ -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 add(severity, message = nil, progname = nil, loc, &block)
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 = nil, progname, severity, &block)
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
- progname = @progname
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
- add(DEBUG, nil, progname, caller_locations(1, 1)[0], &block)
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
- add(INFO, nil, progname, caller_locations(1, 1)[0], &block)
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
- add(WARN, nil, progname, caller_locations(1, 1)[0], &block)
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
- add(ERROR, nil, progname, caller_locations(1, 1)[0], &block)
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
- add(FATAL, nil, progname, caller_locations(1, 1)[0], &block)
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 set_config_client(config_client)
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