/[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.5 - (show annotations)
Tue May 13 08:40:15 2003 UTC (21 years ago) by joko
Branch: MAIN
Changes since 1.4: +5 -2 lines
minor update: renamed attribute

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

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