added 60 s timeout for host/port to show only live ones
[dell-switch] / syslog-count-link.pl
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4
5 # count Dell and Microtik syslog for port and stp events
6
7 ## report all logs:
8 # sudo cat /var/log/switch/sw-[a-z][0-9]*.log | ./syslog-count-link.pl | less -S
9 #
10 ## tail logs and report status on kill -HUP
11 # sudo tail -f /var/log/switch/sw-[a-z][0-9]*.log | ./syslog-count-link.pl &
12
13 use Data::Dump qw(dump);
14 use POSIX qw(strftime);
15
16 my $timeout = $ENV{TIMEOUT} || 60; # forget switch after sec
17
18 my $name = $0;
19 $name =~ s/.*\/([^\/]+)$/$1/;
20 $name =~ s/\.pl$//;
21 my $dir = "/dev/shm/$name";
22 mkdir $dir unless -e $dir;
23
24 our $stat;
25
26 sub print_stats {
27         open(my $fh, '>', "$dir/stats");
28
29         foreach my $host ( sort keys %$stat ) {
30                 foreach my $port ( sort {
31                         my $a1 = $a; $a1 =~ s/\D+//g;
32                         my $b1 = $b; $b1 =~ s/\D+//g;
33                         no warnings;
34                         $a1 <=> $b1;
35                 } keys %{ $stat->{$host} } ) {
36                         next if $port =~ m/^_/;
37                         my $dt = time() - $stat->{$host}->{$port}->[0];
38                         if ( $dt > $timeout ) {
39                                 delete $stat->{$host}->{$port};
40                                 next;
41                         }
42                         my $out = sprintf "%-12s %-4s %-2d %s\n", $host, $port, $dt, $stat->{$host}->{$port}->[1];
43                         print $out;
44                         print $fh $out;
45                 }
46         }
47
48         close($fh);
49 }
50
51 sub reset_stats {
52         if ( -e "$dir/reset" && unlink "$dir/reset" ) {
53                 $stat = {};
54                 warn "# reset stats\n";
55         }
56 }
57
58
59 $SIG{HUP} = sub {
60         print_stats();
61         reset_stats;
62 };
63
64 warn "kill -HUP $$  # to dump stats\n";
65 {
66         open(my $fh, '>', "$dir/pid");
67         print $fh $$;
68         close($fh);
69 }
70
71 sub stat_host_port {
72         my ( $host, $port, $state ) = @_;
73         if ( ! exists $stat->{$host}->{$port} ) {
74                 $stat->{$host}->{$port} = [-1, $state];
75         } else {
76                 $stat->{$host}->{$port}->[1] .= $state;
77         }
78         $stat->{$host}->{$port}->[0] = time();
79         #warn "# stat_host_port ",dump($stat);
80 }
81
82
83 my $host_re = '[\w-]+';
84 my $port_re = '[\w/]+';
85
86 while(<>) {
87         chomp;
88         s/[\r\n]+//;
89
90         reset_stats;
91
92         next if m/^$/;
93         next if m/%PIX-/; # ignore PIX logs
94
95         ## Dell old
96         if ( m/(\S+)\s%LINK-[IW]-(\w+):\s*(\w+)/ ) {
97                 my ($host,$state,$port) = ($1,$2,$3);
98                 stat_host_port( $host, $port, substr($state,0,1) );
99         } elsif ( m/(\S+)\s%STP-W-PORTSTATUS:\s([\w\/]+): STP status (\w+)/ ) {
100                 my ($host,$port,$state) = ($1,$2,$3);
101                 stat_host_port( $host, $port, '-' );
102
103
104         ## Dell new
105         } elsif ( m/LINK - (\w+) - Hostname: <($host_re)>, ($port_re)/ ) {
106                 my ($state, $host, $port ) = ($1,$2,$3);
107                 stat_host_port( $host, $port, substr($state,0,1) );
108         } elsif ( m/STP - PORTSTATUS - Hostname: <($host_re)>,($port_re): STP status (\w+)/ ) {
109                 my ($host,$port,$state) = ($1,$2,$3);
110                 stat_host_port( $host, $port, '-' );
111
112
113         ## Mikrotik
114         } elsif ( m/($host_re) \w+: ([\w\-]+) link (\w+)/ ) {
115                 my ($host, $port, $state ) = ($1,$2,$3);
116                 stat_host_port( $host, $port, substr($state,0,1) );
117
118
119         } elsif ( m'==> /var/log/' ) {
120                 # ignore tail output
121                 next;
122         } else {
123                 warn "IGNORE: [$_]\n";
124                 next;
125         }
126
127         if ( -e "$dir/dump" ) {
128                 print "### ",strftime("%Y-%m-%d %H:%M:%S",localtime(time)), "\n";
129                 print_stats;
130         }
131 }
132
133
134
135 warn "# stat = ", dump($stat);
136 print_stats;
137
138