buffered_logger 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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