Class: LogStruct::SemanticLogger::Logger
- Inherits:
-
SemanticLogger::Logger
- Object
- SemanticLogger::Logger
- LogStruct::SemanticLogger::Logger
- Extended by:
- T::Sig
- Includes:
- Concerns::LogMethods
- Defined in:
- lib/log_struct/semantic_logger/logger.rb
Overview
High-Performance Logger with LogStruct Integration
This logger extends SemanticLogger::Logger to provide optimal logging performance while seamlessly integrating with LogStruct's typed logging system.
Key Benefits Over Rails.logger:
Performance
- 10-100x faster than Rails' default logger for high-volume applications
- Non-blocking I/O: Uses background threads for actual log writes
- Minimal memory allocation: Efficient object reuse and zero-copy operations
- Batched writes: Reduces system calls by batching multiple log entries
Reliability
- Thread-safe operations: Safe for use in multi-threaded environments
- Error resilience: Logger failures don't crash your application
- Graceful fallbacks: Continues operating even if appenders fail
Features
- Structured logging: Native support for LogStruct types and hashes
- Rich metadata: Automatic inclusion of process ID, thread ID, timestamps
- Tagged context: Hierarchical tagging for request/job tracking
- Multiple destinations: Simultaneously log to files, STDOUT, cloud services
Development Experience
- Colorized output: Beautiful ANSI-colored logs in development
- Detailed timing: Built-in measurement of log processing time
- Context preservation: Maintains Rails.logger compatibility
Usage Examples
The logger automatically handles LogStruct types, hashes, and plain messages:
logger = LogStruct::SemanticLogger::Logger.new("MyApp")
# LogStruct typed logging (optimal performance)
log_entry = LogStruct::Log::Plain.new(
message: "User authenticated",
source: LogStruct::Source::App,
event: LogStruct::Event::Security
)
logger.info(log_entry)
# Hash logging (automatically structured)
logger.info({
action: "user_login",
user_id: 123,
ip_address: "192.168.1.1"
})
# Plain string logging (backward compatibility)
logger.info("User logged in successfully")
The logger is a drop-in replacement for Rails.logger and maintains full API compatibility while providing significantly enhanced performance.
Direct Known Subclasses
Integrations::GoodJob::Logger, Integrations::Sidekiq::Logger
Instance Attribute Summary collapse
-
#broadcasts ⇒ Array<T.untyped>
readonly
ActiveSupport::BroadcastLogger compatibility These methods allow Rails.logger to broadcast to multiple loggers.
-
#formatter ⇒ FormatterProxy
readonly
ActiveJob compatibility - expects logger.formatter.current_tags.
Instance Method Summary collapse
-
#<<(msg) ⇒ T.self_type
Support for << operator (used by RailsLogSplitter).
-
#broadcast_to(logger) ⇒ T.untyped
T.untyped for logger param because we accept any logger-like object: ::Logger, ActiveSupport::Logger, test doubles, etc.
- #clear_tags! ⇒ void
-
#current_tags ⇒ Array<String, Symbol>
Ensure compatibility with Rails.logger interface.
- #initialize(name = "Application", level: nil, filter: nil) ⇒ void constructor
- #pop_tags(count = 1) ⇒ void
- #push_tags(*tags) ⇒ Array<T.untyped>
- #stop_broadcasting_to(logger) ⇒ void
-
#tagged(*tags, &block) ⇒ T.untyped
Support for tagged logging.
Constructor Details
#initialize(name = "Application", level: nil, filter: nil) ⇒ void
70 71 72 73 74 75 76 77 78 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 70 def initialize(name = "Application", level: nil, filter: nil) # SemanticLogger::Logger expects positional arguments, not named arguments super(name, level, filter) # T.untyped because users can pass any logger: ::Logger, ActiveSupport::Logger, # custom loggers (FakeLogger in tests), or third-party loggers @broadcasts = T.let([], T::Array[T.untyped]) # ActiveJob expects logger.formatter to exist and respond to current_tags @formatter = T.let(FormatterProxy.new, FormatterProxy) end |
Instance Attribute Details
#broadcasts ⇒ Array<T.untyped> (readonly)
ActiveSupport::BroadcastLogger compatibility These methods allow Rails.logger to broadcast to multiple loggers
83 84 85 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 83 def broadcasts @broadcasts end |
#formatter ⇒ FormatterProxy (readonly)
ActiveJob compatibility - expects logger.formatter.current_tags
87 88 89 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 87 def formatter @formatter end |
Instance Method Details
#<<(msg) ⇒ T.self_type
Support for << operator (used by RailsLogSplitter)
143 144 145 146 147 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 143 def <<(msg) info(msg) @broadcasts.each { |logger| logger << msg if logger.respond_to?(:<<) } self end |
#broadcast_to(logger) ⇒ T.untyped
T.untyped for logger param because we accept any logger-like object: ::Logger, ActiveSupport::Logger, test doubles, etc.
92 93 94 95 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 92 def broadcast_to(logger) @broadcasts << logger logger end |
#clear_tags! ⇒ void
This method returns an undefined value.
123 124 125 126 127 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 123 def # SemanticLogger doesn't have clear_tags!, use pop_tags instead count = ::SemanticLogger..length ::SemanticLogger.(count) if count > 0 end |
#current_tags ⇒ Array<String, Symbol>
Ensure compatibility with Rails.logger interface
118 119 120 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 118 def ::SemanticLogger. end |
#pop_tags(count = 1) ⇒ void
This method returns an undefined value.
137 138 139 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 137 def (count = 1) ::SemanticLogger.(count) end |
#push_tags(*tags) ⇒ Array<T.untyped>
130 131 132 133 134 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 130 def (*) flat = .flatten.compact flat.each { |tag| ::SemanticLogger.(tag) } flat end |
#stop_broadcasting_to(logger) ⇒ void
This method returns an undefined value.
98 99 100 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 98 def stop_broadcasting_to(logger) @broadcasts.delete(logger) end |
#tagged(*tags, &block) ⇒ T.untyped
Support for tagged logging
106 107 108 109 110 111 112 113 114 |
# File 'lib/log_struct/semantic_logger/logger.rb', line 106 def tagged(*, &block) # Convert tags to array and pass individually to avoid splat issues tag_array = .flatten if tag_array.empty? super(&block) else super(*T.unsafe(tag_array), &block) end end |