Module: Asherah::Hooks
- Defined in:
- lib/asherah/hooks.rb
Overview
Log + metrics observability hooks.
The C ABI accepts a single function pointer per hook. We marshal each invocation into a Ruby Hash with symbol keys and yield it to the user-provided Proc. Exceptions raised by the user’s callback are caught and silently swallowed — propagating an exception across the FFI boundary would be undefined behavior (and since Rust 1.81 aborts the process).
The user’s callback may fire from any thread (Rust tokio worker threads, database driver threads). Implementations must be thread-safe and should not block; expensive forwarding (e.g. to a logging framework) should be done by enqueueing work onto a background thread you own.
Class Method Summary collapse
-
.clear_log_hook ⇒ Object
Remove the active log hook.
-
.clear_metrics_hook ⇒ Object
Remove the active metrics hook and disable the metrics gate.
-
.set_log_hook(callback = nil, &block) ⇒ Object
Install a log hook.
-
.set_metrics_hook(callback = nil, &block) ⇒ Object
Install a metrics hook.
Class Method Details
.clear_log_hook ⇒ Object
Remove the active log hook. Idempotent.
125 126 127 128 129 130 131 132 |
# File 'lib/asherah/hooks.rb', line 125 def clear_log_hook @mutex.synchronize do Native.asherah_clear_log_hook @log_callback = nil @log_trampoline = nil end nil end |
.clear_metrics_hook ⇒ Object
Remove the active metrics hook and disable the metrics gate. Idempotent.
169 170 171 172 173 174 175 176 |
# File 'lib/asherah/hooks.rb', line 169 def clear_metrics_hook @mutex.synchronize do Native.asherah_clear_metrics_hook @metrics_callback = nil @metrics_trampoline = nil end nil end |
.set_log_hook(callback = nil, &block) ⇒ Object
Install a log hook. Three forms are supported:
-
A stdlib
Loggerinstance (or any Logger-compatible object that responds to#add,#debug,#info,#warn,#error):Asherah.set_log_hook(Logger.new($stdout))Each Asherah record is forwarded via Logger#add(severity, message, target) so the logger’s own filter rules and formatters apply. The
targetargument is passed asprognamefor routing. -
A
Procor block, yielded a Hash:Asherah.set_log_hook do |event| # event[:level] => :debug | :info | :warn | :error (symbol) # event[:severity] => Logger::DEBUG ... (Logger::Severity int) # event[:target] => "asherah::session" # event[:message] => "..." end -
nilto clear (equivalent to clear_log_hook).
Replaces any previously installed log hook. Exceptions raised from the callback are caught and silently swallowed.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/asherah/hooks.rb', line 97 def set_log_hook(callback = nil, &block) callback ||= block if callback.nil? clear_log_hook return end callback = logger_to_callback(callback) if logger_like?(callback) unless callback.respond_to?(:call) raise ArgumentError, "log hook must be a Logger, Proc, or block" end @mutex.synchronize do @log_callback = callback # Allocate the trampoline OUTSIDE the user block so a slow user # callback can't hold the mutex. @log_trampoline = FFI::Function.new( :void, [:pointer, :int, :string, :string] ) do |_user_data, level, target, | dispatch_log(level, target, ) end rc = Native.asherah_set_log_hook(@log_trampoline, FFI::Pointer::NULL) raise Error, "asherah_set_log_hook failed: rc=#{rc}" if rc != 0 end nil end |
.set_metrics_hook(callback = nil, &block) ⇒ Object
Install a metrics hook. block receives a Hash:
# Timing event:
{ type: :encrypt|:decrypt|:store|:load, duration_ns: Integer, name: nil }
# Cache event:
{ type: :cache_hit|:cache_miss|:cache_stale, duration_ns: 0, name: String }
Installing a hook implicitly enables the global metrics gate; clearing it disables the gate. Replaces any previously installed metrics hook. Pass nil to clear.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/asherah/hooks.rb', line 144 def set_metrics_hook(callback = nil, &block) callback ||= block if callback.nil? clear_metrics_hook return end unless callback.respond_to?(:call) raise ArgumentError, "metrics hook must be callable (Proc or block)" end @mutex.synchronize do @metrics_callback = callback @metrics_trampoline = FFI::Function.new( :void, [:pointer, :int, :uint64, :string] ) do |_user_data, type, duration_ns, name| dispatch_metric(type, duration_ns, name) end rc = Native.asherah_set_metrics_hook(@metrics_trampoline, FFI::Pointer::NULL) raise Error, "asherah_set_metrics_hook failed: rc=#{rc}" if rc != 0 end nil end |