prefab-cloud-ruby 0.18.0 → 0.19.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: d9225ebaadf8be997d152b66cb58ff342d126bc5cfbe489511af4791d89dd5f7
4
- data.tar.gz: cbaf511c7aeaf0ef743b33c2ad00c40bd4d6c8ddba0a17ddff541afeb8e055d9
3
+ metadata.gz: f56ee15a73bef27dbb37cfbc4df7b1004543664ea7b5defc5ae6afbb738a4c23
4
+ data.tar.gz: 151d525aca5d58ee1098fed1f6e87037ee6b2cc8570985f2a922ec028cc3d394
5
5
  SHA512:
6
- metadata.gz: f00e343e6f3f7a7f11351409708979c4e02420eae8bf8d9520cdc58de464b682158b863bcab88b4583c469709c621f066bd8995e482963386b931c877bfd2b1f
7
- data.tar.gz: 5e51d64d2d5adc738e5f8438cd222ae3e4d9fc1f183a789d25486da7197b25c3263fff9a0fac9b33a9acffc169e035630e7a8cb8b3d3770e9e8b669d34b96f68
6
+ metadata.gz: 9d48de76dc679c635a9530625aa0feedd6ddb9193023b98e5c24247f6eded562e9ffcca770116dc5a1bc7dc60a0e7fad2f828f31b791c771c7d3aa587daf77bd
7
+ data.tar.gz: da2371a89c4886ac22d2ce5ef0b7b2e8b732aa8ac2600a699b1598cc1c9138c9a99e075df944d911f790f385ffea81c2b186aaf29d6b40ed7c5f05247d41d22b
data/Gemfile CHANGED
@@ -19,4 +19,5 @@ end
19
19
 
20
20
  group :test do
21
21
  gem "minitest"
22
+ gem "minitest-focus"
22
23
  end
data/Gemfile.lock CHANGED
@@ -30,7 +30,7 @@ GEM
30
30
  faraday (>= 0.8, < 2)
31
31
  hashie (~> 3.5, >= 3.5.2)
32
32
  oauth2 (~> 1.0)
33
- google-protobuf (3.21.4)
33
+ google-protobuf (3.21.9)
34
34
  googleapis-common-protos-types (1.3.0)
35
35
  google-protobuf (~> 3.14)
36
36
  grpc (1.43.1)
@@ -70,10 +70,12 @@ GEM
70
70
  rake (~> 13.0)
71
71
  mini_portile2 (2.8.0)
72
72
  minitest (5.16.2)
73
+ minitest-focus (1.3.1)
74
+ minitest (>= 4, < 6)
73
75
  multi_json (1.15.0)
74
76
  multi_xml (0.6.0)
75
77
  multipart-post (2.1.1)
76
- nokogiri (1.13.6)
78
+ nokogiri (1.13.9)
77
79
  mini_portile2 (~> 2.8.0)
78
80
  racc (~> 1.4)
79
81
  oauth2 (1.4.7)
@@ -86,7 +88,7 @@ GEM
86
88
  public_suffix (4.0.6)
87
89
  racc (1.6.0)
88
90
  rack (2.2.4)
89
- rake (13.0.3)
91
+ rake (13.0.6)
90
92
  rchardet (1.8.0)
91
93
  rdoc (6.3.3)
92
94
  ruby2_keywords (0.0.4)
@@ -119,6 +121,7 @@ DEPENDENCIES
119
121
  juwelier (~> 2.4.9)
120
122
  ld-eventsource
121
123
  minitest
124
+ minitest-focus
122
125
  rdoc
123
126
  simplecov
124
127
  thin
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # prefab-cloud-ruby
2
- Ruby Client for Prefab RateLimits, FeatureFlags, Config as a Service: https://www.prefab.cloud
2
+ Ruby Client for Prefab FeatureFlags, Config as a Service: https://www.prefab.cloud
3
3
 
4
4
  ```ruby
5
5
  client = Prefab::Client.new
@@ -16,11 +16,9 @@ puts @feature_flags.feature_is_on? "MyFeature", "user:1123"
16
16
  ```
17
17
  See full documentation https://www.prefab.cloud/documentation/installation
18
18
 
19
-
20
19
  ## Supports
21
20
 
22
21
  * [FeatureFlags](https://www.prefab.cloud/documentation/feature_flags) as a Service
23
- * [RateLimits](https://www.prefab.cloud/documentation/basic_rate_limits)
24
22
  * Millions of individual limits sharing the same policies
25
23
  * WebUI for tweaking limits & feature flags
26
24
  * Infinite retention for [deduplication workflows](https://www.prefab.cloud/documentation/once_and_only_once)
@@ -44,15 +42,19 @@ end
44
42
 
45
43
  ## Logging & Debugging
46
44
  In classpath or ~/.prefab.overrides.config.yaml set
47
- ```log-level.prefab: debug```
45
+
46
+ ```
47
+ log-level:
48
+ cloud.prefab: debug
49
+ ```
48
50
 
49
51
  To debug issues before this config file has been read, set env var
50
52
  ```
51
- PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL = debug
53
+ PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL=debug
52
54
  ```
53
55
 
54
56
  ## Contributing to prefab-cloud-ruby
55
-
57
+
56
58
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
57
59
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
58
60
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.18.0
1
+ 0.19.0
data/lib/prefab/client.rb CHANGED
@@ -47,10 +47,11 @@ module Prefab
47
47
  end
48
48
 
49
49
  def log
50
- @logger_client ||= Prefab::LoggerClient.new(@options.logdev, formatter: @options.log_formatter)
50
+ @logger_client ||= Prefab::LoggerClient.new(@options.logdev, formatter: @options.log_formatter,
51
+ prefix: @options.log_prefix)
51
52
  end
52
53
 
53
- def log_internal(level, msg, path = "prefab")
54
+ def log_internal(level, msg, path = nil)
54
55
  log.log_internal msg, path, nil, level
55
56
  end
56
57
 
@@ -189,7 +189,7 @@ module Prefab
189
189
  if @config_loader.highwater_mark > starting_highwater_mark
190
190
  @base_client.log_internal Logger::INFO, "Found new checkpoint with highwater id #{@config_loader.highwater_mark} from #{source} in project #{project_id} environment: #{project_env_id} and namespace: '#{@namespace}'"
191
191
  else
192
- @base_client.log_internal Logger::DEBUG, "Checkpoint with highwater id #{@config_loader.highwater_mark} from #{source}. No changes.", "prefab.config_client.load_configs"
192
+ @base_client.log_internal Logger::DEBUG, "Checkpoint with highwater id #{@config_loader.highwater_mark} from #{source}. No changes.", "load_configs"
193
193
  end
194
194
  @base_client.stats.increment("prefab.config.checkpoint.load")
195
195
  @config_resolver.update
@@ -237,7 +237,7 @@ module Prefab
237
237
  @streaming_thread = SSE::Client.new(url,
238
238
  headers: headers,
239
239
  read_timeout: SSE_READ_TIMEOUT,
240
- logger: Prefab::InternalLogger.new("prefab.config.sse", @base_client.log)) do |client|
240
+ logger: Prefab::SseLogger.new(@base_client.log)) do |client|
241
241
  client.on_event do |event|
242
242
  configs = Prefab::Configs.decode(Base64.decode64(event.data))
243
243
  load_configs(configs, :sse)
@@ -18,7 +18,8 @@ module Prefab
18
18
  def to_s
19
19
  str = "\n"
20
20
  @lock.with_read_lock do
21
- @local_store.each do |k, v|
21
+ @local_store.keys.sort.each do |k|
22
+ v = @local_store[k]
22
23
  elements = [k.slice(0..49).ljust(50)]
23
24
  if v.nil?
24
25
  elements << "tombstone"
@@ -5,6 +5,7 @@ module Prefab
5
5
  SEP = "."
6
6
  BASE_KEY = "log-level"
7
7
  UNKNOWN_PATH = "unknown."
8
+ INTERNAL_PREFIX = "cloud.prefab.client"
8
9
 
9
10
  LOG_LEVEL_LOOKUPS = {
10
11
  Prefab::LogLevel::NOT_SET_LOG_LEVEL => Logger::DEBUG,
@@ -16,24 +17,32 @@ module Prefab
16
17
  Prefab::LogLevel::FATAL => Logger::FATAL
17
18
  }
18
19
 
19
- def initialize(logdev, formatter: nil)
20
+ def initialize(logdev, formatter: nil, prefix: nil)
20
21
  super(logdev)
21
22
  self.formatter = formatter
22
23
  @config_client = BootstrappingConfigClient.new
23
- @silences = Concurrent::Map.new(:initial_capacity => 2)
24
+ @silences = Concurrent::Map.new(initial_capacity: 2)
25
+ @prefix = prefix
24
26
  end
25
27
 
26
- def add(severity, message = nil, progname = nil)
27
- loc = caller_locations(1, 1)[0]
28
- add_internal(severity, message, progname, loc)
28
+ def add(severity, message = nil, progname = nil, loc, &block)
29
+ path = get_loc_path(loc)
30
+ path = "#{@prefix}#{@prefix && '.'}#{path}"
31
+
32
+ log(message, path, progname, severity, &block)
29
33
  end
30
34
 
31
- def add_internal(severity, message = nil, progname = nil, loc, &block)
32
- path = get_loc_path(loc)
33
- log_internal(message, path, progname, severity, &block)
35
+ def log_internal(message, path = nil, progname, severity, &block)
36
+ if path
37
+ path = "#{INTERNAL_PREFIX}.#{path}"
38
+ else
39
+ path = INTERNAL_PREFIX
40
+ end
41
+
42
+ log(message, path, progname, severity, &block)
34
43
  end
35
44
 
36
- def log_internal(message, path, progname, severity, &block)
45
+ def log(message, path, progname, severity, &block)
37
46
  level = level_of(path)
38
47
  progname = "#{path}: #{progname}"
39
48
  severity ||= Logger::UNKNOWN
@@ -57,23 +66,23 @@ module Prefab
57
66
  end
58
67
 
59
68
  def debug(progname = nil, &block)
60
- add_internal(DEBUG, nil, progname, caller_locations(1, 1)[0], &block)
69
+ add(DEBUG, nil, progname, caller_locations(1, 1)[0], &block)
61
70
  end
62
71
 
63
72
  def info(progname = nil, &block)
64
- add_internal(INFO, nil, progname, caller_locations(1, 1)[0], &block)
73
+ add(INFO, nil, progname, caller_locations(1, 1)[0], &block)
65
74
  end
66
75
 
67
76
  def warn(progname = nil, &block)
68
- add_internal(WARN, nil, progname, caller_locations(1, 1)[0], &block)
77
+ add(WARN, nil, progname, caller_locations(1, 1)[0], &block)
69
78
  end
70
79
 
71
80
  def error(progname = nil, &block)
72
- add_internal(ERROR, nil, progname, caller_locations(1, 1)[0], &block)
81
+ add(ERROR, nil, progname, caller_locations(1, 1)[0], &block)
73
82
  end
74
83
 
75
84
  def fatal(progname = nil, &block)
76
- add_internal(FATAL, nil, progname, caller_locations(1, 1)[0], &block)
85
+ add(FATAL, nil, progname, caller_locations(1, 1)[0], &block)
77
86
  end
78
87
 
79
88
  def debug?
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Prefab
3
4
  class Options
4
5
  attr_reader :api_key
5
6
  attr_reader :logdev
7
+ attr_reader :log_prefix
6
8
  attr_reader :log_formatter
7
9
  attr_reader :stats
8
10
  attr_reader :shared_cache
@@ -40,6 +42,7 @@ module Prefab
40
42
  shared_cache: NoopCache.new, # Something that quacks like Rails.cache ideally memcached
41
43
  namespace: "",
42
44
  log_formatter: DEFAULT_LOG_FORMATTER,
45
+ log_prefix: nil,
43
46
  prefab_api_url: ENV["PREFAB_API_URL"] || 'https://api.prefab.cloud',
44
47
  prefab_grpc_url: ENV["PREFAB_GRPC_URL"] || 'grpc.prefab.cloud:443',
45
48
  on_no_default: ON_NO_DEFAULT::RAISE, # options :raise, :warn_and_return_nil,
@@ -59,6 +62,7 @@ module Prefab
59
62
  @shared_cache = shared_cache
60
63
  @namespace = namespace
61
64
  @log_formatter = log_formatter
65
+ @log_prefix = log_prefix
62
66
  @prefab_api_url = prefab_api_url
63
67
  @prefab_grpc_url = prefab_grpc_url
64
68
  @on_no_default = on_no_default
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ module Prefab
3
+ class SseLogger < InternalLogger
4
+ def initialize(logger)
5
+ super("sse", logger)
6
+ end
7
+
8
+ # The SSE::Client warns on a perfectly normal stream disconnect, recast to info
9
+ def warn(progname = nil, &block)
10
+ @logger.log_internal yield, @path, progname, INFO
11
+ end
12
+ end
13
+ end
@@ -13,6 +13,7 @@ require 'prefab/errors/missing_default_error'
13
13
  require 'prefab_services_pb'
14
14
  require 'prefab/options'
15
15
  require 'prefab/internal_logger'
16
+ require 'prefab/sse_logger'
16
17
  require 'prefab/config_helper'
17
18
  require 'prefab/config_loader'
18
19
  require 'prefab/config_resolver'
@@ -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.18.0 ruby lib
5
+ # stub: prefab-cloud-ruby 0.19.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "prefab-cloud-ruby".freeze
9
- s.version = "0.18.0"
9
+ s.version = "0.19.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-10-14"
14
+ s.date = "2022-11-19"
15
15
  s.description = "RateLimits & Config as a service".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.extra_rdoc_files = [
@@ -50,6 +50,7 @@ Gem::Specification.new do |s|
50
50
  "lib/prefab/noop_stats.rb",
51
51
  "lib/prefab/options.rb",
52
52
  "lib/prefab/ratelimit_client.rb",
53
+ "lib/prefab/sse_logger.rb",
53
54
  "lib/prefab_pb.rb",
54
55
  "lib/prefab_services_pb.rb",
55
56
  "prefab-cloud-ruby.gemspec",
data/test/test_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'minitest/autorun'
3
+ require "minitest/focus"
3
4
  require 'prefab-cloud-ruby'
4
5
 
5
6
  class MockBaseClient
data/test/test_logger.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'test_helper'
3
4
 
4
5
  class TestCLogger < Minitest::Test
@@ -69,19 +70,19 @@ class TestCLogger < Minitest::Test
69
70
  end
70
71
 
71
72
  def test_log_internal
72
- logger, mock_logdev = mock_logger_expecting /W, \[.*\] WARN -- test.path: : test message/
73
+ logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : test message/)
73
74
  logger.log_internal("test message", "test.path", "", Logger::WARN)
74
75
  mock_logdev.verify
75
76
  end
76
77
 
77
78
  def test_log_internal_unknown
78
- logger, mock_logdev = mock_logger_expecting /A, \[.*\] ANY -- test.path: : test message/
79
+ logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- cloud.prefab.client.test.path: : test message/)
79
80
  logger.log_internal("test message", "test.path", "", Logger::UNKNOWN)
80
81
  mock_logdev.verify
81
82
  end
82
83
 
83
84
  def test_log_internal_silencing
84
- logger, mock_logdev = mock_logger_expecting /W, \[.*\] WARN -- test.path: : should log/, calls: 2
85
+ logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : should log/, calls: 2)
85
86
  logger.silence do
86
87
  logger.log_internal("should not log", "test.path", "", Logger::WARN)
87
88
  end
@@ -89,6 +90,45 @@ class TestCLogger < Minitest::Test
89
90
  mock_logdev.verify
90
91
  end
91
92
 
93
+ def test_log
94
+ logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : test message/)
95
+ logger.log("test message", "test.path", "", Logger::WARN)
96
+ mock_logdev.verify
97
+ end
98
+
99
+ def test_log_unknown
100
+ logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- test.path: : test message/)
101
+ logger.log("test message", "test.path", "", Logger::UNKNOWN)
102
+ mock_logdev.verify
103
+ end
104
+
105
+ def test_log_silencing
106
+ logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : should log/, calls: 2)
107
+ logger.silence do
108
+ logger.log("should not log", "test.path", "", Logger::WARN)
109
+ end
110
+ logger.log("should log", "test.path", "", Logger::WARN)
111
+ mock_logdev.verify
112
+ end
113
+
114
+ def test_logging_with_prefix
115
+ prefix = 'my.own.prefix'
116
+ message = 'this is a test'
117
+
118
+ io = StringIO.new
119
+ options = Prefab::Options.new(logdev: io, log_prefix: prefix, prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY)
120
+ prefab = Prefab::Client.new(options)
121
+
122
+ prefixed_logger = prefab.log
123
+ prefixed_logger.error message
124
+
125
+ assert_logged io.string, 'ERROR', "#{prefix}.test.test_logger.test_logging_with_prefix", message
126
+ end
127
+
128
+ def assert_logged(log_line, level, path, message)
129
+ assert_match(/#{level} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]?\d+: #{path}: #{message}\n/, log_line)
130
+ end
131
+
92
132
  def mock_logger_expecting pattern, configs = {}, calls: 1
93
133
  mock_logdev = Minitest::Mock.new
94
134
  mock_logdev.expect :write, nil do |arg|
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.18.0
4
+ version: 0.19.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-10-14 00:00:00.000000000 Z
11
+ date: 2022-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -237,6 +237,7 @@ files:
237
237
  - lib/prefab/noop_stats.rb
238
238
  - lib/prefab/options.rb
239
239
  - lib/prefab/ratelimit_client.rb
240
+ - lib/prefab/sse_logger.rb
240
241
  - lib/prefab_pb.rb
241
242
  - lib/prefab_services_pb.rb
242
243
  - prefab-cloud-ruby.gemspec