Drop grml-postfix
[grml-scripts.git] / usr_sbin / PrintAnalyzer
1 #!/usr/bin/perl -w
2 #***************************************************************************
3 #    PrintAnalyzer
4 #    Generate some stats from cups page_log file
5 #    copyright            : (C) 1999 - 2003 by Thies Moeller                         
6 #    email                : moeller@tu-harburg.de 
7 #***************************************************************************
8
9 #***************************************************************************
10 #*                                                                         *
11 #*   This program is free software; you can redistribute it and/or modify  *
12 #*   it under the terms of the GNU General Public License as published by  *
13 #*   the Free Software Foundation; either version 2 of the License, or     *
14 #*   (at your option) any later version.                                   * 
15 #*                                                                         *
16 #***************************************************************************
17 use strict;
18 use warnings;
19 use POSIX qw(strftime);
20 use Time::Local;
21 use Getopt::Std;
22
23
24
25 ##############
26 # edit place of your page_log file or give it as option "-f filename"
27 ##############
28 my %opt;
29 my $PAGE_LOG_FILE;
30
31 getopt("f:q",\%opt);
32
33 if (exists $opt{"f"}) { $PAGE_LOG_FILE = $opt{f};}
34 else {$PAGE_LOG_FILE = "/var/log/cups/page_log";}
35
36 ##############
37 # edit start and end of normal work time
38 # activity outside this interval will be marked with an "!" 
39 # to disable set WorkStart to 0 and WorkEnd to 24
40 ##############
41 my $WorkStart = 07;
42 my $WorkEnd   = 22;
43
44
45 ############################ nothing to modify below this line ##############
46
47 my %userRequests  = ();
48 my %userPages     = ();
49 my %hourRequests  = ();
50 my %dateRequests  = ();
51 my %datePages     = ();
52 my %pageRequests  = ();
53 my %queueRequests = ();
54 my %queuePages    = ();
55 my %pageHeu       = ();
56 my %copyRequests  = ();
57 my %logline       = ();
58 my %lastlogline   = ();
59 my %billingStats  = ();
60 my %queueUserStats  = ();
61 my $totalReq      = 0;
62 my $totalPages    = 0;
63
64 sub DateCompare
65 {
66             my $date1 = substr($a, 6, 2) * 1024;  # Years
67             my $date2 = substr($b, 6, 2) * 1024;
68
69             $date1 += substr($a,3,2) * 64;       # Months
70             $date2 += substr($b,3,2) * 64;
71
72             $date1 += substr($a, 0, 2);          # Days
73             $date2 += substr($b, 0, 2);
74             return ($date1 <=> $date2);
75 }
76
77
78 sub tzdiff2sec
79 {
80 ## this method is copied from LogReport Time.pm
81 ## Copyright (C) 2000-2002 Stichting LogReport Foundation LogReport@LogReport.org
82
83     die "tzdiff2sec needs 1 arg\n"
84           unless @_ == 1;
85
86     # e.g. +0100 or -0900 ; +hh:mm, +hhmm, or +hh
87     my ( $sign, $hour, $min ) = $_[0] =~ /^([+-])?(\d\d):?(\d\d)?$/
88             or die "invalid tzdiff format: $_[0]. It must looks like +0100 or -01:00\n";
89     $sign ||= "+";
90     $hour ||= 0;
91     $min  ||= 0;
92     my $sec = $hour * 60 * 60 + $min * 60;
93     $sec *= -1 if $sign eq '-';
94     return $sec;
95 }
96
97 sub getMonth
98 {
99         my $AllMonths= 'JanFebMarAprMayJunJulAugSepOctNovDec';
100         my $month = shift(@_);
101         return index($AllMonths, $month)/3;
102 }
103
104
105
106 sub DateTime2Epoch
107 {
108     my ($day,$month,$year,$hour,$min,$sec,$tz)=
109             unpack'@1 A2 @4 A3 @8 A4 @13 A2 @16 A2 @19 A2 @22 A5', shift();
110
111     my $epoch=timegm  $sec , 
112                       $min , 
113                       $hour, 
114                       $day,  
115                       getMonth($month),       
116                       $year;  
117     return $epoch - tzdiff2sec($tz);
118 }
119
120 sub PrintDayLog
121 {
122         my $dateReq;
123
124 ############# Output Form ################
125 format DAYLOG_TOP =
126
127 Daily Usage
128 Date               %Requests        Pages
129 -----------------------------------------
130 .
131
132 format DAYLOG =
133 @<<<<<<<<<<<<<     @>>>>>>>     @>>>>>>>   
134 $dateReq,$dateRequests{$dateReq},$datePages{$dateReq}
135 .
136 ############# Output Form ################
137
138
139         $-=0;
140         $~="DAYLOG";
141         $^="DAYLOG_TOP";
142         foreach $dateReq (sort DateCompare keys %dateRequests)
143             {
144             #printf("Monat %d\n",getMonth($dateReq));
145             write;
146             }
147 }
148
149 sub PrintUserLog
150 {
151         my $userReq;
152         my $pageperjob;
153
154 ############# Output Form ################
155 format USERLOG_TOP =
156 PrinterAccounting
157 Username            Requests      Pages   Pages/Request
158 --------------------------------------------------------
159 .
160
161 format USERLOG =
162 @<<<<<<<<<<<<<<<<<< @>>>>>>>   @>>>>>>>   @>>>>>>>>
163 $userReq,           $userRequests{$userReq}, $userPages{$userReq}, $pageperjob
164 .
165 ############# Output Form ################
166
167         $-=0;
168         $~="USERLOG";
169         $^="USERLOG_TOP";
170         foreach $userReq (sort { $userPages{$b} <=> $userPages{$a}} keys %userRequests)
171             {
172             $pageperjob = sprintf("%5d", POSIX::ceil($userPages{$userReq} / $userRequests{$userReq}));
173             write ;
174             }
175 }
176
177 sub PrintHourLog
178 {
179         my $hourReq;
180         my $outOfWorkingTime;
181
182 ############# Output Form ################
183 format HOURLOG_TOP =
184 Hour Usage
185 Hour        Requests     
186 ---------------------
187 .
188
189 format HOURLOG =
190 @<@<<<<<     @>>>>>>>  
191 $outOfWorkingTime,$hourReq,$hourRequests{$hourReq}
192 .
193 ############# Output Form ################
194
195
196         $-=0;
197         $~="HOURLOG";
198         $^="HOURLOG_TOP";
199
200          foreach $hourReq (sort {$a <=> $b} keys %hourRequests)
201             {
202             if($hourReq <$WorkStart  || $hourReq > $WorkEnd)
203             {
204                     if($hourRequests{$hourReq} == 0)
205                     {
206                             next;
207                     }
208                     else
209                     {
210                             $outOfWorkingTime = "!";
211                     }
212             }
213             else
214             {
215                    $outOfWorkingTime = " ";
216             }
217             write;
218             }
219
220 }
221
222 sub PrintRequestSize
223 {
224         my $pageReq;
225         my %pageHeu;
226         my $pageHeuK;
227         my $pageperHeu; 
228 ############# Output Form ################
229
230 format REQUESTLOG_TOP =
231 Heuristic
232 JobSize         %Requests
233 ---------------------------
234 .
235
236 format REQUESTLOG =
237 @|||||||||||    @>>>>>>>>
238 $pageHeuK,$pageperHeu
239 .
240 ############# Output Form ################
241
242         # sammeln der Daten
243         foreach $pageReq (sort {$a <=> $b}  keys %pageRequests)
244             {
245             if($pageReq >0 && $pageReq <=10)
246                     {$pageHeu{"1.    0-10"}+=$pageRequests{$pageReq}};
247             if ($pageReq >10 && $pageReq <=20)
248                    {$pageHeu{ "2.   20-30"}+=$pageRequests{$pageReq}};
249             if ($pageReq >20 && $pageReq <=30)
250                    {$pageHeu{ "3.   30-40"}+=$pageRequests{$pageReq}};
251             if ($pageReq >40 && $pageReq <=50)
252                    {$pageHeu{ "4.   40-50"}+=$pageRequests{$pageReq}};
253             if ($pageReq >50 && $pageReq <=100)
254                    {$pageHeu{ "5.  50-100"}+=$pageRequests{$pageReq}};
255             if ($pageReq >100 && $pageReq <=200)
256                    {$pageHeu{ "6. 100-200"}+=$pageRequests{$pageReq}};
257             if ($pageReq >200 )
258                    {$pageHeu{ "7. 200-   "}+=$pageRequests{$pageReq}};
259         }
260         $-=0;
261         $~="REQUESTLOG";
262         $^="REQUESTLOG_TOP";
263
264         foreach $pageHeuK (sort keys %pageHeu)
265             {
266              $pageperHeu = sprintf("%5.2f", 100*$pageHeu{$pageHeuK}/$totalReq);
267              write;
268         }
269 }
270
271 sub PrintCopySize
272 {
273         my $copyReq;
274         my %copyHeu;
275         my $copyHeuK;
276         my $copyperheu;
277 ############# Output Form ################
278 format COPY_TOP =
279 Heuristic
280 Copies           %Requests
281 ---------------------------
282 .
283 format COPYLOG =
284 @|||||||||||||    @>>>>>>>>
285 $copyHeuK,$copyperheu
286 .
287 ############# Output Form ################
288
289         
290         foreach $copyReq (sort {$a <=> $b}  keys %copyRequests)
291             {
292             if($copyReq == 1 )
293                     {$copyHeu{" 1.    single"}+=$copyRequests{$copyReq}};
294             if($copyReq == 2)
295                     {$copyHeu{" 2.    2     "}+=$copyRequests{$copyReq}};                   
296             if($copyReq == 3)
297                     {$copyHeu{" 3.    3     "}+=$copyRequests{$copyReq}};                                   
298             if($copyReq == 4)
299                     {$copyHeu{" 4.    4     "}+=$copyRequests{$copyReq}};                                                   
300             if($copyReq >=5 && $copyReq <=10)
301                     {$copyHeu{" 5.    5-10  "}+=$copyRequests{$copyReq}};                   
302             if ($copyReq >10 && $copyReq <=20)
303                    {$copyHeu{ " 6.   20-30  "}+=$copyRequests{$copyReq}};
304             if ($copyReq >20 && $copyReq <=30)
305                    {$copyHeu{ " 7.   30-40  "}+=$copyRequests{$copyReq}};
306             if ($copyReq >40 && $copyReq <=50)
307                    {$copyHeu{ " 8.   40-50  "}+=$copyRequests{$copyReq}};
308             if ($copyReq >50 && $copyReq <=100)
309                    {$copyHeu{ " 9.  50-100  "}+=$copyRequests{$copyReq}};
310             if ($copyReq >100 && $copyReq <=200)
311                    {$copyHeu{ "10. 100-200  "}+=$copyRequests{$copyReq}};
312             if ($copyReq >200 )
313                    {$copyHeu{ "11. 200-   "}+=$copyRequests{$copyReq}};
314         }
315         $-=0;
316         $~="COPYLOG";
317         $^="COPY_TOP";
318         foreach $copyHeuK (sort keys %copyHeu)
319             {
320              $copyperheu = sprintf("%5.2f", 100*$copyHeu{$copyHeuK}/$totalReq);
321              write;
322         }
323 }
324
325 sub PrintQueueLog
326 {
327         my $queueReq;
328         my $reqperqueue;
329         my $pagepermin;
330         my $pageperqueue ;
331 ############# Output Form ################
332 format QUEUELOG_TOP =
333 Queue Heuristic
334 Queue                      %Requests        %Pages     Pages
335 --------------------------------------------------------------
336 .
337
338 format QUEUELOG =
339 @>>>>>>>>>>>>>>>>>>>>>     @>>>>>>>     @>>>>>>>      @>>>>>>>>
340 $queueReq,$reqperqueue,$pageperqueue,$queuePages{$queueReq}
341 .
342 ############# Output Form ################
343
344
345         $-=0;
346         $~="QUEUELOG";
347         $^="QUEUELOG_TOP";
348     foreach $queueReq (sort { $queuePages{$b} <=> $queuePages{$a} } keys %queuePages)
349      {
350         $reqperqueue  = sprintf("%5.2f", 100*$queueRequests{$queueReq}/$totalReq);
351         $pageperqueue = sprintf("%5.2f", 100*$queuePages{$queueReq}/$totalPages);
352         write;
353     }
354
355 }
356
357 sub PrintBillingLog
358 {
359         my $billing;
360         my $pageperbilling ;
361         my $billinguser;
362
363 ############# Output Form ################
364 format BILLINGLOG_TOP =
365 Billing Heuristic
366 Billing                           Pages
367 --------------------------------------------------------------
368 .
369
370 format BILLINGLOG =
371 @<<<<<<<<<<<<<<<<<<<<<<<<        @>>>>>>>>
372 $billing,$pageperbilling
373 .
374
375 format BILLINGUSERLOG =
376 |- @>>>>>>>>>>>>>>>>>>>>>        @>>>>>>>>
377 $billinguser,$pageperbilling
378 .
379 ############# Output Form ################
380
381
382         $-=0;
383         $~="BILLINGLOG";
384         $^="BILLINGLOG_TOP";
385     foreach $billing (sort keys %billingStats)
386      {
387         $pageperbilling = $billingStats{$billing}{"total_pages"};
388         $~="BILLINGLOG";
389         write;
390         $~="BILLINGUSERLOG";
391         foreach $billinguser ( sort {$billingStats{$billing}{"user"}{$b} <=> $billingStats{$billing}{"user"}{$a}} keys %{$billingStats{$billing}{"user"}})
392         {
393           $pageperbilling = $billingStats{$billing}{"user"}{$billinguser};
394           write;                
395         }
396     }
397
398 }
399
400 sub PrintQueueUserLog
401 {
402         my $queue;
403         my $pageperqueue;
404         my $queueuser;
405
406 ############# Output Form ################
407 format QUEUEUSER_TOP =
408 Queue-User
409 Queue                            Pages
410 --------------------------------------------------------------
411 .
412
413 format QUEUENAME =
414 @<<<<<<<<<<<<<<<<<<<<<<<<        
415 $queue
416 .
417
418 format QUEUEUSERLOG =
419 |- @>>>>>>>>>>>>>>>>>>>>>        @>>>>>>>>
420 $queueuser,$pageperqueue
421 .
422 ############# Output Form ################
423
424
425         $-=0;
426         $~="QUEUENAME";
427         $^="QUEUEUSER_TOP";
428     foreach $queue (sort keys %queueUserStats)
429      {
430         $~="QUEUENAME";
431         write;
432         $~="QUEUEUSERLOG";
433         foreach $queueuser ( sort {$queueUserStats{$queue}{$b} <=> $queueUserStats{$queue}{$a}} keys %{$queueUserStats{$queue}})
434         {
435           $pageperqueue = $queueUserStats{$queue}{$queueuser};
436           write;                
437         }
438     }
439
440 }
441
442 sub HandleNewJob
443 {
444  my $realpages  = $lastlogline{num_pages}*$lastlogline{copies}; 
445  my $hourstring = POSIX::strftime "%H", localtime($lastlogline{time}) ;
446  my $daystring  = POSIX::strftime "%d/%m/%y", localtime($lastlogline{time}) ;
447  
448  $userRequests{$lastlogline{user}}++;
449  $userPages{$lastlogline{user}}+=$realpages;
450  $dateRequests{$daystring}++;
451  $datePages{$daystring}+=$realpages;
452  $pageRequests{$realpages}++;
453  $queueRequests{$lastlogline{printer}}++;
454  $queuePages{$lastlogline{printer}}+=$realpages;
455  $hourRequests{$hourstring}++;         
456  $copyRequests{$lastlogline{copies}}++;
457  $billingStats{$lastlogline{billing}}{"user"}{$lastlogline{user}}     += $realpages;
458  $billingStats{$lastlogline{billing}}{"printer"}{$lastlogline{printer}}  += $realpages;
459  $billingStats{$lastlogline{billing}}{"total_pages"}      += $realpages;
460  $queueUserStats{$lastlogline{printer}}{$lastlogline{user}} += $realpages;
461
462  $totalReq++;
463  $totalPages+=$realpages;
464 }
465
466 sub InitHourHistogram
467 {
468  my $i;
469  for ($i = 0 ; $i <=24 ; $i++)
470  {
471          my $hourstring = sprintf("%02d", $i);
472          $hourRequests{$hourstring}=0;
473  }
474 }
475
476 # main
477 open(PAGELOG,"$PAGE_LOG_FILE") || die "Can't open pagelog file $PAGE_LOG_FILE";
478
479
480 #initialize the hourhistogram
481 InitHourHistogram;
482
483 while(<PAGELOG>)
484 {
485      my $time;
486      my $pagenum;
487      %logline = ();
488      chomp();
489     ($logline{printer},
490      $logline{user},
491      $logline{jobid},
492      $time,
493      $pagenum,
494      $logline{copies},
495      $logline{billing}) =
496         ($_ =~ /^(.*)\s(.*)\s(\d+)\s(\[.*\])\s(\d+)\s(\d+)\s(.*)$/)
497         or do {
498         if(! exists $opt{"q"}) {print STDERR "Cannot convert $_ \n";}
499         next;
500         };
501     # downcase username because of samba
502     $logline{user}=~ tr/A-Z/a-z/;
503     # handle empty user
504     if ($logline{user} eq "") {
505             $logline{user}="TestPages";
506     }
507     # handle empty billing code
508     if ($logline{billing} eq "") {
509             $logline{billing}="-none-";
510     }
511     my $endtime = DateTime2Epoch( $time );
512
513     if ( ! defined $lastlogline{jobid} ||  $lastlogline{jobid} ne $logline{jobid} )
514         {
515             # new job;
516             $logline{num_pages} = 1;
517             $logline{time} = $endtime;
518             if ( defined $lastlogline{jobid} ) {
519                  HandleNewJob;
520                  };
521         } else {
522             # same job; update info
523             $logline{num_pages} = $lastlogline{num_pages} + 1;
524             $logline{time} = $lastlogline{time};
525         }
526         %lastlogline= %logline;
527
528 }
529 close(PAGELOG);
530
531 # handle last job
532 if ( defined $lastlogline{jobid} ) {
533      HandleNewJob;
534      }
535
536
537
538 PrintQueueLog;
539 PrintQueueUserLog;
540 PrintRequestSize;
541 PrintCopySize;
542 PrintBillingLog;
543 PrintUserLog;
544 PrintHourLog;
545 PrintDayLog;
546
547 __END__
548
549 =head1 NAME
550
551 PrintAnalyzer - create statistics from CUPS page_log file
552
553 =head1 SYNOPSIS
554
555  PrintAnalyzer [-f filename][-q] 
556
557 =head1 DESCRIPTION
558
559 This Tool generates statistics from the CUPS page_log file.
560
561 Features:
562
563 =over 8
564
565 =item Queue usage
566
567 =item Pages per user per queue (Accounting)
568
569 =item Jobsize histogram (all queues in one)
570
571 =item Number of copies histogram (all queues in one)
572
573 =item Jobs/Pages per hour (all queues in one)
574
575 =item Jobs/Pages per day (all queues in one)
576
577 =item Jobs/Pages per user (all queues in one)
578
579 =item Pages per Billingcode (all queues in one)
580
581 =item Pages per User per Billingcode (all queues in one)
582
583 =back   
584
585 =head1 OPTIONS AND ARGUMENTS
586
587 =over 8
588
589 =item B<-f> filename
590
591 Location of the page_log file
592
593 =item B<-q>
594
595 Quiet operation
596
597 =back
598
599 =head1 SEE ALSO
600
601  http://www.cups.org
602
603 =head1 AUTHOR
604
605  Thies Moeller
606
607 =cut
608
609
610
611
612
613