Log::Deep::Line - Encapsulates one line from a log file


Log-Deep documentation Contained in the Log-Deep distribution.

Index


Code Index:

NAME

Top

Log::Deep::Line - Encapsulates one line from a log file

VERSION

Top

This documentation refers to Log::Deep::Line version 0.3.1.

SYNOPSIS

Top

   use Log::Deep::Line;

   # create a new line object
   my $line = Log::Deep::Line->new( { show => {}, ... }, $line_text, $file );

DESCRIPTION

Top

SUBROUTINES/METHODS

Top

new ( $options, $line, $file )

Param: $options - hash ref - Configuration options for this line

Param: $line - string - The original text of the log line

Param: $file - Log::Deep::File - Object continuing the log file of interest

Return: Log::Deep::Line - New log deep object

Description: Create a new object from a line ($line) of the log file ($file)

parse ( $line, $file )

Param: $line - string - The original text of the log line

Param: $file - Log::Deep::File - Object continuing the log file of interest

Description: Parses the log line

id ( )

Return: The session id for this log line

Description: Gets the session id for the log line. Will be undef if the log line did not parse correctly.

colour ( [ $colour ] )

Param: $colour - string - A string containing the foreground and background colour to use for this line. The format is 'colour on_colour'.

Return: string - The colour set for this log line

Description: Gets the current colour for this log line and optionally sets the colour.

show ( )

Return: bool - True if the log line should be shown.

Description: Determines if the log line should be shown.

text ( )

Return: The processed text of the line (sans the DATA section).

Description: Processes log line for out putting to a terminal.

data ( )

Return: The contents of the DATA section as specified by the display option

Description: Out puts the DATA section of the log line.

data_missing ($field, $data)

Param: $field - string - The name of the field of data

Param: $data - any - All the data

Return: Array - all the lines to be out put

Description: Returns that there was no data or that the data was undefined

data_sub_fields ($field, $data)

Param: $field - string - The name of the field of data

Param: $data - any - The data being displayed

Return: Array - all the lines to be out put

Description: Shows only the sub keys of $data that are defined to be displayed

data_scalar ($field, $data)

Param: $field - string - The name of the field of data

Param: $data - any - The data being displayed

Return: Array - all the lines to be out put

Description: Just shows the simple data

DIAGNOSTICS

Top

CONFIGURATION AND ENVIRONMENT

Top

DEPENDENCIES

Top

INCOMPATIBILITIES

Top

BUGS AND LIMITATIONS

Top

There are no known bugs in this module.

Please report problems to Ivan Wills (ivan.wills@gmail.com).

Patches are welcome.

AUTHOR

Top

Ivan Wills - (ivan.wills@gmail.com)

LICENSE AND COPYRIGHT

Top


Log-Deep documentation Contained in the Log-Deep distribution.

package Log::Deep::Line;

# Created on: 2009-05-30 21:19:07
# Create by:  Ivan Wills
# $Id$
# $Revision$, $HeadURL$, $Date$
# $Revision$, $Source$, $Date$

use strict;
use warnings;
use version;
use Carp;
use Readonly;
use Data::Dumper qw/Dumper/;
use English qw/ -no_match_vars /;
use base qw/Exporter/;
use Term::ANSIColor;

our $VERSION     = version->new('0.3.1');
our @EXPORT_OK   = qw//;
our %EXPORT_TAGS = ();

Readonly my $LEVEL_COLOURS => {
		info     => '',
		message  => '',
		debug    => '',
		warn  => 'yellow',
		error    => 'red',
		fatal    => 'bold red',
		security => '',
	};

sub new {
	my $caller = shift;
	my $class  = ref $caller ? ref $caller : $caller;
	my ($self, $line, $file) = @_;

	if (ref $self ne 'HASH') {
		$file = $line;
		$line = $self;
		$self = {};
	}

	bless $self, $class;

	$self->parse($line, $file) if $line && $file;

	return $self;
}

sub parse {
	my ($self, $line, $file) = @_;

	# split the line into 5 parts
	# TODO this might cause some problems if the message happens to have a \, in it
	my @log = split /(?<!\\),/, $line, 5;

	if ( @log != 5 && $self->{verbose} ) {
		# get the file name and line number
		my $name    = $file->{name};
		my $line_no = $file->{handle}->input_line_number;

		# output the warnings about the bad line
		warn "The log $name line ($line_no) did not contain 4 columns! Got ". (scalar @log) . " columns\n";
		warn $line if $self->{verbose} > 1;
	}

	# un-quote the individual columns
	for my $col (@log) {
		$col =~ s/ \\ \\ /\\/gxms;
		$col =~ s/ (?<!\\) \\n /\n/gxms;
		$col =~ s/ (?<!\\) \\, /,/gxms;
	}

	# re-process the data so we can display what is needed.
	my $DATA;
	if ( $log[-1] =~ /;$/xms && length $log[-1] < 1_000_000 ) {
		local $SIG{__WARN__} = sub {};
		eval $log[-1];  ## no critic
	}
	else {
		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";
		$DATA = {};
	}

	$self->{date}    = $log[0];
	$self->{session} = $log[1];
	$self->{level}   = $log[2];
	$self->{message} = $log[3];
	$self->{DATA}    = $DATA;

	$self->{file}     = $file;
	$self->{position} = $file->{handle} ? tell $file->{handle} : 0;

	return $self;
}

sub id { $_[0]->{session} };

sub colour {
	my ($self, $colour) = @_;

	if ($colour) {
		my ($foreground, $background) = $colour =~ /^ ( \w+ ) \s+ on_ ( \w+ ) $/xms;
		$self->{fg} = $foreground;
		$self->{bg} = $background;
	}

	return "$self->{fg} on_$self->{bg}";
}

sub show {
	my ($self) = @_;

	# TODO add real filtering body here
	return 0 if !$self->{date} || !$self->{session};

	return 1;
}

sub text {
	my ($self) = @_;
	my $out = '';

#	my $last = $self->{last_line_time} || 0;
#	my $now  = time;
#
#	# check if we are putting line breaks when there is a large time between followed file output
#	if ( $self->{breaks} && $now > $last + $self->{short_break} ) {
#		my $lines = $now > $last + $self->{long_break} ? $self->{long_lines} : $self->{short_lines};
#		$out .= "\n" x $lines;
#	}
#	$self->{last_line_time} = $now;

	# construct the log line determining colours to use etc
	my $level = $self->{mono} ? $self->{level} : colored $self->{level}, $LEVEL_COLOURS->{$self->{level}};
	$out .= $self->{mono} ? '' : color $self->colour();
	$out .= "[$self->{date}]";

	if ( !$self->{verbose} ) {
		# add the session id if the user cares
		$out .= " $self->{session}";
	}
	if ( !$self->{mono} ) {
		# reset the colour if we are not in mono
		$out .= color 'reset';
	}

	# finish constructing the log line
	$out .= " $level - $self->{message}\n";

	return $out;
}

sub data {
	my ($self) = @_;
	my $display = $self->{display};
	my @fields;
	my @out;
	my $data = $self->{DATA};

	$display->{data} = defined $display->{data} ? $display->{data} : 1;

	# check for any fields that should be displayed
	FIELD:
	for my $field ( sort keys %{ $display } ) {
		push @out,
			  $display->{$field} eq 0                                      ? ()
			: !defined $data->{$field}                                     ? data_missing($field, $data)
			: ref $display->{$field} eq 'ARRAY' || $display->{$field} ne 1 ? data_sub_fields($field, $data->{$field})
			: !ref $data->{$field}                                         ? data_scalar($field, $data->{$field})
			: $field ne 'data' || %{ $data->{$field} }                     ? $self->{dump}->Names($field)->Data($data->{$field})->Out()
			:                                                                ();
	}

	return @out;
}

sub data_missing {
	my ( $self, $field, $data ) = @_;
	return if ref $field;
	return if $field eq 'data';
	return "\$$field = " . (exists $data->{field} ? 'undef' : 'missing') . "\n";
}

sub data_sub_fields {
	my ( $self, $field, $data ) = @_;
	my $display = $self->{display};
	my @out;

	# select the specified sub keys of $field
	if ( !ref $display->{$field} ) {
		# convert the display field into an array so that we can select it's sub fields
		$display->{$field} = [ split /,/, $display->{$field} ];
	}

	# out put each named sub field of $field
	for my $sub_field ( @{ $display->{$field} } ) {
		push @out, $self->{dump}->Names( $field . '_' . $sub_field )->Data( $data->{$sub_field} )->Out();
	}

	return @out;
}

sub data_scalar {
	my ( $self, $field, $data ) = @_;

	# out put scalar values with out the DDS formatting
	my $out .= "\$$field = " . ( defined $data ? $data : 'undef' );

	# safely guarentee that there is a new line at the end of this line
	chomp $out;
	$out .= "\n";
	return $out;
}

1;

__END__