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

Annotation of /nfo/perl/libs/Class/Logger.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Dec 16 19:22:26 2003 UTC (20 years, 5 months ago) by ts-dev
Branch: MAIN
first check-in

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

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