File Coverage

blib/lib/Log/Deep/Line.pm
Criterion Covered Total %
statement 59 110 53.6
branch 7 50 14.0
condition 5 18 27.7
subroutine 12 20 60.0
pod 10 10 100.0
total 93 208 44.7


line stmt bran cond sub pod time code
1             package Log::Deep::Line;
2              
3             # Created on: 2009-05-30 21:19:07
4             # Create by: Ivan Wills
5             # $Id$
6             # $Revision$, $HeadURL$, $Date$
7             # $Revision$, $Source$, $Date$
8              
9 3     3   26785 use strict;
  3         4  
  3         102  
10 3     3   14 use warnings;
  3         4  
  3         74  
11 3     3   586 use version;
  3         1519  
  3         14  
12 3     3   184 use Carp;
  3         4  
  3         197  
13 3     3   682 use Readonly;
  3         2806  
  3         147  
14 3     3   16 use Data::Dumper qw/Dumper/;
  3         3  
  3         126  
15 3     3   484 use English qw/ -no_match_vars /;
  3         3949  
  3         16  
16 3     3   1230 use base qw/Exporter/;
  3         4  
  3         253  
17 3     3   2310 use Term::ANSIColor;
  3         20027  
  3         3788  
18              
19             our $VERSION = version->new('0.3.5');
20             our @EXPORT_OK = qw//;
21             our %EXPORT_TAGS = ();
22              
23             Readonly my $LEVEL_COLOURS => {
24             info => '',
25             message => '',
26             debug => '',
27             warn => 'yellow',
28             error => 'red',
29             fatal => 'bold red',
30             security => '',
31             };
32              
33             sub new {
34 1     1 1 13 my $caller = shift;
35 1 50       4 my $class = ref $caller ? ref $caller : $caller;
36 1         3 my ($self, $line, $file) = @_;
37              
38 1 50       5 if (ref $self ne 'HASH') {
39 1         2 $file = $line;
40 1         1 $line = $self;
41 1         3 $self = {};
42             }
43              
44 1         2 bless $self, $class;
45              
46 1 50 33     7 $self->parse($line, $file) if $line && $file;
47              
48 1         5 return $self;
49             }
50              
51             sub parse {
52 4     4 1 3586 my ($self, $line, $file) = @_;
53              
54             # split the line into 5 parts
55             # TODO this might cause some problems if the message happens to have a \, in it
56 4         28 my @log = split /(?
57              
58 4 0 33     14 if ( @log != 5 && $self->{verbose} ) {
59             # get the file name and line number
60 0         0 my $name = $file->{name};
61 0         0 my $line_no = $file->{handle}->input_line_number;
62              
63             # output the warnings about the bad line
64 0         0 warn "The log $name line ($line_no) did not contain 4 columns! Got ". (scalar @log) . " columns\n";
65 0 0       0 warn $line if $self->{verbose} > 1;
66             }
67              
68             # un-quote the individual columns
69 4         6 for my $col (@log) {
70 20         19 $col =~ s/ \\ \\ /\\/gxms;
71 20         20 $col =~ s/ (?
72 20         23 $col =~ s/ (?
73             }
74              
75             # re-process the data so we can display what is needed.
76 4         5 my $DATA;
77 4 50 33     25 if ( $log[-1] =~ /;$/xms && length $log[-1] < 1_000_000 ) {
78 4     0   24 local $SIG{__WARN__} = sub {};
79 4         225 eval $log[-1]; ## no critic
80             }
81             else {
82 0 0       0 warn '' . (length $log[-1] < 1_000_000 ? 'The data is too large to process' : 'There appears to be a problem with the data' ) . ' on line ' . $file->{handle}->input_line_number . "\n";
83 0         0 $DATA = {};
84             }
85              
86 4         15 $self->{date} = $log[0];
87 4         5 $self->{session} = $log[1];
88 4         7 $self->{level} = $log[2];
89 4         5 $self->{message} = $log[3];
90 4         23 $self->{DATA} = $DATA;
91              
92 4         6 $self->{file} = $file;
93 4 50       12 $self->{position} = $file->{handle} ? tell $file->{handle} : 0;
94              
95 4         10 return $self;
96             }
97              
98 0     0 1 0 sub id { $_[0]->{session} };
99              
100             sub colour {
101 0     0 1 0 my ($self, $colour) = @_;
102              
103 0 0       0 if ($colour) {
104 0         0 my ($foreground, $background) = $colour =~ /^ ( \w+ ) \s+ on_ ( \w+ ) $/xms;
105 0         0 $self->{fg} = $foreground;
106 0         0 $self->{bg} = $background;
107             }
108              
109 0         0 return "$self->{fg} on_$self->{bg}";
110             }
111              
112             sub show {
113 2     2 1 6 my ($self) = @_;
114              
115             # TODO add real filtering body here
116 2 100 66     12 return 0 if !$self->{date} || !$self->{session};
117              
118 1         4 return 1;
119             }
120              
121             sub text {
122 0     0 1   my ($self) = @_;
123 0           my $out = '';
124              
125             # my $last = $self->{last_line_time} || 0;
126             # my $now = time;
127             #
128             # # check if we are putting line breaks when there is a large time between followed file output
129             # if ( $self->{breaks} && $now > $last + $self->{short_break} ) {
130             # my $lines = $now > $last + $self->{long_break} ? $self->{long_lines} : $self->{short_lines};
131             # $out .= "\n" x $lines;
132             # }
133             # $self->{last_line_time} = $now;
134              
135             # construct the log line determining colours to use etc
136 0 0         my $level = $self->{mono} ? $self->{level} : colored $self->{level}, $LEVEL_COLOURS->{$self->{level}};
137 0 0         $out .= $self->{mono} ? '' : color $self->colour();
138 0           $out .= "[$self->{date}]";
139              
140 0 0         if ( !$self->{verbose} ) {
141             # add the session id if the user cares
142 0           $out .= " $self->{session}";
143             }
144 0 0         if ( !$self->{mono} ) {
145             # reset the colour if we are not in mono
146 0           $out .= color 'reset';
147             }
148              
149             # finish constructing the log line
150 0           $out .= " $level - $self->{message}\n";
151              
152 0           return $out;
153             }
154              
155             sub data {
156 0     0 1   my ($self) = @_;
157 0           my $display = $self->{display};
158 0           my @fields;
159             my @out;
160 0           my $data = $self->{DATA};
161              
162 0 0         $display->{data} = defined $display->{data} ? $display->{data} : 1;
163              
164             # check for any fields that should be displayed
165             FIELD:
166 0           for my $field ( sort keys %{ $display } ) {
  0            
167             push @out,
168             $display->{$field} eq 0 ? ()
169             : !defined $data->{$field} ? data_missing($field, $data)
170             : ref $display->{$field} eq 'ARRAY' || $display->{$field} ne 1 ? data_sub_fields($field, $data->{$field})
171             : !ref $data->{$field} ? data_scalar($field, $data->{$field})
172 0 0 0       : $field ne 'data' || %{ $data->{$field} } ? $self->{dump}->Names($field)->Data($data->{$field})->Out()
    0 0        
    0          
    0          
    0          
173             : ();
174             }
175              
176 0           return @out;
177             }
178              
179             sub data_missing {
180 0     0 1   my ( $self, $field, $data ) = @_;
181 0 0         return if ref $field;
182 0 0         return if $field eq 'data';
183 0 0         return "\$$field = " . (exists $data->{field} ? 'undef' : 'missing') . "\n";
184             }
185              
186             sub data_sub_fields {
187 0     0 1   my ( $self, $field, $data ) = @_;
188 0           my $display = $self->{display};
189 0           my @out;
190              
191             # select the specified sub keys of $field
192 0 0         if ( !ref $display->{$field} ) {
193             # convert the display field into an array so that we can select it's sub fields
194 0           $display->{$field} = [ split /,/, $display->{$field} ];
195             }
196              
197             # out put each named sub field of $field
198 0           for my $sub_field ( @{ $display->{$field} } ) {
  0            
199 0           push @out, $self->{dump}->Names( $field . '_' . $sub_field )->Data( $data->{$sub_field} )->Out();
200             }
201              
202 0           return @out;
203             }
204              
205             sub data_scalar {
206 0     0 1   my ( $self, $field, $data ) = @_;
207              
208             # out put scalar values with out the DDS formatting
209 0 0         my $out .= "\$$field = " . ( defined $data ? $data : 'undef' );
210              
211             # safely guarentee that there is a new line at the end of this line
212 0           chomp $out;
213 0           $out .= "\n";
214 0           return $out;
215             }
216              
217             1;
218              
219             __END__