@@ -16,41 +16,73 @@ use HeliosX::Logger::HiRes::LogEntry;
1616our $VERSION = ' 0.10_0000' ;
1717
1818our @LOG_PRIORITIES = qw( EMERG ALERT CRIT ERR WARNING NOTICE INFO DEBUG) ;
19+ our %LOG_PRIORITY_MAP = (
20+ EMERG => 0,
21+ ALERT => 1,
22+ CRIT => 2,
23+ ERR => 3,
24+ WARNING => 4,
25+ NOTICE => 5,
26+ INFO => 6,
27+ DEBUG => 7
28+ );
1929our $LIMIT_DEFAULT = 50;
2030
2131our ($OPT_START_DATE , $OPT_END_DATE , $OPT_HOSTNAME , $OPT_PID , $OPT_JOBID ,
22- $OPT_JOBTYPE , $OPT_SERVICE , $OPT_MESSAGE , $OPT_LIMIT , $OPT_SORT );
32+ $OPT_JOBTYPE , $OPT_SERVICE , $OPT_PRIORITY , $OPT_MESSAGE , $OPT_LIMIT ,
33+ $OPT_SORT , $OPT_TAIL , $OPT_FOLLOW );
2334our ($OPT_HELP , $OPT_VERSION , $OPT_DEBUG );
2435
25- our $DEBUG_MODE = 0;
36+ our $DEBUG_MODE = 1;
37+ our $FOLLOW_MODE = 0;
38+ our $TAIL_MODE = 0;
39+ our $LAST_LOGID = 0;
2640
2741GetOptions(
28- " start-date=s" => \$OPT_START_DATE ,
29- " end-date=s" => \$OPT_END_DATE ,
30- " hostname=s" => \$OPT_HOSTNAME ,
31- " pid=i" => \$OPT_PID ,
32- " jobid=s" => \$OPT_JOBID ,
33- " jobtype=s" => \$OPT_JOBTYPE ,
34- " service=s" => \$OPT_SERVICE ,
35- " message=s" => \$OPT_MESSAGE ,
36- " limit=i" => \$OPT_LIMIT ,
37- " sort=s" => \$OPT_SORT ,
38- " help" => \$OPT_HELP ,
39- " version" => \$OPT_VERSION ,
40- " debug" => \$OPT_DEBUG ,
42+ " start-date=s" => \$OPT_START_DATE ,
43+ " end-date=s" => \$OPT_END_DATE ,
44+ " hostname=s" => \$OPT_HOSTNAME ,
45+ " pid=i" => \$OPT_PID ,
46+ " jobid=s" => \$OPT_JOBID ,
47+ " jobtype=s" => \$OPT_JOBTYPE ,
48+ " service=s" => \$OPT_SERVICE ,
49+ " message=s" => \$OPT_MESSAGE ,
50+ " priority=s" => \$OPT_PRIORITY ,
51+ " n|lines|limit=i" => \$OPT_LIMIT ,
52+ " sort=s" => \$OPT_SORT ,
53+ " tail" => \$OPT_TAIL ,
54+ " follow" => \$OPT_FOLLOW ,
55+ " help" => \$OPT_HELP ,
56+ " version" => \$OPT_VERSION ,
57+ " debug" => \$OPT_DEBUG ,
4158);
4259
4360# SPECIAL MODES
4461
4562# Help mode
4663if ($OPT_HELP ) {
47- require Pod::Usage;
48- Pod::Usage::pod2usage(-verbose => 2, -exitstatus => 0);
64+ require Pod::Usage;
65+ Pod::Usage::pod2usage(-verbose => 2, -exitstatus => 0);
4966}
5067
5168# Debug mode
5269$DEBUG_MODE = 1 if $OPT_DEBUG ;
5370
71+ # Follow mode
72+ $FOLLOW_MODE = 1 if $OPT_FOLLOW ;
73+
74+ # Sorting & Tail mode
75+ my $sort_order = ' ascend' ;
76+ if ($OPT_SORT && $OPT_SORT =~/ ^desc/ ) {
77+ $sort_order = ' descend' ;
78+ }
79+
80+ if ( $OPT_TAIL ) {
81+ $TAIL_MODE = 1;
82+ $sort_order = ' descend' ;
83+ }
84+
85+
5486# Setup search options
5587
5688my %search_opts ;
@@ -72,10 +104,17 @@ if ($OPT_SERVICE) {
72104}
73105
74106if ($OPT_JOBTYPE ) {
75- my $jt = Helios::JobType-> lookup(name => $OPT_JOBTYPE );
107+ my $jt = Helios::JobType-> lookup(name => $OPT_JOBTYPE );
76108 $search_opts {jobtypeid } = $jt -> getJobtypeid();
77109}
78110
111+ if ($OPT_PRIORITY ) {
112+ my $p = uc ($OPT_PRIORITY );
113+ if ( defined $LOG_PRIORITY_MAP {$p } ) {
114+ $search_opts {priority } = $LOG_PRIORITY_MAP {$p };
115+
116+ }
117+ }
79118
80119my $limit = $LIMIT_DEFAULT ;
81120
@@ -107,41 +146,247 @@ if ($OPT_START_DATE || $OPT_END_DATE) {
107146 $search_opts {log_time } = \" <= $ed_epoch " ;
108147 }
109148
149+ # start-date or end-date turns off limit
150+ if ($sd_epoch || $ed_epoch ) {
151+ $limit = undef ;
152+ }
153+
110154}
111155
112156
113157if ($OPT_LIMIT ) {
114158 $limit = $OPT_LIMIT ;
115159}
116160
117- my $sort_order = ' ascend' ;
118- if ($OPT_SORT && $OPT_SORT =~/ ^desc/ ) {
119- $sort_order = ' descend' ;
161+ # Follow Mode
162+ # --follow doesn't work with --sort=descend
163+ # UNLESS we have --tail --follow,
164+ # because we have special code for that
165+ if ($FOLLOW_MODE ) {
166+ if (!$TAIL_MODE ) {
167+ if ($sort_order eq ' descend' ) {
168+ print STDERR " Cannot --follow if --sort is set to 'descend'\n " ;
169+ exit (1);
170+ }
171+ }
120172}
121173
122174
175+ # [] t
176+ if ($DEBUG_MODE ) {
177+ print Dumper(\%search_opts );
178+ }
179+
123180
124181eval {
125182 my $drvr = Helios::ObjectDriver-> getDriver();
126183 my @logs = $drvr -> search(' HeliosX::Logger::HiRes::LogEntry' =>
127184 { %search_opts },
128185 { sort => ' log_time' , direction => $sort_order , limit => $limit }
129- );
186+ );
187+
188+ if ($TAIL_MODE ) {
189+ @logs = reverse @logs ;
190+ }
191+
130192 foreach ( @logs ) {
131193# print Dumper($_);
132194 my $tp = localtime $_ -> log_time;
133195 my ($sec , $fract ) = split (/ \. / , $_ -> log_time);
134196 my $date = $tp -> ymd.' ' .$tp -> hms.' .' .$fract ;
135197 my $jobinfo = $_ -> jobid ? ' [Jobid ' .$_ -> jobid.' ]' : ' ' ;
198+ $LAST_LOGID = $_ -> logid;
136199 print $_ -> logid,' [' ,$date ,' ] ' ,$_ -> host,' ' ,$_ -> service,' [' ,$_ -> pid,' ]: ' ,$LOG_PRIORITIES [$_ -> priority],$jobinfo ,' ' ,$_ -> message," \n " ;
137200 }
138201
139202 1;
140203} or do {
141- print $@ ," \n " ;
204+ print STDERR $@ ," \n " ;
142205 exit (42);
143206};
144207
208+ if ($FOLLOW_MODE ) {
209+ while (1) {
210+ eval {
211+ $search_opts {logid } = \" > $LAST_LOGID " ;
212+ my $drvr = Helios::ObjectDriver-> getDriver();
213+ my @logs = $drvr -> search(' HeliosX::Logger::HiRes::LogEntry' =>
214+ { %search_opts },
215+ { sort => ' log_time' , direction => ' ascend' }
216+ );
217+ foreach ( @logs ) {
218+ # print Dumper($_);
219+ my $tp = localtime $_ -> log_time;
220+ my ($sec , $fract ) = split (/ \. / , $_ -> log_time);
221+ my $date = $tp -> ymd.' ' .$tp -> hms.' .' .$fract ;
222+ my $jobinfo = $_ -> jobid ? ' [Jobid ' .$_ -> jobid.' ]' : ' ' ;
223+ $LAST_LOGID = $_ -> logid;
224+ print $_ -> logid,' [' ,$date ,' ] ' ,$_ -> host,' ' ,$_ -> service,' [' ,$_ -> pid,' ]: ' ,$LOG_PRIORITIES [$_ -> priority],$jobinfo ,' ' ,$_ -> message," \n " ;
225+ }
226+ 1;
227+ } or do {
228+ print STDERR $@ , " \n " ;
229+ exit (42);
230+ };
231+ sleep 1;
232+ }
233+ }
234+
235+ exit (0);
236+
237+
238+ =head1 NAME
239+
240+ heliosx_logger_hires_search - search the Helios high resolution log
241+
242+ =head1 SYNOPSIS
243+
244+ # display the log messages for jobid 12345
245+ heliosx_logger_hires_search --jobid=12345
246+
247+ # heliosx_logger_hires_search normally displays only the first 50 messages
248+ # use the -n option to increase/decrease that limit
249+ heliosx_logger_hires_search --jobid=12345 -n 100
250+
251+ # display the last 10 MyService errors, sorted by most recent first
252+ heliosx_logger_hires_search --service=MyService --priority=ERR -n 10 --sort=desc
253+
254+ # display all the MyService log messages for May 29, 2015
255+ # all dates are in ISO8601 format
256+ # specifying dates will turn off the message limit,
257+ # so you will get all the messages for the specified date range
258+ heliosx_logger_hires_search --service=MyService --start-date=2015-05-29T00:00:00 --end-date=2015-05-29T23:59:59
259+
260+ # "tail" and "follow" the log, like 'tail -f' in Unix
261+ heliosx_logger_hires_search --tail --follow
262+
263+ # display the last 100 log messages logged by MyService,
264+ # then follow the log and display any new MyService messages
265+ heliosx_logger_hires_search --service=MyService --t -n 100 -f
266+
267+ =head1 DESCRIPTION
268+
269+ The heliosx_logger_hires_search command can be used to display log messages
270+ matching specified criteria in the enhanced Helios log provided by
271+ HeliosX::Logger::HiRes. It provides a much more convenient way of accessing
272+ log messages than using SQL queries from a database client like SQL*Plus or
273+ sqlite3.
274+
275+ =head1 RUN OPTIONS
276+
277+ =head2 start-date="YYYY-MM-DDTHH24:MI:SS"
278+
279+ =head2 end-date="YYYY-MM-DDTHH24:MI:SS"
280+
281+ Specify a date range of log messages to display. Dates should be in ISO8601
282+ format. If only --start-date is specified, log messages will be displayed from
283+ that date forward until there are no more log messages. If only --end-date is
284+ specified, log messages will be displayed from the the earliest through the
285+ end date specified.
286+
287+ Normally, heliosx_logger_hires_search displays a maximum number of log
288+ messages. The default is 50, but this limit can be raised or lowered with the
289+ -n switch. Specifying a date range, however, turns off this limit; if you
290+ ask for the log messages in a date range, you will get I<all > the log messages
291+ matching your criteria in that range.
292+
293+ =head2 -n, --lines=number_of_lines
294+
295+ Specify the maximum number of log messages to display. The default is 50
296+ lines.
297+
298+ This switch can be combined with the --tail and --follow options to
299+ approximate an output similar to the Unix tail command with -n and -f switches.
300+
301+ =head2 --tail
302+
303+ Display the last log messages matching the given criteria. Similar to using
304+ the Unix 'tail' command on a log file. Defaults to retrieving the last 50
305+ messages, which can be increased or decreased using the -n switch.
306+
307+ =head2 --follow
308+
309+ After the initial log messages have been displayed, the --follow switch
310+ causes heliosx_logger_hires_search to remaining running, displaying any new
311+ log messages that meet the given criteria. This option is similar to the -f
312+ switch of the Unix 'tail' command.
313+
314+ The --follow switch is incompatible with the sort order set to descending
315+ (--sort=desc).
316+
317+ =head2 --sort=asc|desc
318+
319+ Specify the order in which the log messages matching the given criteria are
320+ displayed, either ascending date or descending date order.
321+
322+ You cannot specify --sort=desc with the --follow option, for obvious reasons.
323+
324+ =head1 SEARCH CRITERIA OPTIONS
325+
326+ =head2 --hostname=name_of_host
327+
328+ Display only log messages logged by services on a particular host.
329+
330+ =head2 --pid=process_id
331+
332+ Display only log messages logged by a particular PID. To properly isolate
333+ messages from a specific PID on a specific host, use with the --hostname
334+ option.
335+
336+ =head2 --jobid=jobid
337+
338+ Display only the log messages logged for a particular jobid.
339+
340+ =head2 --jobtype=jobtype_name
341+
342+ Display only the log messages logged for jobs belonging to a particular
343+ jobtype.
344+
345+ =head2 --service=service_name
346+
347+ Display only the log messages logged by a particular service. This will
348+ include NOTICE messages logged by the service agent daemon; if you want to
349+ limit the messages to those associated with a particular job, use --service
350+ with the --jobtype switch.
351+
352+ =head2 --priority=priority_name
353+
354+ Display only log messages of a given priority. The priority names are:
355+
356+ =over 4
357+
358+ =item * EMERG - Emergency
359+
360+ =item * ALERT - Alert
361+
362+ =item * CRIT - Critical
363+
364+ =item * ERR - Error
365+
366+ =item * WARNING - Warning
367+
368+ =item * NOTICE - Notice
369+
370+ =item * INFO - Informational
371+
372+ =item * DEBUG - Debug
373+
374+ =back
375+
376+ =head1 AUTHOR
377+
378+ Andrew Johnson, E<lt> lajandy at cpan dot orgE<gt>
379+
380+ =head1 COPYRIGHT AND LICENSE
381+
382+ Copyright (C) 2015 by Logical Helion, LLC.
383+
384+ This library is free software; you can redistribute it and/or modify it under
385+ the terms of the Artistic License 2.0. See the included LICENSE file for
386+ details.
145387
388+ =head1 WARRANTY
146389
390+ This software comes with no warranty of any kind.
147391
392+ =cut
0 commit comments