ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/MP/LogCatcher.pm
Revision: 1.7
Committed: Thu Mar 22 22:57:50 2012 UTC (12 years, 2 months ago) by root
Branch: MAIN
CVS Tags: rel-2_02, rel-2_01, rel-2_0, HEAD
Changes since 1.6: +9 -9 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.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 root 1.5 This relatively simple module attaches itself to the
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.
14 root 1.1
15 root 1.5 No attempt to buffer log messages on connection loss, or to retransmit
16     lost messages, is done.
17 root 1.1
18     =head1 GLOBALS AND FUNCTIONS
19    
20     =over 4
21    
22     =cut
23    
24     package AnyEvent::MP::LogCatcher;
25    
26     use common::sense;
27     use Carp ();
28     use POSIX ();
29    
30     use AnyEvent ();
31 root 1.5 use AnyEvent::Log ();
32 root 1.1 use AnyEvent::Util ();
33    
34     use AnyEvent::MP;
35     use AnyEvent::MP::Kernel;
36    
37     use base "Exporter";
38    
39 root 1.5 AE::log 7 => "starting log catcher service.";
40 root 1.1
41     our $LOGLEVEL;
42 root 1.6 our $MON;
43     our $PROPAGATE = 1; # set to one when messages ought to be send to remote nodes
44 root 1.7 our %LPORT; # local logging ports
45 root 1.1
46     # other nodes connect via this
47     sub connect {
48     my ($version, $rport, $loglevel) = @_;
49    
50 root 1.6 # context to catch log messages
51 root 1.5 my $ctx = new AnyEvent::Log::Ctx
52     title => "AnyEvent::MP::LogCatcher",
53     level => $loglevel,
54     log_cb => sub {
55 root 1.6 snd $rport, @{ $_[0] }
56     if $PROPAGATE;
57 root 1.5 },
58     fmt_cb => sub {
59     [$_[0], $_[1]->title, $_[2], $_[3]]
60     },
61     ;
62 root 1.1
63 root 1.5 $AnyEvent::Log::COLLECT->attach ($ctx);
64 root 1.1
65 root 1.6 # monitor them, silently die if they die
66 root 1.1 mon $rport, sub {
67 root 1.5 $AnyEvent::Log::COLLECT->detach ($ctx);
68 root 1.1 };
69 root 1.6
70     AE::log 8 => "starting to propagate log messages to $rport";
71 root 1.1 }
72    
73     sub mon_node {
74 root 1.6 my ($node) = @_;
75    
76     # don't log messages from ourselves
77     return if $node eq $NODE;
78    
79 root 1.7 $LPORT{$node} ||= do {
80 root 1.6 my $lport = port {
81     my ($time, $ctx, $level, $msg) = @_;
82 root 1.1
83 root 1.6 $level = 2 if $level < 2; # do not exit just because others do so
84 root 1.1
85 root 1.6 my $diff = AE::now - $time;
86     $diff = (abs $diff) < 1e-3 ? "" : sprintf "%+.3fs", $diff;
87 root 1.1
88 root 1.6 local $PROPAGATE; # do not propagate to other nodes
89     (AnyEvent::Log::ctx $ctx)->log ($level, "[$node$diff] $msg");
90     };
91 root 1.1
92 root 1.6 mon $lport, sub {
93 root 1.7 delete $LPORT{$node}
94     or return; # do not monitor if node is not there
95 root 1.6 AE::log error => "@_"
96 root 1.7 if @_; # log error if there really was one
97     mon_node ($node); # try to reocnnect
98 root 1.6 };
99    
100     # establish connection
101     AnyEvent::MP::Kernel::snd_to_func $node, "AnyEvent::MP::LogCatcher::connect", 0, $lport, $LOGLEVEL;
102 root 1.1
103 root 1.6 mon $node, $lport;
104 root 1.1
105 root 1.6 $lport
106     }
107 root 1.1 }
108    
109 root 1.3 =item AnyEvent::MP::LogCatcher::catch [$level]
110    
111     Starts catching all log messages from all nodes with level C<$level> or
112     lower. If the C<$level> is C<undef>, then stop catching all messages
113     again.
114    
115     Example: start a node that catches all messages (you might have to specify
116     a suitable profile name).
117    
118 root 1.6 AE_VERBOSE=9 aemp run profilename services '[["AnyEvent::MP::LogCatcher::catch",9]]'
119 root 1.3
120     =cut
121    
122 root 1.1 sub catch {
123     $LOGLEVEL = $_[0];
124 root 1.7 kil $_ for values %LPORT;
125     %LPORT = ();
126 root 1.1
127     return unless defined $LOGLEVEL;
128    
129 root 1.6 $MON = db_mon "'l" => sub {
130     my ($family, $add, $chg, $del) = @_;
131    
132 root 1.7 kil delete $LPORT{$_}
133 root 1.6 for @$del;
134    
135     mon_node $_
136     for @$add;
137     };
138 root 1.1
139     ()
140     }
141    
142     =back
143    
144 root 1.6 =head1 LOGGING
145    
146     AnyEvent::MP::LogCatcher logs messages from remote nodes. It logs them
147     into the original logging context and prepends the origin node name
148     and, if the time difference is larger than 1e-4 seconds, also the time
149     difference between local time and origin time.
150    
151 root 1.1 =head1 SEE ALSO
152    
153     L<AnyEvent::MP>.
154    
155     =head1 AUTHOR
156    
157     Marc Lehmann <schmorp@schmorp.de>
158     http://home.schmorp.de/
159    
160     =cut
161    
162     1
163