lumberjack_aziz_light 1.0.5
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 +7 -0
- data/MIT_LICENSE +20 -0
- data/README.rdoc +100 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/lib/lumberjack/device/date_rolling_log_file.rb +58 -0
- data/lib/lumberjack/device/log_file.rb +18 -0
- data/lib/lumberjack/device/null.rb +15 -0
- data/lib/lumberjack/device/rolling_log_file.rb +110 -0
- data/lib/lumberjack/device/size_rolling_log_file.rb +60 -0
- data/lib/lumberjack/device/writer.rb +129 -0
- data/lib/lumberjack/device.rb +26 -0
- data/lib/lumberjack/formatter/exception_formatter.rb +12 -0
- data/lib/lumberjack/formatter/inspect_formatter.rb +10 -0
- data/lib/lumberjack/formatter/pretty_print_formatter.rb +23 -0
- data/lib/lumberjack/formatter/string_formatter.rb +10 -0
- data/lib/lumberjack/formatter.rb +76 -0
- data/lib/lumberjack/log_entry.rb +36 -0
- data/lib/lumberjack/logger.rb +302 -0
- data/lib/lumberjack/rack/unit_of_work.rb +15 -0
- data/lib/lumberjack/rack.rb +5 -0
- data/lib/lumberjack/severity.rb +23 -0
- data/lib/lumberjack/template.rb +71 -0
- data/lib/lumberjack.rb +42 -0
- data/spec/device/date_rolling_log_file_spec.rb +66 -0
- data/spec/device/log_file_spec.rb +26 -0
- data/spec/device/null_spec.rb +12 -0
- data/spec/device/rolling_log_file_spec.rb +129 -0
- data/spec/device/size_rolling_log_file_spec.rb +54 -0
- data/spec/device/writer_spec.rb +118 -0
- data/spec/formatter/exception_formatter_spec.rb +20 -0
- data/spec/formatter/inspect_formatter_spec.rb +13 -0
- data/spec/formatter/pretty_print_formatter_spec.rb +14 -0
- data/spec/formatter/string_formatter_spec.rb +12 -0
- data/spec/formatter_spec.rb +45 -0
- data/spec/log_entry_spec.rb +69 -0
- data/spec/logger_spec.rb +390 -0
- data/spec/lumberjack_spec.rb +29 -0
- data/spec/rack/unit_of_work_spec.rb +26 -0
- data/spec/severity_spec.rb +23 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/template_spec.rb +34 -0
- metadata +92 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module Lumberjack
|
2
|
+
# This is an abstract class for logging devices. Subclasses must implement the +write+ method and
|
3
|
+
# may implement the +close+ and +flush+ methods if applicable.
|
4
|
+
class Device
|
5
|
+
autoload :DateRollingLogFile, File.expand_path("../device/date_rolling_log_file.rb", __FILE__)
|
6
|
+
autoload :LogFile, File.expand_path("../device/log_file.rb", __FILE__)
|
7
|
+
autoload :Null, File.expand_path("../device/null.rb", __FILE__)
|
8
|
+
autoload :RollingLogFile, File.expand_path("../device/rolling_log_file.rb", __FILE__)
|
9
|
+
autoload :SizeRollingLogFile, File.expand_path("../device/size_rolling_log_file.rb", __FILE__)
|
10
|
+
autoload :Writer, File.expand_path("../device/writer.rb", __FILE__)
|
11
|
+
|
12
|
+
# Subclasses must implement this method to write a LogEntry.
|
13
|
+
def write(entry)
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
# Subclasses may implement this method to close the device.
|
18
|
+
def close
|
19
|
+
flush
|
20
|
+
end
|
21
|
+
|
22
|
+
# Subclasses may implement this method to flush any buffers used by the device.
|
23
|
+
def flush
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Lumberjack
|
2
|
+
class Formatter
|
3
|
+
# Format an exception including the backtrace.
|
4
|
+
class ExceptionFormatter
|
5
|
+
def call(exception)
|
6
|
+
message = "#{exception.class.name}: #{exception.message}"
|
7
|
+
message << "#{Lumberjack::LINE_SEPARATOR} #{exception.backtrace.join("#{Lumberjack::LINE_SEPARATOR} ")}" if exception.backtrace
|
8
|
+
message
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Lumberjack
|
5
|
+
class Formatter
|
6
|
+
# Format an object with it's pretty print method.
|
7
|
+
class PrettyPrintFormatter
|
8
|
+
attr_accessor :width
|
9
|
+
|
10
|
+
# Create a new formatter. The maximum width of the message can be specified with the width
|
11
|
+
# parameter (defaults to 79 characters).
|
12
|
+
def initialize(width = 79)
|
13
|
+
@width = width
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(obj)
|
17
|
+
s = StringIO.new
|
18
|
+
PP.pp(obj, s)
|
19
|
+
s.string.chomp
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Lumberjack
|
2
|
+
# This class controls the conversion of log entry messages into strings. This allows you
|
3
|
+
# to log any object you want and have the logging system worry about converting it into a string.
|
4
|
+
#
|
5
|
+
# Formats are added to a Formatter by associating them with a class using the +add+ method. Formats
|
6
|
+
# are any object that responds to the +call+ method.
|
7
|
+
#
|
8
|
+
# By default, all object will be converted to strings using their inspect method except for Strings
|
9
|
+
# and Exceptions. Strings are not converted and Exceptions are converted using the ExceptionFormatter.
|
10
|
+
class Formatter
|
11
|
+
autoload :ExceptionFormatter, File.expand_path("../formatter/exception_formatter.rb", __FILE__)
|
12
|
+
autoload :InspectFormatter, File.expand_path("../formatter/inspect_formatter.rb", __FILE__)
|
13
|
+
autoload :PrettyPrintFormatter, File.expand_path("../formatter/pretty_print_formatter.rb", __FILE__)
|
14
|
+
autoload :StringFormatter, File.expand_path("../formatter/string_formatter.rb", __FILE__)
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@class_formatters = {}
|
18
|
+
@default_formatter = InspectFormatter.new
|
19
|
+
add(Object, @default_formatter)
|
20
|
+
add(String, :string)
|
21
|
+
add(Exception, :exception)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Add a formatter for a class. The formatter can be specified as either an object
|
25
|
+
# that responds to the +call+ method or as a symbol representing one of the predefined
|
26
|
+
# formatters, or as a block to the method call.
|
27
|
+
#
|
28
|
+
# The predefined formatters are: <tt>:inspect</tt>, <tt>:string</tt>, <tt>:exception</tt>, and <tt>:pretty_print</tt>.
|
29
|
+
#
|
30
|
+
# === Examples
|
31
|
+
#
|
32
|
+
# # Use a predefined formatter
|
33
|
+
# formatter.add(MyClass, :pretty_print)
|
34
|
+
#
|
35
|
+
# # Pass in a formatter object
|
36
|
+
# formatter.add(MyClass, Lumberjack::Formatter::PrettyPrintFormatter.new)
|
37
|
+
#
|
38
|
+
# # Use a block
|
39
|
+
# formatter.add(MyClass){|obj| obj.humanize}
|
40
|
+
#
|
41
|
+
# # Add statements can be chained together
|
42
|
+
# formatter.add(MyClass, :pretty_print).add(YourClass){|obj| obj.humanize}
|
43
|
+
def add(klass, formatter = nil, &block)
|
44
|
+
formatter ||= block
|
45
|
+
if formatter.is_a?(Symbol)
|
46
|
+
formatter_class_name = "#{formatter.to_s.gsub(/(^|_)([a-z])/){|m| $~[2].upcase}}Formatter"
|
47
|
+
formatter = Formatter.const_get(formatter_class_name).new
|
48
|
+
end
|
49
|
+
@class_formatters[klass] = formatter
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
# Remove the formatter associated with a class. Remove statements can be chained together.
|
54
|
+
def remove(klass)
|
55
|
+
@class_formatters.delete(klass)
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# Format a message object as a string.
|
60
|
+
def format(message)
|
61
|
+
formatter_for(message.class).call(message)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Find the formatter for a class by looking it up using the class hierarchy.
|
67
|
+
def formatter_for(klass) #:nodoc:
|
68
|
+
while klass != nil do
|
69
|
+
formatter = @class_formatters[klass]
|
70
|
+
return formatter if formatter
|
71
|
+
klass = klass.superclass
|
72
|
+
end
|
73
|
+
@default_formatter
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Lumberjack
|
2
|
+
# An entry in a log is a data structure that captures the log message as well as
|
3
|
+
# information about the system that logged the message.
|
4
|
+
class LogEntry
|
5
|
+
attr_accessor :time, :message, :severity, :progname, :pid, :unit_of_work_id
|
6
|
+
|
7
|
+
TIME_FORMAT = "%Y-%m-%dT%H:%M:%S".freeze
|
8
|
+
|
9
|
+
def initialize(time, severity, message, progname, pid, unit_of_work_id)
|
10
|
+
@time = time
|
11
|
+
@severity = (severity.is_a?(Fixnum) ? severity : Severity.label_to_level(severity))
|
12
|
+
@message = message
|
13
|
+
@progname = progname
|
14
|
+
@pid = pid
|
15
|
+
@unit_of_work_id = unit_of_work_id
|
16
|
+
end
|
17
|
+
|
18
|
+
def severity_label
|
19
|
+
Severity.level_to_label(severity)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
buf = "[#{time.strftime(TIME_FORMAT)}.#{(time.usec / 1000.0).round.to_s.rjust(3, '0')} #{severity_label} #{progname}(#{pid})"
|
24
|
+
if unit_of_work_id
|
25
|
+
buf << " #"
|
26
|
+
buf << unit_of_work_id
|
27
|
+
end
|
28
|
+
buf << "] "
|
29
|
+
buf << message
|
30
|
+
end
|
31
|
+
|
32
|
+
def inspect
|
33
|
+
to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,302 @@
|
|
1
|
+
module Lumberjack
|
2
|
+
# Logger is a thread safe logging object. It has a compatible API with the Ruby
|
3
|
+
# standard library Logger class, the Log4r gem, and ActiveSupport::BufferedLogger.
|
4
|
+
#
|
5
|
+
# === Example
|
6
|
+
#
|
7
|
+
# logger = Lumberjack::Logger.new
|
8
|
+
# logger.info("Starting processing")
|
9
|
+
# logger.debug("Processing options #{options.inspect}")
|
10
|
+
# logger.fatal("OMG the application is on fire!")
|
11
|
+
#
|
12
|
+
# Log entries are written to a logging Device if their severity meets or exceeds the log level.
|
13
|
+
#
|
14
|
+
# Devices may use buffers internally and the log entries are not guaranteed to be written until you call
|
15
|
+
# the +flush+ method. Sometimes this can result in problems when trying to track down extraordinarily
|
16
|
+
# long running sections of code since it is likely that none of the messages logged before the long
|
17
|
+
# running code will appear in the log until the entire process finishes. You can set the +:flush_seconds+
|
18
|
+
# option on the constructor to force the device to be flushed periodically. This will create a new
|
19
|
+
# monitoring thread, but its use is highly recommended.
|
20
|
+
#
|
21
|
+
# Each log entry records the log message and severity along with the time it was logged, the
|
22
|
+
# program name, process id, and unit of work id. The message will be converted to a string, but
|
23
|
+
# otherwise, it is up to the device how these values are recorded. Messages are converted to strings
|
24
|
+
# using a Formatter associated with the logger.
|
25
|
+
class Logger
|
26
|
+
include Severity
|
27
|
+
|
28
|
+
# The Formatter object used to convert messages into strings.
|
29
|
+
attr_reader :formatter
|
30
|
+
|
31
|
+
# The time that the device was last flushed.
|
32
|
+
attr_reader :last_flushed_at
|
33
|
+
|
34
|
+
# The name of the program associated with log messages.
|
35
|
+
attr_writer :progname
|
36
|
+
|
37
|
+
# The device being written to.
|
38
|
+
attr_reader :device
|
39
|
+
|
40
|
+
# Set +silencer+ to false to disable silencing the log.
|
41
|
+
attr_accessor :silencer
|
42
|
+
|
43
|
+
# Create a new logger to log to a Device.
|
44
|
+
#
|
45
|
+
# The +device+ argument can be in any one of several formats.
|
46
|
+
#
|
47
|
+
# If it is a Device object, that object will be used.
|
48
|
+
# If it has a +write+ method, it will be wrapped in a Device::Writer class.
|
49
|
+
# If it is <tt>:null</tt>, it will be a Null device that won't record any output.
|
50
|
+
# Otherwise, it will be assumed to be file path and wrapped in a Device::LogFile class.
|
51
|
+
#
|
52
|
+
# This method can take the following options:
|
53
|
+
#
|
54
|
+
# * <tt>:level</tt> - The logging level below which messages will be ignored.
|
55
|
+
# * <tt>:progname</tt> - The name of the program that will be recorded with each log entry.
|
56
|
+
# * <tt>:flush_seconds</tt> - The maximum number of seconds between flush calls.
|
57
|
+
# * <tt>:roll</tt> - If the log device is a file path, it will be a Device::DateRollingLogFile if this is set.
|
58
|
+
# * <tt>:max_size</tt> - If the log device is a file path, it will be a Device::SizeRollingLogFile if this is set.
|
59
|
+
#
|
60
|
+
# All other options are passed to the device constuctor.
|
61
|
+
def initialize(device = STDOUT, options = {})
|
62
|
+
@thread_settings = {}
|
63
|
+
|
64
|
+
options = options.dup
|
65
|
+
self.level = options.delete(:level) || INFO
|
66
|
+
self.progname = options.delete(:progname)
|
67
|
+
max_flush_seconds = options.delete(:flush_seconds).to_f
|
68
|
+
|
69
|
+
@device = open_device(device, options)
|
70
|
+
@formatter = Formatter.new
|
71
|
+
@lock = Mutex.new
|
72
|
+
@last_flushed_at = Time.now
|
73
|
+
@silencer = true
|
74
|
+
|
75
|
+
create_flusher_thread(max_flush_seconds) if max_flush_seconds > 0
|
76
|
+
end
|
77
|
+
|
78
|
+
# Get the level of severity of entries that are logged. Entries with a lower
|
79
|
+
# severity level will be ignored.
|
80
|
+
def level
|
81
|
+
thread_local_value(:lumberjack_logger_level) || @level
|
82
|
+
end
|
83
|
+
|
84
|
+
# Add a message to the log with a given severity. The message can be either
|
85
|
+
# passed in the +message+ argument or supplied with a block. This method
|
86
|
+
# is not normally called. Instead call one of the helper functions
|
87
|
+
# +fatal+, +error+, +warn+, +info+, or +debug+.
|
88
|
+
#
|
89
|
+
# The severity can be passed in either as one of the Severity constants,
|
90
|
+
# or as a Severity label.
|
91
|
+
#
|
92
|
+
# === Example
|
93
|
+
#
|
94
|
+
# logger.add(Lumberjack::Severity::ERROR, exception)
|
95
|
+
# logger.add(Lumberjack::Severity::INFO, "Request completed")
|
96
|
+
# logger.add(:warn, "Request took a long time")
|
97
|
+
# logger.add(Lumberjack::Severity::DEBUG){"Start processing with options #{options.inspect}"}
|
98
|
+
def add(severity, message = nil, progname = nil)
|
99
|
+
severity = Severity.label_to_level(severity) if severity.is_a?(String) || severity.is_a?(Symbol)
|
100
|
+
if severity && severity >= level
|
101
|
+
time = Time.now
|
102
|
+
message = yield if message.nil? && block_given?
|
103
|
+
message = @formatter.format(message)
|
104
|
+
entry = LogEntry.new(time, severity, message, progname || self.progname, $$, Lumberjack.unit_of_work_id)
|
105
|
+
begin
|
106
|
+
device.write(entry)
|
107
|
+
rescue => e
|
108
|
+
$stderr.puts("#{e.class.name}: #{e.message}#{' at ' + e.backtrace.first if e.backtrace}")
|
109
|
+
$stderr.puts(entry.to_s)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
|
115
|
+
alias_method :log, :add
|
116
|
+
|
117
|
+
# Flush the logging device. Messages are not guaranteed to be written until this method is called.
|
118
|
+
def flush
|
119
|
+
device.flush
|
120
|
+
@last_flushed_at = Time.now
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
|
124
|
+
# Close the logging device.
|
125
|
+
def close
|
126
|
+
flush
|
127
|
+
@device.close if @device.respond_to?(:close)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Log a +FATAL+ message. The message can be passed in either the +message+ argument or in a block.
|
131
|
+
def fatal(message = nil, progname = nil, &block)
|
132
|
+
add(FATAL, message, progname, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Return +true+ if +FATAL+ messages are being logged.
|
136
|
+
def fatal?
|
137
|
+
level <= FATAL
|
138
|
+
end
|
139
|
+
|
140
|
+
# Log an +ERROR+ message. The message can be passed in either the +message+ argument or in a block.
|
141
|
+
def error(message = nil, progname = nil, &block)
|
142
|
+
add(ERROR, message, progname, &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Return +true+ if +ERROR+ messages are being logged.
|
146
|
+
def error?
|
147
|
+
level <= ERROR
|
148
|
+
end
|
149
|
+
|
150
|
+
# Log a +WARN+ message. The message can be passed in either the +message+ argument or in a block.
|
151
|
+
def warn(message = nil, progname = nil, &block)
|
152
|
+
add(WARN, message, progname, &block)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Return +true+ if +WARN+ messages are being logged.
|
156
|
+
def warn?
|
157
|
+
level <= WARN
|
158
|
+
end
|
159
|
+
|
160
|
+
# Log an +INFO+ message. The message can be passed in either the +message+ argument or in a block.
|
161
|
+
def info(message = nil, progname = nil, &block)
|
162
|
+
add(INFO, message, progname, &block)
|
163
|
+
end
|
164
|
+
|
165
|
+
# Return +true+ if +INFO+ messages are being logged.
|
166
|
+
def info?
|
167
|
+
level <= INFO
|
168
|
+
end
|
169
|
+
|
170
|
+
# Log a +DEBUG+ message. The message can be passed in either the +message+ argument or in a block.
|
171
|
+
def debug(message = nil, progname = nil, &block)
|
172
|
+
add(DEBUG, message, progname, &block)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Return +true+ if +DEBUG+ messages are being logged.
|
176
|
+
def debug?
|
177
|
+
level <= DEBUG
|
178
|
+
end
|
179
|
+
|
180
|
+
# Log a message when the severity is not known. Unknown messages will always appear in the log.
|
181
|
+
# The message can be passed in either the +message+ argument or in a block.
|
182
|
+
def unknown(message = nil, progname = nil, &block)
|
183
|
+
add(UNKNOWN, message, progname, &block)
|
184
|
+
end
|
185
|
+
|
186
|
+
alias_method :<<, :unknown
|
187
|
+
|
188
|
+
# Set the minimum level of severity of messages to log.
|
189
|
+
def level=(severity)
|
190
|
+
if severity.is_a?(Fixnum)
|
191
|
+
@level = severity
|
192
|
+
else
|
193
|
+
@level = Severity.label_to_level(severity)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Silence the logger by setting a new log level inside a block. By default, only +ERROR+ or +FATAL+
|
198
|
+
# messages will be logged.
|
199
|
+
#
|
200
|
+
# === Example
|
201
|
+
#
|
202
|
+
# logger.level = Lumberjack::Severity::INFO
|
203
|
+
# logger.silence do
|
204
|
+
# do_something # Log level inside the block is +ERROR+
|
205
|
+
# end
|
206
|
+
def silence(temporary_level = ERROR, &block)
|
207
|
+
if silencer
|
208
|
+
push_thread_local_value(:lumberjack_logger_level, temporary_level, &block)
|
209
|
+
else
|
210
|
+
yield
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Set the program name that is associated with log messages. If a block
|
215
|
+
# is given, the program name will be valid only within the block.
|
216
|
+
def set_progname(value, &block)
|
217
|
+
if block
|
218
|
+
push_thread_local_value(:lumberjack_logger_progname, value, &block)
|
219
|
+
else
|
220
|
+
self.progname = value
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# Get the program name associated with log messages.
|
225
|
+
def progname
|
226
|
+
thread_local_value(:lumberjack_logger_progname) || @progname
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
|
231
|
+
# Set a local value for a thread tied to this object.
|
232
|
+
def set_thread_local_value(name, value) #:nodoc:
|
233
|
+
values = Thread.current[name]
|
234
|
+
unless values
|
235
|
+
values = {}
|
236
|
+
Thread.current[name] = values
|
237
|
+
end
|
238
|
+
if value.nil?
|
239
|
+
values.delete(self)
|
240
|
+
Thread.current[name] = nil if values.empty?
|
241
|
+
else
|
242
|
+
values[self] = value
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Get a local value for a thread tied to this object.
|
247
|
+
def thread_local_value(name) #:nodoc:
|
248
|
+
values = Thread.current[name]
|
249
|
+
values[self] if values
|
250
|
+
end
|
251
|
+
|
252
|
+
# Set a local value for a thread tied to this object within a block.
|
253
|
+
def push_thread_local_value(name, value) #:nodoc:
|
254
|
+
save_val = thread_local_value(name)
|
255
|
+
set_thread_local_value(name, value)
|
256
|
+
begin
|
257
|
+
yield
|
258
|
+
ensure
|
259
|
+
set_thread_local_value(name, save_val)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Open a logging device.
|
264
|
+
def open_device(device, options) #:nodoc:
|
265
|
+
if device.is_a?(Device)
|
266
|
+
device
|
267
|
+
elsif device.respond_to?(:write)
|
268
|
+
Device::Writer.new(device, options)
|
269
|
+
elsif device == :null
|
270
|
+
Device::Null.new
|
271
|
+
else
|
272
|
+
device = device.to_s
|
273
|
+
if options[:roll]
|
274
|
+
Device::DateRollingLogFile.new(device, options)
|
275
|
+
elsif options[:max_size]
|
276
|
+
Device::SizeRollingLogFile.new(device, options)
|
277
|
+
else
|
278
|
+
Device::LogFile.new(device, options)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Create a thread that will periodically call flush.
|
284
|
+
def create_flusher_thread(flush_seconds) #:nodoc:
|
285
|
+
if flush_seconds > 0
|
286
|
+
begin
|
287
|
+
logger = self
|
288
|
+
Thread.new do
|
289
|
+
loop do
|
290
|
+
begin
|
291
|
+
sleep(flush_seconds)
|
292
|
+
logger.flush if Time.now - logger.last_flushed_at >= flush_seconds
|
293
|
+
rescue => e
|
294
|
+
STDERR.puts("Error flushing log: #{e.inspect}")
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|