logue 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ logue
2
+ =====
3
+
4
+ A Ruby gem for generating logging and debugging output. Logging statements
5
+ include the file, line, class and method from which the logging method was
6
+ called.
7
+
8
+ ## EXAMPLES
9
+
10
+ ```
11
+ require 'logue/log'
12
+ require 'logue/loggable'
13
+
14
+ Logue::Log.level = Logue::Log::DEBUG
15
+
16
+ class MyClass
17
+ include Logue::Loggable
18
+
19
+ def mymethod foo
20
+ info "foo: #{foo}"
21
+ end
22
+ end
23
+
24
+ MyClass.new.mymethod "bar"
25
+ ```
26
+
27
+ Produces:
28
+
29
+ ```
30
+ [/tmp/foo.rb : 13] {MyClass#mymethod } foo: bar
31
+ ```
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ module Logue
5
+ class Format
6
+
7
+ def trim_left str, maxlen
8
+ str[0 ... maxlen.to_i.abs]
9
+ end
10
+
11
+ def trim_right str, maxlen
12
+ mxln = maxlen.abs
13
+
14
+ # magic number 3 for the ellipses ...
15
+
16
+ if str.length > mxln
17
+ path = str.split('/')
18
+ newstr = "..."
19
+ path.reverse.each do |element|
20
+ if newstr.length + element.length > mxln
21
+ while newstr.length < mxln
22
+ newstr.insert 0, " "
23
+ end
24
+ return newstr
25
+ else
26
+ if newstr.length > 3
27
+ newstr.insert 3, "/"
28
+ end
29
+ newstr.insert 3, element
30
+ end
31
+ end
32
+ newstr
33
+ else
34
+ str
35
+ end
36
+ end
37
+
38
+ def print_formatted file, line, func, msg, lvl, &blk
39
+ if trim
40
+ file = trim_right file, @file_width
41
+ line = trim_left line, @line_width
42
+ func = trim_left func, @function_width
43
+ end
44
+
45
+ hdr = sprintf @format, file, line, func
46
+ print hdr, msg, lvl, &blk
47
+ end
48
+ end
49
+ end
data/lib/logue/log.rb ADDED
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+ #
4
+ # = log.rb
5
+ #
6
+ # Logging Module
7
+ #
8
+ # Author:: Jeff Pace <jpace@incava.org>
9
+ # Documentation:: Author
10
+ #
11
+
12
+ require 'logue/logger'
13
+ require 'logue/severity'
14
+ require 'rubygems'
15
+ require 'rainbow'
16
+
17
+ #
18
+ # == Log
19
+ #
20
+ # Very minimal logging output. If verbose is set, this displays the method and
21
+ # line number whence called. It can be a mixin to a class, which displays the
22
+ # class and method from where it called. If not in a class, it displays only the
23
+ # method.
24
+ #
25
+ # Remember: all kids love log.
26
+ #
27
+ # == Examples
28
+ #
29
+ # See the unit tests in log_test.rb
30
+ #
31
+ # == Usage
32
+ #
33
+ # The most general usage is simply to call:
34
+ #
35
+ # Log.log "some message"
36
+ #
37
+ # That will simply log the given message.
38
+ #
39
+ # class YourClass
40
+ # include Loggable
41
+ #
42
+ # def some_method(...)
43
+ # log "my message"
44
+ #
45
+ # That will log from the given class and method, showing the line number from
46
+ # which the logger was called.
47
+ #
48
+ # def another_method(...)
49
+ # stack "my message"
50
+ #
51
+ # That will produce a stack trace from the given location.
52
+ #
53
+
54
+ module Logue
55
+ class Log
56
+ $LOGGING_LEVEL = nil
57
+
58
+ DEFAULT_FILENAME_WIDTH = -25
59
+ DEFAULT_LINENUM_WIDTH = 4
60
+ DEFAULT_FUNCTION_WIDTH = -20
61
+
62
+ include Log::Severity
63
+
64
+ # by default, class methods delegate to a single app-wide log.
65
+
66
+ @@log = Logger.new
67
+
68
+ # Returns the logger of the log. A class method delegating to an instance
69
+ # method ... not so good. But temporary.
70
+ def self.logger
71
+ @@log
72
+ end
73
+
74
+ def self.method_missing meth, *args, &blk
75
+ validcolors = Sickill::Rainbow::TERM_COLORS
76
+ # only handling foregrounds, not backgrounds
77
+ if code = validcolors[meth]
78
+ add_color_method meth.to_s, code + 30
79
+ send meth, *args, &blk
80
+ else
81
+ super
82
+ end
83
+ end
84
+
85
+ def self.respond_to? meth
86
+ validcolors = Sickill::Rainbow::TERM_COLORS
87
+ validcolors.include?(meth) || super
88
+ end
89
+
90
+ def self.add_color_method color, code
91
+ instmeth = Array.new
92
+ instmeth << "def #{color} msg = \"\", lvl = Log::DEBUG, depth = 1, cname = nil, &blk"
93
+ instmeth << " log(\"\\e[#{code}m\#{msg\}\\e[0m\", lvl, depth + 1, cname, &blk)"
94
+ instmeth << "end"
95
+ instance_eval instmeth.join("\n")
96
+
97
+ clsmeth = Array.new
98
+ clsmeth << "def #{color} msg = \"\", lvl = Log::DEBUG, depth = 1, cname = nil, &blk"
99
+ clsmeth << " logger.#{color}(\"\\e[#{code}m\#{msg\}\\e[0m\", lvl, depth + 1, cname, &blk)"
100
+ clsmeth << "end"
101
+
102
+ class_eval clsmeth.join("\n")
103
+ end
104
+
105
+ def self.set_default_widths
106
+ logger.set_default_widths
107
+ end
108
+
109
+ def self.verbose
110
+ logger.verbose
111
+ end
112
+
113
+ def self.verbose= v
114
+ logger.verbose = v && v != 0 ? DEBUG : FATAL
115
+ end
116
+
117
+ def self.level= lvl
118
+ logger.level = lvl
119
+ end
120
+
121
+ def self.quiet
122
+ logger.quiet
123
+ end
124
+
125
+ def self.quiet= q
126
+ logger.quiet = q
127
+ end
128
+
129
+ def self.format
130
+ logger.format
131
+ end
132
+
133
+ def self.format= fmt
134
+ logger.format = fmt
135
+ end
136
+
137
+ # Assigns output to the given stream.
138
+ def self.output= io
139
+ logger.output = io
140
+ end
141
+
142
+ def self.output
143
+ logger.output
144
+ end
145
+
146
+ # sets whether to colorize the entire line, or just the message.
147
+ def self.colorize_line= col
148
+ logger.colorize_line = col
149
+ end
150
+
151
+ def self.colorize_line
152
+ logger.colorize_line
153
+ end
154
+
155
+ # Assigns output to a file with the given name. Returns the file; client
156
+ # is responsible for closing it.
157
+ def self.outfile= fname
158
+ logger.outfile = fname
159
+ end
160
+
161
+ def self.outfile
162
+ logger.outfile
163
+ end
164
+
165
+ # Creates a printf format for the given widths, for aligning output.
166
+ def self.set_widths file_width, line_width, func_width
167
+ logger.set_widths file_width, line_width, func_width
168
+ end
169
+
170
+ def self.ignore_file fname
171
+ logger.ignore_file fname
172
+ end
173
+
174
+ def self.ignore_method methname
175
+ logger.ignored_method methname
176
+ end
177
+
178
+ def self.ignore_class classname
179
+ logger.ignored_class classname
180
+ end
181
+
182
+ def self.log_file fname
183
+ logger.log_file fname
184
+ end
185
+
186
+ def self.log_method methname
187
+ logger.log_method methname
188
+ end
189
+
190
+ def self.log_class classname
191
+ logger.log_class classname
192
+ end
193
+
194
+ def self.debug msg = "", depth = 1, &blk
195
+ logger.log msg, DEBUG, depth + 1, &blk
196
+ end
197
+
198
+ def self.info msg = "", depth = 1, &blk
199
+ logger.log msg, INFO, depth + 1, &blk
200
+ end
201
+
202
+ def self.fatal msg = "", depth = 1, &blk
203
+ logger.log msg, FATAL, depth + 1, &blk
204
+ end
205
+
206
+ def self.log msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk
207
+ logger.log msg, lvl, depth + 1, cname, &blk
208
+ end
209
+
210
+ def self.stack msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk
211
+ logger.stack msg, lvl, depth + 1, cname, &blk
212
+ end
213
+
214
+ def self.warn msg = "", depth = 1, &blk
215
+ if verbose
216
+ logger.log msg, WARN, depth + 1, &blk
217
+ else
218
+ $stderr.puts "WARNING: " + msg
219
+ end
220
+ end
221
+
222
+ def self.error msg = "", depth = 1, &blk
223
+ if verbose
224
+ logger.log msg, ERROR, depth + 1, &blk
225
+ else
226
+ $stderr.puts "ERROR: " + msg
227
+ end
228
+ end
229
+
230
+ def self.write msg, depth = 1, cname = nil, &blk
231
+ if verbose
232
+ stack msg, Log::WARN, depth + 1, cname, &blk
233
+ elsif quiet
234
+ # nothing
235
+ else
236
+ $stderr.puts msg
237
+ end
238
+ end
239
+
240
+ def self.set_color lvl, color
241
+ logger.set_color lvl, color
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+ #
4
+ # = log.rb
5
+ #
6
+ # Logging Module
7
+ #
8
+ # Author:: Jeff Pace <jpace@incava.org>
9
+ # Documentation:: Author
10
+ #
11
+
12
+ require 'logue/log'
13
+ require 'rubygems'
14
+ require 'rainbow'
15
+
16
+ #
17
+ # == Loggable
18
+ #
19
+ # Including this module in a class gives access to the logger methods.
20
+ #
21
+ # == Examples
22
+ #
23
+ # See the unit tests in log_test.rb
24
+ #
25
+ # == Usage
26
+ #
27
+ # class YourClass
28
+ # include Loggable
29
+ #
30
+ # def some_method(...)
31
+ # log "my message"
32
+ #
33
+ # That will log from the given class and method, showing the line number from
34
+ # which the logger was called.
35
+ #
36
+ # def another_method(...)
37
+ # stack "my message"
38
+ #
39
+ # That will produce a stack trace from the given location.
40
+ #
41
+
42
+ module Logue
43
+ module Loggable
44
+ # Logs the given message, including the class whence invoked.
45
+ def log msg = "", lvl = Log::DEBUG, depth = 1, &blk
46
+ Log.log msg, lvl, depth + 1, self.class.to_s, &blk
47
+ end
48
+
49
+ def debug msg = "", depth = 1, &blk
50
+ Log.log msg, Log::DEBUG, depth + 1, self.class.to_s, &blk
51
+ end
52
+
53
+ def info msg = "", depth = 1, &blk
54
+ Log.log msg, Log::INFO, depth + 1, self.class.to_s, &blk
55
+ end
56
+
57
+ def warn msg = "", depth = 1, &blk
58
+ Log.log msg, Log::WARN, depth + 1, self.class.to_s, &blk
59
+ end
60
+
61
+ def error msg = "", depth = 1, &blk
62
+ Log.log msg, Log::ERROR, depth + 1, self.class.to_s, &blk
63
+ end
64
+
65
+ def fatal msg = "", depth = 1, &blk
66
+ Log.log msg, Log::FATAL, depth + 1, self.class.to_s, &blk
67
+ end
68
+
69
+ def stack msg = "", lvl = Log::DEBUG, depth = 1, &blk
70
+ Log.stack msg, lvl, depth + 1, self.class.to_s, &blk
71
+ end
72
+
73
+ def write msg = "", depth = 1, &blk
74
+ Log.write msg, depth + 1, self.class.to_s, &blk
75
+ end
76
+
77
+ def method_missing meth, *args, &blk
78
+ validcolors = Sickill::Rainbow::TERM_COLORS
79
+ # only handling foregrounds, not backgrounds
80
+ if code = validcolors[meth]
81
+ add_color_method meth.to_s, code + 30
82
+ send meth, *args, &blk
83
+ else
84
+ super
85
+ end
86
+ end
87
+
88
+ def respond_to? meth
89
+ validcolors = Sickill::Rainbow::TERM_COLORS
90
+ validcolors.include?(meth) || super
91
+ end
92
+
93
+ def add_color_method color, code
94
+ meth = Array.new
95
+ meth << "def #{color}(msg = \"\", lvl = Log::DEBUG, depth = 1, cname = nil, &blk)"
96
+ meth << " Log.#{color} msg, lvl, depth + 1, self.class.to_s, &blk"
97
+ meth << "end"
98
+ self.class.module_eval meth.join("\n")
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+ #
4
+ # = logger.rb
5
+ #
6
+ # Logging Module
7
+ #
8
+ # Author:: Jeff Pace <jpace@incava.org>
9
+ # Documentation:: Author
10
+ #
11
+
12
+ require 'rubygems'
13
+ require 'rainbow'
14
+ require 'pathname'
15
+ require 'logue/severity'
16
+ require 'logue/format'
17
+
18
+ #
19
+ # == Logger
20
+ #
21
+ # This class logs messages. You probably don't want to use this directly; Log is
22
+ # the class containing the necessary class methods.
23
+ #
24
+ # == Examples
25
+ #
26
+ # See the unit tests in log_test.rb
27
+ #
28
+
29
+ module Logue
30
+ class Logger
31
+ $LOGGING_LEVEL = nil
32
+
33
+ attr_accessor :quiet
34
+ attr_accessor :output
35
+ attr_accessor :colorize_line
36
+ attr_accessor :level
37
+ attr_accessor :ignored_files
38
+ attr_accessor :ignored_methods
39
+ attr_accessor :ignored_classes
40
+ attr_accessor :trim
41
+
42
+ include Log::Severity
43
+
44
+ FRAME_RE = Regexp.new('(.*):(\d+)(?::in \`(.*)\')?')
45
+
46
+ def initialize
47
+ set_defaults
48
+ end
49
+
50
+ def verbose= v
51
+ @level = case v
52
+ when TrueClass
53
+ DEBUG
54
+ when FalseClass
55
+ FATAL
56
+ when Integer
57
+ v
58
+ end
59
+ end
60
+
61
+ def set_defaults
62
+ $LOGGING_LEVEL = @level = FATAL
63
+ @ignored_files = Hash.new
64
+ @ignored_methods = Hash.new
65
+ @ignored_classes = Hash.new
66
+ @width = 0
67
+ @output = $stdout
68
+ @colors = Array.new
69
+ @colorize_line = false
70
+ @quiet = false
71
+ @trim = true
72
+
73
+ set_default_widths
74
+ end
75
+
76
+ def set_default_widths
77
+ set_widths Log::DEFAULT_FILENAME_WIDTH, Log::DEFAULT_LINENUM_WIDTH, Log::DEFAULT_FUNCTION_WIDTH
78
+ end
79
+
80
+ def verbose
81
+ level <= DEBUG
82
+ end
83
+
84
+ # Assigns output to a file with the given name. Returns the file; client
85
+ # is responsible for closing it.
86
+ def outfile= f
87
+ @output = f.kind_of?(IO) ? f : File.new(f, "w")
88
+ end
89
+
90
+ # Creates a printf format for the given widths, for aligning output. To lead
91
+ # lines with zeros (e.g., "00317") the line_width argument must be a string,
92
+ # not an integer.
93
+ def set_widths file_width, line_width, func_width
94
+ @file_width = file_width
95
+ @line_width = line_width
96
+ @function_width = func_width
97
+
98
+ @format = "[%#{file_width}s:%#{line_width}d] {%#{func_width}s}"
99
+ end
100
+
101
+ def ignore_file fname
102
+ ignored_files[fname] = true
103
+ end
104
+
105
+ def ignore_method methname
106
+ ignored_methods[methname] = true
107
+ end
108
+
109
+ def ignore_class classname
110
+ ignored_classes[classname] = true
111
+ end
112
+
113
+ def log_file fname
114
+ ignored_files.delete fname
115
+ end
116
+
117
+ def log_method methname
118
+ ignored_methods.delete methname
119
+ end
120
+
121
+ def log_class classname
122
+ ignored_classes.delete classname
123
+ end
124
+
125
+ def debug msg = "", depth = 1, &blk
126
+ log msg, DEBUG, depth + 1, &blk
127
+ end
128
+
129
+ def info msg = "", depth = 1, &blk
130
+ log msg, INFO, depth + 1, &blk
131
+ end
132
+
133
+ def warn msg = "", depth = 1, &blk
134
+ log msg, WARN, depth + 1, &blk
135
+ end
136
+
137
+ def error msg = "", depth = 1, &blk
138
+ log msg, ERROR, depth + 1, &blk
139
+ end
140
+
141
+ def fatal msg = "", depth = 1, &blk
142
+ log msg, FATAL, depth + 1, &blk
143
+ end
144
+
145
+ # Logs the given message.
146
+ def log msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk
147
+ if lvl >= level
148
+ frame = nil
149
+
150
+ stk = caller 0
151
+ stk.reverse.each_with_index do |frm, idx|
152
+ if frm.index(%r{logue/log.*:\d+:in\b})
153
+ break
154
+ else
155
+ frame = frm
156
+ end
157
+ end
158
+
159
+ print_stack_frame frame, cname, msg, lvl, &blk
160
+ end
161
+ end
162
+
163
+ # Shows the current stack.
164
+ def stack msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk
165
+ if lvl >= level
166
+ stk = caller depth
167
+ for frame in stk
168
+ print_stack_frame frame, cname, msg, lvl, &blk
169
+ cname = nil
170
+ msg = ""
171
+ end
172
+ end
173
+ end
174
+
175
+ def print_stack_frame frame, cname, msg, lvl, &blk
176
+ md = FRAME_RE.match frame
177
+ file, line, func = md[1], md[2], (md[3] || "")
178
+ # file.sub!(/.*\//, "")
179
+
180
+ # Ruby 1.9 expands the file name, but 1.8 doesn't:
181
+ pn = Pathname.new(file).expand_path
182
+
183
+ file = pn.to_s
184
+
185
+ if cname
186
+ func = cname + "#" + func
187
+ end
188
+
189
+ if ignored_files[file] || (cname && ignored_classes[cname]) || ignored_methods[func]
190
+ # skip this one.
191
+ else
192
+ print_formatted(file, line, func, msg, lvl, &blk)
193
+ end
194
+ end
195
+
196
+ def print_formatted file, line, func, msg, lvl, &blk
197
+ if trim
198
+ fmt = Format.new
199
+ file = fmt.trim_right file, @file_width
200
+ line = fmt.trim_left line, @line_width
201
+ func = fmt.trim_left func, @function_width
202
+ end
203
+
204
+ hdr = sprintf @format, file, line, func
205
+ print hdr, msg, lvl, &blk
206
+ end
207
+
208
+ def print hdr, msg, lvl, &blk
209
+ if blk
210
+ x = blk.call
211
+ if x.kind_of? String
212
+ msg = x
213
+ else
214
+ return
215
+ end
216
+ end
217
+
218
+ msg = msg.to_s.chomp
219
+
220
+ if lvlcol = @colors[lvl]
221
+ if colorize_line
222
+ line = hdr + " " + msg
223
+ @output.puts line.color(lvlcol)
224
+ else
225
+ @output.puts hdr + " " + msg.color(lvlcol)
226
+ end
227
+ else
228
+ @output.puts hdr + " " + msg
229
+ end
230
+ end
231
+
232
+ def set_color lvl, color
233
+ @colors[lvl] = color
234
+ end
235
+
236
+ def method_missing meth, *args, &blk
237
+ validcolors = Sickill::Rainbow::TERM_COLORS
238
+ # only handling foregrounds, not backgrounds
239
+ if code = validcolors[meth]
240
+ add_color_method meth.to_s, code + 30
241
+ send meth, *args, &blk
242
+ else
243
+ super
244
+ end
245
+ end
246
+
247
+ def respond_to? meth
248
+ validcolors = Sickill::Rainbow::TERM_COLORS
249
+ validcolors.include?(meth) || super
250
+ end
251
+
252
+ def add_color_method color, code
253
+ instmeth = Array.new
254
+ instmeth << "def #{color}(msg = \"\", lvl = DEBUG, depth = 1, cname = nil, &blk)"
255
+ instmeth << " log(\"\\e[#{code}m\#{msg\}\\e[0m\", lvl, depth + 1, cname, &blk)"
256
+ instmeth << "end"
257
+ instance_eval instmeth.join("\n")
258
+
259
+ clsmeth = Array.new
260
+ clsmeth << "def #{color}(msg = \"\", lvl = DEBUG, depth = 1, cname = nil, &blk)"
261
+ clsmeth << " logger.#{color}(\"\\e[#{code}m\#{msg\}\\e[0m\", lvl, depth + 1, cname, &blk)"
262
+ clsmeth << "end"
263
+
264
+ class_eval clsmeth.join("\n")
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+ #
4
+ # = severity.rb
5
+ #
6
+ # Logging Module
7
+ #
8
+ # Author:: Jeff Pace <jpace@incava.org>
9
+ # Documentation:: Author
10
+ #
11
+
12
+ module Logue
13
+ class Log
14
+ module Severity
15
+ DEBUG = 0
16
+ INFO = 1
17
+ WARN = 2
18
+ ERROR = 3
19
+ FATAL = 4
20
+ end
21
+ end
22
+ end
data/lib/logue.rb ADDED
@@ -0,0 +1,17 @@
1
+ loguelibdir = File.dirname(__FILE__)
2
+
3
+ $:.unshift(loguelibdir) unless
4
+ $:.include?(loguelibdir) || $:.include?(File.expand_path(loguelibdir))
5
+
6
+ require 'pathname'
7
+
8
+ rbre = Regexp.new('\.rb$')
9
+
10
+ Pathname.glob(loguelibdir + '/logue/**/*.rb').each do |file|
11
+ fname = file.sub(Regexp.new('^' + loguelibdir + '/'), '').sub(rbre, '')
12
+ require fname
13
+ end
14
+
15
+ module Logue
16
+ VERSION = '1.0.0'
17
+ end
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'pathname'
5
+ require 'test/unit'
6
+ require 'stringio'
7
+ require 'logue/format'
8
+ require 'logue/loggable'
9
+
10
+ module Logue
11
+ class FormatTestCase < Test::Unit::TestCase
12
+ include Logue::Loggable
13
+
14
+ def run_trim_left_test expected, length, str = "something"
15
+ trimmed = Format.new.trim_left(str, length)
16
+ assert_equal expected, trimmed
17
+ end
18
+
19
+ def test_trim_left_short_positive_number
20
+ run_trim_left_test "some", 4
21
+ end
22
+
23
+ def test_trim_left_long
24
+ run_trim_left_test "something", 10
25
+ end
26
+
27
+ def test_trim_left_short_negative_number
28
+ run_trim_left_test "some", -4
29
+ end
30
+
31
+ def run_trim_right_test expected, length, str = "something"
32
+ trimmed = Format.new.trim_right(str, length)
33
+ assert_equal expected, trimmed
34
+ end
35
+
36
+ def test_trim_right_short_positive_number
37
+ run_trim_right_test " ...", 5
38
+ end
39
+
40
+ def test_trim_right_long
41
+ run_trim_right_test "something", 10
42
+ end
43
+
44
+ def test_trim_right_short_negative_number
45
+ run_trim_right_test " ...", -5
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'pathname'
5
+ require 'test/unit'
6
+ require 'stringio'
7
+ require 'logue'
8
+
9
+ include Logue
10
+
11
+ class LogAbyss
12
+ include Loggable
13
+
14
+ def squeal
15
+ log "hello from the abyss"
16
+ stack "turtles all the way down"
17
+ end
18
+ end
19
+
20
+ class LogDepths
21
+ include Loggable
22
+
23
+ def speak
24
+ log "hello from the depths"
25
+ la = LogAbyss.new
26
+ la.squeal
27
+ end
28
+ end
29
+
30
+ class LogInner
31
+ include Loggable
32
+
33
+ def screech
34
+ ldi = LogDepths.new
35
+ log "hello from the innerds"
36
+ ldi.speak
37
+ end
38
+ end
39
+
40
+ class LogStackTestCase < Test::Unit::TestCase
41
+ include Loggable
42
+
43
+ def test_stack
44
+ Log.set_widths(-15, 4, -40)
45
+
46
+ log = Proc.new {
47
+ li = LogInner.new
48
+ li.screech
49
+ }
50
+
51
+ expected_output = [
52
+ "[ ...: 35] {LogInner#screech } hello from the innerds",
53
+ "[ ...: 24] {LogDepths#speak } hello from the depths",
54
+ "[ ...: 15] {LogAbyss#squeal } hello from the abyss",
55
+ "[ ...: 16] {LogAbyss#squeal } turtles all the way down",
56
+ "[ ...: 26] {speak } ",
57
+ "[ ...: 36] {screech } ",
58
+ ]
59
+
60
+ run_test @verbose_setup, log, *expected_output
61
+ end
62
+
63
+ # the ctor is down here so the lines above are less likely to change.
64
+ def initialize test, name = nil
65
+ @nonverbose_setup = Proc.new {
66
+ Log.verbose = false
67
+ Log.output = StringIO.new
68
+ }
69
+
70
+ @verbose_setup = Proc.new {
71
+ Log.verbose = true
72
+ Log.output = StringIO.new
73
+ }
74
+
75
+ super test
76
+ end
77
+
78
+ def run_test setup, log, *expected
79
+ io = setup.call
80
+
81
+ log.call
82
+
83
+ assert_not_nil io
84
+ str = io.string
85
+ assert_not_nil str
86
+
87
+ lines = str.split "\n"
88
+
89
+ (0 ... expected.size).each do |idx|
90
+ if expected[idx]
91
+ assert_equal expected[idx], lines[idx], "index: #{idx}"
92
+ end
93
+ end
94
+
95
+ Log.output = io
96
+ end
97
+ end
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'pathname'
5
+ require 'test/unit'
6
+ require 'stringio'
7
+ require 'logue/loggable'
8
+ require 'logue/testlog/logtestee'
9
+
10
+ include Logue
11
+
12
+ class LogTestCase < Test::Unit::TestCase
13
+ include Loggable
14
+
15
+ def run_log_testee_test(methname, expected, &blk)
16
+ Log.verbose = true
17
+ io = StringIO.new
18
+ Log.output = io
19
+ Log.set_default_widths
20
+
21
+ blk.call if blk
22
+
23
+ lt = LogTestee.new
24
+ lt.send methname
25
+
26
+ str = io.string
27
+
28
+ lines = str.split "\n"
29
+
30
+ (0 ... expected.size).each do |idx|
31
+ if expected[idx]
32
+ assert_equal expected[idx], lines[idx], "index: #{idx}"
33
+ end
34
+ end
35
+
36
+ Log.set_default_widths
37
+ end
38
+
39
+ def run_format_test(expected, &blk)
40
+ Log.verbose = true
41
+ io = StringIO.new
42
+ Log.output = io
43
+ Log.set_default_widths
44
+
45
+ blk.call
46
+
47
+ lt = LogTestee.new
48
+ lt.format_test
49
+
50
+ assert_equal expected.join(''), io.string
51
+
52
+ Log.set_default_widths
53
+ end
54
+
55
+ def test_no_output
56
+ run_log_testee_test(:log_all, Array.new) do
57
+ Log.verbose = false
58
+ end
59
+ end
60
+
61
+ def msg lnum, methname, msg
62
+ sprintf("[ ...testlog/logtestee.rb: %2d] {%-20s} %s", 16 + lnum, methname[0 .. 19], msg)
63
+ end
64
+
65
+ def test_output_arg
66
+ methname = "log_all"
67
+
68
+ expected = Array.new
69
+ (1 .. 6).each do |lnum|
70
+ msg = "hello, world?"
71
+ if lnum == 4 || lnum == 5
72
+ msg = "EXPECTED OUTPUT TO STDERR: hello, world."
73
+ end
74
+ expected << sprintf("[ ...testlog/logtestee.rb: %2d] {%-20s} %s", 16 + lnum, methname[0 .. 19], msg)
75
+ end
76
+
77
+ run_log_testee_test(:log_all, expected)
78
+ end
79
+
80
+ def test_output_block_at_level
81
+ Log.level = Log::DEBUG
82
+
83
+ methname = "log_block"
84
+
85
+ msg = "block party"
86
+
87
+ expected = Array.new
88
+ expected << sprintf("[ ...testlog/logtestee.rb: %2d] {%-20s} %s", 26, methname[0 .. 19], msg)
89
+
90
+ run_log_testee_test(:log_block, expected)
91
+ end
92
+
93
+ def test_output_block_below_level
94
+ expected = Array.new
95
+
96
+ run_log_testee_test(:log_block, expected) do
97
+ Log.level = Log::INFO
98
+ end
99
+ end
100
+
101
+ def test_colors_foreground
102
+ methname = "log_foregrounds"
103
+ expected = Array.new
104
+ expected << sprintf("[ ...testlog/logtestee.rb: %2d] {%-20s} %s", 30, methname[0 .. 19], "\e[37mwhite wedding\e[0m")
105
+ expected << sprintf("[ ...testlog/logtestee.rb: %2d] {%-20s} %s", 31, methname[0 .. 19], "\e[34mblue iris\e[0m")
106
+
107
+ run_log_testee_test(:log_foregrounds, expected)
108
+ end
109
+
110
+ def xxxtest_colors_background
111
+ expected = Array.new
112
+ expected << "[ ...test/logue/log_test.rb: 109] {LogTestCase#test_col} \e[46mred\e[0m"
113
+
114
+ run_log_testee_test(:log_foregrounds, expected) do
115
+ end
116
+ end
117
+
118
+ def test_format_default
119
+ expected = Array.new
120
+ expected << "[ ...testlog/logtestee.rb: 10] {format_test } tamrof\n"
121
+
122
+ run_format_test expected do
123
+ Log.set_default_widths
124
+ end
125
+ end
126
+
127
+ def test_format_flush_filename_left
128
+ expected = Array.new
129
+ expected << "[ ...test/logue/testlog/logtestee.rb: 10] {format_test } tamrof\n"
130
+
131
+ run_format_test expected do
132
+ Log.set_widths(-35, Log::DEFAULT_LINENUM_WIDTH, Log::DEFAULT_FUNCTION_WIDTH)
133
+ end
134
+ end
135
+
136
+ def test_format_flush_linenum_left
137
+ expected = Array.new
138
+ expected << "[ ...testlog/logtestee.rb:10 ] {format_test } tamrof\n"
139
+
140
+ run_format_test expected do
141
+ Log.set_widths(Log::DEFAULT_FILENAME_WIDTH, -10, Log::DEFAULT_FUNCTION_WIDTH)
142
+ end
143
+ end
144
+
145
+ def test_format_flush_function_right
146
+ expected = Array.new
147
+ expected << "[ ...testlog/logtestee.rb: 10] { format_test} tamrof\n"
148
+
149
+ run_format_test expected do
150
+ Log.set_widths(Log::DEFAULT_FILENAME_WIDTH, Log::DEFAULT_LINENUM_WIDTH, 35)
151
+ end
152
+ end
153
+
154
+ def test_format_pad_linenum_zeros
155
+ expected = Array.new
156
+ expected << "[ ...testlog/logtestee.rb:00000010] {format_test } tamrof\n"
157
+
158
+ run_format_test expected do
159
+ Log.set_widths(Log::DEFAULT_FILENAME_WIDTH, "08", Log::DEFAULT_FUNCTION_WIDTH)
160
+ end
161
+ end
162
+
163
+ def test_respond_to_color
164
+ assert Log.respond_to? :blue
165
+ end
166
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'pathname'
5
+ require 'test/unit'
6
+ require 'stringio'
7
+ require 'logue/log'
8
+ require 'logue/loggable'
9
+ require 'logue/testlog/lgbl_testee'
10
+
11
+ class LoggableTestCase < Test::Unit::TestCase
12
+ include Logue::Loggable
13
+
14
+ def test_instance_colors
15
+ Logue::Log.verbose = true
16
+ io = StringIO.new
17
+ Logue::Log.output = io
18
+
19
+ expected = Array.new
20
+ expected << "[...testlog/lgbl_testee.rb: 11] {LgblTestee#crystal } hello!\n"
21
+ expected << "[...testlog/lgbl_testee.rb: 12] {LgblTestee#crystal } azul ... \n"
22
+ expected << "[...testlog/lgbl_testee.rb: 13] {LgblTestee#crystal } rojo?\n"
23
+
24
+ te = LgblTestee.new
25
+ te.crystal
26
+
27
+ # puts io.string
28
+
29
+ assert_equal expected.join(''), io.string
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logue
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jeff Pace
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rainbow
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.1.4
30
+ description: A module that adds logging/trace functionality.
31
+ email: jeugenepace@gmail.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files:
35
+ - README.md
36
+ files:
37
+ - lib/logue.rb
38
+ - lib/logue/format.rb
39
+ - lib/logue/log.rb
40
+ - lib/logue/loggable.rb
41
+ - lib/logue/logger.rb
42
+ - lib/logue/severity.rb
43
+ - test/logue/format_test.rb
44
+ - test/logue/testlog/log_stack_test.rb
45
+ - test/logue/testlog/log_test.rb
46
+ - test/logue/testlog/loggable_test.rb
47
+ - README.md
48
+ homepage: http://jeugenepace.github.com/logue
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.23
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: A minimalist logging module.
72
+ test_files:
73
+ - test/logue/format_test.rb
74
+ - test/logue/testlog/log_stack_test.rb
75
+ - test/logue/testlog/log_test.rb
76
+ - test/logue/testlog/loggable_test.rb