-
Notifications
You must be signed in to change notification settings - Fork 2
/
PostfixJournal.pm
executable file
·125 lines (101 loc) · 2.63 KB
/
PostfixJournal.pm
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
#!/usr/bin/env perl
package PostfixJournal;
use strict;
use warnings;
use MOP4Import::Base::CLI_JSON -as_base;
use MOP4Import::Types
(Journal => [[fields =>
qw/
MESSAGE
_SOURCE_REALTIME_TIMESTAMP
/]],
Entry => [[fields =>
qw/
_queue_id
client
from
uid message-id
size nrcpt
_recipient
_first_timestamp
/
]],
Recipient => [[fields =>
qw/
to relay delay delays dsn status
_info
_status_timestamp
/
]],
);
use JSON ();
sub parse {
(my MY $self, my @fn) = @_;
local @ARGV = @fn;
local $_;
my %queue;
while (<>) {
if (/\P{ASCII}/ and Encode::is_utf8($_)) {
Encode::_utf8_off($_);
}
my Journal $log = JSON::decode_json($_);
my ($queue_id, $kvitems, $info) = $self->decode_message($log->{MESSAGE})
or next;
my Entry $entry = $queue{$queue_id} //= +{
# XXX: ここで型宣言が活かせなくて悔しい
_queue_id => $queue_id,
_first_timestamp => $self->journal_timestamp($log),
};
if ($kvitems->[0][0] eq 'to') {
push @{$entry->{_recipient}}, my Recipient $recpt = +{};
$recpt->{$_->[0]} = $_->[1] for @$kvitems;
$recpt->{_info} = $info;
$recpt->{_status_timestamp} = $self->journal_timestamp($log);
} else {
$entry->{$_->[0]} = $_->[1] for @$kvitems;
}
}
sort {
# XXX: ここで型宣言が使えなくて悔しい
$a->{_first_timestamp} <=> $b->{_first_timestamp}
} values %queue;
}
sub journal_timestamp {
(my MY $self, my Journal $log) = @_;
$log->{_SOURCE_REALTIME_TIMESTAMP} * 0.000001;
}
sub decode_message {
(my MY $self, my $msg) = @_;
$msg =~ s/^([0-9A-F]+): //
or return;
my ($queue_id) = $1;
$msg =~ /=/
or return;
my $info;
if ($msg =~ s/\s*\((.+)\)\z//) {
$info = $1;
}
my @items = map {
/=/ ? [split /=/, $_, 2] : ();
} do {
if ($msg =~ /^uid=/) {
split " ", $msg;
} else {
split /,\s*/, $msg;
}
};
($queue_id, \@items, $info);
}
MY->run(\@ARGV) unless caller;
1;
=head1 NAME
PostfixJournal - parse postfix log from journald json
=head1 SYNOPSIS
journalctl -u postfix --since 14:58:52 --until 14:58:58 --output json |
PostfixJournal.pm parse |
jq .
=head1 SEE ALSO
L<Mail-Log-Hashnize|https://github.com/xtetsuji/p5-Mail-Log-Hashnize.git>
=head1 AUTHOR
hkoba
=cut