prefab-cloud-ruby 0.16.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82381e4b656d675f4b98ee11601cde1920637e52eb5b039814247500207b9fa5
4
- data.tar.gz: 4ff8914774523e745d512d506cc42f20e71a657fd8191d82e7e6ba1878bf04c9
3
+ metadata.gz: d9225ebaadf8be997d152b66cb58ff342d126bc5cfbe489511af4791d89dd5f7
4
+ data.tar.gz: cbaf511c7aeaf0ef743b33c2ad00c40bd4d6c8ddba0a17ddff541afeb8e055d9
5
5
  SHA512:
6
- metadata.gz: aac3fc04c779900ca92a6a859430a2fe7776bee90afba632456ff45e3bacb428dda61314d3cbf5a5b04ce61672e4591afb7ae0248b77352b381f52dcbbfb6f24
7
- data.tar.gz: 5e2008ec802e2f32154bffb34804673187feb618a60edf2aba19666851787e14111e3d6e0fbeeebe8e3192cac56a32f3010b4d46ef507c3d16359886973ee90c
6
+ metadata.gz: f00e343e6f3f7a7f11351409708979c4e02420eae8bf8d9520cdc58de464b682158b863bcab88b4583c469709c621f066bd8995e482963386b931c877bfd2b1f
7
+ data.tar.gz: 5e51d64d2d5adc738e5f8438cd222ae3e4d9fc1f183a789d25486da7197b25c3263fff9a0fac9b33a9acffc169e035630e7a8cb8b3d3770e9e8b669d34b96f68
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ gem 'googleapis-common-protos-types', :platforms => :ruby
10
10
  group :development do
11
11
  gem 'benchmark-ips'
12
12
  gem 'grpc-tools', :platforms => :ruby
13
- gem "rdoc", "~> 3.12"
13
+ gem "rdoc"
14
14
  gem "bundler"
15
15
  gem "juwelier", "~> 2.4.9"
16
16
  gem "simplecov", ">= 0"
data/Gemfile.lock CHANGED
@@ -47,7 +47,6 @@ GEM
47
47
  http-cookie (1.0.4)
48
48
  domain_name (~> 0.5)
49
49
  http-form_data (2.3.0)
50
- json (1.8.6)
51
50
  juwelier (2.4.9)
52
51
  builder
53
52
  bundler
@@ -89,8 +88,7 @@ GEM
89
88
  rack (2.2.4)
90
89
  rake (13.0.3)
91
90
  rchardet (1.8.0)
92
- rdoc (3.12.2)
93
- json (~> 1.4)
91
+ rdoc (6.3.3)
94
92
  ruby2_keywords (0.0.4)
95
93
  semver2 (3.4.2)
96
94
  simplecov (0.18.5)
@@ -121,7 +119,7 @@ DEPENDENCIES
121
119
  juwelier (~> 2.4.9)
122
120
  ld-eventsource
123
121
  minitest
124
- rdoc (~> 3.12)
122
+ rdoc
125
123
  simplecov
126
124
  thin
127
125
 
data/README.md CHANGED
@@ -31,8 +31,7 @@ Many ruby web servers fork. GRPC does not like to be forked. You should manually
31
31
  ```ruby
32
32
 
33
33
  #config/initializers/prefab.rb
34
- $prefab = Prefab::Client.new(shared_cache: Rails.cache,
35
- logdev: $stdout)
34
+ $prefab = Prefab::Client.new
36
35
  Rails.logger = $prefab.log
37
36
  ```
38
37
 
@@ -45,7 +44,7 @@ end
45
44
 
46
45
  ## Logging & Debugging
47
46
  In classpath or ~/.prefab.overrides.config.yaml set
48
- ```log_level.prefab: debug```
47
+ ```log-level.prefab: debug```
49
48
 
50
49
  To debug issues before this config file has been read, set env var
51
50
  ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.16.0
1
+ 0.18.0
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
  module Prefab
3
3
  class AuthInterceptor < GRPC::ClientInterceptor
4
+ VERSION = File.exist?('VERSION') ? File.read('VERSION').chomp : ""
5
+ CLIENT = "prefab-cloud-ruby.#{VERSION}".freeze
6
+
4
7
  def initialize(api_key)
5
- version = File.exist?('VERSION') ? File.read('VERSION').chomp : ""
6
- @client = "prefab-cloud-ruby.#{version}".freeze
7
8
  @api_key = api_key
8
9
  end
9
10
 
@@ -25,7 +26,7 @@ module Prefab
25
26
 
26
27
  def shared(metadata)
27
28
  metadata['auth'] = @api_key
28
- metadata['client'] = @client
29
+ metadata['client'] = CLIENT
29
30
  yield
30
31
  end
31
32
  end
@@ -149,8 +149,7 @@ module Prefab
149
149
  end
150
150
 
151
151
  def load_checkpoint_api_cdn
152
- key_hash = Murmur3.murmur3_32(@base_client.api_key)
153
- url = "#{@options.url_for_api_cdn}/api/v1/configs/0/#{key_hash}/0"
152
+ url = "#{@options.url_for_api_cdn}/api/v1/configs/0"
154
153
  conn = if Faraday::VERSION[0].to_i >= 2
155
154
  Faraday.new(url) do |conn|
156
155
  conn.request :authorization, :basic, AUTH_USER, @base_client.api_key
@@ -15,6 +15,8 @@ module Prefab
15
15
  config_value.feature_flag
16
16
  when :segment
17
17
  config_value.segment
18
+ when :log_level
19
+ config_value.log_level
18
20
  end
19
21
  end
20
22
 
@@ -102,7 +102,7 @@ module Prefab
102
102
  config: Prefab::Config.new(
103
103
  key: k,
104
104
  rows: [
105
- Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(value_from(v)))
105
+ Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(value_from(k, v)))
106
106
  ]
107
107
  )
108
108
  }
@@ -119,10 +119,15 @@ module Prefab
119
119
  end
120
120
  end
121
121
 
122
- def value_from(raw)
122
+ def value_from(key, raw)
123
123
  case raw
124
124
  when String
125
- { string: raw }
125
+ if key.start_with? Prefab::LoggerClient::BASE_KEY
126
+ prefab_log_level_resolve = Prefab::LogLevel.resolve(raw.upcase.to_sym) || Prefab::LogLevel::NOT_SET_LOG_LEVEL
127
+ { log_level: prefab_log_level_resolve }
128
+ else
129
+ { string: raw }
130
+ end
126
131
  when Integer
127
132
  { int: raw }
128
133
  when TrueClass, FalseClass
@@ -165,7 +170,7 @@ module Prefab
165
170
  match: key,
166
171
  config: Prefab::Config.new(
167
172
  key: key,
168
- variants: [Prefab::FeatureFlagVariant.new(value_from(value['value']))],
173
+ variants: [Prefab::FeatureFlagVariant.new(value_from(key, value['value']))],
169
174
  rows: [row]
170
175
  )
171
176
  }
@@ -3,12 +3,22 @@ module Prefab
3
3
  class LoggerClient < Logger
4
4
 
5
5
  SEP = "."
6
- BASE = "log_level"
7
- UNKNOWN = "unknown"
6
+ BASE_KEY = "log-level"
7
+ UNKNOWN_PATH = "unknown."
8
+
9
+ LOG_LEVEL_LOOKUPS = {
10
+ Prefab::LogLevel::NOT_SET_LOG_LEVEL => Logger::DEBUG,
11
+ Prefab::LogLevel::TRACE => Logger::DEBUG,
12
+ Prefab::LogLevel::DEBUG => Logger::DEBUG,
13
+ Prefab::LogLevel::INFO => Logger::INFO,
14
+ Prefab::LogLevel::WARN => Logger::WARN,
15
+ Prefab::LogLevel::ERROR => Logger::ERROR,
16
+ Prefab::LogLevel::FATAL => Logger::FATAL
17
+ }
8
18
 
9
19
  def initialize(logdev, formatter: nil)
10
20
  super(logdev)
11
- self.formatter= formatter
21
+ self.formatter = formatter
12
22
  @config_client = BootstrappingConfigClient.new
13
23
  @silences = Concurrent::Map.new(:initial_capacity => 2)
14
24
  end
@@ -26,7 +36,7 @@ module Prefab
26
36
  def log_internal(message, path, progname, severity, &block)
27
37
  level = level_of(path)
28
38
  progname = "#{path}: #{progname}"
29
- severity ||= UNKNOWN
39
+ severity ||= Logger::UNKNOWN
30
40
  if @logdev.nil? || severity < level || @silences[local_log_id]
31
41
  return true
32
42
  end
@@ -109,8 +119,8 @@ module Prefab
109
119
 
110
120
  # Find the closest match to 'log_level.path' in config
111
121
  def level_of(path)
112
- closest_log_level_match = @config_client.get(BASE, :warn)
113
- path.split(SEP).inject([BASE]) do |memo, n|
122
+ closest_log_level_match = @config_client.get(BASE_KEY, :WARN)
123
+ path.split(SEP).inject([BASE_KEY]) do |memo, n|
114
124
  memo << n
115
125
  val = @config_client.get(memo.join(SEP), nil)
116
126
  unless val.nil?
@@ -118,7 +128,8 @@ module Prefab
118
128
  end
119
129
  memo
120
130
  end
121
- val(closest_log_level_match)
131
+ closest_log_level_match_int = Prefab::LogLevel.resolve(closest_log_level_match)
132
+ LOG_LEVEL_LOOKUPS[closest_log_level_match_int]
122
133
  end
123
134
 
124
135
  def get_loc_path(loc)
@@ -129,7 +140,7 @@ module Prefab
129
140
  # sanitize & clean the path of the caller so the key
130
141
  # looks like log_level.app.models.user
131
142
  def get_path(absolute_path, base_label)
132
- path = (absolute_path || UNKNOWN).dup
143
+ path = (absolute_path || UNKNOWN_PATH).dup
133
144
  path.slice! Dir.pwd
134
145
  path.gsub!(/(.*)?(?=\/lib)/im, "") # replace everything before first lib
135
146
 
@@ -138,17 +149,13 @@ module Prefab
138
149
  path.slice! SEP
139
150
  path
140
151
  end
141
-
142
- def val level
143
- return Object.const_get("Logger::#{level.upcase}")
144
- end
145
152
  end
146
153
 
147
154
  # StubConfigClient to be used while config client initializes
148
155
  # since it may log
149
156
  class BootstrappingConfigClient
150
- def get(key, default=nil)
151
- ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"] || default
157
+ def get(key, default = nil)
158
+ ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"] ? ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"].upcase.to_sym : default
152
159
  end
153
160
  end
154
161
  end
data/lib/prefab_pb.rb CHANGED
@@ -1,4 +1,3 @@
1
- # frozen_string_literal: true
2
1
  # Generated by the protocol buffer compiler. DO NOT EDIT!
3
2
  # source: prefab.proto
4
3
 
@@ -21,6 +20,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
21
20
  optional :feature_flag, :message, 6, "prefab.FeatureFlag"
22
21
  optional :limit_definition, :message, 7, "prefab.LimitDefinition"
23
22
  optional :segment, :message, 8, "prefab.Segment"
23
+ optional :log_level, :enum, 9, "prefab.LogLevel"
24
24
  end
25
25
  end
26
26
  add_message "prefab.Configs" do
@@ -184,6 +184,15 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
184
184
  optional :sequence_name, :string, 3
185
185
  optional :size, :int64, 4
186
186
  end
187
+ add_enum "prefab.LogLevel" do
188
+ value :NOT_SET_LOG_LEVEL, 0
189
+ value :TRACE, 1
190
+ value :DEBUG, 2
191
+ value :INFO, 3
192
+ value :WARN, 5
193
+ value :ERROR, 6
194
+ value :FATAL, 9
195
+ end
187
196
  add_enum "prefab.OnFailure" do
188
197
  value :NOT_SET, 0
189
198
  value :LOG_AND_PASS, 1
@@ -222,5 +231,6 @@ module Prefab
222
231
  CreationResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.CreationResponse").msgclass
223
232
  IdBlock = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlock").msgclass
224
233
  IdBlockRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlockRequest").msgclass
234
+ LogLevel = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LogLevel").enummodule
225
235
  OnFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.OnFailure").enummodule
226
236
  end
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: prefab-cloud-ruby 0.16.0 ruby lib
5
+ # stub: prefab-cloud-ruby 0.18.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "prefab-cloud-ruby".freeze
9
- s.version = "0.16.0"
9
+ s.version = "0.18.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Jeff Dwyer".freeze]
14
- s.date = "2022-09-01"
14
+ s.date = "2022-10-14"
15
15
  s.description = "RateLimits & Config as a service".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.extra_rdoc_files = [
@@ -83,7 +83,7 @@ Gem::Specification.new do |s|
83
83
  s.add_runtime_dependency(%q<googleapis-common-protos-types>.freeze, [">= 0"])
84
84
  s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
85
85
  s.add_development_dependency(%q<grpc-tools>.freeze, [">= 0"])
86
- s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
86
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
87
87
  s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
88
88
  s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.4.9"])
89
89
  s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
@@ -97,7 +97,7 @@ Gem::Specification.new do |s|
97
97
  s.add_dependency(%q<googleapis-common-protos-types>.freeze, [">= 0"])
98
98
  s.add_dependency(%q<benchmark-ips>.freeze, [">= 0"])
99
99
  s.add_dependency(%q<grpc-tools>.freeze, [">= 0"])
100
- s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
100
+ s.add_dependency(%q<rdoc>.freeze, [">= 0"])
101
101
  s.add_dependency(%q<bundler>.freeze, [">= 0"])
102
102
  s.add_dependency(%q<juwelier>.freeze, ["~> 2.4.9"])
103
103
  s.add_dependency(%q<simplecov>.freeze, [">= 0"])
@@ -16,10 +16,11 @@ nested:
16
16
  _: top level
17
17
  string: nested value
18
18
 
19
- logging:
19
+ log-level:
20
20
  app:
21
21
  _: error
22
22
  controller:
23
23
  hello:
24
24
  _: warn
25
25
  index: info
26
+ invalid: not a valid log level
@@ -16,6 +16,9 @@ class TestConfigClient < Minitest::Test
16
16
  def test_load
17
17
  assert_equal "test sample value", @config_client.get("sample")
18
18
  assert_equal 123, @config_client.get("sample_int")
19
+ assert_equal 12.12, @config_client.get("sample_double")
20
+ assert_equal true, @config_client.get("sample_bool")
21
+ assert_equal :ERROR, @config_client.get("log-level.app")
19
22
  end
20
23
 
21
24
  def test_initialization_timeout_error
@@ -21,9 +21,13 @@ class TestConfigLoader < Minitest::Test
21
21
  def test_nested
22
22
  should_be :string, "nested value", "nested.values.string"
23
23
  should_be :string, "top level", "nested.values"
24
- should_be :string, "error", "logging.app"
25
- should_be :string, "warn", "logging.app.controller.hello"
26
- should_be :string, "info", "logging.app.controller.hello.index"
24
+ should_be :log_level, :ERROR, "log-level.app"
25
+ should_be :log_level, :WARN, "log-level.app.controller.hello"
26
+ should_be :log_level, :INFO, "log-level.app.controller.hello.index"
27
+ end
28
+
29
+ def test_invalid_log_level
30
+ should_be :log_level, :NOT_SET_LOG_LEVEL, "log-level.invalid"
27
31
  end
28
32
 
29
33
  def test_load_without_unit_test_env
data/test/test_helper.rb CHANGED
@@ -69,10 +69,11 @@ def default_ff_rule(variant_idx)
69
69
  ]
70
70
  end
71
71
 
72
- def with_env(key, value)
72
+ def with_env(key, value, &block)
73
73
  old_value = ENV[key]
74
74
 
75
75
  ENV[key] = value
76
+ block.call
76
77
  ensure
77
78
  ENV[key] = old_value
78
79
  end
data/test/test_logger.rb CHANGED
@@ -20,6 +20,9 @@ class TestCLogger < Minitest::Test
20
20
  assert_equal "active_support.log_subscriber.info",
21
21
  @logger.get_path("/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'",
22
22
  "info")
23
+ assert_equal "unknown.info",
24
+ @logger.get_path(nil,
25
+ "info")
23
26
  end
24
27
 
25
28
  def test_loc_resolution
@@ -44,24 +47,61 @@ class TestCLogger < Minitest::Test
44
47
  with_env("PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL", "info") do
45
48
  # env var overrides the default level
46
49
  assert_equal Logger::INFO,
47
- @logger.level_of("app.models.user"), "PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info"
50
+ @logger.level_of("app.models.user"), "PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info"
48
51
 
49
52
  @logger.set_config_client(MockConfigClient.new({}))
50
53
  assert_equal Logger::WARN,
51
- @logger.level_of("app.models.user"), "default is warn"
54
+ @logger.level_of("app.models.user"), "default is warn"
52
55
 
53
- @logger.set_config_client(MockConfigClient.new("log_level.app" => "info"))
56
+ @logger.set_config_client(MockConfigClient.new("log-level.app" => :INFO))
54
57
  assert_equal Logger::INFO,
55
- @logger.level_of("app.models.user")
58
+ @logger.level_of("app.models.user")
56
59
 
57
- @logger.set_config_client(MockConfigClient.new("log_level.app" => "debug"))
60
+ @logger.set_config_client(MockConfigClient.new("log-level.app" => :DEBUG))
58
61
  assert_equal Logger::DEBUG,
59
- @logger.level_of("app.models.user")
62
+ @logger.level_of("app.models.user")
60
63
 
61
- @logger.set_config_client(MockConfigClient.new("log_level.app" => "debug",
62
- "log_level.app.models" => "warn"))
63
- assert_equal Logger::WARN,
64
- @logger.level_of("app.models.user")
64
+ @logger.set_config_client(MockConfigClient.new("log-level.app" => :DEBUG,
65
+ "log-level.app.models" => :ERROR))
66
+ assert_equal Logger::ERROR,
67
+ @logger.level_of("app.models.user"), "test leveling"
65
68
  end
66
69
  end
70
+
71
+ def test_log_internal
72
+ logger, mock_logdev = mock_logger_expecting /W, \[.*\] WARN -- test.path: : test message/
73
+ logger.log_internal("test message", "test.path", "", Logger::WARN)
74
+ mock_logdev.verify
75
+ end
76
+
77
+ def test_log_internal_unknown
78
+ logger, mock_logdev = mock_logger_expecting /A, \[.*\] ANY -- test.path: : test message/
79
+ logger.log_internal("test message", "test.path", "", Logger::UNKNOWN)
80
+ mock_logdev.verify
81
+ end
82
+
83
+ def test_log_internal_silencing
84
+ logger, mock_logdev = mock_logger_expecting /W, \[.*\] WARN -- test.path: : should log/, calls: 2
85
+ logger.silence do
86
+ logger.log_internal("should not log", "test.path", "", Logger::WARN)
87
+ end
88
+ logger.log_internal("should log", "test.path", "", Logger::WARN)
89
+ mock_logdev.verify
90
+ end
91
+
92
+ def mock_logger_expecting pattern, configs = {}, calls: 1
93
+ mock_logdev = Minitest::Mock.new
94
+ mock_logdev.expect :write, nil do |arg|
95
+ pattern.match(arg)
96
+ end
97
+
98
+ calls.times.each do
99
+ mock_logdev.expect(:nil?, false)
100
+ end
101
+
102
+ logger = Prefab::LoggerClient.new($stdout)
103
+ logger.instance_variable_set('@logdev', mock_logdev)
104
+ logger.set_config_client(MockConfigClient.new(configs))
105
+ [logger, mock_logdev]
106
+ end
67
107
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prefab-cloud-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dwyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-01 00:00:00.000000000 Z
11
+ date: 2022-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -132,16 +132,16 @@ dependencies:
132
132
  name: rdoc
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
- - - "~>"
135
+ - - ">="
136
136
  - !ruby/object:Gem::Version
137
- version: '3.12'
137
+ version: '0'
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - "~>"
142
+ - - ">="
143
143
  - !ruby/object:Gem::Version
144
- version: '3.12'
144
+ version: '0'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: bundler
147
147
  requirement: !ruby/object:Gem::Requirement