sdk-reforge 1.11.2 → 1.12.0
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/.DS_Store +0 -0
- data/.github/workflows/ruby.yml +1 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +3 -3
- data/README.md +100 -0
- data/VERSION +1 -1
- data/lib/prefab_pb.rb +1 -1
- data/lib/reforge/client.rb +4 -0
- data/lib/reforge/internal_logger.rb +149 -19
- data/lib/reforge/log_level.rb +47 -0
- data/lib/reforge/log_level_client.rb +169 -0
- data/lib/reforge/options.rb +4 -1
- data/lib/reforge/reforge.rb +9 -0
- data/lib/sdk-reforge.rb +8 -1
- data/sdk-reforge.gemspec +7 -4
- data/test/support/common_helpers.rb +5 -2
- data/test/test_log_level_client.rb +264 -0
- metadata +6 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8bd7701858dfa6e149ecf77c03e6912f57a74986e013b2b9557da7c90e39f9b2
|
|
4
|
+
data.tar.gz: 7962dbe8f2e4e6e5d3042b46e0881365d707803ae7ff1e1a328dd412f2872841
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eff80aba938418cc6108053256ccaee55fc4f7d5a4c5c8d56178e3dd818ecbfb88e7f1144df65e9d28f6b8de08b640ef83997e11f05f091ac0bedaf01277bacd
|
|
7
|
+
data.tar.gz: dbc13318df9207918cf6bc7343bcac5221532a65dd6ee58fbfd61e014a4ba98fcd1f6f6efa2050cb7bcc0823573cdb24bbd541d9d45df8c5e614bf3aa8ba3fc5
|
data/.DS_Store
ADDED
|
Binary file
|
data/.github/workflows/ruby.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.12.0 - 2025-10-31
|
|
4
|
+
|
|
5
|
+
- Restore log level functionality with LOG_LEVEL_V2 support
|
|
6
|
+
- Make SemanticLogger optional - SDK now works with or without it
|
|
7
|
+
- Add stdlib Logger support as alternative to SemanticLogger
|
|
8
|
+
- Add InternalLogger that automatically uses SemanticLogger or stdlib Logger
|
|
9
|
+
- Add `logger_key` initialization option for configuring dynamic log levels
|
|
10
|
+
- Add `stdlib_formatter` method for stdlib Logger integration
|
|
11
|
+
|
|
3
12
|
## 1.11.2 - 2025-10-07
|
|
4
13
|
|
|
5
14
|
- Address OpenSSL issue with vulnerability to truncation attack
|
data/Gemfile
CHANGED
|
@@ -9,8 +9,6 @@ gem 'uuid'
|
|
|
9
9
|
|
|
10
10
|
gem 'activesupport', '>= 4'
|
|
11
11
|
|
|
12
|
-
gem 'semantic_logger', '!= 4.16.0', require: "semantic_logger/sync"
|
|
13
|
-
|
|
14
12
|
group :development do
|
|
15
13
|
gem 'allocation_stats'
|
|
16
14
|
gem 'benchmark-ips'
|
|
@@ -21,6 +19,7 @@ group :development do
|
|
|
21
19
|
end
|
|
22
20
|
|
|
23
21
|
group :test do
|
|
22
|
+
gem 'semantic_logger', '!= 4.16.0', require: "semantic_logger/sync"
|
|
24
23
|
gem 'minitest'
|
|
25
24
|
gem 'minitest-focus'
|
|
26
25
|
gem 'minitest-reporters'
|
data/Gemfile.lock
CHANGED
|
@@ -102,7 +102,7 @@ GEM
|
|
|
102
102
|
rake (~> 13.0)
|
|
103
103
|
macaddr (1.7.2)
|
|
104
104
|
systemu (~> 2.6.5)
|
|
105
|
-
mini_portile2 (2.8.
|
|
105
|
+
mini_portile2 (2.8.9)
|
|
106
106
|
minitest (5.22.3)
|
|
107
107
|
minitest-focus (1.4.0)
|
|
108
108
|
minitest (>= 4, < 6)
|
|
@@ -115,7 +115,7 @@ GEM
|
|
|
115
115
|
multi_xml (0.6.0)
|
|
116
116
|
multipart-post (2.4.0)
|
|
117
117
|
mutex_m (0.2.0)
|
|
118
|
-
nokogiri (1.
|
|
118
|
+
nokogiri (1.18.9)
|
|
119
119
|
mini_portile2 (~> 2.8.2)
|
|
120
120
|
racc (~> 1.4)
|
|
121
121
|
oauth2 (1.4.11)
|
|
@@ -128,7 +128,7 @@ GEM
|
|
|
128
128
|
stringio
|
|
129
129
|
public_suffix (5.0.4)
|
|
130
130
|
racc (1.8.1)
|
|
131
|
-
rack (3.
|
|
131
|
+
rack (3.1.18)
|
|
132
132
|
rake (13.1.0)
|
|
133
133
|
rchardet (1.8.0)
|
|
134
134
|
rdoc (6.6.3.1)
|
data/README.md
CHANGED
|
@@ -64,7 +64,107 @@ after_fork do |server, worker|
|
|
|
64
64
|
end
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
## Dynamic Log Levels
|
|
67
68
|
|
|
69
|
+
Reforge supports dynamic log level management for Ruby logging frameworks. This allows you to change log levels in real-time without redeploying your application.
|
|
70
|
+
|
|
71
|
+
Supported loggers:
|
|
72
|
+
- SemanticLogger (optional dependency)
|
|
73
|
+
- Ruby stdlib Logger
|
|
74
|
+
|
|
75
|
+
### Setup with SemanticLogger
|
|
76
|
+
|
|
77
|
+
Add semantic_logger to your Gemfile:
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
# Gemfile
|
|
81
|
+
gem "semantic_logger"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Plain Ruby
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
require "semantic_logger"
|
|
88
|
+
require "sdk-reforge"
|
|
89
|
+
|
|
90
|
+
client = Reforge::Client.new(
|
|
91
|
+
sdk_key: ENV['REFORGE_BACKEND_SDK_KEY'],
|
|
92
|
+
logger_key: 'log-levels.default' # optional, this is the default
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
SemanticLogger.sync!
|
|
96
|
+
SemanticLogger.default_level = :trace # Reforge will handle filtering
|
|
97
|
+
SemanticLogger.add_appender(
|
|
98
|
+
io: $stdout,
|
|
99
|
+
formatter: :json,
|
|
100
|
+
filter: client.log_level_client.method(:semantic_filter)
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### With Rails
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
# Gemfile
|
|
108
|
+
gem "amazing_print"
|
|
109
|
+
gem "rails_semantic_logger"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
# config/application.rb
|
|
114
|
+
$reforge_client = Reforge::Client.new # reads REFORGE_BACKEND_SDK_KEY env var
|
|
115
|
+
|
|
116
|
+
# config/initializers/logging.rb
|
|
117
|
+
SemanticLogger.sync!
|
|
118
|
+
SemanticLogger.default_level = :trace # Reforge will handle filtering
|
|
119
|
+
SemanticLogger.add_appender(
|
|
120
|
+
io: $stdout,
|
|
121
|
+
formatter: Rails.env.development? ? :color : :json,
|
|
122
|
+
filter: $reforge_client.log_level_client.method(:semantic_filter)
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
# puma.rb
|
|
128
|
+
on_worker_boot do
|
|
129
|
+
SemanticLogger.reopen
|
|
130
|
+
Reforge.fork
|
|
131
|
+
end
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### With Ruby stdlib Logger
|
|
135
|
+
|
|
136
|
+
If you're using Ruby's standard library Logger, you can use a dynamic formatter:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
require "logger"
|
|
140
|
+
require "sdk-reforge"
|
|
141
|
+
|
|
142
|
+
client = Reforge::Client.new(
|
|
143
|
+
sdk_key: ENV['REFORGE_BACKEND_SDK_KEY'],
|
|
144
|
+
logger_key: 'log-levels.default' # optional, this is the default
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
logger = Logger.new($stdout)
|
|
148
|
+
logger.level = Logger::DEBUG # Set to most verbose level, Reforge will handle filtering
|
|
149
|
+
logger.formatter = client.log_level_client.stdlib_formatter('MyApp')
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The formatter will check dynamic log levels from Reforge and only output logs that meet the configured threshold.
|
|
153
|
+
|
|
154
|
+
### Configuration
|
|
155
|
+
|
|
156
|
+
In Reforge Launch, create a `LOG_LEVEL_V2` config with your desired key (default: `log-levels.default`). The config will be evaluated with the following context:
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
{
|
|
160
|
+
"reforge-sdk-logging" => {
|
|
161
|
+
"lang" => "ruby",
|
|
162
|
+
"logger-path" => "your_app.your_class" # class name converted to lowercase with dots
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
You can set different log levels for different classes/modules using criteria on the `reforge-sdk-logging.logger-path` property.
|
|
68
168
|
|
|
69
169
|
## Contributing to reforge sdk for ruby
|
|
70
170
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.12.0
|
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\"\xf7\x04\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\x12$\n\x08provided\x18\x0c \x01(\x0b\x32\x10.prefab.ProvidedH\x00\x12\'\n\x08\x64uration\x18\x0f \x01(\x0b\x32\x13.prefab.IsoDurationH\x00\x12\x1c\n\x04json\x18\x10 \x01(\x0b\x32\x0c.prefab.JsonH\x00\x12 \n\x06schema\x18\x11 \x01(\x0b\x32\x0e.prefab.SchemaH\x00\x12\x19\n\x0c\x63onfidential\x18\r \x01(\x08H\x01\x88\x01\x01\x12\x19\n\x0c\x64\x65\x63rypt_with\x18\x0e \x01(\tH\x02\x88\x01\x01\x12\x11\n\x04name\x18\x12 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x13 \x01(\tH\x04\x88\x01\x01\x42\x06\n\x04typeB\x0f\n\r_confidentialB\x0f\n\r_decrypt_withB\x07\n\x05_nameB\x0e\n\x0c_description\"\x14\n\x04Json\x12\x0c\n\x04json\x18\x01 \x01(\t\"!\n\x0bIsoDuration\x12\x12\n\ndefinition\x18\x01 \x01(\t\"b\n\x08Provided\x12+\n\x06source\x18\x01 \x01(\x0e\x32\x16.prefab.ProvidedSourceH\x00\x88\x01\x01\x12\x13\n\x06lookup\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_sourceB\t\n\x07_lookup\"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\"\xa0\x02\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\x12\x17\n\nkeep_alive\x18\x05 \x01(\x08H\x02\x88\x01\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_contextB\r\n\x0b_keep_alive\"\xa4\x04\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\x15\n\x08\x64raft_id\x18\x08 \x01(\x03H\x00\x88\x01\x01\x12,\n\nvalue_type\x18\t \x01(\x0e\x32\x18.prefab.Config.ValueType\x12\x1a\n\x12send_to_client_sdk\x18\n \x01(\x08\x12\x17\n\nschema_key\x18\x0b \x01(\tH\x01\x88\x01\x01\"\xb6\x01\n\tValueType\x12\x16\n\x12NOT_SET_VALUE_TYPE\x10\x00\x12\x07\n\x03INT\x10\x01\x12\n\n\x06STRING\x10\x02\x12\t\n\x05\x42YTES\x10\x03\x12\n\n\x06\x44OUBLE\x10\x04\x12\x08\n\x04\x42OOL\x10\x05\x12\x14\n\x10LIMIT_DEFINITION\x10\x07\x12\r\n\tLOG_LEVEL\x10\t\x12\x0f\n\x0bSTRING_LIST\x10\n\x12\r\n\tINT_RANGE\x10\x0b\x12\x0c\n\x08\x44URATION\x10\x0c\x12\x08\n\x04JSON\x10\rB\x0b\n\t_draft_idB\r\n\x0b_schema_key\"V\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\x12\x15\n\ruser_identity\x18\x04 \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\"\x96\x06\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\"\x8d\x05\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\x12\x1b\n\x17PROP_STARTS_WITH_ONE_OF\x10\x0c\x12#\n\x1fPROP_DOES_NOT_START_WITH_ONE_OF\x10\r\x12\x18\n\x14PROP_CONTAINS_ONE_OF\x10\x0e\x12 \n\x1cPROP_DOES_NOT_CONTAIN_ONE_OF\x10\x0f\x12\x12\n\x0ePROP_LESS_THAN\x10\x10\x12\x1b\n\x17PROP_LESS_THAN_OR_EQUAL\x10\x11\x12\x15\n\x11PROP_GREATER_THAN\x10\x12\x12\x1e\n\x1aPROP_GREATER_THAN_OR_EQUAL\x10\x13\x12\x0f\n\x0bPROP_BEFORE\x10\x14\x12\x0e\n\nPROP_AFTER\x10\x15\x12\x10\n\x0cPROP_MATCHES\x10\x16\x12\x17\n\x13PROP_DOES_NOT_MATCH\x10\x17\x12\x19\n\x15PROP_SEMVER_LESS_THAN\x10\x18\x12\x15\n\x11PROP_SEMVER_EQUAL\x10\x19\x12\x1c\n\x18PROP_SEMVER_GREATER_THAN\x10\x1a\"\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\"\xd6\x02\n\x18\x43onfigEvaluationMetaData\x12\x1d\n\x10\x63onfig_row_index\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17\x63onditional_value_index\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12!\n\x14weighted_value_index\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12%\n\x04type\x18\x04 \x01(\x0e\x32\x12.prefab.ConfigTypeH\x03\x88\x01\x01\x12\x0f\n\x02id\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12\x31\n\nvalue_type\x18\x06 \x01(\x0e\x32\x18.prefab.Config.ValueTypeH\x05\x88\x01\x01\x42\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_indexB\x07\n\x05_typeB\x05\n\x03_idB\r\n\x0b_value_type\"\x8b\x03\n\x11\x43lientConfigValue\x12\r\n\x03int\x18\x01 \x01(\x03H\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x10\n\x06\x64ouble\x18\x03 \x01(\x01H\x00\x12\x0e\n\x04\x62ool\x18\x04 \x01(\x08H\x00\x12%\n\tlog_level\x18\x05 \x01(\x0e\x32\x10.prefab.LogLevelH\x00\x12)\n\x0bstring_list\x18\x07 \x01(\x0b\x32\x12.prefab.StringListH\x00\x12%\n\tint_range\x18\x08 \x01(\x0b\x32\x10.prefab.IntRangeH\x00\x12*\n\x08\x64uration\x18\t \x01(\x0b\x32\x16.prefab.ClientDurationH\x00\x12\x1c\n\x04json\x18\n \x01(\x0b\x32\x0c.prefab.JsonH\x00\x12I\n\x1a\x63onfig_evaluation_metadata\x18\x06 \x01(\x0b\x32 .prefab.ConfigEvaluationMetaDataH\x01\x88\x01\x01\x42\x06\n\x04typeB\x1d\n\x1b_config_evaluation_metadata\"D\n\x0e\x43lientDuration\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x12\x12\n\ndefinition\x18\x03 \x01(\t\"\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\"\x98\x02\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\x12/\n\x0e\x63ontext_shapes\x18\x06 \x01(\x0b\x32\x15.prefab.ContextShapesH\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\"}\n\x06Schema\x12\x0e\n\x06schema\x18\x01 \x01(\t\x12.\n\x0bschema_type\x18\x02 \x01(\x0e\x32\x19.prefab.Schema.SchemaType\"3\n\nSchemaType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03ZOD\x10\x01\x12\x0f\n\x0bJSON_SCHEMA\x10\x02*:\n\x0eProvidedSource\x12\x1b\n\x17PROVIDED_SOURCE_NOT_SET\x10\x00\x12\x0b\n\x07\x45NV_VAR\x10\x01*\x8e\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\x12\n\n\x06SCHEMA\x10\x07*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\x42L\n\x13\x63loud.prefab.domainB\x06PrefabZ-github.com/prefab-cloud/prefab-cloud-go/protob\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\"\xf7\x04\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\x12$\n\x08provided\x18\x0c \x01(\x0b\x32\x10.prefab.ProvidedH\x00\x12\'\n\x08\x64uration\x18\x0f \x01(\x0b\x32\x13.prefab.IsoDurationH\x00\x12\x1c\n\x04json\x18\x10 \x01(\x0b\x32\x0c.prefab.JsonH\x00\x12 \n\x06schema\x18\x11 \x01(\x0b\x32\x0e.prefab.SchemaH\x00\x12\x19\n\x0c\x63onfidential\x18\r \x01(\x08H\x01\x88\x01\x01\x12\x19\n\x0c\x64\x65\x63rypt_with\x18\x0e \x01(\tH\x02\x88\x01\x01\x12\x11\n\x04name\x18\x12 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x13 \x01(\tH\x04\x88\x01\x01\x42\x06\n\x04typeB\x0f\n\r_confidentialB\x0f\n\r_decrypt_withB\x07\n\x05_nameB\x0e\n\x0c_description\"\x14\n\x04Json\x12\x0c\n\x04json\x18\x01 \x01(\t\"!\n\x0bIsoDuration\x12\x12\n\ndefinition\x18\x01 \x01(\t\"b\n\x08Provided\x12+\n\x06source\x18\x01 \x01(\x0e\x32\x16.prefab.ProvidedSourceH\x00\x88\x01\x01\x12\x13\n\x06lookup\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_sourceB\t\n\x07_lookup\"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\"\xa0\x02\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\x12\x17\n\nkeep_alive\x18\x05 \x01(\x08H\x02\x88\x01\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_contextB\r\n\x0b_keep_alive\"\xa4\x04\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\x15\n\x08\x64raft_id\x18\x08 \x01(\x03H\x00\x88\x01\x01\x12,\n\nvalue_type\x18\t \x01(\x0e\x32\x18.prefab.Config.ValueType\x12\x1a\n\x12send_to_client_sdk\x18\n \x01(\x08\x12\x17\n\nschema_key\x18\x0b \x01(\tH\x01\x88\x01\x01\"\xb6\x01\n\tValueType\x12\x16\n\x12NOT_SET_VALUE_TYPE\x10\x00\x12\x07\n\x03INT\x10\x01\x12\n\n\x06STRING\x10\x02\x12\t\n\x05\x42YTES\x10\x03\x12\n\n\x06\x44OUBLE\x10\x04\x12\x08\n\x04\x42OOL\x10\x05\x12\x14\n\x10LIMIT_DEFINITION\x10\x07\x12\r\n\tLOG_LEVEL\x10\t\x12\x0f\n\x0bSTRING_LIST\x10\n\x12\r\n\tINT_RANGE\x10\x0b\x12\x0c\n\x08\x44URATION\x10\x0c\x12\x08\n\x04JSON\x10\rB\x0b\n\t_draft_idB\r\n\x0b_schema_key\"V\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\x12\x15\n\ruser_identity\x18\x04 \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\"\x96\x06\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\"\x8d\x05\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\x12\x1b\n\x17PROP_STARTS_WITH_ONE_OF\x10\x0c\x12#\n\x1fPROP_DOES_NOT_START_WITH_ONE_OF\x10\r\x12\x18\n\x14PROP_CONTAINS_ONE_OF\x10\x0e\x12 \n\x1cPROP_DOES_NOT_CONTAIN_ONE_OF\x10\x0f\x12\x12\n\x0ePROP_LESS_THAN\x10\x10\x12\x1b\n\x17PROP_LESS_THAN_OR_EQUAL\x10\x11\x12\x15\n\x11PROP_GREATER_THAN\x10\x12\x12\x1e\n\x1aPROP_GREATER_THAN_OR_EQUAL\x10\x13\x12\x0f\n\x0bPROP_BEFORE\x10\x14\x12\x0e\n\nPROP_AFTER\x10\x15\x12\x10\n\x0cPROP_MATCHES\x10\x16\x12\x17\n\x13PROP_DOES_NOT_MATCH\x10\x17\x12\x19\n\x15PROP_SEMVER_LESS_THAN\x10\x18\x12\x15\n\x11PROP_SEMVER_EQUAL\x10\x19\x12\x1c\n\x18PROP_SEMVER_GREATER_THAN\x10\x1a\"\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\"\xd6\x02\n\x18\x43onfigEvaluationMetaData\x12\x1d\n\x10\x63onfig_row_index\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17\x63onditional_value_index\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12!\n\x14weighted_value_index\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12%\n\x04type\x18\x04 \x01(\x0e\x32\x12.prefab.ConfigTypeH\x03\x88\x01\x01\x12\x0f\n\x02id\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12\x31\n\nvalue_type\x18\x06 \x01(\x0e\x32\x18.prefab.Config.ValueTypeH\x05\x88\x01\x01\x42\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_indexB\x07\n\x05_typeB\x05\n\x03_idB\r\n\x0b_value_type\"\x8b\x03\n\x11\x43lientConfigValue\x12\r\n\x03int\x18\x01 \x01(\x03H\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x10\n\x06\x64ouble\x18\x03 \x01(\x01H\x00\x12\x0e\n\x04\x62ool\x18\x04 \x01(\x08H\x00\x12%\n\tlog_level\x18\x05 \x01(\x0e\x32\x10.prefab.LogLevelH\x00\x12)\n\x0bstring_list\x18\x07 \x01(\x0b\x32\x12.prefab.StringListH\x00\x12%\n\tint_range\x18\x08 \x01(\x0b\x32\x10.prefab.IntRangeH\x00\x12*\n\x08\x64uration\x18\t \x01(\x0b\x32\x16.prefab.ClientDurationH\x00\x12\x1c\n\x04json\x18\n \x01(\x0b\x32\x0c.prefab.JsonH\x00\x12I\n\x1a\x63onfig_evaluation_metadata\x18\x06 \x01(\x0b\x32 .prefab.ConfigEvaluationMetaDataH\x01\x88\x01\x01\x42\x06\n\x04typeB\x1d\n\x1b_config_evaluation_metadata\"D\n\x0e\x43lientDuration\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x12\x12\n\ndefinition\x18\x03 \x01(\t\"\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\"\x98\x02\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\x12/\n\x0e\x63ontext_shapes\x18\x06 \x01(\x0b\x32\x15.prefab.ContextShapesH\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\"}\n\x06Schema\x12\x0e\n\x06schema\x18\x01 \x01(\t\x12.\n\x0bschema_type\x18\x02 \x01(\x0e\x32\x19.prefab.Schema.SchemaType\"3\n\nSchemaType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03ZOD\x10\x01\x12\x0f\n\x0bJSON_SCHEMA\x10\x02*:\n\x0eProvidedSource\x12\x1b\n\x17PROVIDED_SOURCE_NOT_SET\x10\x00\x12\x0b\n\x07\x45NV_VAR\x10\x01*\xa0\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\x12\n\n\x06SCHEMA\x10\x07\x12\x10\n\x0cLOG_LEVEL_V2\x10\x08*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\x42L\n\x13\x63loud.prefab.domainB\x06PrefabZ-github.com/prefab-cloud/prefab-cloud-go/protob\x06proto3"
|
|
9
9
|
|
|
10
10
|
pool = ::Google::Protobuf::DescriptorPool.generated_pool
|
|
11
11
|
pool.add_serialized_file(descriptor_data)
|
data/lib/reforge/client.rb
CHANGED
|
@@ -53,6 +53,10 @@ module Reforge
|
|
|
53
53
|
@feature_flag_client ||= Reforge::FeatureFlagClient.new(self)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
+
def log_level_client
|
|
57
|
+
@log_level_client ||= Reforge::LogLevelClient.new(self)
|
|
58
|
+
end
|
|
59
|
+
|
|
56
60
|
def context_shape_aggregator
|
|
57
61
|
return nil if @options.collect_max_shapes <= 0
|
|
58
62
|
|
|
@@ -1,43 +1,173 @@
|
|
|
1
|
-
|
|
2
|
-
class InternalLogger < SemanticLogger::Logger
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
3
|
+
module Reforge
|
|
4
|
+
# Internal logger for the Reforge SDK
|
|
5
|
+
# Uses SemanticLogger if available, falls back to stdlib Logger
|
|
6
|
+
class InternalLogger
|
|
4
7
|
def initialize(klass)
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
@klass = klass
|
|
9
|
+
@level_sym = nil # Track the symbol level for consistency
|
|
10
|
+
|
|
11
|
+
if defined?(SemanticLogger)
|
|
12
|
+
@logger = create_semantic_logger
|
|
13
|
+
@using_semantic = true
|
|
14
|
+
else
|
|
15
|
+
@logger = create_stdlib_logger
|
|
16
|
+
@using_semantic = false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Track all instances regardless of logger type
|
|
7
20
|
instances << self
|
|
8
21
|
end
|
|
9
22
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
# Log methods
|
|
24
|
+
def trace(message = nil, &block)
|
|
25
|
+
log_message(:trace, message, &block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def debug(message = nil, &block)
|
|
29
|
+
log_message(:debug, message, &block)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def info(message = nil, &block)
|
|
33
|
+
log_message(:info, message, &block)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def warn(message = nil, &block)
|
|
37
|
+
log_message(:warn, message, &block)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def error(message = nil, &block)
|
|
41
|
+
log_message(:error, message, &block)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def fatal(message = nil, &block)
|
|
45
|
+
log_message(:fatal, message, &block)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def level
|
|
49
|
+
if @using_semantic
|
|
50
|
+
@logger.level
|
|
51
|
+
else
|
|
52
|
+
# Return the symbol level we tracked, or map from Logger constant
|
|
53
|
+
@level_sym || case @logger.level
|
|
54
|
+
when Logger::DEBUG then :debug
|
|
55
|
+
when Logger::INFO then :info
|
|
56
|
+
when Logger::WARN then :warn
|
|
57
|
+
when Logger::ERROR then :error
|
|
58
|
+
when Logger::FATAL then :fatal
|
|
59
|
+
else :warn
|
|
60
|
+
end
|
|
17
61
|
end
|
|
18
62
|
end
|
|
19
63
|
|
|
20
|
-
def
|
|
21
|
-
|
|
64
|
+
def level=(new_level)
|
|
65
|
+
if @using_semantic
|
|
66
|
+
@logger.level = new_level
|
|
67
|
+
else
|
|
68
|
+
# Track the symbol level for consistency
|
|
69
|
+
@level_sym = new_level
|
|
70
|
+
|
|
71
|
+
# Map symbol to Logger constant
|
|
72
|
+
@logger.level = case new_level
|
|
73
|
+
when :trace, :debug then Logger::DEBUG
|
|
74
|
+
when :info then Logger::INFO
|
|
75
|
+
when :warn then Logger::WARN
|
|
76
|
+
when :error then Logger::ERROR
|
|
77
|
+
when :fatal then Logger::FATAL
|
|
78
|
+
else Logger::WARN
|
|
79
|
+
end
|
|
80
|
+
end
|
|
22
81
|
end
|
|
23
82
|
|
|
24
83
|
# Our client outputs debug logging,
|
|
25
84
|
# but if you aren't using Reforge logging this could be too chatty.
|
|
26
85
|
# If you aren't using reforge log filter, only log warn level and above
|
|
27
86
|
def self.using_reforge_log_filter!
|
|
28
|
-
@@instances
|
|
29
|
-
|
|
87
|
+
@@instances&.each do |logger|
|
|
88
|
+
logger.level = :trace
|
|
30
89
|
end
|
|
31
90
|
end
|
|
32
91
|
|
|
33
92
|
private
|
|
34
93
|
|
|
35
|
-
def
|
|
36
|
-
|
|
94
|
+
def create_semantic_logger
|
|
95
|
+
default_level = env_log_level || :warn
|
|
96
|
+
logger = SemanticLogger::Logger.new(@klass, default_level)
|
|
97
|
+
|
|
98
|
+
# Wrap to prevent recursion
|
|
99
|
+
class << logger
|
|
100
|
+
def log(log, message = nil, progname = nil, &block)
|
|
101
|
+
return if recurse_check[local_log_id]
|
|
102
|
+
recurse_check[local_log_id] = true
|
|
103
|
+
begin
|
|
104
|
+
super(log, message, progname, &block)
|
|
105
|
+
ensure
|
|
106
|
+
recurse_check[local_log_id] = false
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def local_log_id
|
|
111
|
+
Thread.current.__id__
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def recurse_check
|
|
117
|
+
@recurse_check ||= Concurrent::Map.new(initial_capacity: 2)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
logger
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def create_stdlib_logger
|
|
125
|
+
require 'logger'
|
|
126
|
+
# When using stdlib Logger (no SemanticLogger), write to $stderr only
|
|
127
|
+
# Tests use $logs for SemanticLogger-filtered output, not stdlib Logger
|
|
128
|
+
logger = Logger.new($stderr)
|
|
129
|
+
|
|
130
|
+
# When SemanticLogger is not available, default to :warn to match SemanticLogger behavior
|
|
131
|
+
default_level_sym = :warn
|
|
132
|
+
@level_sym = env_log_level || default_level_sym
|
|
133
|
+
|
|
134
|
+
logger.level = case @level_sym
|
|
135
|
+
when :trace, :debug then Logger::DEBUG
|
|
136
|
+
when :info then Logger::INFO
|
|
137
|
+
when :warn then Logger::WARN
|
|
138
|
+
when :error then Logger::ERROR
|
|
139
|
+
when :fatal then Logger::FATAL
|
|
140
|
+
else Logger::WARN
|
|
141
|
+
end
|
|
142
|
+
logger.progname = @klass.to_s
|
|
143
|
+
|
|
144
|
+
# Use a custom formatter that mimics SemanticLogger format
|
|
145
|
+
# SemanticLogger format: "ClassName -- Message"
|
|
146
|
+
# This helps tests that expect SemanticLogger-style output
|
|
147
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
|
148
|
+
"#{progname} -- #{msg}\n"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
logger
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def env_log_level
|
|
155
|
+
level_str = ENV['REFORGE_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL']
|
|
156
|
+
level_str&.downcase&.to_sym
|
|
37
157
|
end
|
|
38
158
|
|
|
39
|
-
def
|
|
40
|
-
@
|
|
159
|
+
def log_message(level, message, &block)
|
|
160
|
+
if @using_semantic
|
|
161
|
+
@logger.send(level, message, &block)
|
|
162
|
+
else
|
|
163
|
+
# stdlib Logger doesn't have trace
|
|
164
|
+
level = :debug if level == :trace
|
|
165
|
+
@logger.send(level, message || block&.call)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def instances
|
|
170
|
+
@@instances ||= []
|
|
41
171
|
end
|
|
42
172
|
end
|
|
43
173
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Reforge
|
|
4
|
+
# Public LogLevel enum that maps to the underlying Prefab.Config.LogLevel
|
|
5
|
+
module LogLevel
|
|
6
|
+
TRACE = :trace
|
|
7
|
+
DEBUG = :debug
|
|
8
|
+
INFO = :info
|
|
9
|
+
WARN = :warn
|
|
10
|
+
ERROR = :error
|
|
11
|
+
FATAL = :fatal
|
|
12
|
+
|
|
13
|
+
# Map from PrefabProto::LogLevel enum symbols (uppercase) to our public LogLevel constants (lowercase)
|
|
14
|
+
# When unwrapped, the proto returns uppercase symbols like :INFO, :DEBUG, etc.
|
|
15
|
+
PROTO_SYMBOL_TO_LOG_LEVEL = {
|
|
16
|
+
:NOT_SET_LOG_LEVEL => DEBUG,
|
|
17
|
+
:TRACE => TRACE,
|
|
18
|
+
:DEBUG => DEBUG,
|
|
19
|
+
:INFO => INFO,
|
|
20
|
+
:WARN => WARN,
|
|
21
|
+
:ERROR => ERROR,
|
|
22
|
+
:FATAL => FATAL
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
# Map from PrefabProto::LogLevel enum integer values to our public LogLevel constants
|
|
26
|
+
PROTO_INT_TO_LOG_LEVEL = {
|
|
27
|
+
PrefabProto::LogLevel::NOT_SET_LOG_LEVEL => DEBUG,
|
|
28
|
+
PrefabProto::LogLevel::TRACE => TRACE,
|
|
29
|
+
PrefabProto::LogLevel::DEBUG => DEBUG,
|
|
30
|
+
PrefabProto::LogLevel::INFO => INFO,
|
|
31
|
+
PrefabProto::LogLevel::WARN => WARN,
|
|
32
|
+
PrefabProto::LogLevel::ERROR => ERROR,
|
|
33
|
+
PrefabProto::LogLevel::FATAL => FATAL
|
|
34
|
+
}.freeze
|
|
35
|
+
|
|
36
|
+
def self.from_proto(proto_log_level)
|
|
37
|
+
case proto_log_level
|
|
38
|
+
when Symbol
|
|
39
|
+
PROTO_SYMBOL_TO_LOG_LEVEL.fetch(proto_log_level, DEBUG)
|
|
40
|
+
when Integer
|
|
41
|
+
PROTO_INT_TO_LOG_LEVEL.fetch(proto_log_level, DEBUG)
|
|
42
|
+
else
|
|
43
|
+
DEBUG
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Reforge
|
|
4
|
+
class LogLevelClient
|
|
5
|
+
LOG = Reforge::InternalLogger.new(self)
|
|
6
|
+
|
|
7
|
+
# Map from our LogLevel symbols to SemanticLogger numeric severity levels
|
|
8
|
+
# SemanticLogger levels: trace=0, debug=1, info=2, warn=3, error=4, fatal=5
|
|
9
|
+
SEMANTIC_LOGGER_LEVELS = {
|
|
10
|
+
trace: 0,
|
|
11
|
+
debug: 1,
|
|
12
|
+
info: 2,
|
|
13
|
+
warn: 3,
|
|
14
|
+
error: 4,
|
|
15
|
+
fatal: 5
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
def initialize(base_client)
|
|
19
|
+
@base_client = base_client
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Map from Ruby stdlib Logger severity levels to our LogLevel symbols
|
|
23
|
+
# Ruby Logger levels: DEBUG=0, INFO=1, WARN=2, ERROR=3, FATAL=4, UNKNOWN=5
|
|
24
|
+
STDLIB_LOGGER_LEVELS = {
|
|
25
|
+
0 => :debug, # Logger::DEBUG
|
|
26
|
+
1 => :info, # Logger::INFO
|
|
27
|
+
2 => :warn, # Logger::WARN
|
|
28
|
+
3 => :error, # Logger::ERROR
|
|
29
|
+
4 => :fatal, # Logger::FATAL
|
|
30
|
+
5 => :fatal # Logger::UNKNOWN (treat as fatal)
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
# Check if a log message should be logged based on severity and logger path
|
|
34
|
+
# @param severity [Integer] Logger severity level (0-5 for SemanticLogger, 0-5 for stdlib Logger)
|
|
35
|
+
# @param path [String] Logger path/name
|
|
36
|
+
# @return [Boolean] true if the message should be logged
|
|
37
|
+
def should_log?(severity, path)
|
|
38
|
+
configured_level = get_log_level(path)
|
|
39
|
+
configured_severity = SEMANTIC_LOGGER_LEVELS[configured_level]
|
|
40
|
+
severity >= configured_severity
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# SemanticLogger filter integration
|
|
44
|
+
# @param log [SemanticLogger::Log] The log entry to filter
|
|
45
|
+
# @return [Boolean] true if the log should be output
|
|
46
|
+
# Note: This method requires semantic_logger gem to be installed
|
|
47
|
+
def semantic_filter(log)
|
|
48
|
+
unless defined?(SemanticLogger)
|
|
49
|
+
LOG.warn "semantic_filter called but SemanticLogger is not loaded. Install the 'semantic_logger' gem to use this feature."
|
|
50
|
+
return true # Allow all logs through if SemanticLogger is not available
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class_path = class_path_name(log.name)
|
|
54
|
+
level = SemanticLogger::Levels.index(log.level)
|
|
55
|
+
log.named_tags.merge!({ path: class_path })
|
|
56
|
+
should_log?(level, class_path)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Returns a formatter proc for use with Ruby stdlib Logger
|
|
60
|
+
# Usage:
|
|
61
|
+
# logger = Logger.new($stdout)
|
|
62
|
+
# logger.formatter = client.log_level_client.stdlib_formatter('MyApp')
|
|
63
|
+
# @param logger_name [String] The name/path of the logger
|
|
64
|
+
# @return [Proc] A formatter proc that respects dynamic log levels
|
|
65
|
+
def stdlib_formatter(logger_name)
|
|
66
|
+
proc do |severity, datetime, progname, msg|
|
|
67
|
+
# Convert Logger severity string to integer (DEBUG=0, INFO=1, WARN=2, ERROR=3, FATAL=4)
|
|
68
|
+
severity_int = case severity
|
|
69
|
+
when 'DEBUG' then 0
|
|
70
|
+
when 'INFO' then 1
|
|
71
|
+
when 'WARN' then 2
|
|
72
|
+
when 'ERROR' then 3
|
|
73
|
+
when 'FATAL', 'UNKNOWN' then 4
|
|
74
|
+
else 1
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Check if we should log this message
|
|
78
|
+
if should_log?(severity_int, logger_name)
|
|
79
|
+
# Default formatting
|
|
80
|
+
"[#{datetime.strftime('%Y-%m-%d %H:%M:%S.%L')}] #{severity} -- #{progname}: #{msg}\n"
|
|
81
|
+
else
|
|
82
|
+
nil # Don't output the log
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Get the log level for a given logger name
|
|
88
|
+
# Returns a LogLevel symbol (:trace, :debug, :info, :warn, :error, :fatal)
|
|
89
|
+
# Defaults to :debug if no config is found
|
|
90
|
+
def get_log_level(logger_name)
|
|
91
|
+
logger_key = @base_client.options.logger_key
|
|
92
|
+
|
|
93
|
+
# If logger key is explicitly set to nil or empty, return default
|
|
94
|
+
if logger_key.nil? || logger_key.empty?
|
|
95
|
+
LOG.debug "logger_key is nil or empty, returning default log level DEBUG"
|
|
96
|
+
return Reforge::LogLevel::DEBUG
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Create the evaluation context
|
|
100
|
+
context = {
|
|
101
|
+
"reforge-sdk-logging" => {
|
|
102
|
+
"lang" => "ruby",
|
|
103
|
+
"logger-path" => logger_name
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Get the raw config to check its type first
|
|
108
|
+
raw_config = @base_client.config_client.resolver.raw(logger_key)
|
|
109
|
+
|
|
110
|
+
if raw_config.nil?
|
|
111
|
+
LOG.debug "No raw config found for key '#{logger_key}', returning default DEBUG"
|
|
112
|
+
return Reforge::LogLevel::DEBUG
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Verify it's a LOG_LEVEL_V2 config
|
|
116
|
+
if raw_config.config_type != :LOG_LEVEL_V2
|
|
117
|
+
LOG.warn "Config '#{logger_key}' is not a LOG_LEVEL_V2 config (type: #{raw_config.config_type}), returning default DEBUG"
|
|
118
|
+
return Reforge::LogLevel::DEBUG
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
begin
|
|
122
|
+
# Evaluate the config with the context
|
|
123
|
+
evaluation = @base_client.config_client.send(:_get, logger_key, context)
|
|
124
|
+
|
|
125
|
+
if evaluation.nil?
|
|
126
|
+
LOG.debug "No log level config found for key '#{logger_key}', returning default DEBUG"
|
|
127
|
+
return Reforge::LogLevel::DEBUG
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Get the unwrapped value - this returns a PrefabProto::LogLevel enum value
|
|
131
|
+
proto_log_level = evaluation.report_and_return(@base_client.evaluation_summary_aggregator)
|
|
132
|
+
|
|
133
|
+
# Convert the proto LogLevel to our public LogLevel enum
|
|
134
|
+
Reforge::LogLevel.from_proto(proto_log_level)
|
|
135
|
+
rescue => e
|
|
136
|
+
LOG.warn "Error getting log level for '#{logger_name}': #{e.message}"
|
|
137
|
+
LOG.debug e.backtrace.join("\n")
|
|
138
|
+
Reforge::LogLevel::DEBUG
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
private
|
|
143
|
+
|
|
144
|
+
# Convert a logger class name to a path format
|
|
145
|
+
# e.g., "MyApp::MyClass" becomes "my_app.my_class"
|
|
146
|
+
def class_path_name(class_name)
|
|
147
|
+
begin
|
|
148
|
+
log_class = Object.const_get(class_name)
|
|
149
|
+
if log_class.respond_to?(:superclass) && log_class.superclass != Object
|
|
150
|
+
underscore("#{log_class.superclass.name}.#{log_class.name}")
|
|
151
|
+
else
|
|
152
|
+
underscore(log_class.name.to_s)
|
|
153
|
+
end.gsub(/[^a-z_]/i, '.')
|
|
154
|
+
rescue NameError
|
|
155
|
+
# If we can't resolve the constant, just underscore the name
|
|
156
|
+
underscore(class_name.to_s).gsub(/[^a-z_]/i, '.')
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Convert CamelCase to snake_case
|
|
161
|
+
def underscore(string)
|
|
162
|
+
string.gsub(/::/, '/').
|
|
163
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
|
164
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
|
165
|
+
tr("-", "_").
|
|
166
|
+
downcase
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
data/lib/reforge/options.rb
CHANGED
|
@@ -18,6 +18,7 @@ module Reforge
|
|
|
18
18
|
attr_reader :global_context
|
|
19
19
|
attr_accessor :is_fork
|
|
20
20
|
attr_reader :symbolize_json_names
|
|
21
|
+
attr_reader :logger_key
|
|
21
22
|
|
|
22
23
|
module ON_INITIALIZATION_FAILURE
|
|
23
24
|
RAISE = :raise
|
|
@@ -65,7 +66,8 @@ module Reforge
|
|
|
65
66
|
x_datafile: nil, # DEPRECATED in favor of `datafile`
|
|
66
67
|
x_use_local_cache: false,
|
|
67
68
|
symbolize_json_names: false,
|
|
68
|
-
global_context: {}
|
|
69
|
+
global_context: {},
|
|
70
|
+
logger_key: 'log-levels.default'
|
|
69
71
|
)
|
|
70
72
|
@sdk_key = sdk_key
|
|
71
73
|
@namespace = namespace
|
|
@@ -90,6 +92,7 @@ module Reforge
|
|
|
90
92
|
@is_fork = false
|
|
91
93
|
@global_context = global_context
|
|
92
94
|
@symbolize_json_names = symbolize_json_names
|
|
95
|
+
@logger_key = logger_key
|
|
93
96
|
|
|
94
97
|
# defaults that may be overridden by context_upload_mode
|
|
95
98
|
@collect_shapes = false
|
data/lib/reforge/reforge.rb
CHANGED
|
@@ -49,6 +49,13 @@ module Reforge
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def self.log_filter
|
|
52
|
+
unless defined?(SemanticLogger)
|
|
53
|
+
# SemanticLogger is optional - return a pass-through filter
|
|
54
|
+
# Only log debug message if explicitly enabled
|
|
55
|
+
LOG.debug 'log_filter called but SemanticLogger is not available. Install the semantic_logger gem to use this feature.' if ENV['REFORGE_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'] == 'debug'
|
|
56
|
+
return Proc.new { |log| true } # Pass through all logs
|
|
57
|
+
end
|
|
58
|
+
|
|
52
59
|
InternalLogger.using_reforge_log_filter!
|
|
53
60
|
return Proc.new do |log|
|
|
54
61
|
bootstrap_log_level(log)
|
|
@@ -60,6 +67,8 @@ module Reforge
|
|
|
60
67
|
end
|
|
61
68
|
|
|
62
69
|
def self.bootstrap_log_level(log)
|
|
70
|
+
return true unless defined?(SemanticLogger)
|
|
71
|
+
|
|
63
72
|
level = ENV['REFORGE_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'] ? ENV['REFORGE_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'].downcase.to_sym : :warn
|
|
64
73
|
SemanticLogger::Levels.index(level) <= SemanticLogger::Levels.index(log.level)
|
|
65
74
|
end
|
data/lib/sdk-reforge.rb
CHANGED
|
@@ -5,7 +5,12 @@ module Reforge
|
|
|
5
5
|
VERSION = File.read(File.dirname(__FILE__) + '/../VERSION').strip
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
begin
|
|
9
|
+
require 'semantic_logger'
|
|
10
|
+
rescue LoadError
|
|
11
|
+
# semantic_logger is optional - only needed for dynamic log level filtering
|
|
12
|
+
end
|
|
13
|
+
|
|
9
14
|
require 'reforge/internal_logger'
|
|
10
15
|
require 'concurrent/atomics'
|
|
11
16
|
require 'concurrent'
|
|
@@ -49,6 +54,8 @@ require 'reforge/client'
|
|
|
49
54
|
require 'reforge/config_client_presenter'
|
|
50
55
|
require 'reforge/config_client'
|
|
51
56
|
require 'reforge/feature_flag_client'
|
|
57
|
+
require 'reforge/log_level'
|
|
58
|
+
require 'reforge/log_level_client'
|
|
52
59
|
require 'reforge/reforge'
|
|
53
60
|
require 'reforge/murmer3'
|
|
54
61
|
require 'reforge/javascript_stub'
|
data/sdk-reforge.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: sdk-reforge 1.
|
|
5
|
+
# stub: sdk-reforge 1.12.0 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "sdk-reforge".freeze
|
|
9
|
-
s.version = "1.
|
|
9
|
+
s.version = "1.12.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 = "2025-10-
|
|
14
|
+
s.date = "2025-10-31"
|
|
15
15
|
s.description = "Feature Flags, Live Config as a service".freeze
|
|
16
16
|
s.email = "jeff.dwyer@reforge.com.cloud".freeze
|
|
17
17
|
s.extra_rdoc_files = [
|
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
|
20
20
|
"README.md"
|
|
21
21
|
]
|
|
22
22
|
s.files = [
|
|
23
|
+
".DS_Store",
|
|
23
24
|
".envrc.sample",
|
|
24
25
|
".github/CODEOWNERS",
|
|
25
26
|
".github/pull_request_template.md",
|
|
@@ -73,6 +74,8 @@ Gem::Specification.new do |s|
|
|
|
73
74
|
"lib/reforge/internal_logger.rb",
|
|
74
75
|
"lib/reforge/javascript_stub.rb",
|
|
75
76
|
"lib/reforge/local_config_parser.rb",
|
|
77
|
+
"lib/reforge/log_level.rb",
|
|
78
|
+
"lib/reforge/log_level_client.rb",
|
|
76
79
|
"lib/reforge/murmer3.rb",
|
|
77
80
|
"lib/reforge/options.rb",
|
|
78
81
|
"lib/reforge/periodic_sync.rb",
|
|
@@ -116,6 +119,7 @@ Gem::Specification.new do |s|
|
|
|
116
119
|
"test/test_internal_logger.rb",
|
|
117
120
|
"test/test_javascript_stub.rb",
|
|
118
121
|
"test/test_local_config_parser.rb",
|
|
122
|
+
"test/test_log_level_client.rb",
|
|
119
123
|
"test/test_logger_initialization.rb",
|
|
120
124
|
"test/test_options.rb",
|
|
121
125
|
"test/test_prefab.rb",
|
|
@@ -138,7 +142,6 @@ Gem::Specification.new do |s|
|
|
|
138
142
|
s.add_runtime_dependency(%q<ld-eventsource>.freeze, [">= 0"])
|
|
139
143
|
s.add_runtime_dependency(%q<uuid>.freeze, [">= 0"])
|
|
140
144
|
s.add_runtime_dependency(%q<activesupport>.freeze, [">= 4"])
|
|
141
|
-
s.add_runtime_dependency(%q<semantic_logger>.freeze, ["!= 4.16.0"])
|
|
142
145
|
s.add_development_dependency(%q<allocation_stats>.freeze, [">= 0"])
|
|
143
146
|
s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
|
144
147
|
s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
|
|
@@ -9,8 +9,11 @@ module CommonHelpers
|
|
|
9
9
|
$logs = StringIO.new
|
|
10
10
|
Reforge::Context.global_context.clear
|
|
11
11
|
Reforge::Context.default_context.clear
|
|
12
|
-
|
|
13
|
-
SemanticLogger
|
|
12
|
+
|
|
13
|
+
if defined?(SemanticLogger)
|
|
14
|
+
SemanticLogger.add_appender(io: $logs, filter: Reforge.log_filter)
|
|
15
|
+
SemanticLogger.sync!
|
|
16
|
+
end
|
|
14
17
|
end
|
|
15
18
|
|
|
16
19
|
def teardown
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class TestLogLevelClient < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
super
|
|
8
|
+
@options = Reforge::Options.new(
|
|
9
|
+
prefab_datasources: Reforge::Options::DATASOURCES::LOCAL_ONLY,
|
|
10
|
+
logger_key: 'test.log.level.key'
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
@client = Reforge::Client.new(@options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_get_log_level_returns_debug_when_no_config_exists
|
|
17
|
+
log_level = @client.log_level_client.get_log_level('MyApp::MyClass')
|
|
18
|
+
assert_equal :debug, log_level
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_get_log_level_with_log_level_v2_config
|
|
22
|
+
# Create a LOG_LEVEL_V2 config
|
|
23
|
+
config = PrefabProto::Config.new(
|
|
24
|
+
key: 'test.log.level.key',
|
|
25
|
+
id: 1,
|
|
26
|
+
config_type: PrefabProto::ConfigType::LOG_LEVEL_V2,
|
|
27
|
+
value_type: PrefabProto::Config::ValueType::LOG_LEVEL,
|
|
28
|
+
rows: [
|
|
29
|
+
PrefabProto::ConfigRow.new(
|
|
30
|
+
values: [
|
|
31
|
+
PrefabProto::ConditionalValue.new(
|
|
32
|
+
criteria: [
|
|
33
|
+
PrefabProto::Criterion.new(
|
|
34
|
+
operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
|
|
35
|
+
property_name: 'reforge-sdk-logging.logger-path',
|
|
36
|
+
value_to_match: PrefabProto::ConfigValue.new(
|
|
37
|
+
string_list: PrefabProto::StringList.new(values: ['MyApp::DebugClass'])
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
],
|
|
41
|
+
value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::DEBUG)
|
|
42
|
+
),
|
|
43
|
+
PrefabProto::ConditionalValue.new(
|
|
44
|
+
criteria: [
|
|
45
|
+
PrefabProto::Criterion.new(
|
|
46
|
+
operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
|
|
47
|
+
property_name: 'reforge-sdk-logging.logger-path',
|
|
48
|
+
value_to_match: PrefabProto::ConfigValue.new(
|
|
49
|
+
string_list: PrefabProto::StringList.new(values: ['MyApp::InfoClass'])
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
],
|
|
53
|
+
value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::INFO)
|
|
54
|
+
),
|
|
55
|
+
# Default case - WARN for everything else
|
|
56
|
+
PrefabProto::ConditionalValue.new(
|
|
57
|
+
value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::WARN)
|
|
58
|
+
)
|
|
59
|
+
]
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Load the config into the resolver
|
|
65
|
+
@client.config_client.resolver.instance_variable_get(:@config_loader).set(config, :test)
|
|
66
|
+
@client.config_client.resolver.update
|
|
67
|
+
|
|
68
|
+
# Test that we get DEBUG for MyApp::DebugClass
|
|
69
|
+
log_level = @client.log_level_client.get_log_level('MyApp::DebugClass')
|
|
70
|
+
assert_equal :debug, log_level
|
|
71
|
+
|
|
72
|
+
# Test that we get INFO for MyApp::InfoClass
|
|
73
|
+
log_level = @client.log_level_client.get_log_level('MyApp::InfoClass')
|
|
74
|
+
assert_equal :info, log_level
|
|
75
|
+
|
|
76
|
+
# Test that we get WARN for anything else (default)
|
|
77
|
+
log_level = @client.log_level_client.get_log_level('MyApp::OtherClass')
|
|
78
|
+
assert_equal :warn, log_level
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_get_log_level_with_all_log_levels
|
|
82
|
+
# Create a LOG_LEVEL_V2 config with all log levels
|
|
83
|
+
config = PrefabProto::Config.new(
|
|
84
|
+
key: 'test.log.level.key',
|
|
85
|
+
id: 1,
|
|
86
|
+
config_type: PrefabProto::ConfigType::LOG_LEVEL_V2,
|
|
87
|
+
value_type: PrefabProto::Config::ValueType::LOG_LEVEL,
|
|
88
|
+
rows: [
|
|
89
|
+
PrefabProto::ConfigRow.new(
|
|
90
|
+
values: [
|
|
91
|
+
PrefabProto::ConditionalValue.new(
|
|
92
|
+
criteria: [
|
|
93
|
+
PrefabProto::Criterion.new(
|
|
94
|
+
operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
|
|
95
|
+
property_name: 'reforge-sdk-logging.logger-path',
|
|
96
|
+
value_to_match: PrefabProto::ConfigValue.new(
|
|
97
|
+
string_list: PrefabProto::StringList.new(values: ['TraceLogger'])
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
],
|
|
101
|
+
value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::TRACE)
|
|
102
|
+
),
|
|
103
|
+
PrefabProto::ConditionalValue.new(
|
|
104
|
+
criteria: [
|
|
105
|
+
PrefabProto::Criterion.new(
|
|
106
|
+
operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
|
|
107
|
+
property_name: 'reforge-sdk-logging.logger-path',
|
|
108
|
+
value_to_match: PrefabProto::ConfigValue.new(
|
|
109
|
+
string_list: PrefabProto::StringList.new(values: ['ErrorLogger'])
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
],
|
|
113
|
+
value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::ERROR)
|
|
114
|
+
),
|
|
115
|
+
PrefabProto::ConditionalValue.new(
|
|
116
|
+
criteria: [
|
|
117
|
+
PrefabProto::Criterion.new(
|
|
118
|
+
operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
|
|
119
|
+
property_name: 'reforge-sdk-logging.logger-path',
|
|
120
|
+
value_to_match: PrefabProto::ConfigValue.new(
|
|
121
|
+
string_list: PrefabProto::StringList.new(values: ['FatalLogger'])
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
],
|
|
125
|
+
value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::FATAL)
|
|
126
|
+
)
|
|
127
|
+
]
|
|
128
|
+
)
|
|
129
|
+
]
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Load the config into the resolver
|
|
133
|
+
@client.config_client.resolver.instance_variable_get(:@config_loader).set(config, :test)
|
|
134
|
+
@client.config_client.resolver.update
|
|
135
|
+
|
|
136
|
+
# Test all log levels
|
|
137
|
+
assert_equal :trace, @client.log_level_client.get_log_level('TraceLogger')
|
|
138
|
+
assert_equal :error, @client.log_level_client.get_log_level('ErrorLogger')
|
|
139
|
+
assert_equal :fatal, @client.log_level_client.get_log_level('FatalLogger')
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def test_get_log_level_returns_debug_when_logger_key_is_nil
|
|
143
|
+
options = Reforge::Options.new(
|
|
144
|
+
prefab_datasources: Reforge::Options::DATASOURCES::LOCAL_ONLY,
|
|
145
|
+
logger_key: nil
|
|
146
|
+
)
|
|
147
|
+
client = Reforge::Client.new(options)
|
|
148
|
+
|
|
149
|
+
log_level = client.log_level_client.get_log_level('MyApp::MyClass')
|
|
150
|
+
assert_equal :debug, log_level
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def test_get_log_level_returns_debug_when_logger_key_is_empty
|
|
154
|
+
options = Reforge::Options.new(
|
|
155
|
+
prefab_datasources: Reforge::Options::DATASOURCES::LOCAL_ONLY,
|
|
156
|
+
logger_key: ''
|
|
157
|
+
)
|
|
158
|
+
client = Reforge::Client.new(options)
|
|
159
|
+
|
|
160
|
+
log_level = client.log_level_client.get_log_level('MyApp::MyClass')
|
|
161
|
+
assert_equal :debug, log_level
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_get_log_level_returns_debug_when_config_is_wrong_type
|
|
165
|
+
# Create a regular CONFIG type instead of LOG_LEVEL_V2
|
|
166
|
+
config = PrefabProto::Config.new(
|
|
167
|
+
key: 'test.log.level.key',
|
|
168
|
+
id: 1,
|
|
169
|
+
config_type: PrefabProto::ConfigType::CONFIG,
|
|
170
|
+
value_type: PrefabProto::Config::ValueType::STRING,
|
|
171
|
+
rows: [
|
|
172
|
+
PrefabProto::ConfigRow.new(
|
|
173
|
+
values: [
|
|
174
|
+
PrefabProto::ConditionalValue.new(
|
|
175
|
+
value: PrefabProto::ConfigValue.new(string: 'not a log level')
|
|
176
|
+
)
|
|
177
|
+
]
|
|
178
|
+
)
|
|
179
|
+
]
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Load the config into the resolver
|
|
183
|
+
@client.config_client.resolver.instance_variable_get(:@config_loader).set(config, :test)
|
|
184
|
+
@client.config_client.resolver.update
|
|
185
|
+
|
|
186
|
+
log_level = @client.log_level_client.get_log_level('MyApp::MyClass')
|
|
187
|
+
assert_equal :debug, log_level
|
|
188
|
+
assert_logged [/Config 'test.log.level.key' is not a LOG_LEVEL_V2 config/]
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_log_level_enum_from_proto
|
|
192
|
+
assert_equal :trace, Reforge::LogLevel.from_proto(PrefabProto::LogLevel::TRACE)
|
|
193
|
+
assert_equal :debug, Reforge::LogLevel.from_proto(PrefabProto::LogLevel::DEBUG)
|
|
194
|
+
assert_equal :info, Reforge::LogLevel.from_proto(PrefabProto::LogLevel::INFO)
|
|
195
|
+
assert_equal :warn, Reforge::LogLevel.from_proto(PrefabProto::LogLevel::WARN)
|
|
196
|
+
assert_equal :error, Reforge::LogLevel.from_proto(PrefabProto::LogLevel::ERROR)
|
|
197
|
+
assert_equal :fatal, Reforge::LogLevel.from_proto(PrefabProto::LogLevel::FATAL)
|
|
198
|
+
assert_equal :debug, Reforge::LogLevel.from_proto(PrefabProto::LogLevel::NOT_SET_LOG_LEVEL)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def test_default_logger_key
|
|
202
|
+
options = Reforge::Options.new(
|
|
203
|
+
prefab_datasources: Reforge::Options::DATASOURCES::LOCAL_ONLY
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
assert_equal 'log-levels.default', options.logger_key
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def test_should_log_with_different_severities
|
|
210
|
+
# Create a LOG_LEVEL_V2 config set to INFO
|
|
211
|
+
config = PrefabProto::Config.new(
|
|
212
|
+
key: 'test.log.level.key',
|
|
213
|
+
id: 1,
|
|
214
|
+
config_type: PrefabProto::ConfigType::LOG_LEVEL_V2,
|
|
215
|
+
value_type: PrefabProto::Config::ValueType::LOG_LEVEL,
|
|
216
|
+
rows: [
|
|
217
|
+
PrefabProto::ConfigRow.new(
|
|
218
|
+
values: [
|
|
219
|
+
PrefabProto::ConditionalValue.new(
|
|
220
|
+
value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::INFO)
|
|
221
|
+
)
|
|
222
|
+
]
|
|
223
|
+
)
|
|
224
|
+
]
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
@client.config_client.resolver.instance_variable_get(:@config_loader).set(config, :test)
|
|
228
|
+
@client.config_client.resolver.update
|
|
229
|
+
|
|
230
|
+
# SemanticLogger levels: trace=0, debug=1, info=2, warn=3, error=4, fatal=5
|
|
231
|
+
# With INFO level set, we should log INFO (2) and above, but not DEBUG (1) or TRACE (0)
|
|
232
|
+
assert_equal false, @client.log_level_client.should_log?(0, 'MyApp::MyClass'), 'TRACE should not log'
|
|
233
|
+
assert_equal false, @client.log_level_client.should_log?(1, 'MyApp::MyClass'), 'DEBUG should not log'
|
|
234
|
+
assert_equal true, @client.log_level_client.should_log?(2, 'MyApp::MyClass'), 'INFO should log'
|
|
235
|
+
assert_equal true, @client.log_level_client.should_log?(3, 'MyApp::MyClass'), 'WARN should log'
|
|
236
|
+
assert_equal true, @client.log_level_client.should_log?(4, 'MyApp::MyClass'), 'ERROR should log'
|
|
237
|
+
assert_equal true, @client.log_level_client.should_log?(5, 'MyApp::MyClass'), 'FATAL should log'
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def test_class_path_name_conversion
|
|
241
|
+
client = @client.log_level_client
|
|
242
|
+
|
|
243
|
+
# Test underscore conversion
|
|
244
|
+
assert_equal 'my_app.my_class', client.send(:class_path_name, 'MyApp::MyClass')
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def test_underscore
|
|
248
|
+
client = @client.log_level_client
|
|
249
|
+
|
|
250
|
+
assert_equal 'my_app/my_class', client.send(:underscore, 'MyApp::MyClass')
|
|
251
|
+
assert_equal 'html_parser', client.send(:underscore, 'HTMLParser')
|
|
252
|
+
assert_equal 'my_simple_class', client.send(:underscore, 'MySimpleClass')
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def test_semantic_logger_levels_mapping
|
|
256
|
+
# Verify our SEMANTIC_LOGGER_LEVELS constant matches expectations
|
|
257
|
+
assert_equal 0, Reforge::LogLevelClient::SEMANTIC_LOGGER_LEVELS[:trace]
|
|
258
|
+
assert_equal 1, Reforge::LogLevelClient::SEMANTIC_LOGGER_LEVELS[:debug]
|
|
259
|
+
assert_equal 2, Reforge::LogLevelClient::SEMANTIC_LOGGER_LEVELS[:info]
|
|
260
|
+
assert_equal 3, Reforge::LogLevelClient::SEMANTIC_LOGGER_LEVELS[:warn]
|
|
261
|
+
assert_equal 4, Reforge::LogLevelClient::SEMANTIC_LOGGER_LEVELS[:error]
|
|
262
|
+
assert_equal 5, Reforge::LogLevelClient::SEMANTIC_LOGGER_LEVELS[:fatal]
|
|
263
|
+
end
|
|
264
|
+
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sdk-reforge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeff Dwyer
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2025-10-
|
|
10
|
+
date: 2025-10-31 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: concurrent-ruby
|
|
@@ -113,20 +113,6 @@ dependencies:
|
|
|
113
113
|
- - ">="
|
|
114
114
|
- !ruby/object:Gem::Version
|
|
115
115
|
version: '4'
|
|
116
|
-
- !ruby/object:Gem::Dependency
|
|
117
|
-
name: semantic_logger
|
|
118
|
-
requirement: !ruby/object:Gem::Requirement
|
|
119
|
-
requirements:
|
|
120
|
-
- - "!="
|
|
121
|
-
- !ruby/object:Gem::Version
|
|
122
|
-
version: 4.16.0
|
|
123
|
-
type: :runtime
|
|
124
|
-
prerelease: false
|
|
125
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
126
|
-
requirements:
|
|
127
|
-
- - "!="
|
|
128
|
-
- !ruby/object:Gem::Version
|
|
129
|
-
version: 4.16.0
|
|
130
116
|
- !ruby/object:Gem::Dependency
|
|
131
117
|
name: allocation_stats
|
|
132
118
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -220,6 +206,7 @@ extra_rdoc_files:
|
|
|
220
206
|
- LICENSE.txt
|
|
221
207
|
- README.md
|
|
222
208
|
files:
|
|
209
|
+
- ".DS_Store"
|
|
223
210
|
- ".envrc.sample"
|
|
224
211
|
- ".github/CODEOWNERS"
|
|
225
212
|
- ".github/pull_request_template.md"
|
|
@@ -273,6 +260,8 @@ files:
|
|
|
273
260
|
- lib/reforge/internal_logger.rb
|
|
274
261
|
- lib/reforge/javascript_stub.rb
|
|
275
262
|
- lib/reforge/local_config_parser.rb
|
|
263
|
+
- lib/reforge/log_level.rb
|
|
264
|
+
- lib/reforge/log_level_client.rb
|
|
276
265
|
- lib/reforge/murmer3.rb
|
|
277
266
|
- lib/reforge/options.rb
|
|
278
267
|
- lib/reforge/periodic_sync.rb
|
|
@@ -316,6 +305,7 @@ files:
|
|
|
316
305
|
- test/test_internal_logger.rb
|
|
317
306
|
- test/test_javascript_stub.rb
|
|
318
307
|
- test/test_local_config_parser.rb
|
|
308
|
+
- test/test_log_level_client.rb
|
|
319
309
|
- test/test_logger_initialization.rb
|
|
320
310
|
- test/test_options.rb
|
|
321
311
|
- test/test_prefab.rb
|