File Coverage

blib/lib/AnyEvent/MP/LogCatcher.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             AnyEvent::MP::LogCatcher - catch all logs from all nodes
4              
5             =head1 SYNOPSIS
6              
7             use AnyEvent::MP::LogCatcher;
8              
9             =head1 DESCRIPTION
10              
11             This relatively simple module overrides C<$AnyEvent::MP::Kernel::WARN> on
12             every node and sends all log messages to the node running this service.
13              
14             No attempt to buffer log messages on connection loss, or retransmit lost
15             messages, is done.
16              
17             =head1 GLOBALS AND FUNCTIONS
18              
19             =over 4
20              
21             =cut
22              
23             package AnyEvent::MP::LogCatcher;
24              
25 1     1   1206 use common::sense;
  1         1  
  1         6  
26 1     1   39 use Carp ();
  1         2  
  1         15  
27 1     1   5 use POSIX ();
  1         2  
  1         21  
28              
29 1     1   5 use AnyEvent ();
  1         1  
  1         15  
30 1     1   5 use AnyEvent::Util ();
  1         1  
  1         22  
31              
32 1     1   45 use AnyEvent::MP;
  0            
  0            
33             use AnyEvent::MP::Kernel;
34              
35             use base "Exporter";
36              
37             $AnyEvent::MP::Kernel::WARN->(7, "starting log catcher service.");
38              
39             our $LOGLEVEL;
40             our %lport; # local logging ports
41              
42             # other nodes connect via this
43             sub connect {
44             my ($version, $rport, $loglevel) = @_;
45              
46             my $cb = sub {
47             snd $rport, @_
48             if $_[0] <= $loglevel;
49             };
50              
51             push @AnyEvent::MP::Kernel::WARN, $cb;
52              
53             # monitor them, silently die
54             mon $rport, sub {
55             @AnyEvent::MP::Kernel::WARN = grep $_ != $cb, @AnyEvent::MP::Kernel::WARN;
56             };
57             }
58              
59             sub mon_node {
60             my ($node, $is_up) = @_;
61              
62             return unless $is_up;
63              
64             my $lport = $lport{$node} = port {
65             my ($level, $msg) = @_;
66              
67             $msg =~ s/\n$//;
68              
69             printf STDERR "%s [%s] <%d> %s\n",
70             (POSIX::strftime "%Y-%m-%d %H:%M:%S", localtime time),
71             $node,
72             $level,
73             $msg;
74             };
75              
76             # establish connection
77             AnyEvent::MP::Kernel::snd_to_func $node, "AnyEvent::MP::LogCatcher::connect", 0, $lport, $LOGLEVEL;
78              
79             mon $node, $lport;
80             }
81              
82             =item AnyEvent::MP::LogCatcher::catch [$level]
83              
84             Starts catching all log messages from all nodes with level C<$level> or
85             lower. If the C<$level> is C<undef>, then stop catching all messages
86             again.
87              
88             Example: start a node that catches all messages (you might have to specify
89             a suitable profile name).
90              
91             aemp run profilename services '[["AnyEvent::MP::LogCatcher::catch",9]]'
92              
93             =cut
94              
95             sub catch {
96             $LOGLEVEL = $_[0];
97             kil $_, "restart" for values %lport;
98             %lport = ();
99              
100             return unless defined $LOGLEVEL;
101              
102             mon_node $_, 1
103             for up_nodes;
104              
105             mon_nodes \&mon_node;
106             ()
107             }
108              
109             =back
110              
111             =head1 SEE ALSO
112              
113             L<AnyEvent::MP>.
114              
115             =head1 AUTHOR
116              
117             Marc Lehmann <schmorp@schmorp.de>
118             http://home.schmorp.de/
119              
120             =cut
121              
122             1
123