1 # $Id: logger.rb,v 1.4 2011/12/08 22:54:35 machan Exp $
2
3 require 'singleton'
4
5 require 'tmdoc/tmstd/assertion'
6
7
8 module TmStd
9
10 module Logger
11
12 class File
13 include Singleton
14
15
16 def self.open(file_path = nil, &block)
17 Assertion.opt_kind_of file_path, String
18 Assertion.kind_of block, Proc
19
20 logfile = File.instance
21 logfile.setup
22 logfile.open_file(file_path, &block)
23
24 nil
25 end
26
27
28 def self.verbose_level_event!(verbose_level_event)
29 Assertion.subclass_of verbose_level_event, Event::Abstract
30
31 Event::Abstract.verbose_level_event!(verbose_level_event)
32
33 nil
34 end
35
36
37 def setup
38 unless @is_setupped
39 @is_setupped = true
40 @file = nil
41 end
42
43 nil
44 end
45
46
47 def open_file(file_path = nil, &block)
48 Assertion.opt_kind_of file_path, String
49 Assertion.kind_of block, Proc
50
51 Assertion.assert @is_setupped, 'No setupped'
52 Assertion.nil @file, 'Already opened'
53
54 if file_path
55 begin
56 @file = ::File.open(file_path, "w")
57 @file.sync = true
58 rescue SystemCallError => exception
59 $stderr.printf(
60 "Logfile open error: %s (%s)\n",
61 exception.to_s, exception.class.to_s
62 )
63 raise Exception::LogfileOpenError
64 rescue IOError => exception
65 $stderr.printf(
66 "Logfile open error: '%s'\n", expand_file_name
67 )
68 raise Exception::LogfileOpenError
69 end
70 end
71
72 begin
73 block.call
74 ensure
75 if @file
76 @file.close
77 @file = nil
78 end
79 end
80
81 nil
82 end
83
84
85 def puts(str)
86 Assertion.kind_of str, String
87
88 if @file
89 begin
90 @file.puts str
91 @file.flush
92 rescue
93 ; # Ignore any logging error.
94 end
95 end
96
97 nil
98 end
99 end
100
101
102
103 module Event
104
105 class Abstract
106 def self.verbose_level_event!(verbose_level_event)
107 Assertion.subclass_of verbose_level_event, Abstract
108
109 @verbose_level_event = verbose_level_event
110
111 nil
112 end
113
114
115 def self.verbose_level_event
116 Assertion.boolean @verbose_level_event
117 end
118
119
120 def self.log(occured_event, fmt, args, &block)
121 Assertion.subclass_of occured_event, Abstract
122 Assertion.opt_kind_of fmt, String
123 Assertion.kind_of args, Array
124
125 verbose_level_event =
126 if @verbose_level_event.kind_of?(::Class)
127 @verbose_level_event
128 else
129 Progress # Default level.
130 end
131 write_to_console = occured_event <= verbose_level_event
132
133 arg_str =
134 if fmt
135 if args.size > 0 then format(*([fmt] + args)) else fmt end
136 else
137 nil
138 end
139 formatted_str =
140 if arg_str
141 formatted_lines = []
142 arg_str.split(
143 /\n/
144 ).each_with_index do |line, index|
145 formatted_lines << block.call(line, index)
146 end
147
148 formatted_lines.join("\n")
149 else
150 block.call('', 0)
151 end
152
153 self.raw_log write_to_console, formatted_str
154
155 nil
156 end
157
158
159 def self.raw_log(write_to_console, str)
160 Assertion.kind_of str, String
161
162 if write_to_console
163 $stderr.puts str
164 end
165 Logger::File.instance.puts str
166
167 nil
168 end
169
170
171 def self.format_line(label, line, index)
172 Assertion.kind_of label, String
173 Assertion.kind_of line, String
174 Assertion.kind_of index, Integer
175
176 str = format(
177 "[%-5s]%s %s",
178 label[0, 5],
179 ( if index == 0 then ' ' else '>' end ),
180 line
181 )
182
183 Assertion.kind_of str, String
184 end
185 end
186
187
188
189 class Debug < Abstract
190 def self.log(fmt = nil, *args)
191 Assertion.opt_kind_of fmt, String
192
193 if fmt
194 Debug.__log__ fmt, *args
195 else
196 Debug.__log__
197 end
198
199 nil
200 end
201
202
203 def self.p(str)
204 Assertion.kind_of str, String
205
206 Debug.msgout str
207
208 nil
209 end
210
211
212 def self.msgout(fmt = nil, *args)
213 Assertion.opt_kind_of fmt, String
214
215 num_of_depth = caller(0).size - 1
216 file_path,
217 line_num,
218 in_method = caller(1)[0].split(/:/)
219 file_name = file_path.split(/\//).last
220
221 indent_str =
222 if num_of_depth >= 1
223 '| ' * num_of_depth
224 else
225 '| '
226 end
227 method_str =
228 if in_method
229 in_method.scan(/in `(.*)'/)
230 else
231 '-'
232 end
233 args_str =
234 if fmt
235 if args.size > 0 then format(fmt, *args) else fmt end
236 else
237 ''
238 end
239
240 Debug.__log__(
241 "%s%s %d: %s --- %s\n",
242 indent_str, method_str, line_num, args_str, file_name
243 )
244
245 nil
246 end
247
248
249 def self.__log__(fmt = nil, *args)
250 Assertion.opt_kind_of fmt, String
251
252 Abstract.log(self, fmt, args) { |line, index|
253 self.format_line('DEBUG', line, index)
254 }
255
256 nil
257 end
258 end
259
260
261
262 class Progress < Debug
263 def self.log(fmt = nil, *args)
264 Assertion.opt_kind_of fmt, String
265
266 Abstract.log(self, fmt, args) { |line, index|
267 line
268 }
269
270 nil
271 end
272 end
273
274
275
276 class Information < Progress
277 def self.log(fmt = nil, *args)
278 Assertion.opt_kind_of fmt, String
279
280 Abstract.log(self, fmt, args) { |line, index|
281 self.format_line('INFO', line, index)
282 }
283
284 nil
285 end
286 end
287
288
289
290 class Notice < Information
291 def self.log(fmt = nil, *args)
292 Assertion.opt_kind_of fmt, String
293
294 Abstract.log(self, fmt, args) { |line, index|
295 self.format_line('NOTIC', line, index)
296 }
297
298 nil
299 end
300 end
301
302
303
304 class Warning < Notice
305 def self.log(fmt = nil, *args)
306 Assertion.opt_kind_of fmt, String
307
308 Abstract.log(self, fmt, args) { |line, index|
309 self.format_line('WARN', line, index)
310 }
311
312 nil
313 end
314 end
315
316
317
318 class Error < Warning
319 def self.log(fmt = nil, *args)
320 Assertion.opt_kind_of fmt, String
321
322 Abstract.log(self, fmt, args) { |line, index|
323 self.format_line('ERROR', line, index)
324 }
325
326 nil
327 end
328 end
329
330
331
332 class Fatal < Error
333 def self.log(fmt = nil, *args)
334 Assertion.opt_kind_of fmt, String
335
336 Abstract.log(self, fmt, args) { |line, index|
337 self.format_line('FATAL', line, index)
338 }
339
340 nil
341 end
342 end
343
344 end # TmStd::Logger::Event
345
346 end # TmStd::Logger
347
348 end # TmStd