/[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.4 - (show annotations)
Sat Mar 29 07:16:00 2003 UTC (21 years, 1 month ago) by joko
Branch: MAIN
Changes since 1.3: +5 -2 lines
minor update: changed default log-file-name to 'perl_app.log'

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

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