/usr/share/httpry/plugins/common_log.pm is in httpry-tools 0.1.7-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | #
# ----------------------------------------------------
# httpry - HTTP logging and information retrieval tool
# ----------------------------------------------------
#
# Copyright (c) 2005-2012 Jason Bittel <jason.bittel@gmail.com>
#
package common_log;
use POSIX qw(strftime mktime);
# -----------------------------------------------------------------------------
# GLOBAL VARIABLES
# -----------------------------------------------------------------------------
my %requests = ();
my $fh;
my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
# -----------------------------------------------------------------------------
# Plugin core
# -----------------------------------------------------------------------------
main::register_plugin();
sub new {
return bless {};
}
sub init {
my $self = shift;
my $cfg_dir = shift;
_load_config($cfg_dir);
open OUTFILE, ">$output_file" or die "Cannot open $output_file: $!\n";
$fh = *OUTFILE;
return;
}
sub list {
return qw(direction source-ip dest-ip);
}
sub main {
my $self = shift;
my $record = shift;
my $line = "";
my ($sec, $min, $hour, $mday, $mon, $year);
my $tz_offset;
if ($record->{'direction'} eq '>') {
return unless exists $record->{'timestamp'};
return unless exists $record->{'method'};
return unless exists $record->{'request-uri'};
return unless exists $record->{'http-version'};
# Build the output line: begin with client (remote host) address
$line .= $record->{'source-ip'};
# Append ident and authuser fields
# NOTE: we use the ident field to display the
# hostname/ip of the destination site
if (exists $record->{'host'}) {
$line .= " $record->{'host'} - ";
} else {
$line .= " $record->{'dest-ip'} - ";
}
# Append date field
$record->{'timestamp'} =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/;
($sec, $min, $hour, $mday, $mon, $year) = ($6, $5, $4, $3, $2-1, $1-1900);
# NOTE: We assume the current timezone here; that may not always be accurate, but
# timezone data is not stored in the httpry log files
$tz_offset = strftime("%z", localtime(mktime($sec, $min, $hour, $mday, $mon, $year)));
$line .= sprintf("[%02d/%3s/%04d:%02d:%02d:%02d %5s]", $mday, $months[$mon], $year+1900, $hour, $min, $sec, $tz_offset);
# Append request fields
$line .= " \"$record->{'method'} $record->{'request-uri'} $record->{'http-version'}\"";
if ($ignore_response) {
print $fh "$line - -\n";
} else {
push(@{ $requests{"$record->{'source-ip'}$record->{'dest-ip'}"} }, $line);
}
} elsif ($record->{'direction'} eq '<') {
# NOTE: This is a bit naive, but functional. Basically we match a request with the
# next response from that IP in the log file. This means that under busy conditions
# the responses could be matched to the wrong request but currently there isn't a
# more accurate way to tie them together.
if (exists $requests{"$record->{'dest-ip'}$record->{'source-ip'}"}) {
$line = shift(@{ $requests{"$record->{'dest-ip'}$record->{'source-ip'}"} });
return unless $line;
if (! @{ $requests{"$record->{'dest-ip'}$record->{'source-ip'}"} }) {
delete $requests{"$record->{'dest-ip'}$record->{'source-ip'}"};
}
} else {
return;
}
# Append status code
if (exists $record->{'status-code'}) {
$line .= " $record->{'status-code'}";
} else {
$line .= " -";
}
# Append byte count
if (exists $record->{'content-length'}) {
$line .= " $record->{'content-length'}";
} else {
$line .= " -";
}
# TODO: also support combined log format: add referer and user-agent request headers
print $fh "$line\n";
}
return;
}
sub end {
# TODO: Print lines that don't have a matching response?
close $fh or die "Cannot close $fh: $!\n";
return;
}
# -----------------------------------------------------------------------------
# Load config file and check for required options
# -----------------------------------------------------------------------------
sub _load_config {
my $cfg_dir = shift;
# Load config file; by default in same directory as plugin
if (-e "$cfg_dir/" . __PACKAGE__ . ".cfg") {
require "$cfg_dir/" . __PACKAGE__ . ".cfg";
} else {
die "No config file found\n";
}
# Check for required options and combinations
if (!$output_file) {
die "No output file provided\n";
}
$output_dir = "." if (!$output_dir);
$output_dir =~ s/\/$//; # Remove trailing slash
return;
}
1;
|