File Coverage

blib/lib/HTTPD/Log/Merge.pm
Criterion Covered Total %
statement 71 71 100.0
branch 14 22 63.6
condition 1 3 33.3
subroutine 10 10 100.0
pod 1 4 25.0
total 97 110 88.1


line stmt bran cond sub pod time code
1             package HTTPD::Log::Merge;
2              
3             #------------------------------------------------------------------------------
4             #
5             # Standard pragmas
6             #
7             #------------------------------------------------------------------------------
8              
9             require v5.6.0;
10              
11 2     2   2768 use strict;
  2         5  
  2         86  
12 2     2   15 use warnings;
  2         3  
  2         75  
13              
14 2     2   12 use vars qw( $VERSION );
  2         7  
  2         161  
15              
16             $VERSION = 1.00;
17              
18 2     2   2120 use IO::File;
  2         36722  
  2         312  
19 2     2   1829 use Date::Parse;
  2         19516  
  2         341  
20 2     2   2115 use HTTPD::Log::Filter;
  2         337373  
  2         1657  
21              
22             sub compare_times
23             {
24 62     62 0 80 my $self = shift;
25 166         497 ( $self->{c} ) =
26 62         211 sort { $self->{t}[$a] <=> $self->{t}[$b] }
27 62         88 @{$self->{indexes}}
28             ;
29             }
30              
31             sub new
32             {
33 2     2 0 1502 my $class = shift;
34 2         15 my %args = @_;
35              
36 2         9 my $self = bless \%args, $class;
37 2 50       25 die "logfile option required\n" unless $self->{logfile};
38 2 50       14 die "logfile option should be and arrayref\n"
39             unless ref( $self->{logfile} ) eq 'ARRAY'
40             ;
41 2 50       5 die "two or more logfiles required\n" unless @{$self->{logfile}} > 1;
  2         15  
42 2   33     17 $self->{out_fh} ||= *STDOUT;
43 6 50       401 $self->{fh} = [
44 2         6 map { IO::File->new( $_ ) or die "Can't open $_: $!\n"; }
45 2         6 @{$self->{logfile}}
46             ];
47 6 50       43 $self->{filter} = [
48             map {
49 2         7 my $filter = HTTPD::Log::Filter->new()
50             or die "Can't create filter\n"
51             ;
52 6         2043 my $format = $filter->detect_format( filename => $_ );
53 6 100       10840 my $capture = $format eq 'SQUID' ? 'time' : 'date';
54 6         29 $filter->capture( [ $capture ] );
55 6         2021 $filter;
56             }
57 2         142 @{$self->{logfile}}
58             ];
59              
60 2         9 $self->{indexes} = [ 0 .. @{$self->{logfile}}-1 ];
  2         13  
61 2         5 for ( @{$self->{indexes}} )
  2         9  
62             {
63 6         24 $self->get_line( $_ );
64             }
65 2         11 $self->compare_times();
66 2         10 return $self;
67             }
68              
69             sub get_line
70             {
71 66     66 0 90 my $self = shift;
72 66         81 my $index = shift;
73              
74 66         1948 $self->{line}[$index] = $self->{fh}[$index]->getline;
75 66 100       2407 unless ( defined $self->{line}[$index] )
76             {
77 6         49 $self->{t}[$index] = time;
78 6         14 return;
79             }
80 60 50       221 $self->{filter}[$index]->filter( $self->{line}[$index] )
81             or die
82             "Badly formatted line: $self->{line}[$index]\n",
83             $self->{filter}->re,
84             "\n"
85             ;
86 60         31279 my $time;
87 60         79 eval { $time = $self->{filter}[$index]->time };
  60         355  
88 60 100       769 unless( $time )
89             {
90 30 50       187 my $date = $self->{filter}[$index]->date
91             or die "Can't get date for $self->{logfile}[$index]\n"
92             ;
93 30         356 $time = str2time( $date );
94             }
95 60         6057 $self->{t}[$index] = $time;
96             }
97              
98             sub merge
99             {
100 2     2 1 14 my $self = shift;
101              
102 2         14 my $old_fh = select( $self->{out_fh} );
103 2         5 while ( grep { defined( $_ ) } @{$self->{line}} )
  186         453  
  62         123  
104             {
105 60         164 print $self->{line}[$self->{c}];
106 60         137 $self->get_line( $self->{c} );
107 60         140 $self->compare_times();
108             }
109 2         15 select( $old_fh );
110 2 50       307 print STDERR "\n" if $self->{verbose};
111             }
112              
113             #------------------------------------------------------------------------------
114             #
115             # Start of POD
116             #
117             #------------------------------------------------------------------------------
118              
119             =head1 NAME
120              
121             HTTPD::Log::Merge
122              
123             =head1 SYNOPSIS
124              
125             my $merge = HTTPD::Log::Merge->new(
126             logfile => \@logfiles,
127             verbose => 1,
128             out_fh => \*STDOUT,
129             );
130             $merge->merge;
131              
132             =head1 DESCRIPTION
133              
134             HTTPD::Log::Merge is a simple module for merging httpd logfiles. It takes a
135             list of log files and merges them based on the date of each entry in the
136             logfile. It works for NSCA style httpd logs (Common Log Format, Extended Log
137             Format and the like) - see L for more information on
138             supported log formats.
139              
140             =head1 CONSTRUCTOR
141              
142             The constructor for HTTPD::Log::Merge takes the following options passed as a
143             hash:
144              
145             =head2 logfile
146              
147             This option should contain an array ref of paths to httpd logfiles. The option
148             is required, and there need to be two or more logfiles.
149              
150             =head2 out_fh
151              
152             A filehandle to output merged logfile to. Defaults to STDOUT.
153              
154             =head2 verbose
155              
156             Print interesting stuff to STDERR.
157              
158             =head1 METHODS
159              
160             =head2 merge
161              
162             Does exactly what it says on the can!
163              
164             =head1 AUTHOR
165              
166             Ave Wrigley
167              
168             =head1 COPYRIGHT
169              
170             Copyright (c) 2001 Ave Wrigley. All rights reserved. This program is free
171             software; you can redistribute it and/or modify it under the same terms as Perl
172             itself.
173              
174             =cut
175              
176             #------------------------------------------------------------------------------
177             #
178             # End of POD
179             #
180             #------------------------------------------------------------------------------
181              
182             # True ...
183              
184             1;