From: Steinar H. Gunderson Date: Sun, 16 Nov 2014 12:35:07 +0000 (+0100) Subject: Add a separate script for counting viewers from Varnish logs. X-Git-Url: https://git.sesse.net/?p=remoteglot;a=commitdiff_plain;h=d5d7dc50fe8f44711a2e4d52563ff40db029e819 Add a separate script for counting viewers from Varnish logs. --- diff --git a/varnishcount.pl b/varnishcount.pl new file mode 100755 index 0000000..82356d6 --- /dev/null +++ b/varnishcount.pl @@ -0,0 +1,61 @@ +#! /usr/bin/perl +use Time::HiRes; +use LWP::Simple; +require 'config.pm'; +use strict; +use warnings; +no warnings qw(once); + +$SIG{ALRM} = sub { output(); }; +Time::HiRes::alarm(1.0, 1.0); + +open my $fh, "-|", "varnishncsa -F '%{%s}t %U %q tffb=%{Varnish:time_firstbyte}x' -q 'ReqURL ~ \"^/analysis.pl\"'" + or die "varnishncsa: $!"; +my %uniques = (); + +while (<$fh>) { + chomp; + m#(\d+) /analysis.pl \?ims=\d+&unique=(.*) tffb=(.*)# or next; + $uniques{$2} = { + last_seen => $1 + $3, + grace => undef, + }; + my $now = time; + print "[$now] $1 $2 $3\n"; +} + +sub output { + my $mtime = (stat($remoteglotconf::json_output))[9] - 1; # Compensate for subsecond issues. + my $now = time; + + while (my ($unique, $hash) = each %uniques) { + my $last_seen = $hash->{'last_seen'}; + if ($now - $last_seen <= 5) { + # We've seen this user in the last five seconds; + # it's okay. + next; + } + if ($last_seen >= $mtime) { + # This user has the latest version; + # they are probably just hanging. + next; + } + if (!defined($hash->{'grace'})) { + # They have five seconds after a new JSON has been + # provided to get get it, or they're out. + # We don't simply use $mtime, since we don't want to + # reset the grace timer just because a new JSON is + # published. + $hash->{'grace'} = $mtime; + } + if ($now - $hash->{'grace'} > 5) { + printf "Timing out %s (last_seen=%d, now=%d, mtime=%d, grace=%d)\n", + $unique, $last_seen, $now, $mtime, $hash->{'grace'}; + delete $uniques{$unique}; + } + } + + my $num_viewers = scalar keys %uniques; + printf "%d entries in hash, mtime=$mtime\n", scalar keys %uniques; + LWP::Simple::get('http://127.0.0.1:5000/override-num-viewers?num=' . $num_viewers); +} diff --git a/www/serve-analysis.js b/www/serve-analysis.js index 362b14b..19ab936 100644 --- a/www/serve-analysis.js +++ b/www/serve-analysis.js @@ -32,6 +32,10 @@ var last_seen_clients = {}; // hanging indefinitely (which might have them return errors). var touch_timer = undefined; +// If we are behind Varnish, we can't count the number of clients +// ourselves, so some external log-tailing daemon needs to tell us. +var viewer_count_override = undefined; + var reread_file = function(event, filename) { if (filename != path.basename(json_filename)) { return; @@ -84,6 +88,21 @@ var send_404 = function(response) { response.write('Something went wrong. Sorry.'); response.end(); } +var handle_viewer_override = function(request, u, response) { + // Only accept requests from localhost. + var peer = request.socket.localAddress; + if ((peer != '127.0.0.1' && peer != '::1') || request.headers['x-forwarded-for']) { + console.log("Refusing viewer override from " + peer); + send_404(response); + } else { + viewer_count_override = (u.query)['num']; + response.writeHead(200, { + 'Content-Type': 'text/plain', + }); + response.write('OK.'); + response.end(); + } +} var send_json = function(response, accept_gzip, num_viewers) { var headers = { 'Content-Type': 'text/json', @@ -110,6 +129,10 @@ var mark_recently_seen = function(unique) { } } var count_viewers = function() { + if (viewer_count_override !== undefined) { + return viewer_count_override; + } + var now = (new Date).getTime(); // Go through and remove old viewers, and count them at the same time. @@ -146,7 +169,10 @@ server.on('request', function(request, response) { var unique = (u.query)['unique']; console.log((new Date).getTime()*1e-3 + " " + request.url); - + if (u.pathname === '/override-num-viewers') { + handle_viewer_override(request, u, response); + return; + } if (u.pathname !== '/analysis.pl') { // This is not the request you are looking for. send_404(response);