]> git.proxmox.com Git - pmg-api.git/blame - PMG/API2/Statistics.pm
remove unique constraint from LocalStat(Time)
[pmg-api.git] / PMG / API2 / Statistics.pm
CommitLineData
5de9374c
DM
1package PMG::API2::Statistics;
2
3use strict;
4use warnings;
5use Data::Dumper;
15a1e62c 6use JSON;
0f6b8ccb 7use Time::Local;
5de9374c
DM
8
9use PVE::Tools;
10use PVE::SafeSyslog;
11use PVE::INotify;
12use PVE::Exception qw(raise_param_exc);
13use PVE::RESTHandler;
14use PMG::RESTEnvironment;
15use PVE::JSONSchema qw(get_standard_option);
16
17use PMG::Utils;
44017d49 18use PMG::Config;
5de9374c
DM
19use PMG::RuleDB;
20use PMG::Statistic;
21
22use base qw(PVE::RESTHandler);
23
24__PACKAGE__->register_method ({
25 name => 'index',
26 path => '',
27 method => 'GET',
28 description => "Directory index.",
29 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
30 parameters => {
31 additionalProperties => 0,
d67b777f 32 properties => {},
5de9374c
DM
33 },
34 returns => {
35 type => 'array',
36 items => {
37 type => "object",
38 properties => {},
39 },
40 links => [ { rel => 'child', href => "{name}" } ],
41 },
42 code => sub {
43 my ($param) = @_;
44
45 return [
bcf493af 46 { name => "contact" },
d19c40e0 47 { name => "domains" },
5de9374c 48 { name => "mail" },
6156e4b6 49 { name => "mailcount" },
fea9d463 50 { name => "recent" },
56e1cb1b 51 { name => "recentreceivers" },
89891fa2 52 { name => "maildistribution" },
67832798 53 { name => "spamscores" },
15a1e62c 54 { name => "sender" },
2719ef94 55 { name => "rblcount" },
0ab6dc2a 56 { name => "receiver" },
d67b777f 57 { name => "virus" },
5de9374c
DM
58 ];
59 }});
60
15a1e62c
DM
61my $decode_orderby = sub {
62 my ($orderby, $allowed_props) = @_;
63
64 my $sorters;
65
66 eval { $sorters = decode_json($orderby); };
67 if (my $err = $@) {
68 raise_param_exc({ orderby => 'invalid JSON'});
69 }
70
71 my $schema = {
72 type => 'array',
73 items => {
74 type => "object",
75 properties => {
76 property => {
77 type => 'string',
78 enum => $allowed_props,
79 },
80 direction => {
81 type => 'string',
82 enum => ['ASC', 'DESC'],
83 },
84 },
85 },
86 };
87
88 PVE::JSONSchema::validate($sorters, $schema, "Parameter 'orderby' verification failed\n");
89
90 return $sorters;
91};
92
f194ac27
DM
93my $api_properties = {
94 orderby => {
95 description => "Remote sorting configuration(JSON, ExtJS compatible).",
96 type => 'string',
97 optional => 1,
98 maxLength => 4096,
99 },
15a1e62c
DM
100};
101
f194ac27
DM
102my $default_properties = sub {
103 my ($prop) = @_;
104
105 $prop //= {};
106
107 $prop->{starttime} = get_standard_option('pmg-starttime');
108 $prop->{endtime} = get_standard_option('pmg-endtime');
109
0f6b8ccb
DM
110 $prop->{year} = {
111 description => "Year. Defaults to current year. You will get statistics for the whole year if you do not specify a month or day.",
112 type => 'integer',
113 minimum => 1900,
114 maximum => 3000,
115 optional => 1,
116 };
117
118 $prop->{month} = {
119 description => "Month. You will get statistics for the whole month if you do not specify a day.",
120 type => 'integer',
121 minimum => 1,
122 maximum => 12,
123 optional => 1,
124 };
125
126 $prop->{day} = {
127 description => "Day of month. Get statistics for a single day.",
128 type => 'integer',
129 minimum => 1,
130 maximum => 31,
131 optional => 1,
132 };
133
f194ac27
DM
134 return $prop;
135};
136
137my $extract_start_end = sub {
138 my ($param) = @_;
139
0f6b8ccb
DM
140 my $has_ymd;
141 foreach my $k (qw(year month day)) {
142 if (defined($param->{$k})) {
143 $has_ymd = $k;
144 last;
145 }
146 }
147 my $has_se;
148 foreach my $k (qw(starttime endtime)) {
149 if (defined($param->{$k})) {
150 $has_se = $k;
151 last;
152 }
153 }
154
155 raise_param_exc({ $has_se => "parameter conflicts with parameter '$has_ymd'"})
156 if $has_se && $has_ymd;
157
158 my $start;
159 my $end;
160
161 if ($has_ymd) {
162 my (undef, undef, undef, undef, $month, $year) = localtime(time());
163 $month += 1;
164 $year = $param->{year} if defined($param->{year});
165 if (defined($param->{day})) {
166 $month = $param->{month} if defined($param->{month});
167 $start = timelocal(0, 0, 0, 1, $month - 1, $year);
168 $end = timelocal(0, 0, 0, 1, $month, $year);
169 } elsif (defined($param->{month})) {
170 my $month = $param->{month};
171 if ($month < 12) {
172 $start = timelocal(0, 0, 0, 1, $month - 1, $year);
173 $end = timelocal(0, 0, 0, 1, $month, $year);
174 } else {
175 $start = timelocal(0, 0, 0, 1, 11, $year);
176 $end = timelocal(0, 0, 0, 1, 0, $year + 1);
177 }
178 } else {
179 $start = timelocal(0, 0, 0, 1, 0, $year);
180 $end = timelocal(0, 0, 0, 1, 0, $year + 1);
181 }
182 } else {
183 $start = $param->{starttime} // (time - 86400);
184 $end = $param->{endtime} // ($start + 86400);
185 }
f194ac27
DM
186
187 return ($start, $end);
188};
15a1e62c 189
f194ac27 190my $userstat_limit = 2000; # hardcoded limit
bcf493af
DM
191
192__PACKAGE__->register_method ({
193 name => 'contact',
194 path => 'contact',
195 method => 'GET',
196 description => "Contact Address Statistics.",
197 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
198 parameters => {
199 additionalProperties => 0,
f194ac27 200 properties => $default_properties->({
bcf493af
DM
201 filter => {
202 description => "Contact address filter.",
203 type => 'string',
204 maxLength => 512,
205 optional => 1,
206 },
f194ac27
DM
207 orderby => $api_properties->{orderby},
208 }),
bcf493af
DM
209 },
210 returns => {
211 type => 'array',
212 items => {
213 type => "object",
214 properties => {
215 contact => {
216 description => "Contact email.",
217 type => 'string',
218 },
219 count => {
220 description => "Mail count.",
221 type => 'number',
222 optional => 1,
223 },
224 bytes => {
225 description => "Mail traffic (Bytes).",
226 type => 'number',
227 },
228 viruscount => {
229 description => "Number of sent virus mails.",
230 type => 'number',
231 optional => 1,
232 },
233 },
234 },
235 links => [ { rel => 'child', href => "{contact}" } ],
236 },
237 code => sub {
238 my ($param) = @_;
239
240 my $restenv = PMG::RESTEnvironment->get();
241 my $cinfo = $restenv->{cinfo};
242
f194ac27 243 my ($start, $end) = $extract_start_end->($param);
bcf493af 244
44017d49
DM
245 my $cfg = PMG::Config->new();
246 my $advfilter = $cfg->get('admin', 'advfilter');
247
bcf493af
DM
248 my $stat = PMG::Statistic->new($start, $end);
249 my $rdb = PMG::RuleDB->new();
250
251 my $sorters = [];
252 if ($param->{orderby}) {
253 my $props = ['contact', 'count', 'bytes', 'viruscount'];
254 $sorters = $decode_orderby->($param->{orderby}, $props);
255 }
256
44017d49 257 my $res = $stat->user_stat_contact($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter);
bcf493af
DM
258
259 return $res;
260 }});
261
262__PACKAGE__->register_method ({
263 name => 'contactdetails',
264 path => 'contact/{contact}',
265 method => 'GET',
266 description => "Detailed Contact Statistics.",
267 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
268 parameters => {
269 additionalProperties => 0,
f194ac27 270 properties => $default_properties->({
bcf493af
DM
271 contact => get_standard_option('pmg-email-address', {
272 description => "Contact email address.",
273 }),
274 filter => {
275 description => "Sender address filter.",
276 type => 'string',
277 maxLength => 512,
278 optional => 1,
279 },
f194ac27
DM
280 orderby => $api_properties->{orderby},
281 }),
bcf493af
DM
282 },
283 returns => {
284 type => 'array',
285 items => {
286 type => "object",
287 properties => {
288 time => {
289 description => "Receive time stamp",
290 type => 'integer',
291 },
292 sender => {
293 description => "Sender email.",
294 type => 'string',
295 },
296 bytes => {
297 description => "Mail traffic (Bytes).",
298 type => 'number',
299 },
300 blocked => {
301 description => "Mail was blocked.",
302 type => 'boolean',
303 },
304 spamlevel => {
305 description => "Spam score.",
306 type => 'number',
307 },
308 virusinfo => {
309 description => "Virus name.",
310 type => 'string',
311 optional => 1,
312 },
313 },
314 },
315 },
316 code => sub {
317 my ($param) = @_;
318
319 my $restenv = PMG::RESTEnvironment->get();
320 my $cinfo = $restenv->{cinfo};
321
f194ac27 322 my ($start, $end) = $extract_start_end->($param);
bcf493af
DM
323
324 my $stat = PMG::Statistic->new($start, $end);
325 my $rdb = PMG::RuleDB->new();
326
bcf493af
DM
327 my $sorters = [];
328 if ($param->{orderby}) {
329 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
330 $sorters = $decode_orderby->($param->{orderby}, $props);
331 }
332
333 return $stat->user_stat_contact_details(
0e3a95fa 334 $rdb, $param->{contact}, $userstat_limit, $sorters, $param->{filter});
bcf493af
DM
335 }});
336
15a1e62c
DM
337__PACKAGE__->register_method ({
338 name => 'sender',
339 path => 'sender',
340 method => 'GET',
341 description => "Sender Address Statistics.",
342 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
343 parameters => {
344 additionalProperties => 0,
f194ac27 345 properties => $default_properties->({
15a1e62c
DM
346 filter => {
347 description => "Sender address filter.",
348 type => 'string',
349 maxLength => 512,
350 optional => 1,
351 },
f194ac27
DM
352 orderby => $api_properties->{orderby},
353 }),
15a1e62c
DM
354 },
355 returns => {
356 type => 'array',
357 items => {
358 type => "object",
359 properties => {
360 sender => {
361 description => "Sender email.",
362 type => 'string',
363 },
364 count => {
365 description => "Mail count.",
366 type => 'number',
367 optional => 1,
368 },
369 bytes => {
370 description => "Mail traffic (Bytes).",
371 type => 'number',
372 },
373 viruscount => {
374 description => "Number of sent virus mails.",
375 type => 'number',
376 optional => 1,
377 },
378 },
379 },
380 links => [ { rel => 'child', href => "{sender}" } ],
381 },
382 code => sub {
383 my ($param) = @_;
384
385 my $restenv = PMG::RESTEnvironment->get();
386 my $cinfo = $restenv->{cinfo};
387
f194ac27 388 my ($start, $end) = $extract_start_end->($param);
15a1e62c
DM
389
390 my $stat = PMG::Statistic->new($start, $end);
391 my $rdb = PMG::RuleDB->new();
392
393 my $sorters = [];
394 if ($param->{orderby}) {
395 my $props = ['sender', 'count', 'bytes', 'viruscount'];
396 $sorters = $decode_orderby->($param->{orderby}, $props);
397 }
398
399 my $res = $stat->user_stat_sender($rdb, $userstat_limit, $sorters, $param->{filter});
400
401 return $res;
402 }});
403
404__PACKAGE__->register_method ({
405 name => 'senderdetails',
406 path => 'sender/{sender}',
407 method => 'GET',
408 description => "Detailed Sender Statistics.",
409 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
410 parameters => {
411 additionalProperties => 0,
f194ac27 412 properties => $default_properties->({
15a1e62c
DM
413 sender => get_standard_option('pmg-email-address', {
414 description => "Sender email address.",
415 }),
416 filter => {
417 description => "Receiver address filter.",
418 type => 'string',
419 maxLength => 512,
420 optional => 1,
421 },
f194ac27
DM
422 orderby => $api_properties->{orderby},
423 }),
15a1e62c
DM
424 },
425 returns => {
426 type => 'array',
427 items => {
428 type => "object",
429 properties => {
430 time => {
431 description => "Receive time stamp",
432 type => 'integer',
433 },
434 receiver => {
435 description => "Receiver email.",
436 type => 'string',
437 },
438 bytes => {
439 description => "Mail traffic (Bytes).",
440 type => 'number',
441 },
442 blocked => {
443 description => "Mail was blocked.",
444 type => 'boolean',
445 },
446 spamlevel => {
447 description => "Spam score.",
448 type => 'number',
449 },
0ab6dc2a 450 virusinfo => {
15a1e62c
DM
451 description => "Virus name.",
452 type => 'string',
453 optional => 1,
454 },
455 },
456 },
457 },
458 code => sub {
459 my ($param) = @_;
460
461 my $restenv = PMG::RESTEnvironment->get();
462 my $cinfo = $restenv->{cinfo};
463
f194ac27 464 my ($start, $end) = $extract_start_end->($param);
15a1e62c
DM
465
466 my $stat = PMG::Statistic->new($start, $end);
467 my $rdb = PMG::RuleDB->new();
468
469 my $sorters = [];
470 if ($param->{orderby}) {
0ab6dc2a 471 my $props = ['time', 'receiver', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
15a1e62c
DM
472 $sorters = $decode_orderby->($param->{orderby}, $props);
473 }
474
475 return $stat->user_stat_sender_details(
0e3a95fa 476 $rdb, $param->{sender}, $userstat_limit, $sorters, $param->{filter});
0ab6dc2a
DM
477 }});
478
479__PACKAGE__->register_method ({
480 name => 'receiver',
481 path => 'receiver',
482 method => 'GET',
483 description => "Receiver Address Statistics.",
484 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
485 parameters => {
486 additionalProperties => 0,
f194ac27 487 properties => $default_properties->({
0ab6dc2a
DM
488 filter => {
489 description => "Receiver address filter.",
490 type => 'string',
491 maxLength => 512,
492 optional => 1,
493 },
f194ac27
DM
494 orderby => $api_properties->{orderby},
495 }),
0ab6dc2a
DM
496 },
497 returns => {
498 type => 'array',
499 items => {
500 type => "object",
501 properties => {
502 receiver => {
503 description => "Sender email.",
504 type => 'string',
505 },
506 count => {
507 description => "Mail count.",
508 type => 'number',
509 optional => 1,
510 },
511 bytes => {
512 description => "Mail traffic (Bytes).",
513 type => 'number',
514 },
515 spamcount => {
516 description => "Number of sent spam mails.",
517 type => 'number',
518 optional => 1,
519 },
520 viruscount => {
521 description => "Number of sent virus mails.",
522 type => 'number',
523 optional => 1,
524 },
525 },
526 },
527 links => [ { rel => 'child', href => "{receiver}" } ],
528 },
529 code => sub {
530 my ($param) = @_;
531
532 my $restenv = PMG::RESTEnvironment->get();
533 my $cinfo = $restenv->{cinfo};
534
f194ac27 535 my ($start, $end) = $extract_start_end->($param);
0ab6dc2a 536
44017d49
DM
537 my $cfg = PMG::Config->new();
538 my $advfilter = $cfg->get('admin', 'advfilter');
539
0ab6dc2a
DM
540 my $stat = PMG::Statistic->new($start, $end);
541 my $rdb = PMG::RuleDB->new();
542
543 my $sorters = [];
544 if ($param->{orderby}) {
545 my $props = ['receiver', 'count', 'bytes', 'spamcount', 'viruscount'];
546 $sorters = $decode_orderby->($param->{orderby}, $props);
547 }
548
44017d49 549 my $res = $stat->user_stat_receiver($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter);
0ab6dc2a
DM
550
551 return $res;
552 }});
553
554__PACKAGE__->register_method ({
555 name => 'receiverdetails',
556 path => 'receiver/{receiver}',
557 method => 'GET',
558 description => "Detailed Receiver Statistics.",
559 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
560 parameters => {
561 additionalProperties => 0,
f194ac27 562 properties => $default_properties->({
0ab6dc2a
DM
563 receiver => get_standard_option('pmg-email-address', {
564 description => "Receiver email address.",
565 }),
566 filter => {
567 description => "Sender address filter.",
568 type => 'string',
569 maxLength => 512,
570 optional => 1,
571 },
f194ac27
DM
572 orderby => $api_properties->{orderby},
573 }),
0ab6dc2a
DM
574 },
575 returns => {
576 type => 'array',
577 items => {
578 type => "object",
579 properties => {
580 time => {
581 description => "Receive time stamp",
582 type => 'integer',
583 },
584 sender => {
585 description => "Sender email.",
586 type => 'string',
587 },
588 bytes => {
589 description => "Mail traffic (Bytes).",
590 type => 'number',
591 },
592 blocked => {
593 description => "Mail was blocked.",
594 type => 'boolean',
595 },
596 spamlevel => {
597 description => "Spam score.",
598 type => 'number',
599 },
600 virusinfo => {
601 description => "Virus name.",
602 type => 'string',
603 optional => 1,
604 },
605 },
606 },
607 },
608 code => sub {
609 my ($param) = @_;
610
611 my $restenv = PMG::RESTEnvironment->get();
612 my $cinfo = $restenv->{cinfo};
613
f194ac27 614 my ($start, $end) = $extract_start_end->($param);
0ab6dc2a
DM
615
616 my $stat = PMG::Statistic->new($start, $end);
617 my $rdb = PMG::RuleDB->new();
618
0ab6dc2a
DM
619 my $sorters = [];
620 if ($param->{orderby}) {
621 my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo'];
622 $sorters = $decode_orderby->($param->{orderby}, $props);
623 }
624
625 return $stat->user_stat_receiver_details(
0e3a95fa 626 $rdb, $param->{receiver}, $userstat_limit, $sorters, $param->{filter});
15a1e62c
DM
627 }});
628
d19c40e0
DM
629__PACKAGE__->register_method ({
630 name => 'domains',
631 path => 'domains',
632 method => 'GET',
633 description => "Mail Domains Statistics.",
634 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
635 parameters => {
636 additionalProperties => 0,
f194ac27 637 properties => $default_properties->(),
d19c40e0
DM
638 },
639 returns => {
640 type => 'array',
641 items => {
642 type => "object",
643 properties => {
644 domain => {
645 description => "Domain name.",
646 type => 'string',
647 },
648 count_in => {
649 description => "Incoming mail count.",
650 type => 'number',
651 },
652 count_out => {
653 description => "Outgoing mail count.",
654 type => 'number',
655 },
656 spamcount_in => {
657 description => "Incoming spam mails.",
658 type => 'number',
659 },
660 spamcount_out => {
661 description => "Outgoing spam mails.",
662 type => 'number',
663 },
6bc396fc
DM
664 bytes_in => {
665 description => "Incoming mail traffic (Bytes).",
d19c40e0
DM
666 type => 'number',
667 },
6bc396fc
DM
668 bytes_out => {
669 description => "Outgoing mail traffic (Bytes).",
d19c40e0
DM
670 type => 'number',
671 },
672 viruscount_in => {
673 description => "Number of incoming virus mails.",
674 type => 'number',
675 },
676 viruscount_out => {
677 description => "Number of outgoing virus mails.",
678 type => 'number',
679 },
680 },
681 },
682 },
683 code => sub {
684 my ($param) = @_;
685
686 my $restenv = PMG::RESTEnvironment->get();
687 my $cinfo = $restenv->{cinfo};
688
f194ac27 689 my ($start, $end) = $extract_start_end->($param);
d19c40e0
DM
690
691 my $stat = PMG::Statistic->new($start, $end);
692 my $rdb = PMG::RuleDB->new();
693
694 #PMG::Statistic::update_stats_domainstat_in($rdb->{dbh}, $cinfo);
695 #PMG::Statistic::update_stats_domainstat_out($rdb->{dbh}, $cinfo);
696
697 my $res = $stat->total_domain_stat($rdb);
698
15a1e62c 699
d19c40e0
DM
700 return $res;
701 }});
702
5de9374c
DM
703__PACKAGE__->register_method ({
704 name => 'mail',
705 path => 'mail',
706 method => 'GET',
707 description => "General Mail Statistics.",
708 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
5de9374c
DM
709 parameters => {
710 additionalProperties => 0,
f194ac27 711 properties => $default_properties->(),
5de9374c
DM
712 },
713 returns => {
714 type => "object",
26e55ddd
DM
715 properties => {
716 avptime => {
717 description => "Average mail processing time in seconds.",
718 type => 'number',
d3550ac9
DM
719 },
720 bounces_in => {
721 description => "Incoming bounce mail count (sender = <>).",
722 type => 'number',
723 },
724 bounces_out => {
725 description => "Outgoing bounce mail count (sender = <>).",
726 type => 'number',
727 },
728 count => {
729 description => "Overall mail count (in and out).",
730 type => 'number',
731 },
732 count_in => {
733 description => "Incoming mail count.",
734 type => 'number',
735 },
736 count_out => {
737 description => "Outgoing mail count.",
738 type => 'number',
739 },
740 glcount => {
741 description => "Number of greylisted mails.",
742 type => 'number',
743 },
4681645a
DM
744 rbl_rejects => {
745 description => "Number of RBL rejects.",
746 type => 'integer',
747 },
748 pregreet_rejects => {
749 description => "PREGREET recject count.",
750 type => 'integer',
751 },
d3550ac9 752 junk_in => {
4681645a 753 description => "Incoming junk mail count (viruscount_in + spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
d3550ac9
DM
754 type => 'number',
755 },
756 junk_out => {
757 description => "Outgoing junk mail count (viruscount_out + spamcount_out).",
758 type => 'number',
759 },
760 spamcount_in => {
761 description => "Incoming spam mails.",
762 type => 'number',
763 },
764 spamcount_out => {
765 description => "Outgoing spam mails.",
766 type => 'number',
767 },
768 spfcount => {
769 description => "Mails rejected by SPF.",
770 type => 'number',
771 },
d19c40e0 772 bytes_in => {
d3550ac9
DM
773 description => "Incoming mail traffic (bytes).",
774 type => 'number',
775 },
d19c40e0 776 bytes_out => {
d3550ac9
DM
777 description => "Outgoing mail traffic (bytes).",
778 type => 'number',
779 },
780 viruscount_in => {
781 description => "Number of incoming virus mails.",
782 type => 'number',
783 },
784 viruscount_out => {
785 description => "Number of outgoing virus mails.",
786 type => 'number',
787 },
26e55ddd 788 },
5de9374c
DM
789 },
790 code => sub {
791 my ($param) = @_;
91bc7652 792
5de9374c
DM
793 my $restenv = PMG::RESTEnvironment->get();
794 my $cinfo = $restenv->{cinfo};
795
f194ac27 796 my ($start, $end) = $extract_start_end->($param);
91bc7652 797
5de9374c
DM
798 my $stat = PMG::Statistic->new($start, $end);
799 my $rdb = PMG::RuleDB->new();
91bc7652 800
5de9374c
DM
801 my $res = $stat->total_mail_stat($rdb);
802
4681645a
DM
803 my $rejects = $stat->postscreen_stat($rdb);
804
805 $res->{rbl_rejects} //= 0;
806 if (defined(my $rbl_rejects = $rejects->{rbl_rejects})) {
807 foreach my $k (qw(rbl_rejects junk_in count_in count)) {
808 $res->{$k} += $rbl_rejects;
809 }
810 }
811
812 $res->{pregreet_rejects} //= 0;
813 if (defined(my $pregreet_rejects = $rejects->{pregreet_rejects})) {
814 foreach my $k (qw(pregreet_rejects junk_in count_in count)) {
815 $res->{$k} += $pregreet_rejects;
816 }
817 }
818
5de9374c
DM
819 return $res;
820 }});
821
fea9d463
DC
822__PACKAGE__->register_method ({
823 name => 'recent',
824 path => 'recent',
825 method => 'GET',
826 description => "Mail Count Statistics.",
827 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
828 parameters => {
829 additionalProperties => 0,
830 properties => {
831 hours => {
832 description => "How many hours you want to get",
833 type => 'integer',
834 minimum => 1,
835 maximum => 24,
836 optional => 1,
837 default => 12,
838 },
839 timespan => {
840 description => "The Timespan for one datapoint (in seconds)",
841 type => 'integer',
842 minimum => 1,
843 maximum => 1800,
844 optional => 1,
845 default => 1800,
846 },
847 },
848 },
849 returns => {
850 type => 'array',
851 items => {
852 type => "object",
853 properties => {
854 index => {
855 description => "Time index.",
856 type => 'integer',
857 },
858 time => {
859 description => "Time (Unix epoch).",
860 type => 'integer',
861 },
862 count => {
863 description => "Overall mail count (in and out).",
864 type => 'number',
865 },
866 count_in => {
867 description => "Incoming mail count.",
868 type => 'number',
869 },
870 count_out => {
871 description => "Outgoing mail count.",
872 type => 'number',
873 },
874 spam => {
875 description => "Overall spam mail count (in and out).",
876 type => 'number',
877 },
878 spam_in => {
879 description => "Incoming spam mails (spamcount_in + glcount + spfcount).",
880 type => 'number',
881 },
882 spam_out => {
883 description => "Outgoing spam mails.",
884 type => 'number',
885 },
886 bytes_in => {
887 description => "Number of incoming bytes mails.",
888 type => 'number',
889 },
890 bytes_out => {
891 description => "Number of outgoing bytes mails.",
892 type => 'number',
893 },
894 virus_in => {
895 description => "Number of incoming virus mails.",
896 type => 'number',
897 },
898 virus_out => {
899 description => "Number of outgoing virus mails.",
900 type => 'number',
901 },
902 timespan => {
903 description => "Timespan in seconds for one data point",
904 type => 'number',
905 }
906 },
907 },
908 },
909 code => sub {
910 my ($param) = @_;
911
912 my $restenv = PMG::RESTEnvironment->get();
913
914 my $hours = $param->{hours} // 12;
915 my $span = $param->{timespan} // 1800;
916
917 my $end = time();
918 my $start = $end - 3600*$hours;
919
920 my $stat = PMG::Statistic->new($start, $end);
921 my $rdb = PMG::RuleDB->new();
922
923 my $res = $stat->recent_mailcount($rdb, $span);
924
925 return $res;
926 }});
927
56e1cb1b
DC
928__PACKAGE__->register_method ({
929 name => 'recentreceivers',
930 path => 'recentreceivers',
931 method => 'GET',
932 description => "Top recent Mail Receivers (including spam)",
933 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
934 parameters => {
935 additionalProperties => 0,
936 properties => {
937 hours => {
938 description => "How many hours you want to get",
939 type => 'integer',
940 minimum => 1,
941 maximum => 24,
942 optional => 1,
943 default => 12,
944 },
945 limit => {
946 description => "The maximum number of receivers to return.",
947 type => 'integer',
948 minimum => 1,
949 maximum => 50,
950 optional => 1,
951 default => 5,
952 },
953 },
954 },
955 returns => {
956 type => 'array',
957 items => {
958 type => "object",
959 properties => {
960 count => {
961 description => "The count of incoming not blocked E-Mails",
962 type => 'integer',
963 },
964 receiver => {
965 description => "The receiver",
966 type => 'string',
967 },
968 },
969 },
970 },
971 code => sub {
972 my ($param) = @_;
973
974 my $restenv = PMG::RESTEnvironment->get();
975
976 my $hours = $param->{hours} // 12;
977
978 my $limit = $param->{limit} // 5;
979
980 my $end = time();
981 my $start = $end - 3600*$hours;
982
983 my $stat = PMG::Statistic->new($start, $end);
984 my $rdb = PMG::RuleDB->new();
985
986 my $res = $stat->recent_receivers($rdb, $limit);
987
988 return $res;
989 }});
990
6156e4b6
DM
991__PACKAGE__->register_method ({
992 name => 'mailcount',
993 path => 'mailcount',
994 method => 'GET',
995 description => "Mail Count Statistics.",
996 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
997 parameters => {
998 additionalProperties => 0,
f194ac27 999 properties => $default_properties->({
6156e4b6 1000 timespan => {
f194ac27 1001 description => "Return Mails/<timespan>, where <timespan> is specified in seconds.",
6156e4b6
DM
1002 type => 'integer',
1003 minimum => 3600,
1004 maximum => 366*86400,
1005 optional => 1,
1006 default => 3600,
f194ac27
DM
1007 },
1008 }),
6156e4b6
DM
1009 },
1010 returns => {
1011 type => 'array',
1012 items => {
1013 type => "object",
1014 properties => {
1015 index => {
1016 description => "Time index.",
1017 type => 'integer',
1018 },
1019 time => {
1020 description => "Time (Unix epoch).",
1021 type => 'integer',
1022 },
1023 count => {
1024 description => "Overall mail count (in and out).",
1025 type => 'number',
1026 },
1027 count_in => {
1028 description => "Incoming mail count.",
1029 type => 'number',
1030 },
1031 count_out => {
1032 description => "Outgoing mail count.",
1033 type => 'number',
1034 },
1035 spamcount_in => {
4681645a 1036 description => "Incoming spam mails (spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).",
6156e4b6
DM
1037 type => 'number',
1038 },
1039 spamcount_out => {
1040 description => "Outgoing spam mails.",
1041 type => 'number',
1042 },
1043 viruscount_in => {
1044 description => "Number of incoming virus mails.",
1045 type => 'number',
1046 },
1047 viruscount_out => {
1048 description => "Number of outgoing virus mails.",
1049 type => 'number',
1050 },
4681645a
DM
1051 rbl_rejects => {
1052 description => "Number of RBL rejects.",
1053 type => 'integer',
1054 },
1055 pregreet_rejects => {
1056 description => "PREGREET recject count.",
1057 type => 'integer',
1058 },
6156e4b6
DM
1059 bounces_in => {
1060 description => "Incoming bounce mail count (sender = <>).",
1061 type => 'number',
1062 },
1063 bounces_out => {
1064 description => "Outgoing bounce mail count (sender = <>).",
1065 type => 'number',
1066 },
1067 },
1068 },
1069 },
1070 code => sub {
1071 my ($param) = @_;
1072
1073 my $restenv = PMG::RESTEnvironment->get();
1074 my $cinfo = $restenv->{cinfo};
1075
f194ac27 1076 my ($start, $end) = $extract_start_end->($param);
6156e4b6
DM
1077
1078 my $span = $param->{timespan} // 3600;
1079
1080 my $count = ($end - $start)/$span;
1081
1082 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1083
1084 my $stat = PMG::Statistic->new($start, $end);
1085 my $rdb = PMG::RuleDB->new();
1086
1087 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1088
4681645a
DM
1089 my $rejects = $stat->postscreen_stat_graph($rdb, $span);
1090
6156e4b6
DM
1091 my $res = $stat->traffic_stat_graph ($rdb, $span);
1092
4681645a
DM
1093 my $element_count = scalar(@$res);
1094
1095 for (my $i = 0; $i < $element_count; $i++) {
1096 my $el = $rejects->[$i];
1097 next if !$el;
1098 my $d = $res->[$i];
1099 foreach my $k ('rbl_rejects', 'pregreet_rejects') {
1100 my $count = $el->{$k} // 0;
1101 $d->{$k} = $count;
1102 foreach my $k (qw(count count_in spamcount_in)) {
1103 $d->{$k} += $count;
1104 }
1105 }
1106 }
1107
6156e4b6
DM
1108 return $res;
1109 }});
1110
91bc7652
DM
1111__PACKAGE__->register_method ({
1112 name => 'virus',
1113 path => 'virus',
1114 method => 'GET',
1115 description => "Get Statistics about detected Viruses.",
1116 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
91bc7652
DM
1117 parameters => {
1118 additionalProperties => 0,
f194ac27 1119 properties => $default_properties->(),
91bc7652
DM
1120 },
1121 returns => {
1122 type => 'array',
1123 items => {
1124 type => "object",
1125 properties => {
1126 name => {
1127 description => 'Virus name.',
1128 type => 'string',
1129 },
1130 count => {
1131 description => 'Detection count.',
1132 type => 'integer',
1133 },
1134 },
1135 }
1136 },
1137 code => sub {
1138 my ($param) = @_;
1139
1140 my $restenv = PMG::RESTEnvironment->get();
1141 my $cinfo = $restenv->{cinfo};
1142
f194ac27 1143 my ($start, $end) = $extract_start_end->($param);
91bc7652
DM
1144
1145 my $stat = PMG::Statistic->new($start, $end);
1146 my $rdb = PMG::RuleDB->new();
1147
1148 my $res = $stat->total_virus_stat($rdb);
1149
1150 return $res;
1151 }});
1152
1153__PACKAGE__->register_method ({
67832798
DM
1154 name => 'spamscores',
1155 path => 'spamscores',
91bc7652 1156 method => 'GET',
67832798
DM
1157 description => "Get the count of spam mails grouped by spam score. " .
1158 "Count for score 10 includes mails with spam score > 10.",
91bc7652 1159 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
91bc7652
DM
1160 parameters => {
1161 additionalProperties => 0,
f194ac27 1162 properties => $default_properties->(),
91bc7652
DM
1163 },
1164 returns => {
1165 type => 'array',
1166 items => {
1167 type => "object",
1168 properties => {
1169 level => {
1170 description => 'Spam level.',
1171 type => 'string',
1172 },
1173 count => {
1174 description => 'Detection count.',
1175 type => 'integer',
1176 },
67832798
DM
1177 ratio => {
1178 description => 'Portion of overall mail count.',
1179 type => 'number',
1180 },
91bc7652
DM
1181 },
1182 }
1183 },
1184 code => sub {
1185 my ($param) = @_;
1186
1187 my $restenv = PMG::RESTEnvironment->get();
1188 my $cinfo = $restenv->{cinfo};
1189
f194ac27 1190 my ($start, $end) = $extract_start_end->($param);
91bc7652
DM
1191
1192 my $stat = PMG::Statistic->new($start, $end);
1193 my $rdb = PMG::RuleDB->new();
1194
1195 my $totalstat = $stat->total_mail_stat ($rdb);
1196 my $spamstat = $stat->total_spam_stat($rdb);
1197
d67b777f 1198 my $res = [];
91bc7652 1199
67832798 1200 my $count_in = $totalstat->{count_in};
91bc7652 1201 my $rest = $totalstat->{spamcount_in};
83081b3d
DM
1202
1203 my $levelcount = {};
91bc7652 1204 foreach my $ref (@$spamstat) {
83081b3d
DM
1205 my $level = $ref->{spamlevel} // 0;
1206 next if $level >= 10 || $level < 1;
1207 $rest -= $ref->{count} if $level >= 3;
1208 $levelcount->{$level} = $ref->{count};
91bc7652
DM
1209 }
1210
83081b3d
DM
1211 $levelcount->{0} = $totalstat->{count_in} - $totalstat->{spamcount_in};
1212 $levelcount->{10} = $rest if $rest;
1213
1214 for (my $i = 0; $i <= 10; $i++) {
67832798
DM
1215 my $count = $levelcount->{$i} // 0;
1216 my $ratio = $count_in ? $count/$count_in : 0;
1217 push @$res, { level => $i, count => $count, ratio => $ratio };
83081b3d 1218 }
91bc7652
DM
1219
1220 return $res;
1221 }});
1222
89891fa2
DM
1223__PACKAGE__->register_method ({
1224 name => 'maildistribution',
1225 path => 'maildistribution',
1226 method => 'GET',
1227 description => "Get the count of spam mails grouped by spam score. " .
1228 "Count for score 10 includes mails with spam score > 10.",
1229 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
1230 parameters => {
1231 additionalProperties => 0,
f194ac27 1232 properties => $default_properties->(),
89891fa2
DM
1233 },
1234 returns => {
1235 type => 'array',
1236 items => {
1237 type => "object",
1238 properties => {
1239 index => {
1240 description => "Hour (0-23).",
1241 type => 'integer',
1242 },
1243 count => {
1244 description => "Overall mail count (in and out).",
1245 type => 'number',
1246 },
1247 count_in => {
1248 description => "Incoming mail count.",
1249 type => 'number',
1250 },
1251 count_out => {
1252 description => "Outgoing mail count.",
1253 type => 'number',
1254 },
1255 spamcount_in => {
1256 description => "Incoming spam mails (spamcount_in + glcount + spfcount).",
1257 type => 'number',
1258 },
1259 spamcount_out => {
1260 description => "Outgoing spam mails.",
1261 type => 'number',
1262 },
1263 viruscount_in => {
1264 description => "Number of incoming virus mails.",
1265 type => 'number',
1266 },
1267 viruscount_out => {
1268 description => "Number of outgoing virus mails.",
1269 type => 'number',
1270 },
1271 bounces_in => {
1272 description => "Incoming bounce mail count (sender = <>).",
1273 type => 'number',
1274 },
1275 bounces_out => {
1276 description => "Outgoing bounce mail count (sender = <>).",
1277 type => 'number',
1278 },
1279 },
1280 },
1281 },
1282 code => sub {
1283 my ($param) = @_;
1284
1285 my $restenv = PMG::RESTEnvironment->get();
1286 my $cinfo = $restenv->{cinfo};
1287
f194ac27 1288 my ($start, $end) = $extract_start_end->($param);
89891fa2
DM
1289
1290 my $stat = PMG::Statistic->new($start, $end);
1291 my $rdb = PMG::RuleDB->new();
1292
1293 #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo);
1294
1295 my $res = $stat->traffic_stat_day_dist ($rdb);
1296
1297 return $res;
1298 }});
1299
2719ef94 1300__PACKAGE__->register_method ({
980ce907
DM
1301 name => 'rejectcount',
1302 path => 'rejectcount',
2719ef94 1303 method => 'GET',
980ce907 1304 description => "Early SMTP reject count statistic (RBL, PREGREET rejects with postscreen)",
2719ef94
DM
1305 permissions => { check => [ 'admin', 'qmanager', 'audit'] },
1306 parameters => {
1307 additionalProperties => 0,
1308 properties => $default_properties->({
1309 timespan => {
980ce907 1310 description => "Return RBL/PREGREET rejects/<timespan>, where <timespan> is specified in seconds.",
2719ef94
DM
1311 type => 'integer',
1312 minimum => 3600,
1313 maximum => 366*86400,
1314 optional => 1,
1315 default => 3600,
1316 },
1317 }),
1318 },
1319 returns => {
1320 type => 'array',
1321 items => {
1322 type => "object",
1323 properties => {
1324 index => {
1325 description => "Time index.",
1326 type => 'integer',
1327 },
1328 time => {
1329 description => "Time (Unix epoch).",
1330 type => 'integer',
1331 },
980ce907 1332 rbl_rejects => {
2719ef94 1333 description => "RBL recject count.",
980ce907
DM
1334 type => 'integer',
1335 },
1336 pregreet_rejects => {
1337 description => "PREGREET recject count.",
1338 type => 'integer',
2719ef94
DM
1339 },
1340 },
1341 },
1342 },
1343 code => sub {
1344 my ($param) = @_;
1345
1346 my $restenv = PMG::RESTEnvironment->get();
1347 my $cinfo = $restenv->{cinfo};
1348
1349 my ($start, $end) = $extract_start_end->($param);
1350
1351 my $span = $param->{timespan} // 3600;
1352
1353 my $count = ($end - $start)/$span;
1354
1355 die "too many entries - try to increase parameter 'span'\n" if $count > 5000;
1356
1357 my $stat = PMG::Statistic->new($start, $end);
1358 my $rdb = PMG::RuleDB->new();
1359
4681645a 1360 my $res = $stat->postscreen_stat_graph($rdb, $span);
2719ef94
DM
1361
1362 return $res;
1363 }});
1364
5de9374c 13651;