Class: FiberAudit::Runtime::Probes::Registry

Inherits:
Object
  • Object
show all
Defined in:
lib/fiber_audit/runtime/probes/registry.rb

Overview

Process-local owner of idempotent probe installation and dispatch.

Defined Under Namespace

Modules: RequireInstanceHook, RequireSingletonHook

Constant Summary collapse

PROBE_INSTALLERS =
[
  Subprocess,
  ThreadWait,
  Synchronization,
  ThreadState,
  IOSelect,
  Socket,
  HTTP
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base:) ⇒ Registry

Returns a new instance of Registry.



103
104
105
106
107
108
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 103

def initialize(base:)
  @base = base
  @owner_pid = Process.pid
  @mutex = Mutex.new
  @active = true
end

Instance Attribute Details

#baseObject (readonly)

Returns the value of attribute base.



101
102
103
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 101

def base
  @base
end

#owner_pidObject (readonly)

Returns the value of attribute owner_pid.



101
102
103
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 101

def owner_pid
  @owner_pid
end

Class Method Details

.activate(base:) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 46

def activate(base:)
  raise RuntimeContractError, 'base must be a Runtime::Probes::Base' unless base.is_a?(Base)

  registry = new(base: base)
  @current = registry
  registry.install!
  registry
rescue StandardError
  registry&.deactivate
  @current = nil if @current.equal?(registry)
  raise
end

.currentObject



83
84
85
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 83

def current
  current_for_observation
end

.deactivate(registry) ⇒ Object



78
79
80
81
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 78

def deactivate(registry)
  @current = nil if @current.equal?(registry)
  registry&.deactivate
end

.observe(operation:, measurements: {}, emit_start: false, measurement_builder: nil, &application) ⇒ Object

Raises:

  • (ArgumentError)


59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 59

def observe(operation:, measurements: {}, emit_start: false, measurement_builder: nil, &application)
  raise ArgumentError, 'probe observation requires a block' unless application

  registry = current_for_observation
  return application.call unless registry

  registry.base.observe(
    operation: operation,
    measurements: measurements,
    emit_start: emit_start,
    measurement_builder: measurement_builder,
    &application
  )
end

.rescan_current!Object



74
75
76
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 74

def rescan_current!
  current_for_observation&.scan!
end

Instance Method Details

#active_for_current_process?Boolean

Returns:

  • (Boolean)


146
147
148
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 146

def active_for_current_process?
  @active && owner_pid == Process.pid
end

#deactivateObject



140
141
142
143
144
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 140

def deactivate
  @active = false
  base.deactivate
  self
end

#install!Object



110
111
112
113
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 110

def install!
  scan!
  self
end

#prepend_once(target, hook) ⇒ Object



131
132
133
134
135
136
137
138
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 131

def prepend_once(target, hook)
  unless target.is_a?(Module) && hook.is_a?(Module)
    raise RuntimeContractError, 'probe target and hook must be Modules'
  end

  target.prepend(hook) unless target.ancestors.include?(hook)
  target
end

#scan!Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 115

def scan!
  return self unless active_for_current_process?

  base.with_guard do
    @mutex.synchronize do
      prepend_once(Kernel, RequireInstanceHook)
      prepend_once(Kernel.singleton_class, RequireSingletonHook)
      PROBE_INSTALLERS.each { |installer| installer.install!(self) }
    end
  end
  self
rescue StandardError => e
  base.instrumentation_failure(e)
  self
end

#stale_process?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/fiber_audit/runtime/probes/registry.rb', line 150

def stale_process?
  owner_pid != Process.pid
end