smplkit 3.0.96 → 3.0.97
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/lib/smplkit/account/client.rb +9 -2
- data/lib/smplkit/account/models.rb +18 -0
- data/lib/smplkit/api_support.rb +8 -0
- data/lib/smplkit/audit/buffer.rb +3 -1
- data/lib/smplkit/audit/categories.rb +21 -10
- data/lib/smplkit/audit/client.rb +16 -6
- data/lib/smplkit/audit/event_types.rb +26 -10
- data/lib/smplkit/audit/events.rb +93 -17
- data/lib/smplkit/audit/forwarders.rb +27 -16
- data/lib/smplkit/audit/models.rb +46 -31
- data/lib/smplkit/audit/resource_types.rb +21 -9
- data/lib/smplkit/buffers.rb +15 -0
- data/lib/smplkit/client.rb +38 -6
- data/lib/smplkit/config/client.rb +279 -26
- data/lib/smplkit/config/helpers.rb +44 -6
- data/lib/smplkit/config/models.rb +114 -7
- data/lib/smplkit/config_resolution.rb +6 -4
- data/lib/smplkit/errors.rb +6 -3
- data/lib/smplkit/flags/client.rb +135 -7
- data/lib/smplkit/flags/models.rb +110 -8
- data/lib/smplkit/flags/types.rb +2 -2
- data/lib/smplkit/jobs/client.rb +47 -26
- data/lib/smplkit/jobs/models.rb +47 -18
- data/lib/smplkit/logging/client.rb +125 -16
- data/lib/smplkit/logging/helpers.rb +4 -1
- data/lib/smplkit/logging/levels.rb +3 -1
- data/lib/smplkit/logging/models.rb +71 -5
- data/lib/smplkit/logging/normalize.rb +3 -1
- data/lib/smplkit/logging/resolution.rb +4 -4
- data/lib/smplkit/platform/client.rb +132 -7
- data/lib/smplkit/platform/models.rb +103 -3
- data/lib/smplkit/platform/types.rb +14 -0
- data/lib/smplkit/transport.rb +5 -1
- data/lib/smplkit/ws.rb +1 -1
- metadata +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Smpl Logging has two surfaces on a single client, mirroring how the config,
|
|
6
6
|
# flags, audit, and jobs clients expose their full surface from one class:
|
|
7
7
|
#
|
|
8
|
-
# * *
|
|
8
|
+
# * *CRUD surface* — works immediately, no +install+ required. Two
|
|
9
9
|
# sub-clients (the audit pattern):
|
|
10
10
|
#
|
|
11
11
|
# * +client.logging.loggers+ — logger CRUD + discovery: +new+ / +list+ / +get+
|
|
@@ -47,15 +47,17 @@ module Smplkit
|
|
|
47
47
|
# defaults). The app transport is needed for the WebSocket gateway, which
|
|
48
48
|
# lives on the app service (like flags); the app base URL is returned so a
|
|
49
49
|
# standalone client can open its own WebSocket against the event gateway.
|
|
50
|
+
#
|
|
51
|
+
# @api private
|
|
50
52
|
def self.logging_transport(api_key:, base_url:, profile:, base_domain:, scheme:, debug:, extra_headers:)
|
|
51
|
-
cfg = ConfigResolution.
|
|
53
|
+
cfg = ConfigResolution.resolve_client_config(
|
|
52
54
|
profile: profile, api_key: api_key, base_domain: base_domain, scheme: scheme, debug: debug
|
|
53
55
|
)
|
|
54
56
|
resolved_key = api_key.nil? ? cfg.api_key : api_key
|
|
55
57
|
merged = {}
|
|
56
58
|
merged.merge!(cfg.extra_headers || {})
|
|
57
59
|
merged.merge!(extra_headers || {})
|
|
58
|
-
tcfg = ConfigResolution::
|
|
60
|
+
tcfg = ConfigResolution::ResolvedClientConfig.new(
|
|
59
61
|
api_key: resolved_key, base_domain: cfg.base_domain, scheme: cfg.scheme,
|
|
60
62
|
debug: cfg.debug, extra_headers: merged
|
|
61
63
|
)
|
|
@@ -66,6 +68,8 @@ module Smplkit
|
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
# Discover and load the SDK's built-in logging adapters.
|
|
71
|
+
#
|
|
72
|
+
# @api private
|
|
69
73
|
def self.auto_load_adapters
|
|
70
74
|
adapters = [Adapters::StdlibLoggerAdapter.new]
|
|
71
75
|
|
|
@@ -80,10 +84,20 @@ module Smplkit
|
|
|
80
84
|
adapters
|
|
81
85
|
end
|
|
82
86
|
|
|
83
|
-
|
|
87
|
+
# Fired once per managed logger whose effective level the SDK just applied.
|
|
88
|
+
#
|
|
89
|
+
# @!attribute [rw] id
|
|
90
|
+
# @return [String] The affected logger's normalized id.
|
|
91
|
+
# @!attribute [rw] level
|
|
92
|
+
# @return [String] The newly-applied effective smplkit level string (e.g.
|
|
93
|
+
# +"INFO"+, +"DEBUG"+) — the same value the resolution algorithm returns.
|
|
94
|
+
# @!attribute [rw] source
|
|
95
|
+
# @return [String] Short string identifying the trigger — typically
|
|
96
|
+
# +"websocket"+ or +"manual"+ (a +refresh+ call).
|
|
97
|
+
LoggerChangeEvent = Struct.new(:id, :level, :source, keyword_init: true) do
|
|
84
98
|
def ==(other)
|
|
85
99
|
other.is_a?(LoggerChangeEvent) &&
|
|
86
|
-
|
|
100
|
+
id == other.id && level == other.level && source == other.source
|
|
87
101
|
end
|
|
88
102
|
end
|
|
89
103
|
|
|
@@ -98,7 +112,17 @@ module Smplkit
|
|
|
98
112
|
@buffer = buffer
|
|
99
113
|
end
|
|
100
114
|
|
|
101
|
-
#
|
|
115
|
+
# Queue one or more logger sources for registration with the server.
|
|
116
|
+
#
|
|
117
|
+
# Sources are buffered locally and sent in a batch. The batch is sent
|
|
118
|
+
# automatically once enough sources accumulate; pass +flush: true+ to send
|
|
119
|
+
# the current batch right away instead of waiting.
|
|
120
|
+
#
|
|
121
|
+
# @param items [LoggerSource, Array<LoggerSource>] A single logger source,
|
|
122
|
+
# or an array of them, to queue.
|
|
123
|
+
# @param flush [Boolean] When +true+, send the buffered sources immediately
|
|
124
|
+
# rather than waiting for the batch to fill.
|
|
125
|
+
# @return [void]
|
|
102
126
|
def register(items, flush: false)
|
|
103
127
|
batch = items.is_a?(Array) ? items : [items]
|
|
104
128
|
batch.each do |src|
|
|
@@ -118,6 +142,8 @@ module Smplkit
|
|
|
118
142
|
end
|
|
119
143
|
|
|
120
144
|
# Drain the buffer and POST pending logger sources to the bulk endpoint.
|
|
145
|
+
#
|
|
146
|
+
# @return [void]
|
|
121
147
|
def flush
|
|
122
148
|
batch = @buffer.drain
|
|
123
149
|
return if batch.empty?
|
|
@@ -133,21 +159,38 @@ module Smplkit
|
|
|
133
159
|
end
|
|
134
160
|
|
|
135
161
|
# Synchronous flush — alias of +flush+ for the periodic-flush path.
|
|
162
|
+
#
|
|
163
|
+
# @return [void]
|
|
136
164
|
def flush_sync
|
|
137
165
|
flush
|
|
138
166
|
end
|
|
139
167
|
|
|
140
168
|
# Number of sources queued and awaiting flush.
|
|
169
|
+
#
|
|
170
|
+
# @return [Integer] count of buffered sources not yet sent.
|
|
141
171
|
def pending_count
|
|
142
172
|
@buffer.pending_count
|
|
143
173
|
end
|
|
144
174
|
|
|
145
|
-
#
|
|
175
|
+
# Build a new unsaved logger. The returned +SmplLogger+ is local only;
|
|
176
|
+
# call its +SmplLogger#save+ to persist it.
|
|
177
|
+
#
|
|
178
|
+
# @param id [String] Identifier for the logger (its normalized name).
|
|
179
|
+
# @param managed [Boolean] When +true+ (the default), smplkit controls
|
|
180
|
+
# this logger's level at runtime. Set +false+ to register the logger for
|
|
181
|
+
# visibility without taking over its level.
|
|
182
|
+
# @return [SmplLogger] An unsaved logger bound to this client.
|
|
146
183
|
def new(id, managed: true)
|
|
147
184
|
SmplLogger.new(self, id: id, name: id, resolved_level: nil, managed: managed)
|
|
148
185
|
end
|
|
149
186
|
|
|
150
187
|
# List loggers for the authenticated account.
|
|
188
|
+
#
|
|
189
|
+
# @param page_number [Integer, nil] 1-based page index to fetch. When
|
|
190
|
+
# omitted, the server returns the first page.
|
|
191
|
+
# @param page_size [Integer, nil] Maximum number of loggers per page. When
|
|
192
|
+
# omitted, the server applies its default page size.
|
|
193
|
+
# @return [Array<SmplLogger>] The loggers on the requested page.
|
|
151
194
|
def list(page_number: nil, page_size: nil)
|
|
152
195
|
opts = {}
|
|
153
196
|
opts[:page_number] = page_number unless page_number.nil?
|
|
@@ -156,18 +199,27 @@ module Smplkit
|
|
|
156
199
|
(response.data || []).map { |r| Helpers.logger_resource_to_model(self, ApiSupport::ResourceShim.from_model(r)) }
|
|
157
200
|
end
|
|
158
201
|
|
|
159
|
-
# Fetch
|
|
202
|
+
# Fetch a single logger by id.
|
|
203
|
+
#
|
|
204
|
+
# @param id [String] Identifier of the logger to fetch.
|
|
205
|
+
# @return [SmplLogger] The editable logger resource.
|
|
206
|
+
# @raise [Smplkit::NotFoundError] If no logger with that id exists.
|
|
160
207
|
def get(id)
|
|
161
208
|
response = ApiSupport::ErrorMapping.call { @api.get_logger(id) }
|
|
162
209
|
Helpers.logger_resource_to_model(self, ApiSupport::ResourceShim.from_model(response.data))
|
|
163
210
|
end
|
|
164
211
|
|
|
165
212
|
# Delete a logger by id.
|
|
213
|
+
#
|
|
214
|
+
# @param id [String] Identifier of the logger to delete.
|
|
215
|
+
# @return [void]
|
|
216
|
+
# @raise [Smplkit::NotFoundError] If no logger with that id exists.
|
|
166
217
|
def delete(id)
|
|
167
218
|
ApiSupport::ErrorMapping.call { @api.delete_logger(id) }
|
|
168
219
|
nil
|
|
169
220
|
end
|
|
170
221
|
|
|
222
|
+
# @api private
|
|
171
223
|
def _update_logger(logger)
|
|
172
224
|
response = ApiSupport::ErrorMapping.call { @api.update_logger(logger.id || logger.name, logger_body(logger)) }
|
|
173
225
|
Helpers.logger_resource_to_model(self, ApiSupport::ResourceShim.from_model(response.data))
|
|
@@ -175,6 +227,8 @@ module Smplkit
|
|
|
175
227
|
|
|
176
228
|
# Runtime entry — walks every page and returns an id-keyed Hash of
|
|
177
229
|
# resolution-cache entries (+level+, +group+, +managed+, +environments+).
|
|
230
|
+
#
|
|
231
|
+
# @api private
|
|
178
232
|
def list_logger_entries
|
|
179
233
|
rows = ApiSupport::PaginatedFetch.collect { |opts| @api.list_loggers(opts) }
|
|
180
234
|
rows.to_h { |r| logger_entry_from_resource(ApiSupport::ResourceShim.from_model(r)) }
|
|
@@ -182,6 +236,8 @@ module Smplkit
|
|
|
182
236
|
|
|
183
237
|
# Fetch one logger as a resolution-cache entry. Used by the +logger_changed+
|
|
184
238
|
# WS handler.
|
|
239
|
+
#
|
|
240
|
+
# @api private
|
|
185
241
|
def get_logger_entry(id)
|
|
186
242
|
response = ApiSupport::ErrorMapping.call { @api.get_logger(id) }
|
|
187
243
|
logger_entry_from_resource(ApiSupport::ResourceShim.from_model(response.data))
|
|
@@ -236,14 +292,28 @@ module Smplkit
|
|
|
236
292
|
@api = SmplkitGeneratedClient::Logging::LogGroupsApi.new(http_client)
|
|
237
293
|
end
|
|
238
294
|
|
|
239
|
-
#
|
|
295
|
+
# Build a new unsaved log group. The returned +SmplLogGroup+ is local
|
|
296
|
+
# only; call its +SmplLogGroup#save+ to persist it.
|
|
297
|
+
#
|
|
298
|
+
# @param id [String] Identifier for the log group.
|
|
299
|
+
# @param name [String, nil] Human-readable display name. Defaults to a
|
|
300
|
+
# title-cased version of +id+ when omitted.
|
|
301
|
+
# @param group [String, nil] Identifier of the parent log group, when
|
|
302
|
+
# nesting groups. +nil+ for a top-level group.
|
|
303
|
+
# @return [SmplLogGroup] An unsaved log group bound to this client.
|
|
240
304
|
def new(id, name: nil, group: nil)
|
|
241
305
|
SmplLogGroup.new(
|
|
242
|
-
self, key: id, name: name.nil? ? Smplkit::Helpers.key_to_display_name(id) : name,
|
|
306
|
+
self, key: id, name: name.nil? ? Smplkit::Helpers.key_to_display_name(id) : name, group: group
|
|
243
307
|
)
|
|
244
308
|
end
|
|
245
309
|
|
|
246
310
|
# List log groups for the authenticated account.
|
|
311
|
+
#
|
|
312
|
+
# @param page_number [Integer, nil] 1-based page index to fetch. When
|
|
313
|
+
# omitted, the server returns the first page.
|
|
314
|
+
# @param page_size [Integer, nil] Maximum number of log groups per page.
|
|
315
|
+
# When omitted, the server applies its default page size.
|
|
316
|
+
# @return [Array<SmplLogGroup>] The log groups on the requested page.
|
|
247
317
|
def list(page_number: nil, page_size: nil)
|
|
248
318
|
opts = {}
|
|
249
319
|
opts[:page_number] = page_number unless page_number.nil?
|
|
@@ -254,23 +324,33 @@ module Smplkit
|
|
|
254
324
|
end
|
|
255
325
|
end
|
|
256
326
|
|
|
257
|
-
# Fetch
|
|
327
|
+
# Fetch a single log group by id.
|
|
328
|
+
#
|
|
329
|
+
# @param id [String] Identifier of the log group to fetch.
|
|
330
|
+
# @return [SmplLogGroup] The editable log group resource.
|
|
331
|
+
# @raise [Smplkit::NotFoundError] If no log group with that id exists.
|
|
258
332
|
def get(id)
|
|
259
333
|
response = ApiSupport::ErrorMapping.call { @api.get_log_group(id) }
|
|
260
334
|
Helpers.log_group_resource_to_model(self, ApiSupport::ResourceShim.from_model(response.data))
|
|
261
335
|
end
|
|
262
336
|
|
|
263
337
|
# Delete a log group by id.
|
|
338
|
+
#
|
|
339
|
+
# @param id [String] Identifier of the log group to delete.
|
|
340
|
+
# @return [void]
|
|
341
|
+
# @raise [Smplkit::NotFoundError] If no log group with that id exists.
|
|
264
342
|
def delete(id)
|
|
265
343
|
ApiSupport::ErrorMapping.call { @api.delete_log_group(id) }
|
|
266
344
|
nil
|
|
267
345
|
end
|
|
268
346
|
|
|
347
|
+
# @api private
|
|
269
348
|
def _create_log_group(group)
|
|
270
349
|
response = ApiSupport::ErrorMapping.call { @api.create_log_group(log_group_body(group)) }
|
|
271
350
|
Helpers.log_group_resource_to_model(self, ApiSupport::ResourceShim.from_model(response.data))
|
|
272
351
|
end
|
|
273
352
|
|
|
353
|
+
# @api private
|
|
274
354
|
def _update_log_group(group)
|
|
275
355
|
response = ApiSupport::ErrorMapping.call { @api.update_log_group(group.key, log_group_body(group)) }
|
|
276
356
|
Helpers.log_group_resource_to_model(self, ApiSupport::ResourceShim.from_model(response.data))
|
|
@@ -280,11 +360,17 @@ module Smplkit
|
|
|
280
360
|
# resolution-cache entries (+level+, +group+, +environments+). The +group+
|
|
281
361
|
# key carries the *parent group id* so the resolution algorithm can walk
|
|
282
362
|
# the chain with the same key shape it uses for loggers.
|
|
363
|
+
#
|
|
364
|
+
# @api private
|
|
283
365
|
def list_group_entries
|
|
284
366
|
rows = ApiSupport::PaginatedFetch.collect { |opts| @api.list_log_groups(opts) }
|
|
285
367
|
rows.to_h { |r| group_entry_from_resource(ApiSupport::ResourceShim.from_model(r)) }
|
|
286
368
|
end
|
|
287
369
|
|
|
370
|
+
# Fetch one log group as a resolution-cache entry. Used by the
|
|
371
|
+
# +group_changed+ WS handler.
|
|
372
|
+
#
|
|
373
|
+
# @api private
|
|
288
374
|
def get_group_entry(key)
|
|
289
375
|
response = ApiSupport::ErrorMapping.call { @api.get_log_group(key) }
|
|
290
376
|
group_entry_from_resource(ApiSupport::ResourceShim.from_model(response.data))
|
|
@@ -305,7 +391,7 @@ module Smplkit
|
|
|
305
391
|
end
|
|
306
392
|
|
|
307
393
|
def log_group_body(group)
|
|
308
|
-
# LogGroup server schema: name, level, parent_id (no description).
|
|
394
|
+
# LogGroup server schema: name, level, parent_id, environments (no description).
|
|
309
395
|
SmplkitGeneratedClient::Logging::LogGroupResponse.new(
|
|
310
396
|
data: SmplkitGeneratedClient::Logging::LogGroupResource.new(
|
|
311
397
|
type: "log_group",
|
|
@@ -313,7 +399,8 @@ module Smplkit
|
|
|
313
399
|
attributes: SmplkitGeneratedClient::Logging::LogGroup.new(
|
|
314
400
|
name: group.name,
|
|
315
401
|
level: group.level&.to_s,
|
|
316
|
-
parent_id: group.
|
|
402
|
+
parent_id: group.group,
|
|
403
|
+
environments: Logging.environments_to_wire(group.environments)
|
|
317
404
|
)
|
|
318
405
|
)
|
|
319
406
|
)
|
|
@@ -329,7 +416,7 @@ module Smplkit
|
|
|
329
416
|
# logging.loggers.new("sqlalchemy.engine").save
|
|
330
417
|
# logging.install
|
|
331
418
|
#
|
|
332
|
-
# The
|
|
419
|
+
# The CRUD surface (+loggers+ / +log_groups+ sub-clients) works
|
|
333
420
|
# immediately. +register_adapter+ is a pre-install configuration call. The
|
|
334
421
|
# live surface (+install+ / +on_change+ / +refresh+) requires +install+
|
|
335
422
|
# first; calling +on_change+ / +refresh+ earlier raises +NotInstalledError+.
|
|
@@ -392,6 +479,10 @@ module Smplkit
|
|
|
392
479
|
self
|
|
393
480
|
end
|
|
394
481
|
|
|
482
|
+
# Registered logging adapters.
|
|
483
|
+
#
|
|
484
|
+
# @return [Array<Adapters::Base>] a copy of the adapters this client uses
|
|
485
|
+
# to discover loggers and apply levels.
|
|
395
486
|
def adapters
|
|
396
487
|
@adapters.dup
|
|
397
488
|
end
|
|
@@ -510,9 +601,27 @@ module Smplkit
|
|
|
510
601
|
end
|
|
511
602
|
@connected = false
|
|
512
603
|
end
|
|
604
|
+
|
|
605
|
+
# Release resources held by this client.
|
|
606
|
+
#
|
|
607
|
+
# @api private
|
|
608
|
+
# @return [void]
|
|
513
609
|
alias _close close
|
|
514
610
|
|
|
515
|
-
# Construct
|
|
611
|
+
# Construct a +LoggingClient+, yield it to the block, and close it on exit.
|
|
612
|
+
#
|
|
613
|
+
# Mirrors Ruby's +File.open+ block form: the client is closed
|
|
614
|
+
# automatically when the block returns or raises, so a standalone client's
|
|
615
|
+
# owned transports and WebSocket are always torn down.
|
|
616
|
+
#
|
|
617
|
+
# Smplkit::LoggingClient.open(environment: "production") do |logging|
|
|
618
|
+
# logging.loggers.new("sqlalchemy.engine").save
|
|
619
|
+
# logging.install
|
|
620
|
+
# end
|
|
621
|
+
#
|
|
622
|
+
# @param kwargs [Hash] keyword arguments forwarded to +new+.
|
|
623
|
+
# @yieldparam client [LoggingClient] the constructed client.
|
|
624
|
+
# @return [Object] the block's return value.
|
|
516
625
|
def self.open(**kwargs)
|
|
517
626
|
client = new(**kwargs)
|
|
518
627
|
begin
|
|
@@ -679,7 +788,7 @@ module Smplkit
|
|
|
679
788
|
# Both the key-scoped listeners registered for +logger_id+ and every global
|
|
680
789
|
# listener receive the same payload.
|
|
681
790
|
def fire_for_logger(logger_id, level, source)
|
|
682
|
-
event = LoggerChangeEvent.new(
|
|
791
|
+
event = LoggerChangeEvent.new(id: logger_id, level: level, source: source)
|
|
683
792
|
(@global_listeners + @key_listeners[logger_id]).each do |cb|
|
|
684
793
|
cb.call(event)
|
|
685
794
|
rescue StandardError => e
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Smplkit
|
|
4
4
|
module Logging
|
|
5
|
+
# Resource-to-model conversion helpers for the logging wrapper.
|
|
6
|
+
#
|
|
7
|
+
# @api private
|
|
5
8
|
module Helpers
|
|
6
9
|
module_function
|
|
7
10
|
|
|
@@ -33,7 +36,7 @@ module Smplkit
|
|
|
33
36
|
name: attrs["name"],
|
|
34
37
|
level: attrs["level"] && LogLevel.coerce(attrs["level"]),
|
|
35
38
|
description: attrs["description"],
|
|
36
|
-
|
|
39
|
+
group: attrs["parent_id"],
|
|
37
40
|
environments: attrs["environments"] || {},
|
|
38
41
|
created_at: attrs["created_at"],
|
|
39
42
|
updated_at: attrs["updated_at"]
|
|
@@ -6,7 +6,7 @@ require_relative "../log_level"
|
|
|
6
6
|
module Smplkit
|
|
7
7
|
module Logging
|
|
8
8
|
# Bidirectional mapping between Ruby stdlib +Logger+ levels and smplkit
|
|
9
|
-
# canonical levels
|
|
9
|
+
# canonical levels.
|
|
10
10
|
#
|
|
11
11
|
# Stdlib +Logger+ has DEBUG/INFO/WARN/ERROR/FATAL/UNKNOWN — no TRACE. The
|
|
12
12
|
# +stdlib-logger+ adapter maps smplkit TRACE to stdlib DEBUG when
|
|
@@ -14,6 +14,8 @@ module Smplkit
|
|
|
14
14
|
# discovering — there is no way to distinguish smplkit-TRACE-mapped-to-
|
|
15
15
|
# DEBUG from genuine DEBUG, which is consistent with how the Python
|
|
16
16
|
# +stdlib-logging+ adapter handles the same gap.
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
17
19
|
module Levels
|
|
18
20
|
STDLIB_TO_SMPL = {
|
|
19
21
|
::Logger::DEBUG => LogLevel::DEBUG,
|
|
@@ -21,6 +21,8 @@ module Smplkit
|
|
|
21
21
|
#
|
|
22
22
|
# Accepts both pre-built +LoggerEnvironment+ instances and the wire-shaped
|
|
23
23
|
# +{env_id => {"level" => "ERROR"}}+ dicts.
|
|
24
|
+
#
|
|
25
|
+
# @api private
|
|
24
26
|
def self.convert_environments(value)
|
|
25
27
|
return {} if value.nil? || value.empty?
|
|
26
28
|
|
|
@@ -29,6 +31,7 @@ module Smplkit
|
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
34
|
+
# @api private
|
|
32
35
|
def self.build_logger_environment(env_data)
|
|
33
36
|
return env_data if env_data.is_a?(LoggerEnvironment)
|
|
34
37
|
return LoggerEnvironment.new unless env_data.is_a?(Hash)
|
|
@@ -45,6 +48,8 @@ module Smplkit
|
|
|
45
48
|
|
|
46
49
|
# Convert a typed environments dict to the wire-shaped dict for sending.
|
|
47
50
|
# Entries with +level=nil+ are skipped (no override to send).
|
|
51
|
+
#
|
|
52
|
+
# @api private
|
|
48
53
|
def self.environments_to_wire(environments)
|
|
49
54
|
environments.each_with_object({}) do |(env_id, env), out|
|
|
50
55
|
out[env_id] = { "level" => env.level.to_s } unless env.level.nil?
|
|
@@ -85,6 +90,9 @@ module Smplkit
|
|
|
85
90
|
@updated_at = updated_at
|
|
86
91
|
end
|
|
87
92
|
|
|
93
|
+
# Whether the SDK applies server-driven level changes to this logger.
|
|
94
|
+
#
|
|
95
|
+
# @return [Boolean] +true+ when smplkit controls this logger's level.
|
|
88
96
|
def managed? = !!@managed
|
|
89
97
|
|
|
90
98
|
# Read-only view of per-environment level overrides. Mutate via
|
|
@@ -125,6 +133,10 @@ module Smplkit
|
|
|
125
133
|
@environments = {}
|
|
126
134
|
end
|
|
127
135
|
|
|
136
|
+
# Persist this logger to the server (create or update).
|
|
137
|
+
#
|
|
138
|
+
# @return [self] this logger, refreshed from the server response.
|
|
139
|
+
# @raise [RuntimeError] If the logger was constructed without a client.
|
|
128
140
|
def save
|
|
129
141
|
raise "SmplLogger was constructed without a client; cannot save" if @client.nil?
|
|
130
142
|
|
|
@@ -134,6 +146,11 @@ module Smplkit
|
|
|
134
146
|
end
|
|
135
147
|
alias save! save
|
|
136
148
|
|
|
149
|
+
# Delete this logger from the server.
|
|
150
|
+
#
|
|
151
|
+
# @return [void]
|
|
152
|
+
# @raise [RuntimeError] If the logger was constructed without a client.
|
|
153
|
+
# @raise [Smplkit::NotFoundError] If the logger no longer exists.
|
|
137
154
|
def delete
|
|
138
155
|
raise "SmplLogger was constructed without a client; cannot delete" if @client.nil?
|
|
139
156
|
|
|
@@ -141,6 +158,7 @@ module Smplkit
|
|
|
141
158
|
end
|
|
142
159
|
alias delete! delete
|
|
143
160
|
|
|
161
|
+
# @api private
|
|
144
162
|
def _apply(other)
|
|
145
163
|
@id = other.id
|
|
146
164
|
@name = other.name
|
|
@@ -160,11 +178,11 @@ module Smplkit
|
|
|
160
178
|
# A log group resource — a hierarchical bag of loggers with a shared
|
|
161
179
|
# configured level.
|
|
162
180
|
class SmplLogGroup
|
|
163
|
-
attr_accessor :id, :key, :name, :level, :description, :
|
|
181
|
+
attr_accessor :id, :key, :name, :level, :description, :group,
|
|
164
182
|
:created_at, :updated_at
|
|
165
183
|
|
|
166
184
|
def initialize(client = nil, key:, id: nil, name: nil, level: nil,
|
|
167
|
-
description: nil,
|
|
185
|
+
description: nil, group: nil, environments: nil,
|
|
168
186
|
created_at: nil, updated_at: nil)
|
|
169
187
|
@client = client
|
|
170
188
|
@id = id
|
|
@@ -172,12 +190,54 @@ module Smplkit
|
|
|
172
190
|
@name = name
|
|
173
191
|
@level = level
|
|
174
192
|
@description = description
|
|
175
|
-
@
|
|
176
|
-
@environments = environments
|
|
193
|
+
@group = group
|
|
194
|
+
@environments = Logging.convert_environments(environments)
|
|
177
195
|
@created_at = created_at
|
|
178
196
|
@updated_at = updated_at
|
|
179
197
|
end
|
|
180
198
|
|
|
199
|
+
# Read-only view of per-environment level overrides. Mutate via
|
|
200
|
+
# +set_level+ / +clear_level+ (with +environment: "..."+).
|
|
201
|
+
def environments
|
|
202
|
+
@environments.dup
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Set the log level.
|
|
206
|
+
#
|
|
207
|
+
# With +environment: nil+ (the default), sets the base log level used when
|
|
208
|
+
# no environment-specific override applies. With +environment: "..."+,
|
|
209
|
+
# sets the per-environment override. Changes are local until +save+.
|
|
210
|
+
def set_level(level, environment: nil)
|
|
211
|
+
if environment.nil?
|
|
212
|
+
@level = level
|
|
213
|
+
else
|
|
214
|
+
@environments[environment] = LoggerEnvironment.new(level: level)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Remove a log level.
|
|
219
|
+
#
|
|
220
|
+
# With +environment: nil+ (the default), removes the base log level (the
|
|
221
|
+
# group then inherits from its parent group / ancestor / system default).
|
|
222
|
+
# With +environment: "..."+, removes the per-environment override only.
|
|
223
|
+
# Changes are local until +save+.
|
|
224
|
+
def clear_level(environment: nil)
|
|
225
|
+
if environment.nil?
|
|
226
|
+
@level = nil
|
|
227
|
+
else
|
|
228
|
+
@environments.delete(environment)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Remove all per-environment level overrides.
|
|
233
|
+
def clear_all_environment_levels
|
|
234
|
+
@environments = {}
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Persist this group to the server (create or update).
|
|
238
|
+
#
|
|
239
|
+
# @return [self] this group, refreshed from the server response.
|
|
240
|
+
# @raise [RuntimeError] If the group was constructed without a client.
|
|
181
241
|
def save
|
|
182
242
|
raise "SmplLogGroup was constructed without a client; cannot save" if @client.nil?
|
|
183
243
|
|
|
@@ -192,6 +252,11 @@ module Smplkit
|
|
|
192
252
|
end
|
|
193
253
|
alias save! save
|
|
194
254
|
|
|
255
|
+
# Delete this group from the server.
|
|
256
|
+
#
|
|
257
|
+
# @return [void]
|
|
258
|
+
# @raise [RuntimeError] If the group was constructed without a client.
|
|
259
|
+
# @raise [Smplkit::NotFoundError] If the group no longer exists.
|
|
195
260
|
def delete
|
|
196
261
|
raise "SmplLogGroup was constructed without a client; cannot delete" if @client.nil?
|
|
197
262
|
|
|
@@ -199,13 +264,14 @@ module Smplkit
|
|
|
199
264
|
end
|
|
200
265
|
alias delete! delete
|
|
201
266
|
|
|
267
|
+
# @api private
|
|
202
268
|
def _apply(other)
|
|
203
269
|
@id = other.id
|
|
204
270
|
@key = other.key
|
|
205
271
|
@name = other.name
|
|
206
272
|
@level = other.level
|
|
207
273
|
@description = other.description
|
|
208
|
-
@
|
|
274
|
+
@group = other.group
|
|
209
275
|
@environments = other.environments
|
|
210
276
|
@created_at = other.created_at
|
|
211
277
|
@updated_at = other.updated_at
|
|
@@ -4,12 +4,12 @@ require "set"
|
|
|
4
4
|
|
|
5
5
|
module Smplkit
|
|
6
6
|
module Logging
|
|
7
|
-
# Client-side level resolution
|
|
7
|
+
# Client-side level resolution.
|
|
8
8
|
#
|
|
9
9
|
# The server stores raw configuration and returns it as-is; the SDK is
|
|
10
|
-
# responsible for walking the inheritance chain.
|
|
11
|
-
#
|
|
12
|
-
#
|
|
10
|
+
# responsible for walking the inheritance chain.
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
13
|
module Resolution
|
|
14
14
|
FALLBACK_LEVEL = "INFO"
|
|
15
15
|
|