File Coverage

blib/lib/File/Syslogger.pm
Criterion Covered Total %
statement 17 69 24.6
branch 0 30 0.0
condition n/a
subroutine 6 9 66.6
pod 1 1 100.0
total 24 109 22.0


line stmt bran cond sub pod time code
1             package File::Syslogger;
2              
3 1     1   135180 use 5.006;
  1         4  
4 1     1   39 use strict;
  1         3  
  1         33  
5 1     1   39 use warnings;
  1         3  
  1         77  
6 1     1   808 use POE qw(Wheel::FollowTail);
  1         57745  
  1         11  
7 1     1   97581 use Log::Syslog::Fast ':all';
  1         3530  
  1         250  
8 1     1   10 use Sys::Hostname qw( hostname );
  1         2  
  1         1061  
9              
10             =head1 NAME
11              
12             File::Syslogger - Use POE to tail a file and read new lines into syslog.
13              
14             =head1 VERSION
15              
16             Version 0.0.3
17              
18             =cut
19              
20             our $VERSION = '0.0.3';
21              
22             =head1 SYNOPSIS
23              
24             use File::Syslogger;
25              
26             File::Syslogger->run(
27             pri=>'alert',
28             facility=>'daemon',
29             files=>{
30             {'sagan_eve'}=>{file=>'/var/log/sagan/eve', program=>'saganEve'},
31             {'suricata_eve'}=>{file=>'/var/log/suricata/eve', program=>'suricataEve'},
32             },
33             );
34              
35             =head1 METHODS
36              
37             =head2 run
38              
39             Initiates POE sessions and run them.
40              
41             This will die if there are any config issues.
42              
43             The following options are optionaal.
44              
45             - priority :: The priority of the logged item.
46             Default :: notice
47              
48             - facility :: The facility for logging.
49             Default :: daemon
50              
51             - program :: Name of the program logging.
52             Default :: fileSyslogger
53              
54             - socket :: The syslogd socket.
55             Default :: /var/run/log
56              
57             The option files is a hash of hashes. It has one mandatory
58             key, 'file', which is the file to follow. All the above
59             options may be used in the sub hashes.
60              
61             For priority, below are the various valid values.
62              
63             emerg
64             emergency
65             alert
66             crit
67             critical
68             err
69             error
70             warning
71             notice
72             info
73              
74             For facility, below are the various valid values.
75              
76             kern
77             user
78             mail
79             daemon
80             auth
81             syslog
82             lpr
83             news
84             uucp
85             cron
86             authpriv
87             ftp
88             local0
89             local1
90             local2
91             local3
92             local4
93             local5
94             local6
95             local7
96              
97             File rotation should be picked up POE::Wheel::FollowTail.
98              
99             =cut
100              
101             sub run {
102 0     0 1   my ( $blank, %opts ) = @_;
103              
104 0 0         if ( !defined( $opts{files} ) ) {
105 0           die('"files" is not defined');
106             }
107              
108 0 0         if ( ref( $opts{files} ) ne 'HASH' ) {
109 0           die("$opts{files} is not a hash");
110             }
111              
112 0 0         if ( !defined( $opts{program} ) ) {
113 0           $opts{program} = 'fileSyslogger';
114             }
115              
116 0 0         if ( !defined( $opts{socket} ) ) {
117 0           $opts{socket} = "/var/run/log";
118             }
119              
120             #mapping for severity for constant handling
121 0           my %sev_mapping = (
122             'emerg' => LOG_EMERG,
123             'emergency' => LOG_EMERG,
124             'alert' => LOG_ALERT,
125             'crit' => LOG_CRIT,
126             'critical' => LOG_CRIT,
127             'err' => LOG_ERR,
128             'error' => LOG_ERR,
129             'warning' => LOG_WARNING,
130             'notice' => LOG_NOTICE,
131             'info' => LOG_INFO,
132             );
133              
134             # default to info if none is specified
135 0 0         if ( !defined( $opts{priority} ) ) {
136 0           $opts{priority} = "notice";
137             } else {
138             # one was specified, convert to lower case and make sure it valid
139 0           $opts{priority} = lc( $opts{priority} );
140 0 0         if ( !defined( $sev_mapping{ $opts{priority} } ) ) {
141 0           die( '"' . $opts{priority} . '" is not a known priority' );
142             }
143             }
144              
145             #mapping for facility for constant handling
146 0           my %fac_mapping = (
147             'kern' => LOG_KERN,
148             'user' => LOG_USER,
149             'mail' => LOG_MAIL,
150             'daemon' => LOG_DAEMON,
151             'auth' => LOG_AUTH,
152             'syslog' => LOG_SYSLOG,
153             'lpr' => LOG_LPR,
154             'news' => LOG_NEWS,
155             'uucp' => LOG_UUCP,
156             'cron' => LOG_CRON,
157             'authpriv' => LOG_AUTHPRIV,
158             'ftp' => LOG_FTP,
159             'local0' => LOG_LOCAL0,
160             'local1' => LOG_LOCAL1,
161             'local2' => LOG_LOCAL2,
162             'local3' => LOG_LOCAL3,
163             'local4' => LOG_LOCAL4,
164             'local5' => LOG_LOCAL5,
165             'local6' => LOG_LOCAL6,
166             'local7' => LOG_LOCAL7,
167             );
168              
169             # default to system if none is specified
170 0 0         if ( !defined( $opts{facility} ) ) {
171 0           $opts{facility} = 'daemon';
172             } else {
173             # one was specified, convert to lower case and make sure it valid
174 0           $opts{facility} = lc( $opts{facility} );
175 0 0         if ( !defined( $fac_mapping{ $opts{facility} } ) ) {
176 0           die( '"' . $opts{facility} . '" is not a known facility' );
177             }
178             }
179              
180             # process each file and setup the syslogger
181 0           my $file_count = 0;
182 0           foreach my $item ( keys( %{ $opts{files} } ) ) {
  0            
183              
184             # make sure we have a file specified
185 0 0         if ( !defined( $opts{files}{$item}{file} ) ) {
186 0           die( 'No file specified for "' . $item . '"' );
187             }
188              
189             # figure out what facility to use for this item
190 0           my $item_fac;
191 0 0         if ( defined( $opts{files}{$item}{facility} ) ) {
192              
193             # make sure it is valid
194 0           $item_fac = lc( $opts{files}{$item}{facility} );
195 0 0         if ( !defined( $fac_mapping{ $opts{facility} } ) ) {
196 0           die( '"' . $item_fac . '" in "' . $item . '" is not a known facility' );
197             }
198             } else {
199             # none specified, so using default
200 0           $item_fac = $opts{facility};
201             }
202 0           $item_fac = $fac_mapping{$item_fac};
203              
204             # figure out what facility to use for this item
205 0           my $item_pri;
206 0 0         if ( defined( $opts{files}{$item}{priority} ) ) {
207              
208             # make sure it is valid
209 0           $item_pri = lc( $opts{files}{$item}{priority} );
210 0 0         if ( !defined( $fac_mapping{$item_pri} ) ) {
211 0           die( '"' . $item_pri . '" in "' . $item . '" is not a known facility' );
212             }
213             } else {
214             # none specified, so using default
215 0           $item_pri = $opts{priority};
216             }
217 0           $item_pri = $sev_mapping{$item_pri};
218              
219             # figure out what program name to use
220 0           my $item_program;
221 0 0         if ( defined( $opts{files}{$item}{program} ) ) {
222 0           $item_program = $opts{files}{$item}{program};
223             } else {
224             # none specified, so using default
225 0           $item_program = $opts{program};
226             }
227              
228             # create the logger that will be used by the POE session
229             my $logger
230 0           = Log::Syslog::Fast->new( LOG_UNIX, $opts{socket}, 1, $item_fac, $item_pri, hostname, $item_program );
231              
232             # create the POE session
233             POE::Session->create(
234             inline_states => {
235             _start => sub {
236             $_[HEAP]{tailor} = POE::Wheel::FollowTail->new(
237             Filename => $_[HEAP]{file},
238 0     0     InputEvent => "got_log_line",
239             );
240             },
241             got_log_line => sub {
242 0     0     $_[HEAP]{logger}->send( $_[ARG0] );
243             },
244             },
245 0           heap => { file => $opts{files}{$item}{file}, logger => $logger },
246             );
247              
248 0           $file_count++;
249             } ## end foreach my $item ( keys( %{ $opts{files} } ) )
250              
251 0 0         if ( $file_count == 0 ) {
252 0           die("No files specified");
253             }
254              
255 0           POE::Kernel->run;
256             } ## end sub run
257              
258             =head1 AUTHOR
259              
260             Zane C. Bowers-Hadley, C<< >>
261              
262             =head1 BUGS
263              
264             Please report any bugs or feature requests to C, or through
265             the web interface at L. I will be notified, and then you'll
266             automatically be notified of progress on your bug as I make changes.
267              
268             Or via Github at L.
269              
270             =head1 SUPPORT
271              
272             You can find documentation for this module with the perldoc command.
273              
274             perldoc File::Syslogger
275              
276              
277             You can also look for information at:
278              
279             =over 4
280              
281             =item * GitHub
282              
283             L
284              
285             =item * RT: CPAN's request tracker (report bugs here)
286              
287             L
288              
289             =item * Search CPAN
290              
291             L
292              
293             =back
294              
295              
296             =head1 ACKNOWLEDGEMENTS
297              
298              
299             =head1 LICENSE AND COPYRIGHT
300              
301             This software is Copyright (c) 2025 by Zane C. Bowers-Hadley.
302              
303             This is free software, licensed under:
304              
305             The Artistic License 2.0 (GPL Compatible)
306              
307              
308             =cut
309              
310             1; # End of File::Syslogger