Class: ConvertSdk::LogManager
- Inherits:
-
Object
- Object
- ConvertSdk::LogManager
- Defined in:
- lib/convert_sdk/log_manager.rb
Overview
Multi-sink, level-gated logger with secret redaction wired in by construction.
LogManager is consumed by every manager from the HTTP client (Story 1.5)
onward. It fans messages out to any number of stdlib-+Logger+-compatible
sinks and guarantees, structurally, that no message reaches a sink
without first passing through the Redactor: every public level method
funnels through the single private #emit path, and that path applies the
loggable conversion boundary and redaction before touching a sink. There
is no public method that bypasses #emit.
Levels
Verbosity is gated by the JS-parity LogLevel values (TRACE=0 … SILENT=5).
A call at level L emits only when L >= configured_level; SILENT
suppresses everything. The stdlib Logger has no trace, so both
#trace and #debug dispatch to the sink's #debug — the numeric level
value (0 vs 1), not the sink method, decides whether they emit.
Level conventions (callers choose the level by intent):
trace/debug— decisioning internals (bucketing, rule evaluation).info— lifecycle events (SDK ready, config refreshed).warn— recoverable conditions (stale config, retry).error— internal failures (parse error, exhausted retries).
Message format
Callers pass messages already formatted as {ClassName}#{method}:
{message}. LogManager does not prepend the class name itself — the
format is a usage convention, documented here and enforced at call sites.
Thread safety
The sink list is guarded by @sinks_mutex. Compound operations on the list
happen inside the lock; the (potentially slow, potentially raising) sink
I/O happens outside the lock by iterating a dup snapshot. A sink that
raises is contained (rescue StandardError) so a broken sink never crashes
the host or starves the other sinks.
Constant Summary collapse
- REQUIRED_SINK_METHODS =
The methods every valid sink must respond to (stdlib
Loggercontract). %i[debug info warn error].freeze
Instance Method Summary collapse
-
#add_sink(sink) ⇒ self
Register a sink.
-
#debug(message) ⇒ Object
Log at DEBUG — decisioning internals.
-
#error(message) ⇒ Object
Log at ERROR — internal failures.
-
#info(message) ⇒ Object
Log at INFO — lifecycle events.
-
#initialize(level: LogLevel::ERROR, sink: nil, secrets: []) ⇒ LogManager
constructor
A new instance of LogManager.
-
#register_secret(secret) ⇒ void
Register an additional secret to redact (e.g. once the SDK key is known at
ConvertSdk.createtime). -
#trace(message) ⇒ void
Log at TRACE (finest-grained); dispatches to the sink's
#debug. -
#warn(message) ⇒ Object
Log at WARN — recoverable conditions.
Constructor Details
#initialize(level: LogLevel::ERROR, sink: nil, secrets: []) ⇒ LogManager
Returns a new instance of LogManager.
50 51 52 53 54 55 56 57 |
# File 'lib/convert_sdk/log_manager.rb', line 50 def initialize(level: LogLevel::ERROR, sink: nil, secrets: []) @level = level @redactor = Redactor.new(secrets) @sinks = [] # Thread safety: guarded by @sinks_mutex. @sinks_mutex = Thread::Mutex.new add_sink(sink) unless sink.nil? end |
Instance Method Details
#add_sink(sink) ⇒ self
Register a sink. Accepted iff it duck-types to the stdlib Logger
contract (responds to debug/info/warn/error). An invalid sink is rejected
with a logged error rather than raising — registration must never crash
the host.
69 70 71 72 73 74 75 76 77 |
# File 'lib/convert_sdk/log_manager.rb', line 69 def add_sink(sink) if REQUIRED_SINK_METHODS.all? { |m| sink.respond_to?(m) } @sinks_mutex.synchronize { @sinks << sink } else emit(LogLevel::ERROR, "LogManager#add_sink: rejected sink #{sink.class} " \ "(must respond to #{REQUIRED_SINK_METHODS.join("/")})") end self end |
#debug(message) ⇒ Object
Log at DEBUG — decisioning internals. Dispatches to sink #debug.
|
|
# File 'lib/convert_sdk/log_manager.rb', line 88
|
#error(message) ⇒ Object
Log at ERROR — internal failures.
|
|
# File 'lib/convert_sdk/log_manager.rb', line 88
|
#info(message) ⇒ Object
Log at INFO — lifecycle events.
|
|
# File 'lib/convert_sdk/log_manager.rb', line 88
|
#register_secret(secret) ⇒ void
This method returns an undefined value.
Register an additional secret to redact (e.g. once the SDK key is known
at ConvertSdk.create time). nil/blank is a no-op.
84 85 86 |
# File 'lib/convert_sdk/log_manager.rb', line 84 def register_secret(secret) @redactor.register_secret(secret) end |
#trace(message) ⇒ void
This method returns an undefined value.
Returns log at TRACE (finest-grained); dispatches to the sink's #debug.
|
|
# File 'lib/convert_sdk/log_manager.rb', line 88
|
#warn(message) ⇒ Object
Log at WARN — recoverable conditions.
|
|
# File 'lib/convert_sdk/log_manager.rb', line 88
|