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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide 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 joko 1.1 ## ------------------------------------------------------------------------
2 joko 1.3 ## $Id: Logger.pm,v 1.2 2003/02/20 21:06:27 joko Exp $
3 joko 1.1 ## ------------------------------------------------------------------------
4 joko 1.2 ## $Log: Logger.pm,v $
5 joko 1.3 ## 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 joko 1.2 ## Revision 1.1 2003/02/19 00:34:52 joko
14     ## + initial commit, again refactored to this place
15     ##
16 joko 1.1 ## 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 joko 1.2 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 joko 1.1
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 joko 1.2 # 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 joko 1.1 # set default arguments
137 joko 1.2 $self->{__logger}->{classname} = $calling_class;
138     $self->{__logger}->{functionname} = $calling_sub;
139     # FIXME: deprecate this!
140 joko 1.1 $self->{__logger}->{caller} = caller;
141    
142     # set default values
143     $self->{__logger}->{action} ||= '';
144     $self->{__logger}->{options}->{tag} ||= '';
145    
146 joko 1.2 # FIXME: deprecate this!
147 joko 1.1 #$self->{__logger}->{level} ||= 'info';
148 joko 1.2 #$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 joko 1.1
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 joko 1.2 #$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 joko 1.1 }
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 joko 1.2 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 joko 1.1 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 joko 1.3 # 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 joko 1.1
332     # configure custom logHandler
333    
334     if ($configurator) {
335    
336 joko 1.3 $configurator->{file_filename} = "$basepath/app.log";
337 joko 1.1 $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 joko 1.2
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 joko 1.1
427     1;
428     __END__

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