File Coverage

blib/lib/Fault/Msg.pm
Criterion Covered Total %
statement 9 130 6.9
branch 0 46 0.0
condition n/a
subroutine 3 30 10.0
pod 19 19 100.0
total 31 225 13.7


line stmt bran cond sub pod time code
1             #================================= Msg.pm ====================================
2             # Filename: Msg.pm
3             # Description: Internal message encapsulation class.
4             # Original Author: Dale M. Amon
5             # Revised by: $Author: amon $
6             # Date: $Date: 2008-08-28 23:20:19 $
7             # Version: $Revision: 1.8 $
8             # License: LGPL 2.1, Perl Artistic or BSD
9             #
10             #=============================================================================
11 1     1   5 use strict;
  1         2  
  1         32  
12 1     1   1187 use POSIX;
  1         9947  
  1         24  
13              
14             package Fault::Msg;
15 1     1   3526 use vars qw{@ISA};
  1         3  
  1         1792  
16             @ISA = qw( UNIVERSAL );
17              
18             my $DFT_MSG = "";
19             my $DFT_TYPE = 'BUG';
20             my $DFT_PRI = 'err';
21             my $DFT_PROCESS = "UnspecifiedProcess";
22             my $DFT_PREFIX = "";
23             my $DFT_TAG = "";
24              
25             #=============================================================================
26             # INTERNAL OPS
27             #=============================================================================
28             # CLASS METHODS
29             #-----------------------------------------------------------------------------
30              
31             sub _timestamp ($) {
32 0     0     my @t = (gmtime)[5,4,3,2,1,0]; $t[0] += 1900; $t[1]++;
  0            
  0            
33 0           return sprintf "%04d%02d%02d%02d%02d%02d", @t;
34             }
35              
36             #-----------------------------------------------------------------------------
37              
38 0 0   0     sub _processname ($) {(defined $::PROCESS_NAME) ?
39             $::PROCESS_NAME : $DFT_PROCESS;}
40              
41             #-----------------------------------------------------------------------------
42             # INSTANCE METHODS
43             #-----------------------------------------------------------------------------
44             # Test line without \n as Posix will complain other wise.
45              
46             sub _validate_msg ($;$) {
47 0     0     my ($s,$m) = @_;
48              
49 0 0         if (!defined $m) {$m = undef;}
  0 0          
  0            
50              
51 0           elsif (ref $m) {push @{$s->{'err'}},
52             ("Message cannot be a pointer.");
53 0           $m = $DFT_MSG; }
54              
55             else {
56 0           chomp $m;
57 0 0         if (!POSIX::isprint $m) {push @{$s->{'err'}},
  0            
  0            
58             ("Message contains POSIX non-printable char: " .
59             "\'$m\'.");
60 0           $m = $DFT_MSG;
61             }
62             }
63 0           return $m;
64             }
65              
66             #-----------------------------------------------------------------------------
67              
68             sub _validate_type ($;$) {
69 0     0     my ($s,$t) = @_;
70              
71 0 0         if (!defined $t) {$t = undef;}
  0 0          
  0 0          
72              
73 0           elsif (ref $t) {push @{$s->{'err'}},
  0            
74             ("Type cannot be a pointer.");
75 0           $t = $DFT_TYPE; }
76              
77 0           elsif (!POSIX::isalpha $t) {push @{$s->{'err'}},
  0            
78             ("Type contains char other than [a-zA-Z]: " .
79             "\'$t\'.");
80 0           $t = $DFT_TYPE; }
81              
82             else {$t = uc $t;}
83 0           return $t;
84             }
85              
86             #-----------------------------------------------------------------------------
87              
88             my %valid_priority =
89             ('emerg' => 1,
90             'alert' => 1,
91             'crit' => 1,
92             'err' => 1,
93             'warning' => 1,
94             'notice' => 1,
95             'info' => 1,
96             'debug' => 1 );
97              
98             sub _validate_priority ($;$) {
99 0     0     my ($s,$p) = @_;
100              
101 0 0         if (!defined $p) {$p = undef;}
  0 0          
  0 0          
102              
103 0           elsif (ref $p) {push @{$s->{'err'}},
  0            
104             ("Priority cannot be a pointer.");
105 0           $p = $DFT_PRI; }
106              
107 0           elsif (!exists $valid_priority{lc $p}) {push @{$s->{'err'}},
  0            
108             ("Priority is not a syslog priority:: " .
109             "\'$p\'.");
110 0           $p = $DFT_PRI; }
111              
112             else {$p = lc $p;}
113              
114 0           return $p;
115             }
116              
117             #-----------------------------------------------------------------------------
118              
119             sub _validate_prefix ($;$) {
120 0     0     my ($s,$prefix) = @_;
121              
122 0 0         if (!defined $prefix) {$prefix = $DFT_PREFIX;}
  0 0          
  0 0          
123              
124 0           elsif (ref $prefix) {push @{$s->{'err'}},
  0            
125             ("Prefix cannot be a pointer.");
126 0           $prefix = $DFT_PREFIX; }
127              
128 0           elsif (!POSIX::isprint $prefix) {push @{$s->{'err'}},
  0            
129             ("Prefix contains non-printable char: " .
130             "\'$prefix\'.");
131 0           $prefix = $DFT_PREFIX; }
132              
133             else {$prefix = "[$prefix]: ";}
134              
135 0           return $prefix;
136             }
137              
138             #-----------------------------------------------------------------------------
139              
140             sub _validate_tag ($;$) {
141 0     0     my ($s,$tag) = @_;
142              
143 0 0         if (!defined $tag) {$tag = $DFT_TAG;}
  0 0          
  0 0          
144            
145 0           elsif (ref $tag) {push @{$s->{'err'}},
  0            
146             ("Tag cannot be a pointer.");
147 0           $tag = "Invalid tag (Pointer)";}
148              
149 0           elsif (!POSIX::isprint $tag) {push @{$s->{'err'}},
150             ("Tag contains non-printable char: " .
151             "\'$tag\'.");
152 0           $tag = "Invalid tag (Not printable)";}
153 0           return $tag;
154             }
155              
156             #------------------------------------------------------------------------------
157              
158             my %default_priority =
159             ('BUG' => 'err',
160             'DATA' => 'warning',
161             'SRV' => 'warning',
162             'NET' => 'warning',
163             'NOTE' => 'info' );
164              
165             sub _handle_defaulting ($;$$$) {
166 0     0     my ($c,$m,$t,$p) = @_;
167 0           my $blankflg = (!defined $m);
168              
169 0 0         if (!defined $m) {$m = $DFT_MSG;}
  0            
170 0 0         if (!defined $t) {$t = $DFT_TYPE;}
  0            
171              
172 0 0         if (!defined $p) {
173 0 0         $p = (exists $default_priority{$t}) ?
174             $default_priority{$t} : $DFT_PRI;
175             }
176 0           return ($m,$t,$p,$blankflg);
177             }
178              
179             #=============================================================================
180             # CLASS METHODS
181             #=============================================================================
182              
183             sub new ($;$$$) {
184 0     0 1   my ($c,$m,$t,$p) = @_;
185 0           my $flg;
186 0           my $stamp = $c->_timestamp;
187 0           my $self = bless {}, $c;
188 0           $self->{'err'} = ();
189 0           $m = $self->_validate_msg ($m);
190 0           $t = $self->_validate_type ($t);
191 0           $p = $self->_validate_priority ($p);
192 0           ($m,$t,$p,$flg) = $self->_handle_defaulting ($m,$t,$p);
193              
194 0           @$self{'timestamp','date','time',
195             'process',
196             'msg','type','priority',
197             'blankflg','prefix','tag'} =
198             ($stamp,substr($stamp,0,8),substr($stamp,8,6),
199             $c->_processname,
200             $m,$t,$p,
201             $flg,
202             $DFT_PREFIX,
203             $DFT_TAG,
204             );
205              
206 0           return $self;
207             }
208              
209             #=============================================================================
210             # INSTANCE METHODS
211             #=============================================================================
212              
213             sub set_msg ($;$) {
214 0     0 1   my ($s,$m) = @_;
215 0           $m = $s->_validate_msg($m);
216 0           $s->{'blankflg'} = (!defined $m);
217 0 0         $s->{'msg'} = (defined $m) ? $m : $DFT_MSG;
218 0           return $m;
219             }
220              
221             #-----------------------------------------------------------------------------
222              
223             sub set_type ($;$) {
224 0     0 1   my ($s,$t) = @_;
225 0 0         defined $t || ($t = $DFT_TYPE);
226 0           $t = $s->validate_type($t);
227 0           $s->{'type'} = $t;
228 0           return $t;
229             }
230              
231             #-----------------------------------------------------------------------------
232              
233             sub set_priority ($;$) {
234 0     0 1   my ($s,$p) = @_;
235 0 0         defined $p || ($p = $DFT_PRI);
236 0           $p = $s->validate_priority($p);
237 0           $s->{'priority'} = $p;
238 0           return $p;
239             }
240              
241             #-----------------------------------------------------------------------------
242              
243             sub set_prefix ($;$) {
244 0     0 1   my ($s,$prefix) = @_;
245 0           $s->{'prefix'} = $s->_validate_prefix($prefix);
246 0           return $s->{'prefix'};
247             }
248              
249             #-----------------------------------------------------------------------------
250              
251             sub set_tag ($;$) {
252 0     0 1   my ($s,$tag) = @_;
253 0           $s->{'tag'} = $s->_validate_tag($tag);
254 0           return $s->{'tag'};
255             }
256              
257             #-----------------------------------------------------------------------------
258              
259 0     0 1   sub get ($) {my $s = shift;
260 0           my $m = $s->{'prefix'} . $s->{'msg'};
261 0           (@$s{'timestamp','priority','type','process'}, $m);}
262              
263 0     0 1   sub msg ($) {my $s = shift; $s->{'tag'} . $s->{'msg'};}
  0            
264              
265 0     0 1   sub timestamp ($) {shift->{'timestamp'};}
266 0     0 1   sub time ($) {shift->{'time'};}
267 0     0 1   sub date ($) {shift->{'date'};}
268 0     0 1   sub processname ($) {shift->{'process'};}
269 0     0 1   sub priority ($) {shift->{'priority'};}
270 0     0 1   sub type ($) {shift->{'type'};}
271 0     0 1   sub is_blank ($) {shift->{'blankflg'};}
272 0     0 1   sub prefix ($) {shift->{'prefix'};}
273 0     0 1   sub tag ($) {shift->{'tag'};}
274              
275             #-----------------------------------------------------------------------------
276              
277             sub stamped_log_line ($) {
278 0     0 1   my $s = shift;
279 0           my ($d,$t,$p,$type,$priority,$m,$prefix,$tag) =
280             @$s{'date','time','process','type','priority','msg','prefix','tag'};
281 0           return "$d $t UTC> $p: $type($priority): ${prefix}${tag}${m}";
282             }
283              
284             #-----------------------------------------------------------------------------
285              
286             sub unstamped_log_line ($) {
287 0     0 1   my $s = shift;
288 0           my ($p,$type,$priority,$m,$prefix,$tag) =
289             @$s{'process','type','priority','msg','prefix','tag'};
290 0           return "$p: $type($priority): ${prefix}${tag}${m}";
291             }
292            
293             #=============================================================================
294             # POD DOCUMENTATION
295             #=============================================================================
296             # You may extract and format the documention section with the 'perldoc' cmd.
297              
298             =head1 NAME
299              
300             Fault::Msg - Internal message encapsulation class.
301              
302             =head1 SYNOPSIS
303              
304             use Fault::Msg;
305             $self = Fault::Msg->new ($m,$t,$p);
306             $m = $self->set_msg ($m);
307             $t = $self->set_type ($t);
308             $p = $self->set_priority ($p);
309             $prefix = $self->set_prefix ($prefix);
310             $tag = $self->set_tag ($tag);
311              
312             ($stamp,$p,$t,$process,$taggedmsg) = $self->get;
313              
314             $taggedmsg = $self->msg;
315             $stamp = $self->timestamp;
316             $time = $self->time;
317             $date = $self->date;
318             $processname = $self->processname;
319             $p = $self->priority;
320             $t = $self->type;
321             $prefix = $self->prefix;
322             $tag = $self->tag;
323             $bool = $self->is_blank;
324             $line = $self->stamped_log_line;
325             $line = $self->unstamped_log_line;
326              
327             =head1 Inheritance
328              
329             UNIVERSAL
330             Fault::Msg
331              
332             =head1 Description
333              
334             A Fault::Msg is an object internal to the Fault::Logger system. It encapsultes
335             all the required information about a message that will be used for a fault or
336             log report. It makes certain that all required values are present and correct
337             so that other internal classes do not have to do so.
338              
339             The message text itself is stored in three parts: prefix, tag and msg. The
340             prefix is used only in printed log lines. A tag, if present, is included as
341             if it were part of the message text.
342              
343             =head1 Examples
344              
345             None.
346              
347             =head1 Class Variables
348              
349             None.
350              
351             =head1 Instance Variables
352              
353             timestamp The time and date stamp at the time of creation of Msg.
354             date The date portion of the timestamp string.
355             time The time portion of the timestamp string.
356             process $::PROCESS_NAME or a default value.
357             msg The base message text.
358             type The message type.
359             priority The syslog priority type.
360             blankflg True if the base message is a default.
361             prefix A special prefix text that is not 'part' of the message.
362             tag A prefix that when set is alway included with the base
363             message.
364              
365             =head1 Class Methods
366              
367             =over 4
368              
369             =item B<$self = Fault::Msg-Enew ($m,$t,$p)>
370              
371             =item B<$self = Fault::Msg-Enew ($m,$t)>
372              
373             =item B<$self = Fault::Msg-Enew ($m)>
374              
375             =item B<$self = Fault::Msg-Enew>
376              
377             Create an instance of $Fault::Msg for the message, type
378             and priority specified. If values are undef, defaults will
379             be used for the missing values.
380              
381             If the message ends with a newline, it is removed. If there
382             are embedded format chars the line will be rejected by
383             POSIX::printable.
384              
385             =head1 Instance Methods
386              
387             =over 4
388              
389             =item B<$date = $self-Edate>
390              
391             Return the date string, yyyymmdd.
392              
393             =item B<($stamp,$p,$t,$process,$taggedmsg) = $self-Eget>
394              
395             Return the basic list of items used in a log message. Taggedmsg does
396             not include the prefix as prefix's are for log printing.
397              
398             =item B<$bool = $self-Eis_blank>
399              
400             Return true if the base message text is empty and has been replaced
401             by a default.
402              
403             =item B<$taggedmsg = $self-Emsg>
404              
405             Return a concatenated string consisting of the tag and the base message.
406              
407             =item B<$p = $self-Epriority>
408              
409             Return the priority.
410              
411             =item B<$prefix = $self-Eprefix>
412              
413             Return the message prefix.
414              
415             =item B<$processname = $self-Eprocessname>
416              
417             Return the messages originating process name.
418              
419             =item B<$m = $self-Eset_msg ($m)>
420              
421             Set the base message string. An undefined value will set the blank
422             message flag and set the base message to an informative default message.
423              
424             If the message ends with a newline, it is removed. If there
425             are embedded format chars the line will be rejected by
426             POSIX::printable.
427              
428             =item B<$p = $self-Eset_priority ($p)>
429              
430             Set the syslog priority string. An undefined $p will set the priority to
431             a default value compatible with the current string type setting.
432             [See Fault::Logger for more information on defaulting.]
433              
434             =item B<$prefix = $self-Eset_prefix ($prefix)>
435              
436             Set the prefix string. A prefix will appear before a message and
437             tag in the format '[$prefix] '. A prefix will only appear in strings
438             generated via stamped_log_line and unstamped_log_line.
439              
440             An undefined $prefix will set prefix to the default value: "".
441              
442             =item B<$tag = $self-Eset_tag ($tag)>
443              
444             Set a message tag. A tag will be prepended to the message when ever
445             it is used. A undefined $tag will set tag to the default value: "".
446              
447             =item B<$t = $self-Eset_type ($t)>
448              
449             Set the type of the message. An undefined type string will set type
450             to the default value: 'BUG'.
451              
452             =item B<$line = $self-Estamped_log_line>
453              
454             Return a line formatted for use in a private log format or printing
455             format:
456              
457             "$date $time UTC> $process: $type($priority): ${prefix}${tag}${msg}"
458              
459             =item B<$tag = $self-Etag>
460              
461             Return the tag string.
462              
463             =item B<$time = $self-Etime>
464              
465             Return a time string. A time is formatted: hhmmss.
466              
467             =item B<$stamp = $self-Etimestamp>
468              
469             Return the message timestamp. A timestamp is formatted: yyyymmddhhmmss.
470              
471             =item B<$t = $self-Etype>
472              
473             Return the message type string.
474              
475             =item B<$line = $self-Eunstamped_log_line>
476              
477             Return a line formatted for use in a syslog format:
478              
479             "$process: $type($priority): ${prefix}${tag}${msg}"
480              
481             =back 4
482              
483             =head1 Private Class Method
484              
485             None.
486              
487             =head1 Private Instance Methods
488              
489             None.
490              
491             =head1 Errors and Warnings
492              
493             None.
494              
495             =head1 KNOWN BUGS
496              
497             POSIX::isprint is used to filter whether a message is junk or not.
498             It should probably make an effort to sanitize the string of format
499             characters rather than reject a potentially good message.
500              
501             See TODO.
502              
503             =head1 Errors and Warnings
504              
505             None.
506              
507             =head1 SEE ALSO
508              
509             None.
510              
511             =head1 AUTHOR
512              
513             Dale Amon
514              
515             =cut
516            
517             #=============================================================================
518             # CVS HISTORY
519             #=============================================================================
520             # $Log: Msg.pm,v $
521             # Revision 1.8 2008-08-28 23:20:19 amon
522             # perldoc section regularization.
523             #
524             # Revision 1.7 2008-08-17 21:56:37 amon
525             # Make all titles fit CPAN standard.
526             #
527             # Revision 1.6 2008-07-24 21:17:24 amon
528             # Moved all todo notes to elsewhere; made Stderr the default delegate instead of Stdout.
529             #
530             # Revision 1.5 2008-07-24 19:11:29 amon
531             # Notepad now uses Fault::Msg class which moves all the timestamp and
532             # digitalsig issues to Msg.
533             #
534             # Revision 1.4 2008-07-23 22:56:30 amon
535             # I forgot chomp does not return the chomped string. Fixed the code
536             # accordingly.
537             #
538             # Revision 1.3 2008-07-23 22:32:51 amon
539             # chomp line ends in Msg class rather than fail unconditionally due to
540             # POSIX::isprint.
541             #
542             # Revision 1.2 2008-05-07 18:38:20 amon
543             # Documentation fixes.
544             #
545             # Revision 1.1 2008-05-07 17:45:35 amon
546             # Put most of the message handling into this class.
547             #
548             # $DATE Dale Amon
549             # Created.
550             1;