… | |
… | |
6 | |
6 | |
7 | use AnyEvent::MP::LogCatcher; |
7 | use AnyEvent::MP::LogCatcher; |
8 | |
8 | |
9 | =head1 DESCRIPTION |
9 | =head1 DESCRIPTION |
10 | |
10 | |
11 | This relatively simple module overrides C<$AnyEvent::MP::Kernel::WARN> on |
11 | This relatively simple module attaches itself to the |
12 | every node and sends all log messages to the node running this service. |
12 | C<$AnyEvent::Log::COLLECT> context on every node and sends all log |
|
|
13 | messages to the node showing interest via the C<catch> function. |
13 | |
14 | |
14 | No attempt to buffer log messages on connection loss, or retransmit lost |
15 | No attempt to buffer log messages on connection loss, or to retransmit |
15 | messages, is done. |
16 | lost messages, is done. |
16 | |
17 | |
17 | =head1 GLOBALS AND FUNCTIONS |
18 | =head1 GLOBALS AND FUNCTIONS |
18 | |
19 | |
19 | =over 4 |
20 | =over 4 |
20 | |
21 | |
… | |
… | |
25 | use common::sense; |
26 | use common::sense; |
26 | use Carp (); |
27 | use Carp (); |
27 | use POSIX (); |
28 | use POSIX (); |
28 | |
29 | |
29 | use AnyEvent (); |
30 | use AnyEvent (); |
|
|
31 | use AnyEvent::Log (); |
30 | use AnyEvent::Util (); |
32 | use AnyEvent::Util (); |
31 | |
33 | |
32 | use AnyEvent::MP; |
34 | use AnyEvent::MP; |
33 | use AnyEvent::MP::Kernel; |
35 | use AnyEvent::MP::Kernel; |
34 | |
36 | |
35 | use base "Exporter"; |
37 | use base "Exporter"; |
36 | |
38 | |
37 | $AnyEvent::MP::Kernel::WARN->(7, "starting log catcher service."); |
39 | AE::log 7 => "starting log catcher service."; |
38 | |
40 | |
39 | our $LOGLEVEL; |
41 | our $LOGLEVEL; |
40 | our %lport; # local logging ports |
42 | our %lport; # local logging ports |
41 | |
43 | |
42 | # other nodes connect via this |
44 | # other nodes connect via this |
43 | sub connect { |
45 | sub connect { |
44 | my ($version, $rport, $loglevel) = @_; |
46 | my ($version, $rport, $loglevel) = @_; |
45 | |
47 | |
46 | my $cb = sub { |
48 | my $ctx = new AnyEvent::Log::Ctx |
|
|
49 | title => "AnyEvent::MP::LogCatcher", |
|
|
50 | level => $loglevel, |
|
|
51 | log_cb => sub { |
47 | snd $rport, @_ |
52 | snd $rport, @{ $_[0] }; |
48 | if $_[0] <= $loglevel; |
53 | }, |
|
|
54 | fmt_cb => sub { |
|
|
55 | [$_[0], $_[1]->title, $_[2], $_[3]] |
|
|
56 | }, |
49 | }; |
57 | ; |
50 | |
58 | |
51 | push @AnyEvent::MP::Kernel::WARN, $cb; |
59 | $AnyEvent::Log::COLLECT->attach ($ctx); |
52 | |
60 | |
53 | # monitor them, silently die |
61 | # monitor them, silently die |
54 | mon $rport, sub { |
62 | mon $rport, sub { |
55 | @AnyEvent::MP::Kernel::WARN = grep $_ != $cb, @AnyEvent::MP::Kernel::WARN; |
63 | $AnyEvent::Log::COLLECT->detach ($ctx); |
56 | }; |
64 | }; |
57 | } |
65 | } |
58 | |
66 | |
59 | sub mon_node { |
67 | sub mon_node { |
60 | my ($node, $is_up) = @_; |
68 | my ($node, $is_up) = @_; |
61 | |
69 | |
62 | return unless $is_up; |
70 | return unless $is_up; |
63 | |
71 | |
64 | my $lport = $lport{$node} = port { |
72 | my $lport = $lport{$node} = port { |
65 | my ($level, $msg) = @_; |
73 | my ($time, $ctx, $level, $msg) = @_; |
66 | |
74 | |
67 | $msg =~ s/\n$//; |
75 | $level = 2 if $level < 2; # do not exit because others do so |
68 | |
76 | |
69 | printf STDERR "%s [%s] <%d> %s\n", |
77 | my $diff = $time - AE::now; |
70 | (POSIX::strftime "%Y-%m-%d %H:%M:%S", localtime time), |
78 | $diff = $diff < 1e-4 ? "" : sprintf ", %gs", $diff; |
71 | $node, |
79 | AE::log $level, "[$node$diff] $msg"; |
72 | $level, |
|
|
73 | $msg; |
|
|
74 | }; |
80 | }; |
75 | |
81 | |
76 | # establish connection |
82 | # establish connection |
77 | AnyEvent::MP::Kernel::snd_to_func $node, "AnyEvent::MP::LogCatcher::connect", 0, $lport, $LOGLEVEL; |
83 | AnyEvent::MP::Kernel::snd_to_func $node, "AnyEvent::MP::LogCatcher::connect", 0, $lport, $LOGLEVEL; |
78 | |
84 | |