]>
git.proxmox.com Git - pmg-api.git/blob - src/PMG/API2/Statistics.pm
adc7650b17548ecf52c5c85648e0206118a0a798
1 package PMG
::API2
::Statistics
;
12 use PVE
::Exception
qw(raise_param_exc);
14 use PMG
::RESTEnvironment
;
15 use PVE
::JSONSchema
qw(get_standard_option);
22 use base
qw(PVE::RESTHandler);
24 __PACKAGE__-
>register_method ({
28 description
=> "Directory index.",
29 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
31 additionalProperties
=> 0,
40 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
46 { name
=> "contact" },
47 { name
=> "domains" },
49 { name
=> "mailcount" },
51 { name
=> "recentreceivers" },
52 { name
=> "maildistribution" },
53 { name
=> "spamscores" },
55 { name
=> "rblcount" },
56 { name
=> "receiver" },
61 my $decode_orderby = sub {
62 my ($orderby, $allowed_props) = @_;
66 eval { $sorters = decode_json
($orderby); };
68 raise_param_exc
({ orderby
=> 'invalid JSON'});
78 enum
=> $allowed_props,
82 enum
=> ['ASC', 'DESC'],
88 PVE
::JSONSchema
::validate
($sorters, $schema, "Parameter 'orderby' verification failed\n");
93 my $api_properties = {
95 description
=> "Remote sorting configuration(JSON, ExtJS compatible).",
102 my $default_properties = sub {
107 $prop->{starttime
} = get_standard_option
('pmg-starttime');
108 $prop->{endtime
} = get_standard_option
('pmg-endtime');
111 description
=> "Year. Defaults to current year. You will get statistics for the whole year if you do not specify a month or day.",
119 description
=> "Month. You will get statistics for the whole month if you do not specify a day.",
127 description
=> "Day of month. Get statistics for a single day.",
137 my $extract_start_end = sub {
141 foreach my $k (qw(year month day)) {
142 if (defined($param->{$k})) {
148 foreach my $k (qw(starttime endtime)) {
149 if (defined($param->{$k})) {
155 raise_param_exc
({ $has_se => "parameter conflicts with parameter '$has_ymd'"})
156 if $has_se && $has_ymd;
162 my (undef, undef, undef, undef, $month, $year) = localtime(time());
164 $year = $param->{year
} if defined($param->{year
});
165 if (defined($param->{day
})) {
166 my $day = $param->{day
};
167 $month = $param->{month
} if defined($param->{month
});
168 $start = timelocal
(0, 0, 0, $day, $month - 1, $year);
169 $end = timelocal
(59, 59, 23, $day, $month - 1, $year);
170 } elsif (defined($param->{month
})) {
171 my $month = $param->{month
};
173 $start = timelocal
(0, 0, 0, 1, $month - 1, $year);
174 $end = timelocal
(0, 0, 0, 1, $month, $year);
176 $start = timelocal
(0, 0, 0, 1, 11, $year);
177 $end = timelocal
(0, 0, 0, 1, 0, $year + 1);
180 $start = timelocal
(0, 0, 0, 1, 0, $year);
181 $end = timelocal
(0, 0, 0, 1, 0, $year + 1);
184 $start = $param->{starttime
} // (time - 86400);
185 $end = $param->{endtime
} // ($start + 86400);
188 return ($start, $end);
191 my $userstat_limit = 2000; # hardcoded limit
193 __PACKAGE__-
>register_method ({
197 description
=> "Contact Address Statistics.",
198 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
200 additionalProperties
=> 0,
201 properties
=> $default_properties->({
203 description
=> "Contact address filter.",
208 orderby
=> $api_properties->{orderby
},
217 description
=> "Contact email.",
221 description
=> "Mail count.",
226 description
=> "Mail traffic (Bytes).",
230 description
=> "Number of sent virus mails.",
236 links
=> [ { rel
=> 'child', href
=> "{contact}" } ],
241 my ($start, $end) = $extract_start_end->($param);
243 my $cfg = PMG
::Config-
>new();
244 my $advfilter = $cfg->get('admin', 'advfilter');
246 my $stat = PMG
::Statistic-
>new($start, $end);
247 my $rdb = PMG
::RuleDB-
>new();
250 if ($param->{orderby
}) {
251 my $props = ['contact', 'count', 'bytes', 'viruscount'];
252 $sorters = $decode_orderby->($param->{orderby
}, $props);
255 my $res = $stat->user_stat_contact($rdb, $userstat_limit, $sorters, $param->{filter
}, $advfilter);
260 __PACKAGE__-
>register_method ({
261 name
=> 'contactdetails',
262 path
=> 'contact/{contact}',
264 description
=> "Detailed Contact Statistics.",
265 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
267 additionalProperties
=> 0,
268 properties
=> $default_properties->({
269 contact
=> get_standard_option
('pmg-email-address', {
270 description
=> "Contact email address.",
273 description
=> "Sender address filter.",
278 orderby
=> $api_properties->{orderby
},
287 description
=> "Receive time stamp",
291 description
=> "Sender email.",
295 description
=> "Mail traffic (Bytes).",
299 description
=> "Mail was blocked.",
303 description
=> "Spam score.",
307 description
=> "Virus name.",
317 my $restenv = PMG
::RESTEnvironment-
>get();
318 my $cinfo = $restenv->{cinfo
};
320 my ($start, $end) = $extract_start_end->($param);
322 my $stat = PMG
::Statistic-
>new($start, $end);
323 my $rdb = PMG
::RuleDB-
>new();
326 if ($param->{orderby
}) {
327 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
328 $sorters = $decode_orderby->($param->{orderby
}, $props);
331 return $stat->user_stat_contact_details(
332 $rdb, $param->{contact
}, $userstat_limit, $sorters, $param->{filter
});
335 __PACKAGE__-
>register_method ({
339 description
=> "Sender Address Statistics.",
340 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
342 additionalProperties
=> 0,
343 properties
=> $default_properties->({
345 description
=> "Sender address filter.",
350 orderby
=> $api_properties->{orderby
},
359 description
=> "Sender email.",
363 description
=> "Mail count.",
368 description
=> "Mail traffic (Bytes).",
372 description
=> "Number of sent virus mails.",
378 links
=> [ { rel
=> 'child', href
=> "{sender}" } ],
383 my ($start, $end) = $extract_start_end->($param);
385 my $stat = PMG
::Statistic-
>new($start, $end);
386 my $rdb = PMG
::RuleDB-
>new();
389 if ($param->{orderby
}) {
390 my $props = ['sender', 'count', 'bytes', 'viruscount'];
391 $sorters = $decode_orderby->($param->{orderby
}, $props);
394 my $res = $stat->user_stat_sender($rdb, $userstat_limit, $sorters, $param->{filter
});
399 __PACKAGE__-
>register_method ({
400 name
=> 'senderdetails',
401 path
=> 'sender/{sender}',
403 description
=> "Detailed Sender Statistics.",
404 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
406 additionalProperties
=> 0,
407 properties
=> $default_properties->({
408 sender
=> get_standard_option
('pmg-email-address', {
409 description
=> "Sender email address.",
412 description
=> "Receiver address filter.",
417 orderby
=> $api_properties->{orderby
},
426 description
=> "Receive time stamp",
430 description
=> "Receiver email.",
434 description
=> "Mail traffic (Bytes).",
438 description
=> "Mail was blocked.",
442 description
=> "Spam score.",
446 description
=> "Virus name.",
456 my $restenv = PMG
::RESTEnvironment-
>get();
457 my $cinfo = $restenv->{cinfo
};
459 my ($start, $end) = $extract_start_end->($param);
461 my $stat = PMG
::Statistic-
>new($start, $end);
462 my $rdb = PMG
::RuleDB-
>new();
465 if ($param->{orderby
}) {
466 my $props = ['time', 'receiver', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
467 $sorters = $decode_orderby->($param->{orderby
}, $props);
470 return $stat->user_stat_sender_details(
471 $rdb, $param->{sender
}, $userstat_limit, $sorters, $param->{filter
});
474 __PACKAGE__-
>register_method ({
478 description
=> "Receiver Address Statistics.",
479 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
481 additionalProperties
=> 0,
482 properties
=> $default_properties->({
484 description
=> "Receiver address filter.",
489 orderby
=> $api_properties->{orderby
},
498 description
=> "Sender email.",
502 description
=> "Mail count.",
507 description
=> "Mail traffic (Bytes).",
511 description
=> "Number of sent spam mails.",
516 description
=> "Number of sent virus mails.",
522 links
=> [ { rel
=> 'child', href
=> "{receiver}" } ],
527 my ($start, $end) = $extract_start_end->($param);
529 my $cfg = PMG
::Config-
>new();
530 my $advfilter = $cfg->get('admin', 'advfilter');
532 my $stat = PMG
::Statistic-
>new($start, $end);
533 my $rdb = PMG
::RuleDB-
>new();
536 if ($param->{orderby
}) {
537 my $props = ['receiver', 'count', 'bytes', 'spamcount', 'viruscount'];
538 $sorters = $decode_orderby->($param->{orderby
}, $props);
541 my $res = $stat->user_stat_receiver($rdb, $userstat_limit, $sorters, $param->{filter
}, $advfilter);
546 __PACKAGE__-
>register_method ({
547 name
=> 'receiverdetails',
548 path
=> 'receiver/{receiver}',
550 description
=> "Detailed Receiver Statistics.",
551 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
553 additionalProperties
=> 0,
554 properties
=> $default_properties->({
555 receiver
=> get_standard_option
('pmg-email-address', {
556 description
=> "Receiver email address.",
559 description
=> "Sender address filter.",
564 orderby
=> $api_properties->{orderby
},
573 description
=> "Receive time stamp",
577 description
=> "Sender email.",
581 description
=> "Mail traffic (Bytes).",
585 description
=> "Mail was blocked.",
589 description
=> "Spam score.",
593 description
=> "Virus name.",
603 my $restenv = PMG
::RESTEnvironment-
>get();
604 my $cinfo = $restenv->{cinfo
};
606 my ($start, $end) = $extract_start_end->($param);
608 my $stat = PMG
::Statistic-
>new($start, $end);
609 my $rdb = PMG
::RuleDB-
>new();
612 if ($param->{orderby
}) {
613 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
614 $sorters = $decode_orderby->($param->{orderby
}, $props);
617 return $stat->user_stat_receiver_details(
618 $rdb, $param->{receiver
}, $userstat_limit, $sorters, $param->{filter
});
621 __PACKAGE__-
>register_method ({
625 description
=> "Mail Domains Statistics.",
626 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
628 additionalProperties
=> 0,
629 properties
=> $default_properties->(),
637 description
=> "Domain name.",
641 description
=> "Incoming mail count.",
645 description
=> "Outgoing mail count.",
649 description
=> "Incoming spam mails.",
653 description
=> "Outgoing spam mails.",
657 description
=> "Incoming mail traffic (Bytes).",
661 description
=> "Outgoing mail traffic (Bytes).",
665 description
=> "Number of incoming virus mails.",
669 description
=> "Number of outgoing virus mails.",
678 my ($start, $end) = $extract_start_end->($param);
680 my $stat = PMG
::Statistic-
>new($start, $end);
681 my $rdb = PMG
::RuleDB-
>new();
683 #PMG::Statistic::update_stats_domainstat_in($rdb->{dbh}, $cinfo);
684 #PMG::Statistic::update_stats_domainstat_out($rdb->{dbh}, $cinfo);
686 my $res = $stat->total_domain_stat($rdb);
692 __PACKAGE__-
>register_method ({
696 description
=> "General Mail Statistics.",
697 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
699 additionalProperties
=> 0,
700 properties
=> $default_properties->(),
706 description
=> "Average mail processing time in seconds.",
710 description
=> "Incoming bounce mail count (sender = <>).",
714 description
=> "Outgoing bounce mail count (sender = <>).",
718 description
=> "Overall mail count (in and out).",
722 description
=> "Incoming mail count.",
726 description
=> "Outgoing mail count.",
730 description
=> "Number of greylisted mails.",
734 description
=> "Number of RBL rejects.",
737 pregreet_rejects
=> {
738 description
=> "PREGREET recject count.",
742 description
=> "Incoming junk mail count (viruscount_in + spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
746 description
=> "Outgoing junk mail count (viruscount_out + spamcount_out).",
750 description
=> "Incoming spam mails.",
754 description
=> "Outgoing spam mails.",
758 description
=> "Mails rejected by SPF.",
762 description
=> "Incoming mail traffic (bytes).",
766 description
=> "Outgoing mail traffic (bytes).",
770 description
=> "Number of incoming virus mails.",
774 description
=> "Number of outgoing virus mails.",
782 my ($start, $end) = $extract_start_end->($param);
784 my $stat = PMG
::Statistic-
>new($start, $end);
785 my $rdb = PMG
::RuleDB-
>new();
787 my $res = $stat->total_mail_stat($rdb);
789 my $rejects = $stat->postscreen_stat($rdb);
791 $res->{rbl_rejects
} //= 0;
792 if (defined(my $rbl_rejects = $rejects->{rbl_rejects
})) {
793 foreach my $k (qw(rbl_rejects junk_in count_in count)) {
794 $res->{$k} += $rbl_rejects;
798 $res->{pregreet_rejects
} //= 0;
799 if (defined(my $pregreet_rejects = $rejects->{pregreet_rejects
})) {
800 foreach my $k (qw(pregreet_rejects junk_in count_in count)) {
801 $res->{$k} += $pregreet_rejects;
808 __PACKAGE__-
>register_method ({
812 description
=> "Mail Count Statistics.",
813 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
815 additionalProperties
=> 0,
818 description
=> "How many hours you want to get",
826 description
=> "The Timespan for one datapoint (in seconds)",
841 description
=> "Time index.",
845 description
=> "Time (Unix epoch).",
849 description
=> "Overall mail count (in and out).",
853 description
=> "Incoming mail count.",
857 description
=> "Outgoing mail count.",
861 description
=> "Overall spam mail count (in and out).",
865 description
=> "Incoming spam mails (spamcount_in + glcount + spfcount).",
869 description
=> "Outgoing spam mails.",
873 description
=> "Number of incoming bytes mails.",
877 description
=> "Number of outgoing bytes mails.",
881 description
=> "Number of incoming virus mails.",
885 description
=> "Number of outgoing virus mails.",
889 description
=> "Timespan in seconds for one data point",
898 my $hours = $param->{hours
} // 12;
899 my $span = $param->{timespan
} // 1800;
902 my $start = $end - 3600*$hours;
904 my $stat = PMG
::Statistic-
>new($start, $end);
905 my $rdb = PMG
::RuleDB-
>new();
907 my $res = $stat->recent_mailcount($rdb, $span);
912 __PACKAGE__-
>register_method ({
913 name
=> 'recentreceivers',
914 path
=> 'recentreceivers',
916 description
=> "Top recent Mail Receivers (including spam)",
917 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
919 additionalProperties
=> 0,
922 description
=> "How many hours you want to get",
930 description
=> "The maximum number of receivers to return.",
945 description
=> "The count of incoming not blocked E-Mails",
949 description
=> "The receiver",
958 my $hours = $param->{hours
} // 12;
960 my $limit = $param->{limit
} // 5;
963 my $start = $end - 3600*$hours;
965 my $stat = PMG
::Statistic-
>new($start, $end);
966 my $rdb = PMG
::RuleDB-
>new();
968 my $res = $stat->recent_receivers($rdb, $limit);
973 __PACKAGE__-
>register_method ({
977 description
=> "Mail Count Statistics.",
978 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
980 additionalProperties
=> 0,
981 properties
=> $default_properties->({
983 description
=> "Return Mails/<timespan>, where <timespan> is specified in seconds.",
986 maximum
=> 366*86400,
998 description
=> "Time index.",
1002 description
=> "Time (Unix epoch).",
1006 description
=> "Overall mail count (in and out).",
1010 description
=> "Incoming mail count.",
1014 description
=> "Outgoing mail count.",
1018 description
=> "Incoming spam mails (spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
1022 description
=> "Outgoing spam mails.",
1026 description
=> "Number of incoming virus mails.",
1030 description
=> "Number of outgoing virus mails.",
1034 description
=> "Number of RBL rejects.",
1037 pregreet_rejects
=> {
1038 description
=> "PREGREET recject count.",
1042 description
=> "Incoming bounce mail count (sender = <>).",
1046 description
=> "Outgoing bounce mail count (sender = <>).",
1055 my ($start, $end) = $extract_start_end->($param);
1057 my $span = $param->{timespan
} // 3600;
1059 my $count = ($end - $start)/$span;
1061 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1063 my $stat = PMG
::Statistic-
>new($start, $end);
1064 my $rdb = PMG
::RuleDB-
>new();
1066 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1068 my $rejects = $stat->postscreen_stat_graph($rdb, $span);
1070 my $res = $stat->traffic_stat_graph ($rdb, $span);
1072 my $element_count = scalar(@$res);
1074 for (my $i = 0; $i < $element_count; $i++) {
1075 my $el = $rejects->[$i];
1078 foreach my $k ('rbl_rejects', 'pregreet_rejects') {
1079 my $count = $el->{$k} // 0;
1081 foreach my $k (qw(count count_in spamcount_in)) {
1090 __PACKAGE__-
>register_method ({
1094 description
=> "Get Statistics about detected Viruses.",
1095 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1097 additionalProperties
=> 0,
1098 properties
=> $default_properties->(),
1106 description
=> 'Virus name.',
1110 description
=> 'Detection count.',
1119 my ($start, $end) = $extract_start_end->($param);
1121 my $stat = PMG
::Statistic-
>new($start, $end);
1122 my $rdb = PMG
::RuleDB-
>new();
1124 my $res = $stat->total_virus_stat($rdb);
1129 __PACKAGE__-
>register_method ({
1130 name
=> 'spamscores',
1131 path
=> 'spamscores',
1133 description
=> "Get the count of spam mails grouped by spam score. " .
1134 "Count for score 10 includes mails with spam score > 10.",
1135 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1137 additionalProperties
=> 0,
1138 properties
=> $default_properties->(),
1146 description
=> 'Spam level.',
1150 description
=> 'Detection count.',
1154 description
=> 'Portion of overall mail count.',
1163 my ($start, $end) = $extract_start_end->($param);
1165 my $stat = PMG
::Statistic-
>new($start, $end);
1166 my $rdb = PMG
::RuleDB-
>new();
1168 my $totalstat = $stat->total_mail_stat ($rdb);
1169 my $spamstat = $stat->total_spam_stat($rdb);
1173 my $count_in = $totalstat->{count_in
};
1175 my $levelcount = {};
1177 foreach my $ref (@$spamstat) {
1178 if (my $level = $ref->{spamlevel
}) {
1179 next if $level < 1; # just to be sure
1180 $spamcount += $ref->{count
};
1181 $level = 10 if $level > 10;
1182 $levelcount->{$level} += $ref->{count
};
1186 $levelcount->{0} = $count_in - $spamcount;
1188 for (my $i = 0; $i <= 10; $i++) {
1189 my $count = $levelcount->{$i} // 0;
1190 my $ratio = $count_in ?
$count/$count_in : 0;
1191 push @$res, { level
=> $i, count
=> $count, ratio
=> $ratio };
1197 __PACKAGE__-
>register_method ({
1198 name
=> 'maildistribution',
1199 path
=> 'maildistribution',
1201 description
=> "Get the count of spam mails grouped by spam score. " .
1202 "Count for score 10 includes mails with spam score > 10.",
1203 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1205 additionalProperties
=> 0,
1206 properties
=> $default_properties->(),
1214 description
=> "Hour (0-23).",
1218 description
=> "Overall mail count (in and out).",
1222 description
=> "Incoming mail count.",
1226 description
=> "Outgoing mail count.",
1230 description
=> "Incoming spam mails (spamcount_in + glcount + spfcount).",
1234 description
=> "Outgoing spam mails.",
1238 description
=> "Number of incoming virus mails.",
1242 description
=> "Number of outgoing virus mails.",
1246 description
=> "Incoming bounce mail count (sender = <>).",
1250 description
=> "Outgoing bounce mail count (sender = <>).",
1259 my ($start, $end) = $extract_start_end->($param);
1261 my $stat = PMG
::Statistic-
>new($start, $end);
1262 my $rdb = PMG
::RuleDB-
>new();
1264 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1266 my $res = $stat->traffic_stat_day_dist ($rdb);
1271 __PACKAGE__-
>register_method ({
1272 name
=> 'rejectcount',
1273 path
=> 'rejectcount',
1275 description
=> "Early SMTP reject count statistic (RBL, PREGREET rejects with postscreen)",
1276 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1278 additionalProperties
=> 0,
1279 properties
=> $default_properties->({
1281 description
=> "Return RBL/PREGREET rejects/<timespan>, where <timespan> is specified in seconds.",
1284 maximum
=> 366*86400,
1296 description
=> "Time index.",
1300 description
=> "Time (Unix epoch).",
1304 description
=> "RBL recject count.",
1307 pregreet_rejects
=> {
1308 description
=> "PREGREET recject count.",
1317 my ($start, $end) = $extract_start_end->($param);
1319 my $span = $param->{timespan
} // 3600;
1321 my $count = ($end - $start)/$span;
1323 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1325 my $stat = PMG
::Statistic-
>new($start, $end);
1326 my $rdb = PMG
::RuleDB-
>new();
1328 my $res = $stat->postscreen_stat_graph($rdb, $span);