Module: Smplkit::Logging::Resolution
- Defined in:
- lib/smplkit/logging/resolution.rb
Overview
Client-side level resolution per ADR-034 §3.1.
The server stores raw configuration and returns it as-is; the SDK is responsible for walking the inheritance chain. Mirrors the Python SDK’s smplkit.logging._resolution verbatim — both implementations MUST resolve identically for any given (loggers, groups, env) input.
Constant Summary collapse
- FALLBACK_LEVEL =
"INFO"
Class Method Summary collapse
- .env_level_of(entry, environment) ⇒ Object
-
.find_resolution_source(logger_id, environment, loggers, groups) ⇒ Object
Human-readable label for which resolution step won.
-
.resolve_for_entry(logger_id, environment, loggers, groups) ⇒ Object
Try to resolve a level for a single entry (logger or ancestor).
-
.resolve_group_chain(group_id, environment, groups) ⇒ Object
Walk the group chain looking for a level.
-
.resolve_level(logger_id, environment, loggers, groups) ⇒ Object
Resolve the effective level for
logger_idinenvironment.
Class Method Details
.env_level_of(entry, environment) ⇒ Object
107 108 109 110 111 112 113 114 115 |
# File 'lib/smplkit/logging/resolution.rb', line 107 def env_level_of(entry, environment) envs = entry["environments"] return nil unless envs.is_a?(Hash) env_data = envs[environment] return nil unless env_data.is_a?(Hash) env_data["level"] end |
.find_resolution_source(logger_id, environment, loggers, groups) ⇒ Object
Human-readable label for which resolution step won. Only consulted when debug logging is enabled; mirrors Python’s _find_resolution_source.
94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/smplkit/logging/resolution.rb', line 94 def find_resolution_source(logger_id, environment, loggers, groups) entry = loggers[logger_id] return "not found" if entry.nil? return %(env override "#{environment}") if env_level_of(entry, environment) return "base level" if entry["level"] group_id = entry["group"] return %(group "#{group_id}") if resolve_group_chain(group_id, environment, groups) "unknown" end |
.resolve_for_entry(logger_id, environment, loggers, groups) ⇒ Object
Try to resolve a level for a single entry (logger or ancestor). Returns nil if no level is found at any step of 1–3.
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/smplkit/logging/resolution.rb', line 59 def resolve_for_entry(logger_id, environment, loggers, groups) entry = loggers[logger_id] return nil if entry.nil? env_level = env_level_of(entry, environment) return env_level if env_level base = entry["level"] return base if base resolve_group_chain(entry["group"], environment, groups) end |
.resolve_group_chain(group_id, environment, groups) ⇒ Object
Walk the group chain looking for a level. Cycle-safe via visited.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/smplkit/logging/resolution.rb', line 73 def resolve_group_chain(group_id, environment, groups) visited = Set.new current_id = group_id while !current_id.nil? && !visited.include?(current_id) visited.add(current_id) group = groups[current_id] break if group.nil? env_level = env_level_of(group, environment) return env_level if env_level base = group["level"] return base if base current_id = group["group"] end nil end |
.resolve_level(logger_id, environment, loggers, groups) ⇒ Object
Resolve the effective level for logger_id in environment.
Resolution chain (first non-nil wins):
1. Logger's own +environments[env].level+
2. Logger's own +level+
3. Group chain (recursive: group env level → group level → parent group …)
4. Dot-notation ancestry (+com.acme.payments+ → +com.acme+ → +com+,
applying steps 1–3 at each)
5. System fallback: +"INFO"+
loggers and groups are id-keyed Hashes whose values are Hashes with the same shape as the Python SDK: “level”, “group” (parent group id for loggers; parent_id for groups), “environments” (Hash keyed by env name with {“level” => “…”} values).
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/smplkit/logging/resolution.rb', line 33 def resolve_level(logger_id, environment, loggers, groups) result = resolve_for_entry(logger_id, environment, loggers, groups) if result if Smplkit::Debug.enabled source = find_resolution_source(logger_id, environment, loggers, groups) Smplkit.debug("resolution", "#{logger_id} -> #{result} (source: #{source})") end return result end parts = logger_id.split(".") (parts.length - 1).downto(1) do |i| ancestor_id = parts[0, i].join(".") result = resolve_for_entry(ancestor_id, environment, loggers, groups) if result Smplkit.debug("resolution", "#{logger_id} -> #{result} (source: ancestor \"#{ancestor_id}\")") return result end end Smplkit.debug("resolution", "#{logger_id} -> #{FALLBACK_LEVEL} (source: system default)") FALLBACK_LEVEL end |