Class: Lumberjack::Device::Test
- Inherits:
-
Device
- Object
- Device
- Lumberjack::Device::Test
- Defined in:
- lib/lumberjack/device/test.rb
Overview
An in-memory logging device designed specifically for testing and debugging scenarios. This device captures log entries in a thread-safe buffer, allowing test code to make assertions about logged content, verify logging behavior, and inspect log entry details without writing to external outputs.
The device provides matching capabilities through integration with LogEntryMatcher, supporting pattern matching on messages, severity levels, attributes, and program names. This makes it ideal for comprehensive logging verification in test suites.
The buffer is automatically managed with configurable size limits to prevent memory issues during long-running tests, and provides both individual entry access and bulk matching operations.
Instance Attribute Summary collapse
-
#entry_formatter ⇒ Lumberjack::EntryFormatter?
Entry formatter used by
include?,match, andclosest_matchwhen building matchers. -
#max_entries ⇒ Integer
The maximum number of entries to retain in the buffer.
-
#options ⇒ Hash
readonly
Configuration options passed to the constructor.
Class Method Summary collapse
-
.formatted_expectation(expectation, indent: 0) ⇒ String
Format a log entry or expectation hash into a more human readable format.
Instance Method Summary collapse
-
#clear ⇒ void
Clear all captured log entries from the buffer.
-
#closest_match(message: nil, severity: nil, attributes: nil, progname: nil, formatter: nil) ⇒ Lumberjack::LogEntry?
Get the closest matching log entry from the captured entries based on a scoring system.
-
#entries ⇒ Array<Lumberjack::LogEntry>
Return a thread-safe copy of all captured log entries.
-
#include?(options) ⇒ Boolean
Test whether any captured log entries match the specified criteria.
-
#initialize(options = {}) ⇒ Test
constructor
Initialize a new Test device with configurable buffer management.
-
#last_entry ⇒ Lumberjack::LogEntry?
Return the most recently captured log entry.
-
#match(message: nil, severity: nil, attributes: nil, progname: nil, formatter: nil) ⇒ Lumberjack::LogEntry?
Find and return the first captured log entry that matches the specified criteria.
-
#write(entry) ⇒ void
Write a log entry to the in-memory buffer.
-
#write_to(logger) ⇒ void
Write the captured log entries out to another logger or device.
Constructor Details
#initialize(options = {}) ⇒ Test
Initialize a new Test device with configurable buffer management. The device creates a thread-safe in-memory buffer for capturing log entries with automatic size management to prevent memory issues.
175 176 177 178 179 180 181 |
# File 'lib/lumberjack/device/test.rb', line 175 def initialize( = {}) @buffer = [] @max_entries = [:max_entries] || 1000 @entry_formatter = [:entry_formatter] @lock = Mutex.new @options = .dup end |
Instance Attribute Details
#entry_formatter ⇒ Lumberjack::EntryFormatter?
Entry formatter used by include?, match, and closest_match when
building matchers. Log entries are captured after the logger's formatter
has been applied, so setting this to the same formatter used by the logger
allows expectations to be written with unformatted values:
logger.device.entry_formatter = logger.formatter
98 99 100 |
# File 'lib/lumberjack/device/test.rb', line 98 def entry_formatter @entry_formatter end |
#max_entries ⇒ Integer
Returns The maximum number of entries to retain in the buffer.
80 81 82 |
# File 'lib/lumberjack/device/test.rb', line 80 def max_entries @max_entries end |
#options ⇒ Hash (readonly)
Configuration options passed to the constructor. While these don't affect device behavior, they can be useful in tests to verify that options are correctly passed through device creation and configuration pipelines.
87 88 89 |
# File 'lib/lumberjack/device/test.rb', line 87 def @options end |
Class Method Details
.formatted_expectation(expectation, indent: 0) ⇒ String
Format a log entry or expectation hash into a more human readable format. This is
intended for use in test failure messages to help diagnose why a match failed when
calling include? or match.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/lumberjack/device/test.rb', line 112 def formatted_expectation(expectation, indent: 0) if expectation.is_a?(Lumberjack::LogEntry) expectation = { "severity" => expectation.severity_label, "message" => expectation., "progname" => expectation.progname, "attributes" => expectation.attributes } end expectation = expectation.transform_keys(&:to_s).compact severity = Lumberjack::Severity.coerce(expectation["severity"]) if expectation.include?("severity") = [] indent_str = " " * indent << "#{indent_str}severity: #{Lumberjack::Severity.level_to_label(severity)}" if severity << "#{indent_str}message: #{expectation["message"]}" if expectation.include?("message") << "#{indent_str}progname: #{expectation["progname"]}" if expectation.include?("progname") expected_attributes = expectation["attributes"] if expected_attributes.is_a?(Hash) unless expected_attributes.empty? attributes = Lumberjack::Utils.flatten_attributes(expected_attributes) label = "attributes:" prefix = "#{indent_str}#{label}" attributes.sort_by(&:first).each do |name, value| << "#{prefix} #{name}: #{formatted_value(value)}" prefix = "#{indent_str}#{" " * label.length}" end end elsif expected_attributes # Matchers like RSpec's hash_including are matched against the attributes hash as a whole. << "#{indent_str}attributes: #{formatted_value(expected_attributes)}" end .join(Lumberjack::LINE_SEPARATOR) end |
Instance Method Details
#clear ⇒ void
This method returns an undefined value.
Clear all captured log entries from the buffer. This method is useful for resetting the device state between tests or when you want to start fresh log capture without creating a new device instance.
227 228 229 230 |
# File 'lib/lumberjack/device/test.rb', line 227 def clear @lock.synchronize { @buffer = [] } nil end |
#closest_match(message: nil, severity: nil, attributes: nil, progname: nil, formatter: nil) ⇒ Lumberjack::LogEntry?
Get the closest matching log entry from the captured entries based on a scoring system. This method evaluates how well each entry matches the specified criteria and returns the entry with the highest score, provided it meets a minimum threshold. If no entries meet the threshold, nil is returned.
This method can be used in tests to return the best match when an assertion fails to aid in diagnosing why no entries met the criteria.
383 384 385 386 387 388 389 390 391 392 |
# File 'lib/lumberjack/device/test.rb', line 383 def closest_match(message: nil, severity: nil, attributes: nil, progname: nil, formatter: nil) matcher = LogEntryMatcher.new( message: , severity: severity, attributes: attributes, progname: progname, formatter: formatter || entry_formatter ) matcher.closest(entries) end |
#entries ⇒ Array<Lumberjack::LogEntry>
Return a thread-safe copy of all captured log entries. The returned array is a snapshot of the current buffer state and can be safely modified without affecting the internal buffer.
208 209 210 |
# File 'lib/lumberjack/device/test.rb', line 208 def entries @lock.synchronize { @buffer.dup } end |
#include?(options) ⇒ Boolean
Test whether any captured log entries match the specified criteria. This method provides a convenient interface for making assertions about logged content using flexible pattern matching capabilities.
Severity can be specified as a numeric constant (Logger::WARN), symbol
(:warn), or string ("warn"). Messages support exact string matching or
regular expression patterns. Attributes support nested matching using
dot notation and can use any matcher values supported by your test
framework (e.g., RSpec's anything, instance_of, etc.).
302 303 304 305 |
# File 'lib/lumberjack/device/test.rb', line 302 def include?() = .transform_keys(&:to_sym) !!match(**) end |
#last_entry ⇒ Lumberjack::LogEntry?
Return the most recently captured log entry. This provides quick access to the latest logged information without needing to access the full entries array.
218 219 220 |
# File 'lib/lumberjack/device/test.rb', line 218 def last_entry @lock.synchronize { @buffer.last } end |
#match(message: nil, severity: nil, attributes: nil, progname: nil, formatter: nil) ⇒ Lumberjack::LogEntry?
Find and return the first captured log entry that matches the specified criteria. This method is useful when you need to inspect specific entry details or perform more complex assertions on individual entries.
Uses the same flexible matching capabilities as include? but returns the actual LogEntry object instead of a boolean result.
350 351 352 353 354 355 356 357 358 359 |
# File 'lib/lumberjack/device/test.rb', line 350 def match(message: nil, severity: nil, attributes: nil, progname: nil, formatter: nil) matcher = LogEntryMatcher.new( message: , severity: severity, attributes: attributes, progname: progname, formatter: formatter || entry_formatter ) entries.detect { |entry| matcher.match?(entry) } end |
#write(entry) ⇒ void
This method returns an undefined value.
Write a log entry to the in-memory buffer. The method is thread-safe and automatically manages buffer size by removing the oldest entries when the maximum capacity is exceeded. Entries are ignored if max_entries is set to less than 1.
190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/lumberjack/device/test.rb', line 190 def write(entry) return if max_entries < 1 @lock.synchronize do @buffer << entry while @buffer.size > max_entries @buffer.shift end end end |
#write_to(logger) ⇒ void
This method returns an undefined value.
Write the captured log entries out to another logger or device. This can be useful in testing scenarios where you want to preserve log output for failed tests.
238 239 240 241 242 243 244 245 |
# File 'lib/lumberjack/device/test.rb', line 238 def write_to(logger) device = (logger.is_a?(Lumberjack::Device) ? logger : logger.device) entries.each do |entry| device.write(entry) end nil end |