/[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.3 - (hide annotations)
Thu Dec 18 18:19:01 2003 UTC (20 years, 4 months ago) by ts-dev
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +7 -3 lines
typo; create instance at startup

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

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