-modifying tests to use new service MQ API, implementing more of service MQ API
[oweals/gnunet.git] / contrib / gnunet-logread
index d5c8b1676469aeab91743ecf66abb4b1e2138fd9..5b125a5a459959e078b820273c9260c5744af7e3 100755 (executable)
@@ -1,31 +1,37 @@
 #!/usr/bin/env perl
-
-# Usage:
-#   gnunet-service |& gnunet-logread
-#   gnunet-logread service.log
-#
-# Options:
-#   -n <component_name>                Name of this component to use for IPC logging.
-#   -i </path/to/ipc.sock>     Path to IPC logging socket.
-#  Passing on log messages to IPC socket:
-#   -L <LOGLEVEL>              Minimum level of messages to pass on.
-#                               Log levels: NONE, ERROR, WARNING, INFO, DEBUG.
-#   -m <regex>                 Only pass on messages matching a regular expression.
+# helper tool to make gnunet logs more readable
+# try 'gnunet-logread -h' for usage
 
 use strict;
 use warnings;
+my $DEFAULT_SOCKET = '/tmp/gnunet-logread-ipc.sock';
+
+print STDERR <<X if -t STDIN and $#ARGV == -1;
+*** For a usage message, try '$0 -h'.
+*** For documentation, try 'perldoc $0'.
+*** Listening for GNUNET_log events on STDIN. Type CTRL-D to terminate.
+
+X
 
 use Getopt::Std;
+my (%opts, $name, $ipc, $msg_level, $msg_regex);
+getopts ('i:x:n:s:L:m:fhq', \%opts);
+
+use Pod::Usage qw( pod2usage );
+die pod2usage if $opts{h};
+
+use POSIX qw(mkfifo);
+
 use Term::ANSIColor qw(:constants :pushpop);
 $Term::ANSIColor::AUTOLOCAL = 1;
 
-my (%opts, $name, $ipc, $msg_level, $msg_regex);
-getopts ('n:i:L:m:', \%opts);
+my %levels = ( NONE => 0, ERROR => 1, WARNING => 2, INFO => 4, DEBUG => 8 );
 
 # Message type numbers to names
 my %msgtypes;
 my $prefix = $ENV{GNUNET_PREFIX} || '/usr';
 my $filename = "$prefix/include/gnunet/gnunet_protocols.h";
+$ipc = $opts{s} || $DEFAULT_SOCKET;
 
 if (open HEADER, $filename)
 {
@@ -34,26 +40,49 @@ if (open HEADER, $filename)
         $msgtypes{$2} = $1 if /^\s*#define\s+GNUNET_MESSAGE_TYPE_(\w+)\s+(\d+)/i;
     }
     close HEADER;
+} else {
+    warn <<X;
+Could not read $filename for message codes:
+       $!.
+Please provide a \$GNUNET_PREFIX environment variable to replace "/usr".
+Try also '$0 -h' for help.
+
+X
 }
-else
-{
-    warn "$filename: $!, try setting \$GNUNET_PREFIX";
+
+die "You can't read and write the socket at the same time"
+  if exists $opts{f} and exists $opts{n};
+
+if ((exists $opts{n} or exists $opts{f}) and not -r $ipc) {
+    undef $!;
+    die "Could not mkfifo $ipc: $!" unless mkfifo $ipc, 0600;
+    system('chgrp', 'gnunet', $ipc);
+    die "Could not chgrp $ipc to 'gnunet': $!" if $!;
+    chmod 0660, $ipc;
+    die "Could not chmod $ipc to allow gnunet group writes: $!" if $!;
 }
 
-my %levels = ( NONE => 0, ERROR => 1, WARNING => 2, INFO => 4, DEBUG => 8 );
-if (exists $opts{n})
-{
+if (exists $opts{n}) {
     $name = $opts{n};
-    $ipc = $opts{i} || '/tmp/gnunet-logread-ipc.sock';
-    $msg_level = exists $levels{$opts{L}} ? $levels{$opts{L}} : 0;
+    $msg_level = $opts{L} && exists $levels{$opts{L}} ? $levels{$opts{L}} : 0;
     $msg_regex = $opts{m};
     print STDERR "RE: /$msg_regex/\n" if defined $msg_regex;
-    open IPC, '>', $ipc or die "$ipc: $!\n";
+    open O, '>', $ipc or die "Cannot write to $ipc: $!";
 }
 
-while (<>)
-{
-    if (fileno IPC) {
+if (exists $opts{f}) {
+    open(I, $ipc) or die "Cannot read from $ipc: $!";
+    &perform while <I>;
+    close I;
+} else {
+    &perform while <>;
+}
+fileno O and close O;
+exit;
+
+
+sub perform {
+    if (fileno O) {
         my ($time, $type, $size, $from, $to, $level, $msg);
         if (($time, $type, $size, $from, $to) =
             /^([A-Z][a-z]{2}\ .[0-9]\ [0-9:]{8}(?:-[0-9]{6})?)\ util-.*\b
@@ -68,8 +97,8 @@ while (<>)
             my ($time, $type, $size, $from, $to) = ($1, $2, $3,
                                                 $4 || $name, $5 || $name);
             my $msg = exists $msgtypes{$type} ? $msgtypes{$type} : $type;
-            my $ofh = select IPC;
-            print IPC "$time\t$from -> $to\t$msg ($size)\n";
+            my $ofh = select O;
+            print O "$time\t$from -> $to\t$msg ($size)\n";
             $| = 1;
             select $ofh;
         }
@@ -80,9 +109,11 @@ while (<>)
                  && $levels{$level} <= $msg_level
                  && (!defined $msg_regex || $msg =~ /$msg_regex/i)))
         {
-            print IPC "$time\t$name\t$level: $msg\n";
+            print O "$time\t$name\t$level: $msg\n";
         }
     }
+    return if $opts{x} and /$opts{x}/io;
+    return if $opts{i} and not /$opts{i}/io;
 
     # Timestamp (e.g. Nov 01 19:36:11-384136)
     s/^([A-Z][a-z]{2} .[0-9] [0-9:]{8}(?:-[0-9]{6})?)/YELLOW $1/e;
@@ -108,4 +139,61 @@ while (<>)
     print;
 }
 
-fileno IPC and close IPC;
+__END__
+
+=pod
+
+=head1 NAME
+
+gnunet-logread - a GNUnet log analyzer, colorizer and aggregator
+
+=head1 SYNOPSIS
+
+       <gnunet-service> |& $0 [<options>]
+    or
+       $0 [<options>] [<logfile>]
+
+ Options:
+    -f                         Follow input from IPC FIFO socket.
+
+   Regular screen output options:
+    -i <regex>                 Include only messages that match <regex>.
+    -x <regex>                 Exclude all messages that match <regex>.
+    -q                         Quiet: Do not show usage advice to new users.
+
+   Options to forward messages to the IPC FIFO socket:
+    -n <component_name>                Name of the component we are forwarding messages for.
+    -s </path/to/ipc.sock>     Default = $DEFAULT_SOCKET
+    -L <LOGLEVEL>              Minimum level of messages to forward:
+                                Log levels: NONE, ERROR, WARNING, INFO, DEBUG.
+    -m <regex>                 Only forward messages matching a regular expression.
+
+ See 'perldoc gnunet-logread' for a longer explanation.
+
+=head1 MOTIVATION
+
+GNUnet debug logs are a tedious read, but given a complex system that we 
+cannot run all parts of in a debugger all the time, some gathering and
+structuring of events and message passing is useful.
+
+At first, this tool simply makes logs easier to read. Both if viewed in
+real-time or taken from disk. Then it also allows to extract all message
+passing events from it and forward them to a special process that aggregates
+all message passing events and therefore helps you make sense of all the
+inter-process communication (IPC) happening between the various pieces of
+the GNUnet system beast.
+
+That master process is simply an extra gnunet-logread that you run in a
+separate window and adorn it with the '-f' flag. The submitting processes
+instead need to be given a '-n' flag. That is because from the GNUnet logs
+it isn't clear which process events belong to. For example you may be
+having events taking place in the 'util' subsystem of gnunet-psyc-service
+just as much as in the 'util' subsystem of gnunet-multicast-service. In
+order to make sense of them it is necessary to manually add that info. This
+could be remedied by extending the semantics of the GNUNET_log facility
+instead, but that is still subject to further consideration.
+
+=head1 AUTHORS
+
+tg & lynX
+