smplkit 3.0.18 → 3.0.19
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/logging/client.rb +46 -61
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8dc0e8067c66c43e659ad29aff4756448763e90c251e300d598762a7aad1130b
|
|
4
|
+
data.tar.gz: 0a658e3773fcb670b7891c6fc5b18ffeea16780a3195c8e0aa866132e2018fe9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6f1ef7cc9470990ee57fbe8587fff5f4a0ac5f9ab2199186b4f585fbe8dfc8dc9efd74acc8787f3c4a3fab4b9acc4c2860118e6f5b91c4934f8684d0c8d88f7f
|
|
7
|
+
data.tar.gz: 9c8cf307db3e470c047b518aeb079b558d7c19f1687293e1103d1570104fc2c2bfde6f2591f090a94bf46cc3b438123d38e7caa7db2f7b1a923aad91b096e4c5
|
|
@@ -14,6 +14,17 @@ module Smplkit
|
|
|
14
14
|
# and the SDK walks the chain (env override → base → group chain →
|
|
15
15
|
# dot-notation ancestry) to compute each managed logger's effective
|
|
16
16
|
# level. See {Smplkit::Logging::Resolution}.
|
|
17
|
+
#
|
|
18
|
+
# Change-listener contract — every call the SDK makes to
|
|
19
|
+
# +adapter.apply_level(logger_id, new_level)+ is paired with exactly one
|
|
20
|
+
# listener notification for that logger, and every notification
|
|
21
|
+
# corresponds to exactly one adapter apply. A trigger that moves N
|
|
22
|
+
# loggers' effective levels invokes the global listener N times (once
|
|
23
|
+
# per logger), each invocation also fires every matching key-scoped
|
|
24
|
+
# listener for that id. There are no batch / summary events and no
|
|
25
|
+
# deletion-flavored events — logger / group deletions only emit
|
|
26
|
+
# listener invocations for *dependents* whose computed effective level
|
|
27
|
+
# actually moved; the deleted key itself emits nothing.
|
|
17
28
|
class LoggingClient
|
|
18
29
|
def initialize(parent, manage:, metrics:, logging_base_url:, app_base_url:)
|
|
19
30
|
@parent = parent
|
|
@@ -30,18 +41,16 @@ module Smplkit
|
|
|
30
41
|
# We keep originals so adapter.apply_level receives whatever the
|
|
31
42
|
# framework's registry indexes by.
|
|
32
43
|
@name_map = {}
|
|
33
|
-
# normalized_id → resolution-cache entry.
|
|
34
|
-
# +_fetch_and_apply+ and mutated by the +logger_changed+ /
|
|
35
|
-
# +logger_deleted+ WS handlers.
|
|
44
|
+
# normalized_id → resolution-cache entry.
|
|
36
45
|
@loggers_cache = {}
|
|
37
46
|
# group id → resolution-cache entry. Without this, any managed
|
|
38
47
|
# logger with +level=null+ that inherits from a group silently
|
|
39
48
|
# keeps whatever level its adapter had at startup.
|
|
40
49
|
@groups_cache = {}
|
|
41
|
-
# normalized_id → resolved level (string).
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
50
|
+
# normalized_id → last-applied resolved level (string). Drives the
|
|
51
|
+
# lockstep between adapter.apply_level and listener notifications:
|
|
52
|
+
# we only push (and fire) when the freshly-resolved level differs
|
|
53
|
+
# from what's recorded here.
|
|
45
54
|
@resolved_levels = {}
|
|
46
55
|
end
|
|
47
56
|
|
|
@@ -62,7 +71,7 @@ module Smplkit
|
|
|
62
71
|
end
|
|
63
72
|
|
|
64
73
|
flush_initial_registration
|
|
65
|
-
fetch_and_apply(trigger: "install")
|
|
74
|
+
fetch_and_apply(trigger: "install", source: "manual")
|
|
66
75
|
|
|
67
76
|
@ws_manager = @parent._ensure_ws
|
|
68
77
|
@ws_manager.on("logger_changed") { |data| handle_logger_changed(data) }
|
|
@@ -101,9 +110,9 @@ module Smplkit
|
|
|
101
110
|
end
|
|
102
111
|
|
|
103
112
|
# Re-fetch all loggers and groups and re-apply resolved levels. Fires
|
|
104
|
-
#
|
|
113
|
+
# listeners only for loggers whose effective level moved.
|
|
105
114
|
def refresh
|
|
106
|
-
fetch_and_apply(trigger: "refresh")
|
|
115
|
+
fetch_and_apply(trigger: "refresh", source: "manual")
|
|
107
116
|
end
|
|
108
117
|
|
|
109
118
|
def on_change(name = nil, &block)
|
|
@@ -164,27 +173,25 @@ module Smplkit
|
|
|
164
173
|
end
|
|
165
174
|
|
|
166
175
|
# Full re-fetch of loggers + groups, then apply resolved levels.
|
|
167
|
-
|
|
168
|
-
def fetch_and_apply(trigger:)
|
|
176
|
+
def fetch_and_apply(trigger:, source: "websocket")
|
|
169
177
|
Smplkit.debug("resolution", "full resolution pass starting (trigger: #{trigger})")
|
|
170
178
|
loggers = @manage.loggers.list_logger_entries
|
|
171
179
|
groups = @manage.log_groups.list_group_entries
|
|
172
180
|
@loggers_cache = loggers
|
|
173
181
|
@groups_cache = groups
|
|
174
|
-
apply_levels(source:
|
|
182
|
+
apply_levels(source: source)
|
|
175
183
|
rescue StandardError => e
|
|
176
184
|
Smplkit.debug("resolution", "fetch_and_apply failed (trigger: #{trigger}): #{e.class}: #{e.message}")
|
|
177
185
|
end
|
|
178
186
|
|
|
179
|
-
#
|
|
180
|
-
#
|
|
181
|
-
#
|
|
182
|
-
#
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
#
|
|
187
|
+
# Apply newly-resolved levels in lockstep with listener
|
|
188
|
+
# notifications. For every locally-tracked managed logger whose
|
|
189
|
+
# freshly-computed effective level differs from the last applied
|
|
190
|
+
# value: push to adapters, then fire each global + matching
|
|
191
|
+
# key-scoped listener. No adapter push happens without a paired
|
|
192
|
+
# listener notification, and no notification fires without a
|
|
193
|
+
# paired adapter push.
|
|
186
194
|
def apply_levels(source: "websocket")
|
|
187
|
-
changed = []
|
|
188
195
|
@name_map.each do |raw_name, normalized_id|
|
|
189
196
|
entry = @loggers_cache[normalized_id]
|
|
190
197
|
next if entry.nil?
|
|
@@ -193,16 +200,14 @@ module Smplkit
|
|
|
193
200
|
resolved_string = Resolution.resolve_level(
|
|
194
201
|
normalized_id, @parent._environment, @loggers_cache, @groups_cache
|
|
195
202
|
)
|
|
203
|
+
previous = @resolved_levels[normalized_id]
|
|
204
|
+
next if previous == resolved_string
|
|
205
|
+
|
|
196
206
|
coerced = LogLevel.coerce(resolved_string)
|
|
207
|
+
@resolved_levels[normalized_id] = resolved_string
|
|
197
208
|
push_to_adapters(raw_name, coerced)
|
|
198
|
-
|
|
199
|
-
if previous != resolved_string
|
|
200
|
-
@resolved_levels[normalized_id] = resolved_string
|
|
201
|
-
changed << [normalized_id, coerced]
|
|
202
|
-
end
|
|
209
|
+
fire_change_event(normalized_id, coerced, source: source)
|
|
203
210
|
end
|
|
204
|
-
fire_resolved_change_events(changed, source: source)
|
|
205
|
-
changed
|
|
206
211
|
end
|
|
207
212
|
|
|
208
213
|
def push_to_adapters(raw_name, coerced_level)
|
|
@@ -213,14 +218,12 @@ module Smplkit
|
|
|
213
218
|
end
|
|
214
219
|
end
|
|
215
220
|
|
|
216
|
-
def
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
Smplkit.debug("logging", "listener raised: #{e.class}: #{e.message}")
|
|
223
|
-
end
|
|
221
|
+
def fire_change_event(normalized_id, level, source:)
|
|
222
|
+
event = LoggerChangeEvent.new(name: normalized_id, level: level, source: source)
|
|
223
|
+
(@global_listeners + @key_listeners[normalized_id]).each do |cb|
|
|
224
|
+
cb.call(event)
|
|
225
|
+
rescue StandardError => e
|
|
226
|
+
Smplkit.debug("logging", "listener raised: #{e.class}: #{e.message}")
|
|
224
227
|
end
|
|
225
228
|
end
|
|
226
229
|
|
|
@@ -240,17 +243,16 @@ module Smplkit
|
|
|
240
243
|
apply_levels(source: "websocket")
|
|
241
244
|
end
|
|
242
245
|
|
|
246
|
+
# Deletion is a pure cache eviction. The deleted key itself fires
|
|
247
|
+
# nothing; dependents whose effective level moves fire through the
|
|
248
|
+
# normal apply path.
|
|
243
249
|
def handle_logger_deleted(data)
|
|
244
250
|
key = data["id"] || data["name"] || ""
|
|
245
251
|
normalized = Normalize.normalize_logger_name(key)
|
|
246
252
|
return if normalized.empty?
|
|
247
253
|
|
|
248
|
-
|
|
249
|
-
@resolved_levels.delete(normalized)
|
|
250
|
-
return unless existed
|
|
251
|
-
|
|
254
|
+
@loggers_cache.delete(normalized)
|
|
252
255
|
apply_levels(source: "websocket")
|
|
253
|
-
fire_deletion_event(normalized)
|
|
254
256
|
end
|
|
255
257
|
|
|
256
258
|
def handle_group_changed(data)
|
|
@@ -272,36 +274,19 @@ module Smplkit
|
|
|
272
274
|
key = data["id"] || data["key"] || ""
|
|
273
275
|
return if key.to_s.empty?
|
|
274
276
|
|
|
275
|
-
|
|
276
|
-
return unless existed
|
|
277
|
-
|
|
277
|
+
@groups_cache.delete(key)
|
|
278
278
|
apply_levels(source: "websocket")
|
|
279
|
-
fire_deletion_event(key)
|
|
280
279
|
end
|
|
281
280
|
|
|
282
281
|
def handle_loggers_changed(_data)
|
|
283
282
|
fetch_and_apply(trigger: "loggers_changed WS event")
|
|
284
283
|
end
|
|
285
|
-
|
|
286
|
-
def fire_deletion_event(key)
|
|
287
|
-
event = LoggerChangeEvent.new(name: key, level: nil, source: "websocket", deleted: true)
|
|
288
|
-
(@global_listeners + @key_listeners[key]).each do |cb|
|
|
289
|
-
cb.call(event)
|
|
290
|
-
rescue StandardError => e
|
|
291
|
-
Smplkit.debug("logging", "listener raised: #{e.class}: #{e.message}")
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
284
|
end
|
|
295
285
|
|
|
296
|
-
LoggerChangeEvent = Struct.new(:name, :level, :source,
|
|
297
|
-
def initialize(name:, level:, source:, deleted: false)
|
|
298
|
-
super
|
|
299
|
-
end
|
|
300
|
-
|
|
286
|
+
LoggerChangeEvent = Struct.new(:name, :level, :source, keyword_init: true) do
|
|
301
287
|
def ==(other)
|
|
302
288
|
other.is_a?(LoggerChangeEvent) &&
|
|
303
|
-
name == other.name && level == other.level &&
|
|
304
|
-
source == other.source && deleted == other.deleted
|
|
289
|
+
name == other.name && level == other.level && source == other.source
|
|
305
290
|
end
|
|
306
291
|
end
|
|
307
292
|
end
|