Class: Smplkit::Logging::Adapters::SemanticLoggerAdapter

Inherits:
Base
  • Object
show all
Defined in:
lib/smplkit/logging/adapters/semantic_logger_adapter.rb

Overview

Adapter for the semantic_logger gem.

SemanticLogger has its own internal logger registry and its own level system that natively includes TRACE — a 1-to-1 map across all seven smplkit canonical levels.

New-logger detection uses Module#prepend on SemanticLogger::Logger to intercept initialize. The hook is installed once globally and shared across all adapter instances via a class-level @adapters list, matching the same pattern used by StdlibLoggerAdapter.

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSemanticLoggerAdapter

Returns a new instance of SemanticLoggerAdapter.



27
28
29
30
31
32
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 27

def initialize
  super
  @loggers = Concurrent::Hash.new
  @on_new = nil
  @uninstalled = false
end

Class Attribute Details

.global_lockObject (readonly)

Returns the value of attribute global_lock.



98
99
100
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 98

def global_lock
  @global_lock
end

.hook_moduleObject (readonly)

Returns the value of attribute hook_module.



98
99
100
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 98

def hook_module
  @hook_module
end

Class Method Details

.adaptersObject



100
101
102
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 100

def adapters
  @adapters ||= Concurrent::Array.new
end

.build_hookObject

Uses define_method so the adapter_class reference is captured as a closure, avoiding constant-lookup issues in anonymous modules.



110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 110

def build_hook
  adapter_class = self
  Module.new do
    define_method(:initialize) do |klass, level = nil, filter = nil|
      super(klass, level, filter)
      adapter_class.adapters.each do |adapter|
        adapter.on_new_logger_created(self)
      rescue StandardError
        # Don't let hook errors break logger creation.
      end
    end
  end
end

.hook_installed?Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 104

def hook_installed?
  !@hook_module.nil?
end

.reset_hook!Object



124
125
126
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 124

def reset_hook!
  @hook_module = nil
end

Instance Method Details

#apply_level(logger_name, level) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 53

def apply_level(logger_name, level)
  logger = @loggers[logger_name]
  return unless logger
  return unless logger.respond_to?(:level=)

  logger.level = Levels.smpl_level_to_semantic(level)
end

#discoverObject



42
43
44
45
46
47
48
49
50
51
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 42

def discover
  rows = []
  all_loggers.each do |name, logger|
    level = logger.respond_to?(:level) ? logger.level : nil
    smpl_level = Levels.semantic_level_to_smpl(level)
    rows << [name, smpl_level, smpl_level]
  end

  rows.uniq { |row| row[0] }
end

#install_hook(&on_new_logger) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 61

def install_hook(&on_new_logger)
  @on_new = on_new_logger
  @uninstalled = false

  self.class.global_lock.synchronize do
    unless self.class.hook_installed?
      hook = self.class.build_hook
      ::SemanticLogger::Logger.prepend(hook)
      self.class.instance_variable_set(:@hook_module, hook)
    end
    self.class.adapters << self unless self.class.adapters.include?(self)
  end
end

#nameObject



34
35
36
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 34

def name
  "semantic-logger"
end

#on_new_logger_created(logger) ⇒ Object

Called by the prepended hook when a new SemanticLogger::Logger is created.



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 83

def on_new_logger_created(logger)
  return if @uninstalled

  name = logger.name
  return unless name

  @loggers[name] = logger
  level = logger.respond_to?(:level) ? logger.level : nil
  smpl_level = Levels.semantic_level_to_smpl(level)
  @on_new&.call(name, smpl_level, smpl_level)
rescue StandardError
  nil
end

#track(name, logger) ⇒ Object



38
39
40
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 38

def track(name, logger)
  @loggers[name] = logger
end

#uninstall_hookObject



75
76
77
78
79
80
# File 'lib/smplkit/logging/adapters/semantic_logger_adapter.rb', line 75

def uninstall_hook
  @uninstalled = true
  self.class.global_lock.synchronize do
    self.class.adapters.delete(self)
  end
end