]>
git.proxmox.com Git - pmg-api.git/blob - PMG/API2/Statistics.pm
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 $restenv = PMG
::RESTEnvironment-
>get();
242 my $cinfo = $restenv->{cinfo
};
244 my ($start, $end) = $extract_start_end->($param);
246 my $cfg = PMG
::Config-
>new();
247 my $advfilter = $cfg->get('admin', 'advfilter');
249 my $stat = PMG
::Statistic-
>new($start, $end);
250 my $rdb = PMG
::RuleDB-
>new();
253 if ($param->{orderby
}) {
254 my $props = ['contact', 'count', 'bytes', 'viruscount'];
255 $sorters = $decode_orderby->($param->{orderby
}, $props);
258 my $res = $stat->user_stat_contact($rdb, $userstat_limit, $sorters, $param->{filter
}, $advfilter);
263 __PACKAGE__-
>register_method ({
264 name
=> 'contactdetails',
265 path
=> 'contact/{contact}',
267 description
=> "Detailed Contact Statistics.",
268 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
270 additionalProperties
=> 0,
271 properties
=> $default_properties->({
272 contact
=> get_standard_option
('pmg-email-address', {
273 description
=> "Contact email address.",
276 description
=> "Sender address filter.",
281 orderby
=> $api_properties->{orderby
},
290 description
=> "Receive time stamp",
294 description
=> "Sender email.",
298 description
=> "Mail traffic (Bytes).",
302 description
=> "Mail was blocked.",
306 description
=> "Spam score.",
310 description
=> "Virus name.",
320 my $restenv = PMG
::RESTEnvironment-
>get();
321 my $cinfo = $restenv->{cinfo
};
323 my ($start, $end) = $extract_start_end->($param);
325 my $stat = PMG
::Statistic-
>new($start, $end);
326 my $rdb = PMG
::RuleDB-
>new();
329 if ($param->{orderby
}) {
330 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
331 $sorters = $decode_orderby->($param->{orderby
}, $props);
334 return $stat->user_stat_contact_details(
335 $rdb, $param->{contact
}, $userstat_limit, $sorters, $param->{filter
});
338 __PACKAGE__-
>register_method ({
342 description
=> "Sender Address Statistics.",
343 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
345 additionalProperties
=> 0,
346 properties
=> $default_properties->({
348 description
=> "Sender address filter.",
353 orderby
=> $api_properties->{orderby
},
362 description
=> "Sender email.",
366 description
=> "Mail count.",
371 description
=> "Mail traffic (Bytes).",
375 description
=> "Number of sent virus mails.",
381 links
=> [ { rel
=> 'child', href
=> "{sender}" } ],
386 my $restenv = PMG
::RESTEnvironment-
>get();
387 my $cinfo = $restenv->{cinfo
};
389 my ($start, $end) = $extract_start_end->($param);
391 my $stat = PMG
::Statistic-
>new($start, $end);
392 my $rdb = PMG
::RuleDB-
>new();
395 if ($param->{orderby
}) {
396 my $props = ['sender', 'count', 'bytes', 'viruscount'];
397 $sorters = $decode_orderby->($param->{orderby
}, $props);
400 my $res = $stat->user_stat_sender($rdb, $userstat_limit, $sorters, $param->{filter
});
405 __PACKAGE__-
>register_method ({
406 name
=> 'senderdetails',
407 path
=> 'sender/{sender}',
409 description
=> "Detailed Sender Statistics.",
410 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
412 additionalProperties
=> 0,
413 properties
=> $default_properties->({
414 sender
=> get_standard_option
('pmg-email-address', {
415 description
=> "Sender email address.",
418 description
=> "Receiver address filter.",
423 orderby
=> $api_properties->{orderby
},
432 description
=> "Receive time stamp",
436 description
=> "Receiver email.",
440 description
=> "Mail traffic (Bytes).",
444 description
=> "Mail was blocked.",
448 description
=> "Spam score.",
452 description
=> "Virus name.",
462 my $restenv = PMG
::RESTEnvironment-
>get();
463 my $cinfo = $restenv->{cinfo
};
465 my ($start, $end) = $extract_start_end->($param);
467 my $stat = PMG
::Statistic-
>new($start, $end);
468 my $rdb = PMG
::RuleDB-
>new();
471 if ($param->{orderby
}) {
472 my $props = ['time', 'receiver', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
473 $sorters = $decode_orderby->($param->{orderby
}, $props);
476 return $stat->user_stat_sender_details(
477 $rdb, $param->{sender
}, $userstat_limit, $sorters, $param->{filter
});
480 __PACKAGE__-
>register_method ({
484 description
=> "Receiver Address Statistics.",
485 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
487 additionalProperties
=> 0,
488 properties
=> $default_properties->({
490 description
=> "Receiver address filter.",
495 orderby
=> $api_properties->{orderby
},
504 description
=> "Sender email.",
508 description
=> "Mail count.",
513 description
=> "Mail traffic (Bytes).",
517 description
=> "Number of sent spam mails.",
522 description
=> "Number of sent virus mails.",
528 links
=> [ { rel
=> 'child', href
=> "{receiver}" } ],
533 my $restenv = PMG
::RESTEnvironment-
>get();
534 my $cinfo = $restenv->{cinfo
};
536 my ($start, $end) = $extract_start_end->($param);
538 my $cfg = PMG
::Config-
>new();
539 my $advfilter = $cfg->get('admin', 'advfilter');
541 my $stat = PMG
::Statistic-
>new($start, $end);
542 my $rdb = PMG
::RuleDB-
>new();
545 if ($param->{orderby
}) {
546 my $props = ['receiver', 'count', 'bytes', 'spamcount', 'viruscount'];
547 $sorters = $decode_orderby->($param->{orderby
}, $props);
550 my $res = $stat->user_stat_receiver($rdb, $userstat_limit, $sorters, $param->{filter
}, $advfilter);
555 __PACKAGE__-
>register_method ({
556 name
=> 'receiverdetails',
557 path
=> 'receiver/{receiver}',
559 description
=> "Detailed Receiver Statistics.",
560 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
562 additionalProperties
=> 0,
563 properties
=> $default_properties->({
564 receiver
=> get_standard_option
('pmg-email-address', {
565 description
=> "Receiver email address.",
568 description
=> "Sender address filter.",
573 orderby
=> $api_properties->{orderby
},
582 description
=> "Receive time stamp",
586 description
=> "Sender email.",
590 description
=> "Mail traffic (Bytes).",
594 description
=> "Mail was blocked.",
598 description
=> "Spam score.",
602 description
=> "Virus name.",
612 my $restenv = PMG
::RESTEnvironment-
>get();
613 my $cinfo = $restenv->{cinfo
};
615 my ($start, $end) = $extract_start_end->($param);
617 my $stat = PMG
::Statistic-
>new($start, $end);
618 my $rdb = PMG
::RuleDB-
>new();
621 if ($param->{orderby
}) {
622 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
623 $sorters = $decode_orderby->($param->{orderby
}, $props);
626 return $stat->user_stat_receiver_details(
627 $rdb, $param->{receiver
}, $userstat_limit, $sorters, $param->{filter
});
630 __PACKAGE__-
>register_method ({
634 description
=> "Mail Domains Statistics.",
635 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
637 additionalProperties
=> 0,
638 properties
=> $default_properties->(),
646 description
=> "Domain name.",
650 description
=> "Incoming mail count.",
654 description
=> "Outgoing mail count.",
658 description
=> "Incoming spam mails.",
662 description
=> "Outgoing spam mails.",
666 description
=> "Incoming mail traffic (Bytes).",
670 description
=> "Outgoing mail traffic (Bytes).",
674 description
=> "Number of incoming virus mails.",
678 description
=> "Number of outgoing virus mails.",
687 my $restenv = PMG
::RESTEnvironment-
>get();
688 my $cinfo = $restenv->{cinfo
};
690 my ($start, $end) = $extract_start_end->($param);
692 my $stat = PMG
::Statistic-
>new($start, $end);
693 my $rdb = PMG
::RuleDB-
>new();
695 #PMG::Statistic::update_stats_domainstat_in($rdb->{dbh}, $cinfo);
696 #PMG::Statistic::update_stats_domainstat_out($rdb->{dbh}, $cinfo);
698 my $res = $stat->total_domain_stat($rdb);
704 __PACKAGE__-
>register_method ({
708 description
=> "General Mail Statistics.",
709 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
711 additionalProperties
=> 0,
712 properties
=> $default_properties->(),
718 description
=> "Average mail processing time in seconds.",
722 description
=> "Incoming bounce mail count (sender = <>).",
726 description
=> "Outgoing bounce mail count (sender = <>).",
730 description
=> "Overall mail count (in and out).",
734 description
=> "Incoming mail count.",
738 description
=> "Outgoing mail count.",
742 description
=> "Number of greylisted mails.",
746 description
=> "Number of RBL rejects.",
749 pregreet_rejects
=> {
750 description
=> "PREGREET recject count.",
754 description
=> "Incoming junk mail count (viruscount_in + spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
758 description
=> "Outgoing junk mail count (viruscount_out + spamcount_out).",
762 description
=> "Incoming spam mails.",
766 description
=> "Outgoing spam mails.",
770 description
=> "Mails rejected by SPF.",
774 description
=> "Incoming mail traffic (bytes).",
778 description
=> "Outgoing mail traffic (bytes).",
782 description
=> "Number of incoming virus mails.",
786 description
=> "Number of outgoing virus mails.",
794 my $restenv = PMG
::RESTEnvironment-
>get();
795 my $cinfo = $restenv->{cinfo
};
797 my ($start, $end) = $extract_start_end->($param);
799 my $stat = PMG
::Statistic-
>new($start, $end);
800 my $rdb = PMG
::RuleDB-
>new();
802 my $res = $stat->total_mail_stat($rdb);
804 my $rejects = $stat->postscreen_stat($rdb);
806 $res->{rbl_rejects
} //= 0;
807 if (defined(my $rbl_rejects = $rejects->{rbl_rejects
})) {
808 foreach my $k (qw(rbl_rejects junk_in count_in count)) {
809 $res->{$k} += $rbl_rejects;
813 $res->{pregreet_rejects
} //= 0;
814 if (defined(my $pregreet_rejects = $rejects->{pregreet_rejects
})) {
815 foreach my $k (qw(pregreet_rejects junk_in count_in count)) {
816 $res->{$k} += $pregreet_rejects;
823 __PACKAGE__-
>register_method ({
827 description
=> "Mail Count Statistics.",
828 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
830 additionalProperties
=> 0,
833 description
=> "How many hours you want to get",
841 description
=> "The Timespan for one datapoint (in seconds)",
856 description
=> "Time index.",
860 description
=> "Time (Unix epoch).",
864 description
=> "Overall mail count (in and out).",
868 description
=> "Incoming mail count.",
872 description
=> "Outgoing mail count.",
876 description
=> "Overall spam mail count (in and out).",
880 description
=> "Incoming spam mails (spamcount_in + glcount + spfcount).",
884 description
=> "Outgoing spam mails.",
888 description
=> "Number of incoming bytes mails.",
892 description
=> "Number of outgoing bytes mails.",
896 description
=> "Number of incoming virus mails.",
900 description
=> "Number of outgoing virus mails.",
904 description
=> "Timespan in seconds for one data point",
913 my $restenv = PMG
::RESTEnvironment-
>get();
915 my $hours = $param->{hours
} // 12;
916 my $span = $param->{timespan
} // 1800;
919 my $start = $end - 3600*$hours;
921 my $stat = PMG
::Statistic-
>new($start, $end);
922 my $rdb = PMG
::RuleDB-
>new();
924 my $res = $stat->recent_mailcount($rdb, $span);
929 __PACKAGE__-
>register_method ({
930 name
=> 'recentreceivers',
931 path
=> 'recentreceivers',
933 description
=> "Top recent Mail Receivers (including spam)",
934 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
936 additionalProperties
=> 0,
939 description
=> "How many hours you want to get",
947 description
=> "The maximum number of receivers to return.",
962 description
=> "The count of incoming not blocked E-Mails",
966 description
=> "The receiver",
975 my $restenv = PMG
::RESTEnvironment-
>get();
977 my $hours = $param->{hours
} // 12;
979 my $limit = $param->{limit
} // 5;
982 my $start = $end - 3600*$hours;
984 my $stat = PMG
::Statistic-
>new($start, $end);
985 my $rdb = PMG
::RuleDB-
>new();
987 my $res = $stat->recent_receivers($rdb, $limit);
992 __PACKAGE__-
>register_method ({
996 description
=> "Mail Count Statistics.",
997 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
999 additionalProperties
=> 0,
1000 properties
=> $default_properties->({
1002 description
=> "Return Mails/<timespan>, where <timespan> is specified in seconds.",
1005 maximum
=> 366*86400,
1017 description
=> "Time index.",
1021 description
=> "Time (Unix epoch).",
1025 description
=> "Overall mail count (in and out).",
1029 description
=> "Incoming mail count.",
1033 description
=> "Outgoing mail count.",
1037 description
=> "Incoming spam mails (spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
1041 description
=> "Outgoing spam mails.",
1045 description
=> "Number of incoming virus mails.",
1049 description
=> "Number of outgoing virus mails.",
1053 description
=> "Number of RBL rejects.",
1056 pregreet_rejects
=> {
1057 description
=> "PREGREET recject count.",
1061 description
=> "Incoming bounce mail count (sender = <>).",
1065 description
=> "Outgoing bounce mail count (sender = <>).",
1074 my $restenv = PMG
::RESTEnvironment-
>get();
1075 my $cinfo = $restenv->{cinfo
};
1077 my ($start, $end) = $extract_start_end->($param);
1079 my $span = $param->{timespan
} // 3600;
1081 my $count = ($end - $start)/$span;
1083 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1085 my $stat = PMG
::Statistic-
>new($start, $end);
1086 my $rdb = PMG
::RuleDB-
>new();
1088 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1090 my $rejects = $stat->postscreen_stat_graph($rdb, $span);
1092 my $res = $stat->traffic_stat_graph ($rdb, $span);
1094 my $element_count = scalar(@$res);
1096 for (my $i = 0; $i < $element_count; $i++) {
1097 my $el = $rejects->[$i];
1100 foreach my $k ('rbl_rejects', 'pregreet_rejects') {
1101 my $count = $el->{$k} // 0;
1103 foreach my $k (qw(count count_in spamcount_in)) {
1112 __PACKAGE__-
>register_method ({
1116 description
=> "Get Statistics about detected Viruses.",
1117 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1119 additionalProperties
=> 0,
1120 properties
=> $default_properties->(),
1128 description
=> 'Virus name.',
1132 description
=> 'Detection count.',
1141 my $restenv = PMG
::RESTEnvironment-
>get();
1142 my $cinfo = $restenv->{cinfo
};
1144 my ($start, $end) = $extract_start_end->($param);
1146 my $stat = PMG
::Statistic-
>new($start, $end);
1147 my $rdb = PMG
::RuleDB-
>new();
1149 my $res = $stat->total_virus_stat($rdb);
1154 __PACKAGE__-
>register_method ({
1155 name
=> 'spamscores',
1156 path
=> 'spamscores',
1158 description
=> "Get the count of spam mails grouped by spam score. " .
1159 "Count for score 10 includes mails with spam score > 10.",
1160 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1162 additionalProperties
=> 0,
1163 properties
=> $default_properties->(),
1171 description
=> 'Spam level.',
1175 description
=> 'Detection count.',
1179 description
=> 'Portion of overall mail count.',
1188 my $restenv = PMG
::RESTEnvironment-
>get();
1189 my $cinfo = $restenv->{cinfo
};
1191 my ($start, $end) = $extract_start_end->($param);
1193 my $stat = PMG
::Statistic-
>new($start, $end);
1194 my $rdb = PMG
::RuleDB-
>new();
1196 my $totalstat = $stat->total_mail_stat ($rdb);
1197 my $spamstat = $stat->total_spam_stat($rdb);
1201 my $count_in = $totalstat->{count_in
};
1203 my $levelcount = {};
1205 foreach my $ref (@$spamstat) {
1206 if (my $level = $ref->{spamlevel
}) {
1207 next if $level < 1; # just to be sure
1208 $spamcount += $ref->{count
};
1209 $level = 10 if $level > 10;
1210 $levelcount->{$level} += $ref->{count
};
1214 $levelcount->{0} = $count_in - $spamcount;
1216 for (my $i = 0; $i <= 10; $i++) {
1217 my $count = $levelcount->{$i} // 0;
1218 my $ratio = $count_in ?
$count/$count_in : 0;
1219 push @$res, { level
=> $i, count
=> $count, ratio
=> $ratio };
1225 __PACKAGE__-
>register_method ({
1226 name
=> 'maildistribution',
1227 path
=> 'maildistribution',
1229 description
=> "Get the count of spam mails grouped by spam score. " .
1230 "Count for score 10 includes mails with spam score > 10.",
1231 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1233 additionalProperties
=> 0,
1234 properties
=> $default_properties->(),
1242 description
=> "Hour (0-23).",
1246 description
=> "Overall mail count (in and out).",
1250 description
=> "Incoming mail count.",
1254 description
=> "Outgoing mail count.",
1258 description
=> "Incoming spam mails (spamcount_in + glcount + spfcount).",
1262 description
=> "Outgoing spam mails.",
1266 description
=> "Number of incoming virus mails.",
1270 description
=> "Number of outgoing virus mails.",
1274 description
=> "Incoming bounce mail count (sender = <>).",
1278 description
=> "Outgoing bounce mail count (sender = <>).",
1287 my $restenv = PMG
::RESTEnvironment-
>get();
1288 my $cinfo = $restenv->{cinfo
};
1290 my ($start, $end) = $extract_start_end->($param);
1292 my $stat = PMG
::Statistic-
>new($start, $end);
1293 my $rdb = PMG
::RuleDB-
>new();
1295 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1297 my $res = $stat->traffic_stat_day_dist ($rdb);
1302 __PACKAGE__-
>register_method ({
1303 name
=> 'rejectcount',
1304 path
=> 'rejectcount',
1306 description
=> "Early SMTP reject count statistic (RBL, PREGREET rejects with postscreen)",
1307 permissions
=> { check
=> [ 'admin', 'qmanager', 'audit'] },
1309 additionalProperties
=> 0,
1310 properties
=> $default_properties->({
1312 description
=> "Return RBL/PREGREET rejects/<timespan>, where <timespan> is specified in seconds.",
1315 maximum
=> 366*86400,
1327 description
=> "Time index.",
1331 description
=> "Time (Unix epoch).",
1335 description
=> "RBL recject count.",
1338 pregreet_rejects
=> {
1339 description
=> "PREGREET recject count.",
1348 my $restenv = PMG
::RESTEnvironment-
>get();
1349 my $cinfo = $restenv->{cinfo
};
1351 my ($start, $end) = $extract_start_end->($param);
1353 my $span = $param->{timespan
} // 3600;
1355 my $count = ($end - $start)/$span;
1357 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1359 my $stat = PMG
::Statistic-
>new($start, $end);
1360 my $rdb = PMG
::RuleDB-
>new();
1362 my $res = $stat->postscreen_stat_graph($rdb, $span);