aboutsummaryrefslogtreecommitdiff
path: root/contrib/gnunet-logread
blob: 2e54d133f30a003ab6b420f58b34179877cd1c06 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env perl
# 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';

use Getopt::Std;
my (%opts, $name, $ipc, $msg_level, $msg_regex);
getopts ('i:x:n:s:L:m:fh', \%opts);

die <<X if $opts{h};
Usage:
	<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>.

   Options to enable message passing to IPC socket:
    -n <component_name>		Name of this component to use for IPC logging.
    -s </path/to/ipc.sock>	Default = $DEFAULT_SOCKET
    -L <LOGLEVEL>		Minimum level of messages to pass on.
                                Log levels: NONE, ERROR, WARNING, INFO, DEBUG.
    -m <regex>		        Only pass messages matching a regular expression.
X

use POSIX qw(mkfifo);

use Term::ANSIColor qw(:constants :pushpop);
$Term::ANSIColor::AUTOLOCAL = 1;

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)
{
    while (<HEADER>)
    {
        $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
}

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 $!;
}

if (exists $opts{n}) {
    $name = $opts{n};
    $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 O, '>', $ipc or die "Cannot write to $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
             (?: Received | Transmitting )\ message \b.*?\b
             type \s+ (\d+) \b.*?\b
             size \s+ (\d+) \b.*?\b
             (?: from \s+ (\S+)
               | to   \s+ (\S+) ) /x)
        {
            $from ||= $name;
            $to ||= $name;
            my ($time, $type, $size, $from, $to) = ($1, $2, $3,
                                                $4 || $name, $5 || $name);
            my $msg = exists $msgtypes{$type} ? $msgtypes{$type} : $type;
            my $ofh = select O;
            print O "$time\t$from -> $to\t$msg ($size)\n";
            $| = 1;
            select $ofh;
        }
        if (($time, $level, $msg) =
            /^([A-Z][a-z]{2}\ .[0-9]\ [0-9:]{8}(?:-[0-9]{6})?)
              \s+\S+\s+(\S+)\s+(.+)/x
            and (exists $levels{$level}
                 && $levels{$level} <= $msg_level
                 && (!defined $msg_regex || $msg =~ /$msg_regex/i)))
        {
            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;

    # Log levels
    s/\b(ERROR  )\b/RED $1/ex;
    s/\b(WARNING)\b/YELLOW $1/ex;
    s/\b(INFO   )\b/GREEN $1/ex;
    s/\b(DEBUG  )\b/BRIGHT_BLACK $1/ex;

    # Service names
    # TODO: might read the list from $GNUNET_PREFIX/libexec/gnunet/
    s/\b(multicast|psyc|psycstore|social)\b/BLUE $1/gex;

    # Add message type names
    s/(\s+type\s+)(\d+)/
      $1 . BRIGHT_CYAN (exists $msgtypes{$2} ? $msgtypes{$2} : 'UNKNOWN') .
      CYAN " ($2)"/gei;

    # logread-ipc output
    s/(\s+)([A-Z_]+)( \(\d+\))$/$1 . BRIGHT_CYAN $2 . CYAN $3/e;

    print;
}