Browse Source

subscribe unsubscribe on change but not yet on boot

main
pvincent 1 month ago
parent
commit
2b9afab0fc
  1. 22
      config/initializers/semantic_logger.rb
  2. 2
      lib/live/definable.rb
  3. 3
      lib/semantic/fancy_formatter.rb
  4. 68
      lib/semantic/instrumentation_manager.rb
  5. 18
      lib/semantic/subscribers/action_controller.rb
  6. 1
      lib/semantic/subscribers/action_view.rb

22
config/initializers/semantic_logger.rb

@ -1,22 +1,18 @@
RailsSemanticLogger::Rack::Logger.logger.level = :info # useful for remaining log like "[Rack::Log] Started..." RailsSemanticLogger::Rack::Logger.logger.level = :info # useful for remaining log like "[Rack::Log] Started..."
SemanticLogger.clear_appenders! SemanticLogger.clear_appenders!
im = nil
# Zeitwerk reload message # Zeitwerk reload message
Rails.autoloaders.main.on_load('ApplicationController') { SemanticLogger[:Zeitwerk].debug('reload!') }
all_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]
}
Rails.configuration.after_initialize do
all_notifications.each do |event_group, hooks|
hooks.each { |hook| ActiveSupport::Notifications.unsubscribe("#{hook}.#{event_group}") }
Rails.autoloaders.main.on_load('ApplicationController') do
SemanticLogger[:zeitwerk].debug('reload!')
im = Semantic::InstrumentationManager.new
end end
Rails.configuration.after_initialize do
Semantic::InstrumentationManager.clear
ActiveSupport::Notifications.subscribe('rolling.live_constant') do |event| ActiveSupport::Notifications.subscribe('rolling.live_constant') do |event|
SemanticLogger[:live_notifications].warn('rolling.live_constant', event.payload)
# FIXME: to be continued...
im.process(event.payload[:changes])
rescue StandardError => e
puts e
end end
end end

2
lib/live/definable.rb

@ -30,6 +30,8 @@ module Live
def trigger_rolling_event(changes) def trigger_rolling_event(changes)
ActiveSupport::Notifications.instrument('rolling.live_constant', changes:) ActiveSupport::Notifications.instrument('rolling.live_constant', changes:)
FileUtils.touch(MAIN_CSS) if defined?(RailsLiveReload) # triggering RailsLiveReload FileUtils.touch(MAIN_CSS) if defined?(RailsLiveReload) # triggering RailsLiveReload
rescue StandardError => e
logger.error(e)
end end
def override(constant, raw) def override(constant, raw)

3
lib/semantic/fancy_formatter.rb

@ -131,7 +131,8 @@ module Semantic
def centerize(text, max_length = CENTER_SIZE) = text.reverse.truncate(max_length).reverse.center(max_length) def centerize(text, max_length = CENTER_SIZE) = text.reverse.truncate(max_length).reverse.center(max_length)
def origin def origin
taint = log.name.include?('_') ? TEXT_GRAY_400 : TEXT_CYAN
true_class = log.name == log.name.upcase_first
taint = true_class ? TEXT_CYAN : TEXT_GRAY_400
colorize(centerize(log.name), taint) colorize(centerize(log.name), taint)
end end

68
lib/semantic/instrumentation_manager.rb

@ -0,0 +1,68 @@
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

18
lib/semantic/subscribers/action_controller.rb

@ -21,9 +21,9 @@ module Semantic
request = event.payload[:request] request = event.payload[:request]
path = colorize(request.filtered_path, BOLD) path = colorize(request.filtered_path, BOLD)
dimensions = Semantic::AnsiDimensions.new(rails: '╓─╖', before: 1)
dimensions = Semantic::FancyDimensions.new(rails: '╓─╖', before: 1)
if defined?(@previously_redirect) && @previously_redirect if defined?(@previously_redirect) && @previously_redirect
dimensions = Semantic::AnsiDimensions.new(rails: '╓║╖', before: 0)
dimensions = Semantic::FancyDimensions.new(rails: '╓║╖', before: 0)
@previously_redirect = false @previously_redirect = false
end end
logger.info("Started #{request.raw_request_method} #{path}", dimensions:) logger.info("Started #{request.raw_request_method} #{path}", dimensions:)
@ -44,7 +44,7 @@ module Semantic
end end
end end
def finish_processing(event)
def process_action(event)
session_value = @transactions.delete(event.transaction_id) # delete previous session_value from start_processing session_value = @transactions.delete(event.transaction_id) # delete previous session_value from start_processing
SemanticLogger.tagged(session_value) do SemanticLogger.tagged(session_value) do
payload = event.payload payload = event.payload
@ -70,17 +70,17 @@ module Semantic
dimensions = case status_family dimensions = case status_family
when 2 when 2
Semantic::AnsiDimensions.new(rails: TERMINUS_STRING)
Semantic::FancyDimensions.new(rails: TERMINUS_STRING)
when 3 when 3
Semantic::AnsiDimensions.new(rails: '╙║╜')
Semantic::FancyDimensions.new(rails: '╙║╜')
when 4 when 4
Semantic::AnsiDimensions.new(rails: '╙╨╜')
Semantic::FancyDimensions.new(rails: '╙╨╜')
when 5 when 5
Semantic::AnsiDimensions.new(rails: '╙║╜')
Semantic::FancyDimensions.new(rails: '╙║╜')
end end
logger.info("Completed #{colorize(status, BOLD)} #{Rack::Utils::HTTP_STATUS_CODES[status]}", dimensions:) logger.info("Completed #{colorize(status, BOLD)} #{Rack::Utils::HTTP_STATUS_CODES[status]}", dimensions:)
logger.info(' ', dimensions: Semantic::AnsiDimensions.new(rails: ' ║ ')) if status_family == 3
logger.info(' ', dimensions: Semantic::AnsiDimensions.new(rails: '╓║╖')) if status_family == 5
logger.info(' ', dimensions: Semantic::FancyDimensions.new(rails: ' ║ ')) if status_family == 3
logger.info(' ', dimensions: Semantic::FancyDimensions.new(rails: '╓║╖')) if status_family == 5
end end
end end

1
lib/semantic/subscribers/action_view.rb

@ -9,7 +9,6 @@ module Semantic
def initialize def initialize
super(:action_view) super(:action_view)
logger.level = Hot::Constants.log_action_view ? :debug : :fatal
end end
def render_partial(event) def render_partial(event)

Loading…
Cancel
Save