class Metric
A cached metric reference that avoids hash lookups on the fast path.
This class caches all the details needed to write directly to shared memory, including the buffer, offset, and type. When the observer changes, the cache is invalidated and rebuilt on the next access.
Definitions
def self.for(field, observer)
Create a new metric for the given field and observer.
Signature
-
parameter
fieldSymbol The field name for this metric.
-
parameter
observerObserver | Nil The observer to associate with this metric.
-
returns
Metric A new metric instance.
Implementation
def self.for(field, observer)
self.new(field).tap do |metric|
metric.observer = observer
end
end
def initialize(name)
Initialize a new metric.
Signature
-
parameter
nameSymbol The field name for this metric.
Implementation
def initialize(name)
@name = name.to_sym
@value = 0
@observer = nil
@cached_field = nil
@cached_buffer = nil
@guard = Mutex.new
end
attr :name
Signature
-
attribute
Symbol The field name for this metric.
attr :value
Signature
-
attribute
Numeric The current value of this metric.
attr :guard
Signature
-
attribute
Mutex The mutex for thread safety.
def observer=(observer)
Set the observer and rebuild cache.
This is called when the registry assigns a new observer (or removes it). The cache is invalidated and then immediately recomputed so that the fast write path doesn't need to re-check the observer on the first write.
Signature
-
parameter
observerObserver | Nil The new observer (or nil).
Implementation
def observer=(observer)
@guard.synchronize do
@observer = observer
if @observer
if field = @observer.schema[@name]
if buffer = @observer.buffer
@cached_field = field
@cached_buffer = buffer
return write_direct(@value)
end
end
end
@cached_field = nil
@cached_buffer = nil
end
end
def increment
Increment the metric value.
Signature
-
returns
Integer The new value of the field.
Implementation
def increment
@guard.synchronize do
@value += 1
write_direct(@value)
end
@value
end
def track(&block)
Track an operation: increment before the block, decrement after it completes.
Returns the block's return value. Use for active/count metrics that should reflect the number of operations currently in progress.
Signature
-
returns
Object The block's return value.
Implementation
def track(&block)
raise ArgumentError, "block required" unless block_given?
increment
begin
yield
ensure
decrement
end
end
def decrement
Decrement the metric value.
Uses the fast path (direct buffer write) when cache is valid and observer is available.
Signature
-
returns
Integer The new value of the field.
Implementation
def decrement
@guard.synchronize do
@value -= 1
write_direct(@value)
end
@value
end
def set(value)
Set the metric value.
Uses the fast path (direct buffer write) when cache is valid and observer is available.
Signature
-
parameter
valueNumeric The value to set.
Implementation
def set(value)
@guard.synchronize do
@value = value
write_direct(@value)
end
end
def write_direct(value)
Write directly to the cached buffer if available.
This is the fast path that avoids hash lookups. Always ensures cache is valid first. If there's no observer or buffer, silently does nothing.
Signature
-
parameter
valueNumeric The value to write.
-
returns
Boolean Whether the write succeeded.
Implementation
def write_direct(value)
if @cached_buffer
@cached_buffer.set_value(@cached_field.type, @cached_field.offset, value)
end
return true
rescue => error
Console.warn(self, "Failed to write metric value!", metric: {name: @name, value: value}, exception: error)
return false
end