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 +Logger+ contract).
%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.create+ time).
-
#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
|