smplkit 1.0.10 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42f9ef066eeb2612d4c6c4cc042933337e10562047eb41400506466a47ec4e99
4
- data.tar.gz: 69d8819176f26b5199f2c508a71d77397106bfabe0ea5b99b071a3e83199dd0d
3
+ metadata.gz: 45b89bb8091aeb0e42f1e6ccbf0b94cde98f827bae408770317658dd24c4de3c
4
+ data.tar.gz: 06eff16b91b28ef98f9fc2b7a64253d099154a6730a7ecbf1f2e99df9d8629c3
5
5
  SHA512:
6
- metadata.gz: 8f05531a8b81d3aa42895ed48f8e7b1680d9cf9a490c356b5ce4cf311b304d862964cb49e18b72e7e982ce1e351b2f7be2234c0be06be6c58cae3d3566c37c53
7
- data.tar.gz: f45d376af397dad147c4ae24100bdfd990766e511ce4a2de10539e3d358375098c413bf46f09c7f8e149d0333aa3c5efdca88baaebdd275ebda03490fff5370c
6
+ metadata.gz: 8f06ccbadf581ad0f7253ebb80ca35ecc6f1dcd94c63ad476bbfd742068702774f9b2dc416da6d6f035fd50502cebea17bfae6d8a203f4d0f4c39dec495c30ef
7
+ data.tar.gz: 6ac31365d9a694b9b11e0a8b00e7ca37c3a8fa5354fe678ef91fdc7bcd7a3ad257220b5521a4704ebdb210838c3e4ad120afe5dc4af01686f7339538510b0024
@@ -15,7 +15,15 @@ module Smplkit
15
15
  # SemanticLogger has its own internal logger registry and its own level
16
16
  # system that natively includes TRACE — a 1-to-1 map across all seven
17
17
  # smplkit canonical levels.
18
+ #
19
+ # New-logger detection uses +Module#prepend+ on +SemanticLogger::Logger+
20
+ # to intercept +initialize+. The hook is installed once globally and
21
+ # shared across all adapter instances via a class-level +@adapters+ list,
22
+ # matching the same pattern used by +StdlibLoggerAdapter+.
18
23
  class SemanticLoggerAdapter < Base
24
+ @hook_module = nil
25
+ @global_lock = Mutex.new
26
+
19
27
  def initialize
20
28
  super
21
29
  @loggers = Concurrent::Hash.new
@@ -33,8 +41,6 @@ module Smplkit
33
41
 
34
42
  def discover
35
43
  rows = []
36
- # Default named loggers SemanticLogger creates: itself + the global
37
- # one. Customers add more via +SemanticLogger[ClassOrName]+.
38
44
  all_loggers.each do |name, logger|
39
45
  level = logger.respond_to?(:level) ? logger.level : nil
40
46
  smpl_level = Levels.semantic_level_to_smpl(level)
@@ -55,25 +61,75 @@ module Smplkit
55
61
  def install_hook(&on_new_logger)
56
62
  @on_new = on_new_logger
57
63
  @uninstalled = false
58
- # SemanticLogger's API for new-logger interception varies across
59
- # versions. The Ruby SDK initial release relies on +discover+ being
60
- # called periodically — full prepend-based interception will be
61
- # filled in once tested against the targeted +semantic_logger+
62
- # version pinned in dev deps. (See ISSUES.md.)
64
+
65
+ self.class.global_lock.synchronize do
66
+ unless self.class.hook_installed?
67
+ hook = self.class.build_hook
68
+ ::SemanticLogger::Logger.prepend(hook)
69
+ self.class.instance_variable_set(:@hook_module, hook)
70
+ end
71
+ self.class.adapters << self unless self.class.adapters.include?(self)
72
+ end
63
73
  end
64
74
 
65
75
  def uninstall_hook
66
76
  @uninstalled = true
77
+ self.class.global_lock.synchronize do
78
+ self.class.adapters.delete(self)
79
+ end
80
+ end
81
+
82
+ # Called by the prepended hook when a new SemanticLogger::Logger is created.
83
+ def on_new_logger_created(logger)
84
+ return if @uninstalled
85
+
86
+ name = logger.name
87
+ return unless name
88
+
89
+ @loggers[name] = logger
90
+ level = logger.respond_to?(:level) ? logger.level : nil
91
+ smpl_level = Levels.semantic_level_to_smpl(level)
92
+ @on_new&.call(name, smpl_level, smpl_level)
93
+ rescue StandardError
94
+ nil
95
+ end
96
+
97
+ class << self
98
+ attr_reader :global_lock, :hook_module
99
+
100
+ def adapters
101
+ @adapters ||= Concurrent::Array.new
102
+ end
103
+
104
+ def hook_installed?
105
+ !@hook_module.nil?
106
+ end
107
+
108
+ # Uses define_method so the adapter_class reference is captured as a
109
+ # closure, avoiding constant-lookup issues in anonymous modules.
110
+ def build_hook
111
+ adapter_class = self
112
+ Module.new do
113
+ define_method(:initialize) do |klass, level = nil, filter = nil|
114
+ super(klass, level, filter)
115
+ adapter_class.adapters.each do |adapter|
116
+ adapter.on_new_logger_created(self)
117
+ rescue StandardError
118
+ # Don't let hook errors break logger creation.
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def reset_hook!
125
+ @hook_module = nil
126
+ end
67
127
  end
68
128
 
69
129
  private
70
130
 
71
131
  def all_loggers
72
132
  loggers = @loggers.dup
73
- if defined?(::SemanticLogger::Logger) && ::SemanticLogger::Logger.respond_to?(:processors)
74
- # No-op probe to keep this method tolerant of the live API.
75
- end
76
-
77
133
  if defined?(::SemanticLogger) &&
78
134
  ::SemanticLogger.respond_to?(:default_level) &&
79
135
  ::SemanticLogger.respond_to?(:[])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smplkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.10
4
+ version: 1.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Smpl Solutions LLC