buffered_logger 0.0.2 → 0.1.0

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.
data/README ADDED
@@ -0,0 +1,105 @@
1
+ ABOUT
2
+ -------------------------------------------------------------------------------
3
+ The 'buffered_logger' gem is an extension to ActiveSupport::BufferedLogger which
4
+ gives the the little logger some much needed formatting support. The actual
5
+ logging work is still delegated to to active_support/buffered_logger.
6
+
7
+
8
+ FEATURES
9
+ -------------------------------------------------------------------------------
10
+ - per thread indentation
11
+ - per thread auto flush setting
12
+ - temporary indentation blocks
13
+ - per severity formatting
14
+ - ansi color output formats
15
+
16
+
17
+ USAGE
18
+ -------------------------------------------------------------------------------
19
+ # default initialization
20
+ l = BufferedLogger.new(STDOUT)
21
+
22
+ # changing the severity level
23
+ l.level = :warn
24
+ l.level = 1
25
+
26
+ # formatter constructor (initializes the master thread's formatters)
27
+ l = BufferedLogger.new(STDOUT, :debug,
28
+ { :info => "$green INFO: $white %s",
29
+ :warn => "$yellow WARNING: $white %s",
30
+ :error => "$red ERROR: $white %s" } )
31
+
32
+ # setting formatting after initialization
33
+ l.info_formatter = "$green INFO: $white %s",
34
+ l.warn_formatter = "$yellow WARNING: $white %s"
35
+ l.error_formatter = "$red ERROR: $white %s"
36
+
37
+ # checking the current thread's formatting
38
+ l.info_formatter.to_s
39
+ l.warn_formatter.to_s
40
+ ...
41
+
42
+ # checking the current thread's indentation
43
+ l.padding.to_s
44
+
45
+ # setting the current thread's indentation
46
+ l.indent(4) # move cursor right 4 spaces
47
+ l.indent(-2) # move cursor left 2 spaces
48
+ l.indent(:reset) # reset indentation
49
+
50
+ # temporarily indenting using an indent block
51
+ l.indent do
52
+ l.info 'some info'
53
+ ...
54
+ l.info 'some more info'
55
+ end
56
+
57
+ # setting auto_flushing
58
+ l.auto_flushing = 2
59
+
60
+
61
+ USAGE DETAILS
62
+ -------------------------------------------------------------------------------
63
+ * Severity Levels
64
+ - severity level is optional and defaults to :debug
65
+ - severity level can be provided as an Integer or Symbol
66
+ 0 - DEBUG
67
+ 1 - INFO
68
+ 2 - WARN
69
+ 3 - ERROR
70
+ 4 - FATAL
71
+ 5 - UNKNOWN
72
+
73
+ * ActiveSupport::BufferedLogger
74
+ - native buffered_logger functionality is preserved
75
+ $ ActiveSupport::BufferedLogger.public_instance_methods(false)
76
+ => ["add", "info", "fatal?", "auto_flushing", "fatal", "silencer", "debug",
77
+ "info?", "warn?", "auto_flushing=", "silencer=", "level", "error?", "unknown",
78
+ "debug?", "flush", "level=", "open_log", "warn", "unknown?", "silence",
79
+ "error", "close"]
80
+
81
+ * ANSI Color
82
+ - colors are only supported when logging to STDOUT
83
+ - any ansi method may be used in a format string following a '$' symbol
84
+ $ Term::ANSIColor.instance_methods
85
+ => ["black", "on_yellow", "underscore", "rapid_blink", "white", "bold",
86
+ "yellow", "on_cyan", "strikethrough", "on_green", "uncolored", "blink",
87
+ "cyan", "reset", "green", "on_magenta", "clear", "concealed", "on_red",
88
+ "dark", "underline", "magenta", "red", "on_blue", "negative", "on_black",
89
+ "italic", "blue", "on_white"]
90
+
91
+ * Indentation
92
+ - the padding is calculated on a per thread basis and each thread has an
93
+ indentation counter which is shared across all severity levels
94
+
95
+ * Formatting
96
+ - formatters are set on a per thread/per severity basis, meaning that every
97
+ severity level for every thread allows for a custom formatter
98
+ - the formatter search order is as follows
99
+ 1. current thread's formatter for specified severity
100
+ 2. master thread's formatter for specified severity
101
+ 3. master thread's default formatter
102
+
103
+ * Thread Buffering
104
+ - the auto_flushing setting is set per thread and each thread defaults to
105
+ the autoflush setting of the master thread unless explicitly configured
data/TODO ADDED
@@ -0,0 +1,3 @@
1
+ TODO
2
+ - tests for Buffering module
3
+ - tests for Logger (include classic functionality)
@@ -0,0 +1,66 @@
1
+ module BufferedLogger::Buffering
2
+ MAX_BUFFER_SIZE = 1000
3
+
4
+ def initialize
5
+ @buffer = Hash.new { |h,k| h[k] = [] }
6
+ @auto_flushing = BufferedLogger::ThreadHash.new
7
+ @auto_flushing[master_thread] = 1
8
+ @guard = Mutex.new
9
+ super()
10
+ end
11
+
12
+ def buffer_text
13
+ buffer.join('')
14
+ end
15
+
16
+ def auto_flushing
17
+ @auto_flushing[Thread.current] || @auto_flushing[master_thread]
18
+ end
19
+
20
+ # Set the auto-flush period. Set to true to flush after every log message,
21
+ # to an integer to flush every N messages, or to false, nil, or zero to
22
+ # never auto-flush. If you turn auto-flushing off, be sure to regularly
23
+ # flush the log yourself -- it will eat up memory until you do.
24
+ def auto_flushing=(period)
25
+ @auto_flushing[Thread.current] =
26
+ case period
27
+ when true; 1
28
+ when false, nil, 0; MAX_BUFFER_SIZE
29
+ when Integer; period
30
+ else raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}"
31
+ end
32
+ end
33
+
34
+ def flush
35
+ @guard.synchronize do
36
+ buffer.each do |content|
37
+ @log.write(content)
38
+ end
39
+
40
+ # Important to do this even if buffer was empty or else @buffer will
41
+ # accumulate empty arrays for each request where nothing was logged.
42
+ clear_buffer
43
+ end
44
+ end
45
+
46
+ def close
47
+ flush
48
+ @log.close if @log.respond_to?(:close)
49
+ @log = nil
50
+ end
51
+
52
+ private
53
+
54
+ def auto_flush
55
+ flush if buffer.size >= auto_flushing
56
+ end
57
+
58
+ def buffer
59
+ @buffer[Thread.current]
60
+ end
61
+
62
+ def clear_buffer
63
+ @buffer.delete(Thread.current)
64
+ end
65
+
66
+ end
@@ -0,0 +1,92 @@
1
+ require 'term/ansicolor'
2
+
3
+ module BufferedLogger::Formatting
4
+ DEFAULT_LEVEL = :default
5
+
6
+ private
7
+
8
+ def initialize
9
+ @formatter = BufferedLogger::ThreadHash.new { |h,k| h[k] = {} }
10
+ super()
11
+ end
12
+
13
+ def formatter(severity = DEFAULT_LEVEL)
14
+ @formatter[Thread.current][severity] || @formatter[master_thread][severity] || default_formatter
15
+ end
16
+
17
+ def set_formatter(severity = DEFAULT_LEVEL, format = nil)
18
+ @formatter[Thread.current][severity] = BufferedLogger::Formatter.new(:format => format, :color => color?)
19
+ end
20
+
21
+ def default_formatter
22
+ @formatter[master_thread][DEFAULT_LEVEL] ||= BufferedLogger::Formatter.new(:color => color?)
23
+ end
24
+
25
+ # magic format getters/setters
26
+
27
+ def method_missing(method, *args, &block)
28
+ case method.to_s
29
+ when /^(#{BufferedLogger::SEVERITY_LEVELS.join('|')})_formatter(=)?$/
30
+ $2 ? set_formatter($1.to_sym, args[0]) : formatter($1.to_sym)
31
+ else
32
+ super(method, *args, &block)
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+
39
+ class BufferedLogger::Formatter
40
+ include ::Term::ANSIColor
41
+
42
+ FORMAT = "%s"
43
+ COLOR = true
44
+
45
+ def initialize(params = {})
46
+ @format = params[:format] || FORMAT
47
+ @color = params[:color] == false ? false : COLOR
48
+ end
49
+
50
+ # format accessors
51
+
52
+ def to_s
53
+ @format
54
+ end
55
+
56
+ def format=(format)
57
+ @format = format.to_s
58
+ end
59
+
60
+ # color accessors
61
+
62
+ def color?
63
+ @color
64
+ end
65
+
66
+ def toggle_color
67
+ @color = !@color
68
+ end
69
+
70
+ # formatting
71
+
72
+ def %(message)
73
+ formatted_message = @format % message.to_s
74
+ color? ? parse_color(formatted_message) : formatted_message
75
+ end
76
+
77
+ private
78
+
79
+ def parse_color(message)
80
+ color_methods = Term::ANSIColor.instance_methods
81
+ color_matcher = /#{color_methods.map {|m| "\\$#{m}\\s?"}.join('|')}/
82
+
83
+ strings = message.split(color_matcher)
84
+ colors = message.scan(color_matcher).map { |c| c[1..-1].strip }
85
+
86
+ colored_message = ''
87
+ strings[1..-1].each_with_index { |s,i| colored_message << self.send(colors[i], s) }
88
+ strings[0] + colored_message
89
+ end
90
+
91
+ end
92
+
@@ -0,0 +1,61 @@
1
+ module BufferedLogger::Indentation
2
+ # padding is set at the thread level
3
+
4
+ def initialize
5
+ @padding = BufferedLogger::ThreadHash.new { |h,k| h[k] = BufferedLogger::Padding.new }
6
+ super()
7
+ end
8
+
9
+ def padding
10
+ @padding[Thread.current]
11
+ end
12
+
13
+ def indent(level, &block)
14
+ if block_given?
15
+ padding.indent(level)
16
+ ret_val = block.call
17
+ padding.indent(-level)
18
+ return ret_val
19
+ else
20
+ padding.indent(level)
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ class BufferedLogger::Padding
27
+ PADDING_CHAR = ' '
28
+ PADDING_RESET= :reset
29
+ attr_reader :padding_char
30
+
31
+ def initialize(params = {})
32
+ @padding = ''
33
+ @padding_char = params[:padding_char] || PADDING_CHAR
34
+ indent(params[:indent] || 0)
35
+ end
36
+
37
+ def padding_char=(char)
38
+ @padding_char = char.to_s[0..1]
39
+ end
40
+
41
+ def to_s
42
+ @padding
43
+ end
44
+
45
+ def indent(indent_level)
46
+ @padding = \
47
+ if indent_level == PADDING_RESET
48
+ ''
49
+ elsif indent_level > 0
50
+ @padding + (@padding_char * indent_level)
51
+ else
52
+ @padding[0..(-1+indent_level)]
53
+ end
54
+ indent_level
55
+ end
56
+
57
+ def %(message)
58
+ @padding + message.to_s
59
+ end
60
+
61
+ end
@@ -0,0 +1,114 @@
1
+ require 'thread'
2
+ require 'active_support/core_ext/class'
3
+
4
+ class BufferedLogger
5
+ include Indentation
6
+ include Formatting
7
+ include Buffering
8
+
9
+ module Severity
10
+ DEBUG = 0
11
+ INFO = 1
12
+ WARN = 2
13
+ ERROR = 3
14
+ FATAL = 4
15
+ UNKNOWN = 5
16
+ end
17
+ include Severity
18
+
19
+ SEVERITY_LEVELS = Severity.constants.map { |c| c.downcase.to_sym }.freeze
20
+ SEVERITY_MAP = Severity.constants.inject({}) do |h,c|
21
+ h[c.downcase.to_sym] = Severity.const_get(c); h
22
+ end.freeze
23
+
24
+
25
+ ##
26
+ # :singleton-method:
27
+ # Set to false to disable the silencer
28
+ cattr_accessor :silencer
29
+ self.silencer = true
30
+
31
+ attr_accessor :level
32
+ attr_reader :master_thread
33
+ private :master_thread
34
+
35
+ def initialize(log, level = DEBUG, params = {})
36
+ @master_thread = Thread.current
37
+ super()
38
+
39
+ @level = severity_to_const(level)
40
+ if log.respond_to?(:write)
41
+ @log = log
42
+ elsif File.exist?(log)
43
+ @log = open_log(log, (File::WRONLY | File::APPEND))
44
+ else
45
+ FileUtils.mkdir_p(File.dirname(log))
46
+ @log = open_log(log, (File::WRONLY | File::APPEND | File::CREAT))
47
+ end
48
+ params.each { |k,v| SEVERITY_LEVELS.include?(k) ? set_formatter(k, v) : next }
49
+ end
50
+
51
+ def open_log(log, mode)
52
+ open(log, mode).tap do |open_log|
53
+ open_log.set_encoding(Encoding::BINARY) if open_log.respond_to?(:set_encoding)
54
+ open_log.sync = true
55
+ end
56
+ end
57
+
58
+ def add(severity, message = nil, progname = nil, &block)
59
+ return if @level > severity
60
+ message = (message || (block && block.call) || progname).to_s
61
+ # If a newline is necessary then create a new message ending with a newline.
62
+ # Ensures that the original message is not mutated.
63
+ message = "#{message}\n" unless message[-1] == ?\n
64
+ buffer << message
65
+ auto_flush
66
+ message
67
+ end
68
+
69
+ for severity in SEVERITY_LEVELS
70
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
71
+ def #{severity}(message = nil, progname = nil, &block)
72
+ add(#{SEVERITY_MAP[severity]}, padding % (formatter(:#{severity}) % message.to_s), progname, &block)
73
+ nil
74
+ end
75
+
76
+ def #{severity}?
77
+ #{SEVERITY_MAP[severity]} >= @level
78
+ end
79
+ EOT
80
+ end
81
+
82
+ # Silences the logger for the duration of the block.
83
+ def silence(temporary_level = ERROR)
84
+ if silencer
85
+ begin
86
+ old_logger_level, self.level = level, temporary_level
87
+ yield self
88
+ ensure
89
+ self.level = old_logger_level
90
+ end
91
+ else
92
+ yield self
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ def color?
99
+ @log == STDOUT
100
+ end
101
+
102
+ def severity_to_const(severity)
103
+ case severity
104
+ when Integer
105
+ severity
106
+ when Symbol
107
+ SEVERITY_MAP[severity]
108
+ else
109
+ severity.to_i
110
+ end
111
+ end
112
+
113
+ end
114
+
@@ -0,0 +1,12 @@
1
+ class BufferedLogger::ThreadHash < Hash
2
+
3
+ def []=(k,v)
4
+ sweep if !include?(k) && k.is_a?(Thread)
5
+ super
6
+ end
7
+
8
+ def sweep
9
+ self.delete_if { |k,v| k.is_a?(Thread) && !k.alive? }
10
+ end
11
+
12
+ end
@@ -1,58 +1,7 @@
1
- require 'rubygems'
2
- require 'active_support/buffered_logger'
3
- require 'forwardable'
1
+ class BufferedLogger; end
4
2
 
5
- class BufferedLogger
6
- extend Forwardable
7
-
8
- def_delegators :@logger, :level, :flush, :auto_flushing=
9
-
10
- DEFAULT_FORMATTER = "%s"
11
- DEFAULT_PADDING = ""
12
- PADDING_CHAR = " "
13
-
14
- def initialize(log_file, log_level, log_count = nil, log_size = nil)
15
- @logger = ActiveSupport::BufferedLogger.new(log_file, log_level)
16
- @padding, @formatter = {}, {}
17
- end
18
-
19
- def buffer
20
- buf = @logger.send(:buffer)
21
- buf && buf.join('')
22
- end
23
-
24
- # overwrite all the logging methods
25
- class_eval do
26
- [:debug, :info, :warn, :error, :fatal, :unknown].each do |method|
27
- define_method(method) do |message|
28
- @logger.send(method, (padding + formatter) % message.to_s)
29
- end
30
- end
31
- end
32
-
33
- def indent(indent_level)
34
- @padding[Thread.current] = \
35
- if indent_level == :reset
36
- ""
37
- elsif indent_level > 0
38
- padding + (PADDING_CHAR * indent_level)
39
- else
40
- padding[0..(-1+indent_level)]
41
- end
42
- end
43
-
44
- def formatter=(format)
45
- @formatter[Thread.current] = format
46
- end
47
-
48
- protected
49
-
50
- def padding
51
- @padding[Thread.current] ||= DEFAULT_PADDING
52
- end
53
-
54
- def formatter
55
- @formatter[Thread.current] ||= DEFAULT_FORMATTER
56
- end
57
-
58
- end
3
+ require 'buffered_logger/thread_hash'
4
+ require 'buffered_logger/buffering'
5
+ require 'buffered_logger/indentation'
6
+ require 'buffered_logger/formatting'
7
+ require 'buffered_logger/logger'
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe BufferedLogger do
4
+ before :each do
5
+ @f = StringIO.new
6
+ @l = BufferedLogger.new(@f)
7
+ end
8
+
9
+ describe 'buffering' do
10
+ end
11
+
12
+ end
@@ -0,0 +1,120 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe BufferedLogger::Formatter do
4
+ before :each do
5
+ @f = BufferedLogger::Formatter.new
6
+ end
7
+
8
+ describe 'initialization and accessors' do
9
+ it "should init a new formatter object" do
10
+ @f.should be_an_instance_of BufferedLogger::Formatter
11
+ end
12
+
13
+ it "should return the default format string" do
14
+ @f.to_s.should == '%s'
15
+ end
16
+
17
+ it "should set the format string" do
18
+ @f.format = '%d'
19
+ @f.to_s.should == '%d'
20
+ end
21
+
22
+ it 'should check if color is enabled by default' do
23
+ @f.color?.should be_true
24
+ end
25
+
26
+ it 'should toggle the color setting' do
27
+ @f.toggle_color
28
+ @f.color?.should be_false
29
+ @f.toggle_color
30
+ @f.color?.should be_true
31
+ end
32
+
33
+ it 'should construct a formatter object based on params' do
34
+ f = BufferedLogger::Formatter.new(:format => '%s%s%s', :color => false)
35
+ f.to_s.should == '%s%s%s'
36
+ f.color?.should be_false
37
+ end
38
+ end
39
+
40
+ describe 'formatting' do
41
+ it 'should parse color codes' do
42
+ s = "$blue blue $green green $red red"
43
+ @f.send(:parse_color, s).should == "\e[34mblue \e[0m\e[32mgreen \e[0m\e[31mred\e[0m"
44
+ end
45
+
46
+ it 'should format an input string' do
47
+ s = 'text'
48
+ (@f % s).should == 'text'
49
+ @f.format = '### %s ###'
50
+ (@f % s).should == '### text ###'
51
+ @f.format = '$blue ### $red %s $blue ###'
52
+ (@f % s).should == "\e[34m### \e[0m\e[31mtext \e[0m\e[34m###\e[0m"
53
+ end
54
+ end
55
+ end
56
+
57
+ describe BufferedLogger do
58
+ before :each do
59
+ @f = StringIO.new
60
+ @l = BufferedLogger.new(@f)
61
+ end
62
+
63
+ describe 'formatting' do
64
+ it 'should use appropriate formatting for each thread' do
65
+ @l.send(:set_formatter, :info, "$blue %s")
66
+ @l.info "oh"
67
+
68
+ t = Thread.new do
69
+ @l.send(:set_formatter, :info, "$red %s")
70
+ @l.info 'blah'
71
+ end; t.join
72
+
73
+ t = Thread.new do
74
+ @l.info 'hey'
75
+ end; t.join
76
+
77
+ @l.info "haha"
78
+
79
+ # colors are off so the keywords won't be parsed
80
+ @f.string.should == "$blue oh\n$red blah\n$blue hey\n$blue haha\n"
81
+ end
82
+
83
+ it 'should use appropriate formatting for each severity level' do
84
+ @l.send(:set_formatter, :error, "$red %s")
85
+ @l.send(:set_formatter, :info, "$blue %s")
86
+ @l.error 'error'
87
+ @l.info 'info'
88
+ @f.string.should == "$red error\n$blue info\n"
89
+ end
90
+
91
+ it 'should use the master thread formatter if one isnt set' do
92
+ @l.send(:set_formatter, :error, "$red %s")
93
+ @l.error 'test'
94
+
95
+ t = Thread.new do
96
+ @l.error 'blah'
97
+ end; t.join
98
+ @f.string.should == "$red test\n$red blah\n"
99
+ end
100
+
101
+ it 'should use the master thread default formatter if one isnt set' do
102
+ t_formatter = nil
103
+ t = Thread.new do
104
+ t_formatter = @l.send(:formatter, :info)
105
+ end; t.join
106
+
107
+ t_formatter.should == @l.send(:formatter, :info)
108
+ t_formatter.should == @l.send(:formatter, :error)
109
+ end
110
+
111
+ it 'should allow syntactic sugar to get/set formatters' do
112
+ BufferedLogger::SEVERITY_LEVELS.each do |s|
113
+ @l.send("#{s}_formatter=", "$green #{s}: $white %s")
114
+ @l.send("#{s}_formatter").to_s.should == "$green #{s}: $white %s"
115
+ end
116
+ end
117
+
118
+ end
119
+
120
+ end
@@ -0,0 +1,92 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+
3
+ describe BufferedLogger::Padding do
4
+
5
+ before :each do
6
+ @p = BufferedLogger::Padding.new
7
+ end
8
+
9
+ describe 'initialization and accessors' do
10
+ it "should initialize a new padding object" do
11
+ @p.should be_an_instance_of BufferedLogger::Padding
12
+ end
13
+
14
+ it "should set padding character" do
15
+ @p.padding_char = '#'
16
+ @p.padding_char.should == '#'
17
+ end
18
+
19
+ it "should return the padding string" do
20
+ @p.to_s.should == ''
21
+ end
22
+
23
+ it "should construct pre-padded strings" do
24
+ p = BufferedLogger::Padding.new(:indent => 4, :padding_char => '#')
25
+ p.to_s.should == '####'
26
+ end
27
+ end
28
+
29
+ describe 'indentation' do
30
+ it "should indent padding a positive amount" do
31
+ @p.indent(2)
32
+ @p.to_s.should == ' '
33
+ end
34
+
35
+ it "should indent padding a negative amount" do
36
+ @p.indent(3)
37
+ @p.indent(-2)
38
+ @p.to_s.should == ' '
39
+ end
40
+
41
+ it "should reset padding indentation" do
42
+ @p.indent(10)
43
+ @p.indent(:reset)
44
+ @p.to_s.should == ''
45
+ end
46
+ end
47
+
48
+ describe 'formatting' do
49
+ it "should apply padding to any input string" do
50
+ s = 'text'
51
+ @p.indent(4)
52
+ (@p % s).should == ' text'
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+
59
+ describe BufferedLogger do
60
+ before :each do
61
+ @f = StringIO.new
62
+ @l = BufferedLogger.new(@f)
63
+ end
64
+
65
+ describe 'indentation' do
66
+ it 'should use appropriate indentation for each thread' do
67
+ @l.indent(4)
68
+ @l.info 'hello'
69
+
70
+ t = Thread.new do
71
+ @l.indent(2)
72
+ @l.info 'blah'
73
+ end; t.join
74
+
75
+ t = Thread.new do
76
+ @l.info 'hey'
77
+ end; t.join
78
+
79
+ @l.info 'hi'
80
+
81
+ @f.string.should == " hello\n blah\nhey\n hi\n"
82
+ end
83
+
84
+ it 'should temporarily indent any logging in an indent block' do
85
+ @l.indent(4) do
86
+ @l.info 'blah'
87
+ end
88
+ @l.info 'blah'
89
+ @f.string.should == " blah\nblah\n"
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,75 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper.rb")
2
+ require 'rubygems'
3
+ require 'active_support/buffered_logger'
4
+
5
+ describe BufferedLogger do
6
+ before :each do
7
+ @f = StringIO.new
8
+ @l = BufferedLogger.new(@f)
9
+ end
10
+
11
+ describe 'initialization and accessors' do
12
+ it 'should initialize a new logger object' do
13
+ @l.should be_an_instance_of BufferedLogger
14
+ end
15
+
16
+ it 'should initialize a logger object using a severity level symbol' do
17
+ l = BufferedLogger.new(@f, :info)
18
+ l.info "info"
19
+ l.debug "debug"
20
+ l.warn "warn"
21
+ @f.string.should == "info\nwarn\n"
22
+ end
23
+
24
+ it 'should support color when printing to STDOUT' do
25
+ l = BufferedLogger.new(STDOUT)
26
+ l.send(:color?).should == true
27
+ end
28
+
29
+ it 'should not support color when not printing to STDOUT' do
30
+ @l.send(:color?).should == false
31
+ end
32
+
33
+ it 'should autoset formatters during init' do
34
+ l = BufferedLogger.new(STDOUT, 0, {:info => '$green INFO: $white %s', :warn => '$yellow WARNING: $white %s', :error => '$red ERROR: $white %s'})
35
+ l.send(:formatter, :info).to_s.should == '$green INFO: $white %s'
36
+ l.send(:formatter, :warn).to_s.should == '$yellow WARNING: $white %s'
37
+ l.send(:formatter, :error).to_s.should == '$red ERROR: $white %s'
38
+ end
39
+ end
40
+
41
+ describe 'delegation and magic methods' do
42
+ it 'should maintain backwards compatibility with buffered_logger interface' do
43
+ delegated = ActiveSupport::BufferedLogger.public_instance_methods(false)
44
+ delegated.each { |method| @l.should respond_to(method) }
45
+ end
46
+
47
+ it 'should respond to magic methods' do
48
+ magic = BufferedLogger::SEVERITY_LEVELS
49
+ magic.each { |method| @l.should respond_to(method) }
50
+ end
51
+ end
52
+
53
+ describe 'logging' do
54
+ it 'should log to a IO object' do
55
+ severities = BufferedLogger::SEVERITY_LEVELS
56
+ severities.each do |s|
57
+ f = StringIO.new
58
+ l = BufferedLogger.new(f)
59
+ l.send(s, "#{s}_message")
60
+ f.string.should == "#{s}_message\n"
61
+ end
62
+ end
63
+
64
+ it 'should buffer unflushed statements' do
65
+ @l.auto_flushing = 0
66
+ @l.info 'test'
67
+ @l.info 'test2'
68
+ @l.buffer_text.should == "test\ntest2\n"
69
+ @f.string.should == ''
70
+ @l.flush
71
+ @f.string.should == "test\ntest2\n"
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,4 @@
1
+ $: << File.join(File.dirname(__FILE__), "../lib")
2
+ require 'rspec'
3
+ require 'stringio'
4
+ require 'buffered_logger'
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 2
10
- version: 0.0.2
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Skryl
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-24 00:00:00 -05:00
18
+ date: 2011-07-19 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: "0"
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
- description: ActiveSupport's BufferedLogger with a few enhancements
35
+ description: A thread safe logger with formatting extensions. Based on active_support/buffered_logger.
36
36
  email: rut216@gmail.com
37
37
  executables: []
38
38
 
@@ -41,7 +41,19 @@ extensions: []
41
41
  extra_rdoc_files: []
42
42
 
43
43
  files:
44
+ - lib/buffered_logger/buffering.rb
45
+ - lib/buffered_logger/formatting.rb
46
+ - lib/buffered_logger/indentation.rb
47
+ - lib/buffered_logger/logger.rb
48
+ - lib/buffered_logger/thread_hash.rb
44
49
  - lib/buffered_logger.rb
50
+ - spec/buffering_spec.rb
51
+ - spec/formatting_spec.rb
52
+ - spec/indentation_spec.rb
53
+ - spec/logger_spec.rb
54
+ - spec/spec_helper.rb
55
+ - README
56
+ - TODO
45
57
  has_rdoc: true
46
58
  homepage: http://github.com/skryl
47
59
  licenses: []
@@ -75,6 +87,6 @@ rubyforge_project:
75
87
  rubygems_version: 1.6.2
76
88
  signing_key:
77
89
  specification_version: 3
78
- summary: Extending ActiveSupport's BufferedLogger
90
+ summary: A flexible, thread safe logger with custom formatting and ANSI color support
79
91
  test_files: []
80
92