PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/swatch-3.2.3/lib/Swatch/Throttle.pm

#
Perl | 232 lines | 187 code | 27 blank | 18 comment | 12 complexity | ef0cf379d33f5701b38cfc098afb142a MD5 | raw file
Possible License(s): GPL-2.0
  1. package Swatch::Throttle;
  2. require 5.000;
  3. require Exporter;
  4. use strict;
  5. use Carp;
  6. use Date::Calc;
  7. use Date::Manip;
  8. use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  9. @ISA = qw(Exporter);
  10. @EXPORT = qw/
  11. flushLogRecords
  12. throttle
  13. readHistory
  14. saveHistory
  15. /;
  16. $VERSION = '20030701';
  17. #
  18. # %LogRecords = (
  19. # <string> => { # keyed by "key" below
  20. # KEY => <string>, # generated key
  21. # FIRST => @dmyhms, # time of first log
  22. # LAST => @dmyhms, # time of last log
  23. # COUNT => <int>, # num of logs seen since last report
  24. # },
  25. # );
  26. my %LogRecords = ();
  27. ################################################################
  28. sub readHistory {
  29. my $file = shift;
  30. my $return;
  31. if (-f $file) {
  32. unless ($return = do $file) {
  33. warn "couldn't parse $file: $@" if $@;
  34. warn "couldn't do $file: $!" unless defined $return;
  35. warn "couldn't run file" unless $return;
  36. }
  37. }
  38. return;
  39. }
  40. ################################################################
  41. sub saveHistory {
  42. my $file = shift;
  43. my $fh = new FileHandle $file, "w";
  44. my $date = localtime(time);
  45. if (defined $fh) {
  46. $fh->print(q/
  47. ################################################################
  48. # THIS FILE WAS GENERATED BY SWATCH AT $date.
  49. # DO NOT EDIT!!!
  50. ################################################################
  51. $Swatch::Throttle::LogRecords = (
  52. /);
  53. foreach my $key ( keys %LogRecords ) {
  54. $fh->print("\t'$key' => {\n");
  55. foreach my $attr ( keys %{ $LogRecords{$key} } ) {
  56. $fh->print("\t\t$attr => ");
  57. if ($attr =~ /FIRST|LAST|HOLD_DHMS/) {
  58. $fh->print("[ ");
  59. foreach my $elem (@{ $LogRecords{$key}{$attr} }) {
  60. $fh->print("\'$elem\', ");
  61. }
  62. $fh->print("],\n");
  63. } else {
  64. $fh->print("\"$LogRecords{$key}{$attr}\",\n");
  65. }
  66. }
  67. $fh->print("\t},\n");
  68. }
  69. $fh->print(");\n");
  70. $fh->close;
  71. } else {
  72. }
  73. }
  74. ################################################################
  75. # throttle() - returns the
  76. ################################################################
  77. sub throttle {
  78. my %opts = (
  79. MESSAGE => $_,
  80. EXTRA_CUTS => [], # regex(s) used for creating key if key=log
  81. KEY => 'log',
  82. TIME_FROM => 'realtime',
  83. TIME_REGEX => '^(\w{3}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2})\s+',
  84. @_
  85. );
  86. my @dmyhms;
  87. my $key;
  88. my $cur_rec;
  89. my $msg = $opts{"MESSAGE"};
  90. ## get the time ##
  91. if ($opts{TIME_FROM} eq 'realtime') {
  92. @dmyhms = Date::Calc::Today_and_Now();
  93. } else {
  94. if ($opts{MESSAGE} =~ /$opts{TIME_REGEX}/ and $1 ne '') {
  95. my $date = Date::Calc::ParseDate($1);
  96. if (not $date) {
  97. warn "Cannot parse date from \"$opts{MESSAGE}\" using \"$opts{TIME_REGEX}\"\n";
  98. } else {
  99. @dmyhms = Date::Manip::UnixDate($date, "%Y", "%m", "%d", "%H", "%M", "%S");
  100. }
  101. }
  102. }
  103. ## get the key ##
  104. if ($opts{KEY} eq 'log') {
  105. $key = $opts{MESSAGE};
  106. $key =~ s/$opts{TIME_REGEX}//;
  107. if (defined $opts{EXTRA_CUTS}) {
  108. foreach my $re (@{ $opts{EXTRA_CUTS} }) {
  109. $key =~ s/$re//g;
  110. }
  111. }
  112. } else {
  113. $key = $opts{KEY};
  114. }
  115. ## just make the record if it doesn't exist yet ##
  116. if (not defined $LogRecords{$key}) {
  117. my $rec = ();
  118. $rec->{KEY} = $key;
  119. $rec->{FIRST} = [ @dmyhms ];
  120. $rec->{LAST} = [ @dmyhms ];
  121. $rec->{HOLD_DHMS} = $opts{HOLD_DHMS} if defined $opts{HOLD_DHMS};
  122. $rec->{COUNT} = 1;
  123. $LogRecords{$key} = $rec;
  124. return $msg;
  125. } else {
  126. $cur_rec = $LogRecords{$key};
  127. $cur_rec->{COUNT}++;
  128. if (defined $opts{THRESHOLD} and $cur_rec->{COUNT} == $opts{THRESHOLD}) {
  129. ## threshold exceeded ##
  130. chomp $msg;
  131. $msg = "$msg (threshold $opts{THRESHOLD} exceeded)";
  132. $cur_rec->{COUNT} = 0;
  133. } elsif (defined $opts{HOLD_DHMS}
  134. and past_hold_time($cur_rec->{LAST},
  135. \@dmyhms, $opts{HOLD_DHMS})) {
  136. ## hold time exceeded ##
  137. chomp $msg;
  138. $msg = "$msg (seen $cur_rec->{COUNT} times)";
  139. $cur_rec->{COUNT} = 0;
  140. $cur_rec->{LAST} = [ @dmyhms ];
  141. } else {
  142. $msg = '';
  143. }
  144. $LogRecords{$key} = $cur_rec if exists($LogRecords{$key}); ## save any new values ##
  145. }
  146. return $msg;
  147. }
  148. ################################################################
  149. # Checks to see if the current time is less than the last
  150. # time plus the minimum hold time.
  151. ################################################################
  152. sub past_hold_time {
  153. my $last = shift; ## pointer to YMDHMS array of last message
  154. my $cur = shift; ## pointer to YMDHMS array of current message
  155. my $hold = shift; ## pointer to DHMS array of min. hold time
  156. my @ymdhms = Date::Calc::Add_Delta_DHMS( @{ $last }, @{ $hold } );
  157. my @delta = Date::Calc::Delta_DHMS( @ymdhms, @{ $cur } );
  158. return( $delta[0] > 0 or $delta[1] > 0
  159. or $delta[2] > 0 or $delta[3] > 0 );
  160. }
  161. ################
  162. sub flushOldLogRecords {
  163. my @dmyhms = Date::Calc::Today_and_Now();
  164. foreach my $key (keys %LogRecords) {
  165. if (defined $LogRecords{$key}->{HOLD_DHMS}) {
  166. if (past_hold_time($LogRecords{$key}->{LAST}, \@dmyhms, $LogRecords{$key}->{HOLD_DHMS})
  167. and $LogRecords{$key}->{COUNT} == 0) {
  168. delete($LogRecords{$key});
  169. }
  170. }
  171. }
  172. }
  173. ## The POD ###
  174. =head1 NAME
  175. Swatch::Throttle - Perl extension for throttling and thresholding in swatch(1)
  176. =head1 SYNOPSIS
  177. use Swatch::Throttle;
  178. throttle(
  179. extra_cuts => @array_of_regular_expressions,
  180. hold_dhms => @DHMS,
  181. key => 'log'|<regex>|<user defined>,
  182. log_msg => <message>,
  183. threshold => <n>,
  184. time_from => 'realtime'|'timestamp',
  185. time_regex => <regex>,
  186. );
  187. =head1 SWATCH SYNTAX
  188. throttle threshold=<n>,\
  189. delay=<hours>:<minutes>:<seconds>,\
  190. key=log|regex|<regex>
  191. =head1 DESCRIPTION
  192. =head1 AUTHOR
  193. E. Todd Atkins, todd.atkins@stanfordalumni.org
  194. =head1 SEE ALSO
  195. perl(1), swatch(1).
  196. =cut
  197. 1;