Browse Source

instrumentalizer/zing

main
pvincent 3 months ago
parent
commit
2a361d5290
  1. 2
      app/controllers/strong_controller.rb
  2. 2
      app/views/hot/index.html.erb
  3. 2
      app/views/scores/index.html.erb
  4. 65
      config/initializers/instrumentalizing.rb
  5. 1
      config/initializers/monkey_patches.rb
  6. 28
      config/initializers/semantic_logger.rb
  7. 4
      config/puma.rb
  8. 6
      lib/live/constants.rb
  9. 2
      lib/live/definable.rb
  10. 50
      lib/semantic/instrumentalizer.rb
  11. 68
      lib/semantic/instrumentation_manager.rb

2
app/controllers/strong_controller.rb

@ -1,6 +1,6 @@
class StrongController < ApplicationController
def index
logger.info(Hot::Constants)
logger.info('Live::Constant ')
end
def update

2
app/views/hot/index.html.erb

@ -1,4 +1,4 @@
<div>
<h1 class="font-bold text-4xl">Hot#index</h1>
<%= Hot::Live %>
ssss
</div>

2
app/views/scores/index.html.erb

@ -2,8 +2,8 @@
List of Scores
</h1>
ACTION_CONTROLLER = <%=Live::Constants::ACTION_CONTROLLER%><br/>
ACTION_VIEW = <%=Live::Constants::ACTION_VIEW%><br/>
ACTIVE_RECORD = <%=Live::Constants::ACTIVE_RECORD%><br/>
<div class="m-5 flex justify-end">
<%= link_to "New score", new_score_path, class: "border rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %>

65
config/initializers/instrumentalizing.rb

@ -0,0 +1,65 @@
return if Rails.application.tailwind_watcher?
RailsSemanticLogger::Rack::Logger.logger.level = :info # useful for remaining log like "[Rack::Log] Started..."
SemanticLogger.clear_appenders!
return unless Rails.application.server?
def build_instrumentation_config
{
action_controller: true,
action_view: Live::Constants::ACTION_VIEW
# active_record: Live::Constants::ACTIVE_RECORD
}.map do |key, value|
key if value
end.compact
end
Rails.autoloaders.main.on_load('ApplicationController') do
puts '--- Zeitwerk RELOAD ---'
Semantic::Instrumentalizer.activate(*build_instrumentation_config)
end
Rails.configuration.after_initialize do
puts '---- AFTER INITIALIZE ---------'
Rails.logger.name = 'rails'
ActiveSupport::Notifications.subscribe('rolling.live_constant') do |event|
puts event.payload[:changes].inspect
# TODO: if key includes ACTIVE_RECORD ACTION_VIEW
Semantic::Instrumentalizer.activate(*build_instrumentation_config)
end
# im = nil
# Rails.autoloaders.main.on_load('ApplicationController') do
# SemanticLogger[:zeitwerk].debug('reload!')
# im = Semantic::InstrumentationManager.new
# end
# Semantic::InstrumentationManager.clear
# bootstrap = [{ kind: :restored, constant: 'ACTION_VIEW', type: :boolean, old_value: false, new_value: true },
# { kind: :restored, constant: 'ACTION_CONTROLLER', type: :boolean, old_value: false, new_value: true }]
# im ||= Semantic::InstrumentationManager.new
# im.process(bootstrap)
end
# RAILS_HOOKS = %i[
# action_controller
# action_controller_api
# action_controller_base
# action_dispatch_request
# action_dispatch_response
# action_view
# active_job
# active_model
# active_record
# active_record_fixture_set
# after_initialize
# after_routes_loaded
# before_configuration
# before_eager_load
# before_initialize
# i18n
# message_pack
# ].freeze

1
config/initializers/monkey_patches.rb

@ -8,7 +8,6 @@ def grant(patch)
end
end
puts 'MonkeyPatcher runs:'
patches = Dir.glob(Rails.root.join('lib', 'monkey_patches', '**', '*.rb'))
patches.each do |file|
patch = Pathname.new(file).relative_path_from(Rails.root.join('lib', 'monkey_patches')).to_s

28
config/initializers/semantic_logger.rb

@ -1,28 +0,0 @@
return if Rails.application.tailwind_watcher?
RailsSemanticLogger::Rack::Logger.logger.level = :info # useful for remaining log like "[Rack::Log] Started..."
SemanticLogger.clear_appenders!
im = nil
# Zeitwerk reload message
Rails.autoloaders.main.on_load('ApplicationController') do
SemanticLogger[:zeitwerk].debug('reload!')
im = Semantic::InstrumentationManager.new
end
Rails.configuration.after_initialize do
Rails.logger.name = 'error_trap'
Semantic::InstrumentationManager.clear
bootstrap = [{ kind: :restored, constant: 'ACTION_VIEW', type: :boolean, old_value: false, new_value: true },
{ kind: :restored, constant: 'ACTION_CONTROLLER', type: :boolean, old_value: false, new_value: true }]
im ||= Semantic::InstrumentationManager.new
im.process(bootstrap)
ActiveSupport::Notifications.subscribe('rolling.live_constant') do |event|
puts event.payload[:changes].inspect
im.process(event.payload[:changes])
rescue StandardError => e
puts e
end
end

4
config/puma.rb

@ -33,3 +33,7 @@ pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' }
# Allow puma to be restarted by `bin/rails restart` command.
plugin :tmp_restart
on_booted do
puts '********************* PUMA: booted **********************'
end

6
lib/live/constants.rb

@ -4,10 +4,10 @@ module Live
extend Definable
STIMULUS_DEBUG = boolean false
ACTION_VIEW = boolean true
ACTION_CONTROLLER = boolean true
ACTION_VIEW = boolean false
ACTIVE_RECORD = boolean false
MY_INTEGER = integer 8
MY_STRING = string 'titi'
MY_STRING = string 'tutu'
end
end

2
lib/live/definable.rb

@ -84,7 +84,7 @@ module Live
value = typed_value(type, raw_value, default)
definitions[constant] = { type:, default:, value: }
# logger.debug('new definitions', definitions)
puts("-- new definition #{constant}:#{definitions[constant]}")
value
end

50
lib/semantic/instrumentalizer.rb

@ -0,0 +1,50 @@
module Semantic
# enable/disable instrumentation callbacks
class Instrumentalizer
NOTIFICATIONS = {
action_controller: %i[start_processing process_action redirect_to],
action_view: %i[render_partial render_template render_collection render_layout],
active_record: %i[sql strict_loading instantiation start_transaction transaction]
}.freeze
class << self
def activate(*event_groups)
reset
event_groups.each { |event_group| enable(event_group) }
end
private
def logger = @logger ||= SemanticLogger[:instrumentation]
def reset
NOTIFICATIONS.each do |event_group, hooks|
hooks.each { |hook| ActiveSupport::Notifications.unsubscribe("#{hook}.#{event_group}") }
end
end
def enable(event_group)
logger.debug { "enabling: #{event_group}" }
log_subscriber = build_log_subscriber_from(event_group)
NOTIFICATIONS[event_group].each do |hook|
logger.info("subscribe to #{hook}.#{event_group}")
ActiveSupport::Notifications.subscribe("#{hook}.#{event_group}") do |event|
# logger.debug("SEND #{log_subscriber} hook=#{hook}")
log_subscriber.send(hook, event)
end
end
end
def build_log_subscriber_from(event_group)
classname = event_group.to_s.camelize
case classname
when 'ActionController'
Semantic::Subscribers.const_get(classname).new('toto1')
else
Semantic::Subscribers.const_get(classname).new
end
end
end
end
end

68
lib/semantic/instrumentation_manager.rb

@ -1,68 +0,0 @@
module Semantic
class InstrumentationManager
NOTIFICATIONS = {
action_controller: %i[start_processing process_action redirect_to],
action_view: %i[render_partial render_template render_collection render_layout],
active_record: %i[sql strict_loading instantiation start_transaction transaction]
}.freeze
def logger = @logger ||= SemanticLogger[:instrumentation]
def initialize
logger.debug 're-initialized'
end
def self.clear
NOTIFICATIONS.each do |event_group, hooks|
hooks.each { |hook| ActiveSupport::Notifications.unsubscribe("#{hook}.#{event_group}") }
end
end
def process(changes)
logger.info "process called with #{changes.size} change(s)"
changes.each do |change|
constant = change[:constant]
value = change[:new_value]
case constant
when 'ACTION_VIEW', 'ACTION_CONTROLLER', 'ACTIVE_RECORD'
value ? enable(constant) : disable(constant)
end
end
logger.info 'DONE'
end
def enable(constant)
logger.info("enable: #{constant}")
event_group = constant.underscore.to_sym
log_subscriber = build_log_subscriber_from(event_group.to_s.camelize)
logger.warn(log_subscriber)
NOTIFICATIONS[event_group].each do |hook|
logger.info("subscribe to #{hook}.#{event_group}")
ActiveSupport::Notifications.subscribe("#{hook}.#{event_group}") do |event|
# logger.debug("SEND #{log_subscriber} hook=#{hook}")
log_subscriber.send(hook, event)
end
end
end
def disable(constant)
logger.info("disable: #{constant}")
event_group = constant.underscore.to_sym
logger.debug(NOTIFICATIONS[event_group].size)
NOTIFICATIONS[event_group].each do |hook|
logger.info("unsubscribe to #{hook}.#{event_group}")
ActiveSupport::Notifications.unsubscribe("#{hook}.#{event_group}")
end
end
def build_log_subscriber_from(classname)
case classname
when 'ActionController' then Semantic::Subscribers.const_get(classname).new('toto1')
else Semantic::Subscribers.const_get(classname).new
end
end
end
end
Loading…
Cancel
Save