/[cvs]/nfo/perl/libs/DesignPattern/Logger.pm
ViewVC logotype

Contents of /nfo/perl/libs/DesignPattern/Logger.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations)
Fri Mar 28 07:23:25 2003 UTC (21 years, 1 month ago) by joko
Branch: MAIN
Changes since 1.2: +17 -4 lines
fix to basepath calculation

1 ## ------------------------------------------------------------------------
2 ## $Id: Logger.pm,v 1.2 2003/02/20 21:06:27 joko Exp $
3 ## ------------------------------------------------------------------------
4 ## $Log: Logger.pm,v $
5 ## Revision 1.2 2003/02/20 21:06:27 joko
6 ## + configurable by package globals
7 ## + standalone mode (object creation via 'new')
8 ## + some comments
9 ## + Log::Dispatch gets configured inside here now
10 ## + coordinated stack tracing
11 ## + convenient shortcut methods resembling the syslog levels
12 ##
13 ## Revision 1.1 2003/02/19 00:34:52 joko
14 ## + initial commit, again refactored to this place
15 ##
16 ## Revision 1.3 2003/02/18 18:33:59 joko
17 ## + fix: just logs if possible
18 ##
19 ## Revision 1.2 2003/02/18 16:37:22 joko
20 ## + fix: ...::Hardwired is an optional module
21 ##
22 ## Revision 1.1 2003/02/18 15:57:34 joko
23 ## + initial commit, refactored from DesignPattern::Object::Logger
24 ##
25 ## Revision 1.2 2003/02/14 14:20:42 joko
26 ## + decreased default log-level to debug
27 ##
28 ## Revision 1.1 2002/12/22 14:17:38 joko
29 ## + initial check-in, refactored
30 ##
31 ## Revision 1.1 2002/12/19 01:14:48 cvsjoko
32 ## + initial check-in
33 ##
34 ## ------------------------------------------------------------------------
35
36
37 package DesignPattern::Logger;
38
39 use strict;
40 use warnings;
41
42 use Data::Dumper;
43 use Log::Dispatch;
44 use Log::Dispatch::Screen;
45 use Log::Dispatch::Config;
46 use Cwd;
47 use DesignPattern::Object;
48
49 use vars qw(
50 $LEVEL_DEFAULT
51 $ENABLE_NAMESPACE
52 $NAMESPACE_LEVEL
53 $ENABLE_METHODS
54 $METHOD_LEVELS
55 $TRACE_STACK_LEVELS
56 );
57
58 # default behaviour
59 $LEVEL_DEFAULT = 'debug';
60 $ENABLE_NAMESPACE = 1;
61 $NAMESPACE_LEVEL = undef;
62 $ENABLE_METHODS = 0;
63 $METHOD_LEVELS = [3];
64 $TRACE_STACK_LEVELS = [];
65
66
67 # TODO: review, revise and rewire this!
68 #my $logger = Log::Dispatch::Config->instance;
69
70 sub __init {
71 my $self = shift;
72 my $action = shift;
73 my $message = shift;
74 #my $options = shift; # ??? or: $self->{__logger}->{options} already...?
75
76 # configure
77 if (!$self->{__logger}->{configured}) {
78 $self->{__logger}->{configured} = 1;
79 $self->_configure_LogDispatch();
80 }
81
82 # set passed-in arguments
83 $self->{__logger}->{action} = $action;
84 $self->{__logger}->{message} = $message;
85
86 # trace
87 #my $tmp = caller(2);
88 #print Dumper($tmp);
89 #exit;
90
91
92 # handle caller
93
94 # determine class- and subroutinename of context calling us
95 # this task can be controlled by tuning its behaviour
96 # this can be changed by setting
97 # DesignPattern::Logger::...
98 # ...
99 # ...
100 my $calling_class;
101 my $calling_sub;
102
103
104 # Default behaviour is:
105 # Use classname from $self and suppress subroutine name.
106 # In case of using this together with DesignPattern::Bridge,
107 # the classnames of child objects are suppressed.
108 # Instead, the classname of the parent container object
109 # gets used *always*.
110 $calling_class = '';
111 $calling_sub = '';
112
113 # Log class names (en-/disabled, take from specified level)
114 if ($ENABLE_NAMESPACE) {
115 $calling_class = ref $self;
116 if ($NAMESPACE_LEVEL) {
117 my @entry = caller($NAMESPACE_LEVEL);
118 $calling_class = $entry[0];
119 }
120 }
121
122 # Log method names (en-/disabled, multi-level)
123 if ($ENABLE_METHODS) {
124 my @methods;
125 foreach (@{$METHOD_LEVELS}) {
126 (my $c_package, my $c_filename, my $c_line, my $c_subroutine, my $c_hasargs,
127 my $c_wantarray, my $c_evaltext, my $c_is_require, my $c_hints, my $c_bitmask) = caller($_);
128 $c_subroutine =~ s/.*:://;
129 push @methods, $c_subroutine;
130 }
131 $calling_sub = join(': ', @methods);
132 }
133
134
135
136 # set default arguments
137 $self->{__logger}->{classname} = $calling_class;
138 $self->{__logger}->{functionname} = $calling_sub;
139 # FIXME: deprecate this!
140 $self->{__logger}->{caller} = caller;
141
142 # set default values
143 $self->{__logger}->{action} ||= '';
144 $self->{__logger}->{options}->{tag} ||= '';
145
146 # FIXME: deprecate this!
147 #$self->{__logger}->{level} ||= 'info';
148 #$self->{__logger}->{level} ||= 'debug';
149 $self->{__logger}->{level} ||= $LEVEL_DEFAULT;
150
151 # handle stacktrace
152 foreach (@$TRACE_STACK_LEVELS) {
153 #print "trace-level: ", $_, "\n";
154 #(my $c_package, my $c_filename, my $c_line, my $c_subroutine, my $c_hasargs,
155 #my $c_wantarray, my $c_evaltext, my $c_is_require, my $c_hints, my $c_bitmask) = caller($_);
156 my @entry = caller($_);
157 push @{$self->{__logger}->{trace}->{stack}}, \@entry;
158 }
159
160 }
161
162 sub __out {
163 my $self = shift;
164 my $message = shift;
165
166 # if message given here, append to message stored inside object
167 $self->{__logger}->{message} .= ' - ' . $message if $message;
168
169 # TODO: refactor this:
170 # - push '$self->__get_prefix()' to additional log-entry-metadata, don't show it on/in any console/logfile output
171 #$logger->log( level => $self->{__logger}->{level}, message => $self->__get_prefix_long() . $message );
172 #$logger->log( level => $self->{__logger}->{level}, message => $message );
173 #$logger->warning( __PACKAGE__ . "->_skip: '$caller' (mixed into '$classname'): ($options->{tag}) $message.");
174 #$self->{__logger}->{instance}->log( level => $self->{__logger}->{level}, message => $self->__get_prefix_short() . $self->{__logger}->{message} );
175 #$self->{__logger}->{instance}->log( level => $self->{__logger}->{level}, message => $self->__get_prefix_module() . $self->{__logger}->{message} );
176 $self->{__logger}->{instance}->log( level => $self->{__logger}->{level}, message => $self->__get_prefix_best() . $self->{__logger}->{message} );
177 }
178
179
180 sub __handle_options {
181 my $self = shift;
182 #my $options = shift; # ??? or: $self->{__logger}->{options} already...?
183 }
184
185 sub __get_prefix_long {
186 my $self = shift;
187 return __PACKAGE__ . "->$self->{__logger}->{action}: '$self->{__logger}->{caller}' (mixed into '$self->{__logger}->{classname}'): ($self->{__logger}->{options}->{tag}) - ";
188 }
189
190 sub __get_prefix_short {
191 my $self = shift;
192 my $tag_append = '';
193 $tag_append = "$self->{__logger}->{options}->{tag} - " if $self->{__logger}->{options}->{tag};
194 return $self->{__logger}->{classname} . "->$self->{__logger}->{action}: $tag_append";
195 }
196
197 sub __get_prefix_module {
198 my $self = shift;
199 my $tag_append = '';
200 $tag_append = "$self->{__logger}->{options}->{tag} - " if $self->{__logger}->{options}->{tag};
201 return $self->{__logger}->{classname} . ": $tag_append";
202 }
203
204
205 sub __get_prefix_best {
206 my $self = shift;
207 my $namespace = $self->{__logger}->{classname};
208 my $method = '';
209 my $tag_append = '';
210 #$namespace = $namespace . ": " if $namespace;
211 $method = "->" . $self->{__logger}->{functionname} if $self->{__logger}->{functionname};
212 #$method .= ': ' if $method;
213 $tag_append = "$self->{__logger}->{options}->{tag} - " if $self->{__logger}->{options}->{tag};
214
215 my @line;
216 push @line, $namespace if $namespace;
217 push @line, $method if $method;
218 push @line, $tag_append if $tag_append;
219
220 #print Dumper(@line);
221
222 #return join(': ', @line);
223 my $result = join('', @line);
224 $result .= ': ' if $result;
225
226 return $result;
227
228 }
229
230
231 sub log {
232 my $self = shift;
233 my $message = shift;
234
235 # automagically instantiate the object if not there
236 # TODO: do this by creating a dummy object inheriting from DesignPattern::Logger,
237 # for now this just don't work because which dummy one to take: Data::Code::Null?
238 #if (! ref $self) {
239 # $self = DesignPattern::Object->fromPackage('DesignPattern::Logger');
240 #}
241
242 $self->{__logger}->{level} = shift; # TODO: implement propagation of this into Log::Dispatch-object '$logger'!
243 $self->{__logger}->{options} = shift; # TODO: implement additional behaviours: e.g. { exit => 1 } would exit after tracedump
244
245 #$self->__init('log', $message);
246 $self->__init('log', $message);
247 $self->__out();
248
249 }
250
251 sub skip {
252 my $self = shift;
253 my $message = shift;
254 my $condition = shift;
255 $self->{__logger}->{level} = shift; # TODO: implement propagation of this into Log::Dispatch-object '$logger'!
256 $self->{__logger}->{options} = shift; # TODO: implement additional behaviours: e.g. { exit => 1 } would exit after tracedump
257
258 my $classname = ref $self;
259 my $caller = caller;
260
261 $self->{__logger}->{options}->{tag} ||= '';
262
263 if ($condition) {
264 # V1:
265 #$logger->warning( __PACKAGE__ . "->_skip: '$caller' (mixed into '$classname'): ($options->{tag}) $message.");
266 # V2:
267 $self->__init('skip', $message);
268 $self->__out();
269 return 1;
270 }
271 }
272
273 sub trace {
274 my $self = shift;
275 my $message = shift;
276 my $data = shift;
277 my $condition = shift;
278 $self->{__logger}->{level} = shift; # TODO: implement propagation of this into Log::Dispatch-object '$logger'!
279 $self->{__logger}->{options} = shift; # TODO: implement additional behaviours: e.g. { exit => 1 } would exit after tracedump
280
281 my $classname = ref $self;
282 my $caller = caller;
283
284 $self->{__logger}->{options}->{tag} ||= '';
285
286 # don't do _any_ tracing if disabled
287 return if $self->{TRACE_DISABLED};
288
289 # overwrite condition with local configured want-TRACE
290 $condition ||= $self->{TRACE};
291
292 # dump data
293 my $result = 0;
294 if ($condition) {
295 $message .= " - " . Dumper($data);
296
297 # V1:
298 # $self->__init('trace');
299 # $logger->info( __PACKAGE__ . "->trace: '$caller' (mixed into '$classname'): ($options->{tag}) $message.");
300
301 # V2:
302 $self->__init('trace', $message);
303 $self->__out();
304
305 $result = 1;
306 } else {
307 $result = 0;
308 }
309
310 # handle additional options
311 if ($self->{TRACE_OPTIONS}) {
312 exit if $self->{__logger}->{options}->{exit};
313 }
314
315 return $result;
316 }
317
318
319 sub _configure_LogDispatch {
320 my $self = shift;
321
322 my $configurator = DesignPattern::Object->fromPackage('Log::Dispatch::Configurator::Hardwired');
323
324 # check if running inside a 'PROJECT' space
325 my $basepath = cwd();
326 my $postpone = '/..';
327 if (-d $basepath . $postpone . '/PROJECT') {
328 $basepath .= $postpone;
329 $basepath .= "/var/log";
330 }
331
332 # configure custom logHandler
333
334 if ($configurator) {
335
336 $configurator->{file_filename} = "$basepath/app.log";
337 $configurator->{screen_min_level} = 'info';
338
339 if ($self->{quiet}) {
340 $configurator->{screen_min_level} = 8;
341 }
342
343 if ($self->{debug}) {
344 $configurator->{screen_min_level} = 'debug';
345 }
346
347 if ($self->{verbose}) {
348 $configurator->{verbose} = 1;
349 }
350
351 Log::Dispatch::Config->configure($configurator);
352 $self->{__logger}->{instance} = Log::Dispatch::Config->instance;
353
354 } else {
355
356 #Log::Dispatch::Config->configure();
357 #Log::Dispatch->configure();
358 #$self->{__logger}->{instance} = Log::Dispatch->new;
359 $self->{__logger}->{instance} = Log::Dispatch::Screen->new( name => 'screen', 'min_level' => 'debug', stderr => 1 );
360
361 }
362
363
364 }
365
366 sub configure_logger {
367 my $self = shift;
368
369 # automagically instantiate the object if not there
370 # TODO: do this by creating a dummy object inheriting from DesignPattern::Logger,
371 # for now this just don't work because which dummy one to take: Data::Code::Null?
372 if (! ref $self) {
373 $self = DesignPattern::Object->fromPackage('DesignPattern::Logger');
374 }
375
376 #print "logconfig\n";
377 $self->_configure_LogDispatch();
378 }
379
380
381
382 # for standalone use
383 sub new { my $class = shift; my $self = {}; bless $self, $class; }
384
385 # convenient shortcuts
386 # FIXME: create these automagically by mungling with symbolic references
387 # or: make this object tied to recieve kinda events on method calls
388
389 sub debug {
390 my $self = shift;
391 my $message = shift;
392 $self->log($message, 'debug');
393 }
394
395 sub warning {
396 my $self = shift;
397 my $message = shift;
398 $self->log($message, 'warning');
399 }
400
401 sub info {
402 my $self = shift;
403 my $message = shift;
404 $self->log($message, 'info');
405 }
406
407 sub notice {
408 my $self = shift;
409 my $message = shift;
410 $self->log($message, 'notice');
411 }
412
413
414
415 =pod
416
417 =head1 TODO
418
419 o $TRACE_STACK_LEVELS (traces stack history)
420 o $ENABLE_DEBUG (en-/disables level 'debug')
421 o $ENABLE_LOG (en-/disables logging completely)
422
423
424 =cut
425
426
427 1;
428 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed