blob: 2b3adc3cae256ec432f1d43819e21d468c46c14c [file] [log] [blame]
#!/usr/bin/perl
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
use strict;
use warnings;
use LWP::UserAgent;
use IO::Socket::SSL;
use Data::Dumper;
use Getopt::Std;
my %histogram = (0 => 0,
60 => 0,
3600 => 0,
86400 => 0,
604800 => 0,
2592000 => 0,
30758400 => 0,
'inf' => 0,
'undef' => 0
);
my %histogram_with_heuristic = (0 => 0,
60 => 0,
3600 => 0,
86400 => 0,
604800 => 0,
2592000 => 0,
30758400 => 0,
'inf' => 0,
'undef' => 0
);
my %pretty_name = (0 => '0',
60 => '1 minute',
3600 => '1 hour',
86400 => '1 day',
604800 => '1 week',
2592000 => '1 month',
30758400 => '1 year',
'inf' => '> 1 year',
'undef' => 'undef'
);
my $debug = 0;
#-----------------------------------------------------------------------------
sub addToHistogram($$) {
my($hist, $value) = @_;
if (! defined $value) {
$hist->{undef}++
} elsif ($value <= 0) {
$hist->{0}++;
} elsif ($value <= 60) {
$hist->{60}++;
} elsif ($value <= 3600) {
$hist->{3600}++;
} elsif ($value <= 86400) {
$hist->{86400}++;
} elsif ($value <= 604800) {
$hist->{604800}++;
} elsif ($value <= 2592000) {
$hist->{2592000}++;
} elsif ($value <= 30758400) {
$hist->{30758400}++;
} else {
$hist->{inf}++;
}
}
#-----------------------------------------------------------------------------
sub usage() {
print "USAGE: traffic_cacheable.pl [file]\n";
print "\t-h\thelp";
print "\n\ntraffic_cacheable.pl can read from a file or stdin\n";
exit;
}
#-----------------------------------------------------------------------------
{
my %opts;
getopts("h", \%opts);
usage() if (defined $opts{h});
my $ua = LWP::UserAgent->new(
ssl_opts => {
verify_hostname => 0,
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
},
);
my %response_codes;
my %cache_control_exists;
my %expires_exists;
my %last_modified_exists;
my %pragma_exists;
my $cc_and_expires_noexist = 0;
my $cache_headers_noexist = 0;
my $ats_cache_hit = 0;
my $count = 0;
while (my $url = <>) {
$count++;
chomp $url;
my $req = HTTP::Request->new(GET => $url);
print "Testing url: $url\n" if $debug;
print STDERR "\rTesting url: $count" if ! $debug;
my $res = $ua->request($req);
my $freshness = $res->freshness_lifetime(heuristic_expiry => 0);
my $freshness_with_heuristic = $res->freshness_lifetime();
if ($res->is_success) {
my $cache_control = $res->header('Cache-Control');
my $expires = $res->header('Expires');
my $last_modified = $res->header('Last-Modified');
my $pragma = $res->header('Pragma');
my $via = $res->header('Via');
print "\tcode: ", $res->code, "\n" if $debug;
print "\tCache-Control: ", $cache_control, "\n" if $debug;
print "\tExpires: ", $expires, "\n" if $debug;
print "\tcalculated age: ", $res->current_age, "\n" if $debug;
print "\tfreshness lifetime: ", $freshness, "\n" if $debug;
$response_codes{$res->code}++;
if ($res->code == 200) {
addToHistogram(\%histogram, $freshness);
addToHistogram(\%histogram_with_heuristic, $freshness_with_heuristic);
# check cache-control
if (defined $cache_control) {
$cache_control_exists{private}++ if $cache_control =~ m|private|i;
$cache_control_exists{'no-cache'}++ if $cache_control =~ m|no-cache|i;
$cache_control_exists{'no-store'}++ if $cache_control =~ m|no-store|i;
$cache_control_exists{'max-age'}++ if $cache_control =~ m|max-age|i;
$cache_control_exists{'maxage'}++ if $cache_control =~ m|maxage|i;
} else {
$cache_control_exists{undef}++;
}
# check expires
if (defined $expires) {
$expires_exists{defined}++;
} else {
$expires_exists{undef}++;
}
# check last-modified
if (defined $last_modified) {
$last_modified_exists{defined}++;
} else {
$last_modified_exists{undef}++;
}
# check pragma
if (defined $pragma) {
$pragma_exists{defined}++;
} else {
$pragma_exists{undef}++;
}
# check via
if (defined $via) {
my @items = split(/,/, $via);
my $last = pop(@items);
#print "$last\n";
if (my($codes) = $last =~ m|\[([\w\s]+)\]|) {
#print "$codes\n";
$ats_cache_hit++ if ($codes =~ m|^c[HR]|);
}
}
$cc_and_expires_noexist++ if (! defined $cache_control && ! defined $expires);
$cache_headers_noexist++ if (! defined $cache_control && ! defined $expires && ! defined $last_modified);
}
}
#last if $count == 5;
}
print "\n" if ! $debug;
print "\n";
print "Total Tested: $count\n";
print "Response Codes:\n";
foreach my $key (sort keys %response_codes) {
printf("\t%s: %d (%.2f%%)\n", $key, $response_codes{$key}, $response_codes{$key} / $count * 100);
}
print "Freshness:\n";
foreach my $key (0, 60, 3600, 86400, 604800, 2592000, 30758400, 'inf', 'undef') {
printf("\t%s: %d (%.2f%%)\n", $pretty_name{$key}, $histogram{$key}, $histogram{$key} / $count * 100);
}
print "Freshness with Heuristic using Last-Modified (RFC 7234 4.2.2):\n";
foreach my $key (0, 60, 3600, 86400, 604800, 2592000, 30758400, 'inf', 'undef') {
printf("\t%s: %d (%.2f%%)\n", $pretty_name{$key}, $histogram_with_heuristic{$key}, $histogram_with_heuristic{$key} / $count * 100);
}
print "Headers:\n";
print "\tCache-Control:\n";
foreach my $key (sort keys %cache_control_exists) {
printf("\t\t%s: %d (%.2f%%)\n", $key, $cache_control_exists{$key}, $cache_control_exists{$key} / $count * 100);
}
print "\tExpires:\n";
foreach my $key (sort keys %expires_exists) {
printf("\t\t%s: %d (%.2f%%)\n", $key, $expires_exists{$key}, $expires_exists{$key} / $count * 100);
}
print "\tLast-Modified:\n";
foreach my $key (sort keys %last_modified_exists) {
printf("\t\t%s: %d (%.2f%%)\n", $key, $last_modified_exists{$key}, $last_modified_exists{$key} / $count * 100);
}
print "\tPragma:\n";
foreach my $key (sort keys %pragma_exists) {
printf("\t\t%s: %d (%.2f%%)\n", $key, $pragma_exists{$key}, $pragma_exists{$key} / $count * 100);
}
print "Extra:\n";
printf("\t%s: %d (%.2f%%)\n", 'Cache-Control / Expires not set', $cc_and_expires_noexist, $cc_and_expires_noexist / $count * 100);
printf("\t%s: %d (%.2f%%)\n", 'Cache-Control / Expires / Last-Modified not set', $cache_headers_noexist, $cache_headers_noexist / $count * 100);
printf("\t%s: %d (%.2f%%)\n", 'ATS Cache Hit (via header)', $ats_cache_hit, $ats_cache_hit / $count * 100);
}