aboutsummaryrefslogtreecommitdiff
path: root/contrib/scripts/gnunet-logread/gnunet-logread
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/scripts/gnunet-logread/gnunet-logread')
-rwxr-xr-xcontrib/scripts/gnunet-logread/gnunet-logread198
1 files changed, 198 insertions, 0 deletions
diff --git a/contrib/scripts/gnunet-logread/gnunet-logread b/contrib/scripts/gnunet-logread/gnunet-logread
new file mode 100755
index 000000000..9b1c65401
--- /dev/null
+++ b/contrib/scripts/gnunet-logread/gnunet-logread
@@ -0,0 +1,198 @@
1#!@PERL@
2# helper tool to make gnunet logs more readable
3# try 'gnunet-logread -h' for usage
4
5use strict;
6use warnings;
7my $DEFAULT_SOCKET = '/tmp/gnunet-logread-ipc.sock';
8
9print STDERR <<X if -t STDIN and $#ARGV == -1;
10*** For a usage message, try '$0 -h'.
11*** For documentation, try 'perldoc $0'.
12*** Listening for GNUNET_log events on STDIN. Type CTRL-D to terminate.
13
14X
15
16use Getopt::Std;
17my (%opts, $name, $ipc, $msg_level, $msg_regex);
18getopts ('i:x:n:s:L:m:fhq', \%opts);
19
20use Pod::Usage qw( pod2usage );
21die pod2usage if $opts{h};
22
23use POSIX qw(mkfifo);
24
25use Term::ANSIColor qw(:constants :pushpop);
26$Term::ANSIColor::AUTOLOCAL = 1;
27
28my %levels = ( NONE => 0, ERROR => 1, WARNING => 2, INFO => 4, DEBUG => 8 );
29
30# Message type numbers to names
31my %msgtypes;
32my $prefix = $ENV{GNUNET_PREFIX} || '/usr';
33my $filename = "$prefix/include/gnunet/gnunet_protocols.h";
34$ipc = $opts{s} || $DEFAULT_SOCKET;
35
36if (open HEADER, $filename)
37{
38 while (<HEADER>)
39 {
40 $msgtypes{$2} = $1 if /^\s*#define\s+GNUNET_MESSAGE_TYPE_(\w+)\s+(\d+)/i;
41 }
42 close HEADER;
43} else {
44 warn <<X;
45Could not read $filename for message codes:
46 $!.
47Please provide a \$GNUNET_PREFIX environment variable to replace "/usr".
48Try also '$0 -h' for help.
49
50X
51}
52
53die "You can't read and write the socket at the same time"
54 if exists $opts{f} and exists $opts{n};
55
56if ((exists $opts{n} or exists $opts{f}) and not -r $ipc) {
57 undef $!;
58 die "Could not mkfifo $ipc: $!" unless mkfifo $ipc, 0600;
59 system('chgrp', 'gnunet', $ipc);
60 die "Could not chgrp $ipc to 'gnunet': $!" if $!;
61 chmod 0660, $ipc;
62 die "Could not chmod $ipc to allow gnunet group writes: $!" if $!;
63}
64
65if (exists $opts{n}) {
66 $name = $opts{n};
67 $msg_level = $opts{L} && exists $levels{$opts{L}} ? $levels{$opts{L}} : 0;
68 $msg_regex = $opts{m};
69 print STDERR "RE: /$msg_regex/\n" if defined $msg_regex;
70 open O, '>', $ipc or die "Cannot write to $ipc: $!";
71}
72
73if (exists $opts{f}) {
74 open(I, $ipc) or die "Cannot read from $ipc: $!";
75 &perform while <I>;
76 close I;
77} else {
78 &perform while <>;
79}
80fileno O and close O;
81exit;
82
83
84sub perform {
85 if (fileno O) {
86 my ($time, $type, $size, $from, $to, $level, $msg);
87 if (($time, $type, $size, $from, $to) =
88 /^([A-Z][a-z]{2}\ .[0-9]\ [0-9:]{8}(?:-[0-9]{6})?)\ util-client-.*\b
89 (?: Received | Transmitting )\ message \b.*?\b
90 type \s+ (\d+) \b.*?\b
91 size \s+ (\d+) \b.*?\b
92 (?: from \s+ (\S+)
93 | to \s+ (\S+) ) /x)
94 {
95 $from ||= $name;
96 $to ||= $name;
97 my ($time, $type, $size, $from, $to) = ($1, $2, $3,
98 $4 || $name, $5 || $name);
99 my $msg = exists $msgtypes{$type} ? $msgtypes{$type} : $type;
100 my $ofh = select O;
101 print O "$time\t$from -> $to\t$msg ($size)\n";
102 $| = 1;
103 select $ofh;
104 }
105 if (($time, $level, $msg) =
106 /^([A-Z][a-z]{2}\ .[0-9]\ [0-9:]{8}(?:-[0-9]{6})?)
107 \s+\S+\s+(\S+)\s+(.+)/x
108 and (exists $levels{$level}
109 && $levels{$level} <= $msg_level
110 && (!defined $msg_regex || $msg =~ /$msg_regex/i)))
111 {
112 print O "$time\t$name\t$level: $msg\n";
113 }
114 }
115 return if $opts{x} and /$opts{x}/io;
116 return if $opts{i} and not /$opts{i}/io;
117
118 # Timestamp (e.g. Nov 01 19:36:11-384136)
119 s/^([A-Z][a-z]{2} .[0-9] [0-9:]{8}(?:-[0-9]{6})?)/YELLOW $1/e;
120
121 # Log levels
122 s/\b(ERROR )\b/RED $1/ex;
123 s/\b(WARNING)\b/YELLOW $1/ex;
124 s/\b(INFO )\b/GREEN $1/ex;
125 s/\b(DEBUG )\b/BRIGHT_BLACK $1/ex;
126
127 # Service names
128 # TODO: might read the list from $GNUNET_PREFIX/libexec/gnunet/
129 s/\b(multicast|psyc|psycstore|social)\b/BLUE $1/gex;
130
131 # Add message type names
132 s/(\s+type\s+)(\d+)/
133 $1 . BRIGHT_CYAN (exists $msgtypes{$2} ? $msgtypes{$2} : 'UNKNOWN') .
134 CYAN " ($2)"/gei;
135
136 # logread-ipc output
137 s/(\s+)([A-Z_]+)( \(\d+\))$/$1 . BRIGHT_CYAN $2 . CYAN $3/e;
138
139 print;
140}
141
142__END__
143
144=pod
145
146=head1 NAME
147
148gnunet-logread - a GNUnet log analyzer, colorizer and aggregator
149
150=head1 SYNOPSIS
151
152 <gnunet-service> |& $0 [<options>]
153 or
154 $0 [<options>] [<logfile>]
155
156 Options:
157 -f Follow input from IPC FIFO socket.
158
159 Regular screen output options:
160 -i <regex> Include only messages that match <regex>.
161 -x <regex> Exclude all messages that match <regex>.
162 -q Quiet: Do not show usage advice to new users.
163
164 Options to forward messages to the IPC FIFO socket:
165 -n <component_name> Name of the component we are forwarding messages for.
166 -s </path/to/ipc.sock> Default = $DEFAULT_SOCKET
167 -L <LOGLEVEL> Minimum level of messages to forward:
168 Log levels: NONE, ERROR, WARNING, INFO, DEBUG.
169 -m <regex> Only forward messages matching a regular expression.
170
171 See 'perldoc gnunet-logread' for a longer explanation.
172
173=head1 MOTIVATION
174
175GNUnet debug logs are a tedious read, but given a complex system that we
176cannot run all parts of in a debugger all the time, some gathering and
177structuring of events and message passing is useful.
178
179At first, this tool simply makes logs easier to read. Both if viewed in
180real-time or taken from disk. Then it also allows to extract all message
181passing events from it and forward them to a special process that aggregates
182all message passing events and therefore helps you make sense of all the
183inter-process communication (IPC) happening between the various pieces of
184the GNUnet system beast.
185
186That master process is simply an extra gnunet-logread that you run in a
187separate window and adorn it with the '-f' flag. The submitting processes
188instead need to be given a '-n' flag. That is because from the GNUnet logs
189it isn't clear which process events belong to. For example you may be
190having events taking place in the 'util' subsystem of gnunet-psyc-service
191just as much as in the 'util' subsystem of gnunet-multicast-service. In
192order to make sense of them it is necessary to manually add that info. This
193could be remedied by extending the semantics of the GNUNET_log facility
194instead, but that is still subject to further consideration.
195
196=head1 AUTHORS
197
198tg & lynX