diff options
Diffstat (limited to 'contrib/scripts/gnunet-logread/gnunet-logread')
-rwxr-xr-x | contrib/scripts/gnunet-logread/gnunet-logread | 198 |
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 | |||
5 | use strict; | ||
6 | use warnings; | ||
7 | my $DEFAULT_SOCKET = '/tmp/gnunet-logread-ipc.sock'; | ||
8 | |||
9 | print 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 | |||
14 | X | ||
15 | |||
16 | use Getopt::Std; | ||
17 | my (%opts, $name, $ipc, $msg_level, $msg_regex); | ||
18 | getopts ('i:x:n:s:L:m:fhq', \%opts); | ||
19 | |||
20 | use Pod::Usage qw( pod2usage ); | ||
21 | die pod2usage if $opts{h}; | ||
22 | |||
23 | use POSIX qw(mkfifo); | ||
24 | |||
25 | use Term::ANSIColor qw(:constants :pushpop); | ||
26 | $Term::ANSIColor::AUTOLOCAL = 1; | ||
27 | |||
28 | my %levels = ( NONE => 0, ERROR => 1, WARNING => 2, INFO => 4, DEBUG => 8 ); | ||
29 | |||
30 | # Message type numbers to names | ||
31 | my %msgtypes; | ||
32 | my $prefix = $ENV{GNUNET_PREFIX} || '/usr'; | ||
33 | my $filename = "$prefix/include/gnunet/gnunet_protocols.h"; | ||
34 | $ipc = $opts{s} || $DEFAULT_SOCKET; | ||
35 | |||
36 | if (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; | ||
45 | Could not read $filename for message codes: | ||
46 | $!. | ||
47 | Please provide a \$GNUNET_PREFIX environment variable to replace "/usr". | ||
48 | Try also '$0 -h' for help. | ||
49 | |||
50 | X | ||
51 | } | ||
52 | |||
53 | die "You can't read and write the socket at the same time" | ||
54 | if exists $opts{f} and exists $opts{n}; | ||
55 | |||
56 | if ((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 | |||
65 | if (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 | |||
73 | if (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 | } | ||
80 | fileno O and close O; | ||
81 | exit; | ||
82 | |||
83 | |||
84 | sub 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 | |||
148 | gnunet-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 | |||
175 | GNUnet debug logs are a tedious read, but given a complex system that we | ||
176 | cannot run all parts of in a debugger all the time, some gathering and | ||
177 | structuring of events and message passing is useful. | ||
178 | |||
179 | At first, this tool simply makes logs easier to read. Both if viewed in | ||
180 | real-time or taken from disk. Then it also allows to extract all message | ||
181 | passing events from it and forward them to a special process that aggregates | ||
182 | all message passing events and therefore helps you make sense of all the | ||
183 | inter-process communication (IPC) happening between the various pieces of | ||
184 | the GNUnet system beast. | ||
185 | |||
186 | That master process is simply an extra gnunet-logread that you run in a | ||
187 | separate window and adorn it with the '-f' flag. The submitting processes | ||
188 | instead need to be given a '-n' flag. That is because from the GNUnet logs | ||
189 | it isn't clear which process events belong to. For example you may be | ||
190 | having events taking place in the 'util' subsystem of gnunet-psyc-service | ||
191 | just as much as in the 'util' subsystem of gnunet-multicast-service. In | ||
192 | order to make sense of them it is necessary to manually add that info. This | ||
193 | could be remedied by extending the semantics of the GNUNET_log facility | ||
194 | instead, but that is still subject to further consideration. | ||
195 | |||
196 | =head1 AUTHORS | ||
197 | |||
198 | tg & lynX | ||