From 7564eb9c5f047b787ba01fa913761b7e5d12f1bd Mon Sep 17 00:00:00 2001 From: Mike Heins Date: Sat, 6 Dec 2003 22:52:37 +0000 Subject: [PATCH] * Add [traffic-report] tag and modified admin/reports/traffic/ByAffiliate page which calls it. Now reports on large files without crashing the system. Probably can handle up to 500MB files with on any kind of a reasonable server. * Don't track admin pages. --- code/UI_Tag/traffic_report.coretag | 286 ++++++++++++++++++ .../admin/reports/traffic/ByAffiliate.html | 244 +-------------- lib/Vend/Dispatch.pm | 7 +- 3 files changed, 291 insertions(+), 246 deletions(-) create mode 100644 code/UI_Tag/traffic_report.coretag diff --git a/code/UI_Tag/traffic_report.coretag b/code/UI_Tag/traffic_report.coretag new file mode 100644 index 000000000..7a5d70b28 --- /dev/null +++ b/code/UI_Tag/traffic_report.coretag @@ -0,0 +1,286 @@ +UserTag traffic-report Order save +UserTag traffic-report addAttr +UserTag traffic-report Routine < errmsg('Date'), + affiliate => errmsg('Affiliate'), + campaign => errmsg('Campaign'), + visits => errmsg('Visits'), + hits => errmsg('Hits'), + pages => errmsg('Pages'), + views => errmsg('Prod. views'), + incart => errmsg('Items in cart'), + orders => errmsg('Orders'), + ); + + my %hmap = qw/ + VIEWPAGE pages + VIEWPROD views + ADDITEM incart + ORDER orders + /; + + if(ref $opt->{header}) { + for(keys %{$opt->{header}}) { + $header{$_} = errmsg($opt->{header}{$_}); + } + } + + my $cols = $opt->{show} || 'date affiliate visits hits pages views incart orders'; + my @cols = grep /\w/, split /[\0,\s]+/, $cols; + my $numcols = scalar(@cols); + + my @out = < + + +EOF + for(@cols) { + push @out, "$header{$_}"; + } + + push @out, < + +EOF + + my $file = $Vend::Cfg->{TrackFile}; + unless (-f $file) { + push @out, "No traffic statistics found"; + return; + } + + unless(open REPORT, "< $file") { + push @out, "Cannot open file $file"; + return; + } + + my $affiliate = $opt->{affiliate} || $CGI::values{affiliate}; + my $begin_date = $opt->{begin_date} || $CGI::values{ui_begin_date}; + my $end_date = $opt->{end_date} || $CGI::values{ui_end_date}; + my $Tag = new Vend::Tags; + + if($begin_date) { + $begin_date = filter_value('date_change', $begin_date); + look(\*REPORT, $begin_date) if $begin_date; + } + + $end_date = filter_value('date_change', $end_date) + if $end_date; + + my %names = qw/ + 01 January + 02 February + 03 March + 04 April + 05 May + 06 June + 07 July + 08 August + 09 September + 10 October + 11 November + 12 December + /; + + my $timeout = $::Variable->{VISIT_TIMEOUT} || (30 * 10); + + my $by_day = $opt->{by_day} || $CGI::values{ui_by_day}; + my $len; + $len = $by_day ? 8 : 6; + + my $done; + my $prev; + my $break_check = sub { + if(! defined($prev)) { + $prev = $_[0]; + return; + } + if ($_[0] gt $end_date) { + $done = 1; + return 1; + } + return if $_[0] eq $prev; + $prev = $_[0]; + return 1; + }; + + + BREAK: { + my $hits; + my $interval_count = 0; + my $interval_total = 0; + my $max_interval = 0; + my $min_interval = 9999999; + my $out = ''; + my $visits; + my %action_by_aff; + my %action_by_day; + my %action_by_period; + my %action_by_tag; + my %action_by_visit; + my %action_by_visit_number; + my %actions_per_visit_boolean; + my %hits_by_day; + my %hits_by_item; + my %hits_by_page; + my %hits_by_period; + my %hits_by_session; + my %last_access; + my %session_by_order; + my %session_by_page; + my %visit_by_aff; + my %visit_by_aff_by_day; + my %visit_by_aff_by_period; + my %visit_by_day; + my %visit_by_ip; + my %visit_by_period; + my %visit_by_session; + my %visit_by_user; + my %visit_number; + + + + my $donelines = 0; + + ## To fudge around break + my $saved_line; + my $recall; + + COUNT: + while () { + chop; + + ## To fudge around break, so that we can break then recall + ## the line where we broke + if($recall) { + $saved_line = $_; + $_ = $recall; + undef $recall; + } + my $line = [ split /\t/, $_ , 7]; + + my $per = substr($line->[0], 0, $len); + $break_check->($per) + and do { + $recall = $_; + last COUNT; + }; + my $update_visit; + my $interval; + $hits++; + $hits_by_period{$per}++; + $hits_by_day{$line->[0]}++; + $hits_by_session{$line->[1]}++ + or $update_visit = 1; + + $interval = $line->[4] - $last_access{$line->[1]} + if $last_access{$line->[1]}; + if($interval) { + $max_interval = $interval + if $interval > $max_interval; + $min_interval = $interval + if $interval < $min_interval; + $interval_total += $interval; + $interval_count++; + $update_visit = 1 if $interval > $timeout; + } + $last_access{$line->[1]} = $line->[4]; + + my $visit_number; + if($update_visit) { + $visits++; + $visit_number = "$line->[1]:" . $visit_by_session{$line->[1]}++; + $visit_by_period{$per}++; + $visit_by_day{$line->[0]}++; + $visit_by_user{$line->[2]}++; + $visit_by_ip{$line->[3]}++; + $visit_by_aff{$line->[5]}++; + $visit_by_aff_by_period{$per}{$line->[5]}++; + $visit_by_aff_by_day{$line->[0]}{$line->[5]}++; + } + + # Leave this at & instead of UrlJoiner because of Vend::Track + my (@items) = split /(?:^|&)([A-Z]+)=/, $line->[6]; + shift @items; +#::logDebug("items = " . ::uneval(\@items)) if $line->[6] =~ / \& /; + while (@items) { + my($tag, $val) = splice(@items, 0, 2); + $action_by_visit{$tag}++ + unless $action_by_visit_number{$visit_number}{$tag}++; + $action_by_tag{$tag}{$val}++; + $action_by_aff{$line->[5]}{$tag}++; + $action_by_period{$per}{$tag}++; + $action_by_day{$line->[0]}{$tag}++; + } + + ## To fudge around break + if($saved_line) { + $_ = $saved_line; + undef $saved_line; + redo COUNT; + } + } +#::logDebug("action_by_visit=" . ::uneval(\%action_by_visit)); + foreach my $one (sort keys %visit_by_period) { + my ($yr, $mon, $day) = $one =~ /(\d\d\d\d)(\d\d)(\d\d)?/; + my $date; + my %output; + push @out, "\n"; + $date = $day ? "$names{$mon} $day, $yr" : "$names{$mon} $yr"; + $output{date} = < +$date + +EOF + my (@number) = grep /\S/, keys %{ $visit_by_aff_by_period{$one} }; + my $count = scalar(@number); + $output{affiliate} = < +$count + +EOF + + $output{visits} = < +$visit_by_period{$one} + +EOF + + $output{hits} = < +$hits_by_period{$one} + +EOF + for(qw/ VIEWPAGE VIEWPROD ADDITEM ORDER /) { + $count = $action_by_period{$one}{$_} || 0; + my $pct = ''; + $pct = $action_by_visit{$_} / $visit_by_period{$one} * 100 + if $visit_by_period{$one}; + $pct = $pct <= 0 ? '' : sprintf( "
%.2f%%
", $pct); + $output{$hmap{$_}} = < +$count$pct + +EOF + } + for(@cols) { + push @out, $output{$_}; + } + push @out, ''; + } + + redo BREAK unless $done or eof(REPORT); + } + push @out, < + +EOF + return join "\n", @out; +} +EOR diff --git a/dist/lib/UI/pages/admin/reports/traffic/ByAffiliate.html b/dist/lib/UI/pages/admin/reports/traffic/ByAffiliate.html index 3a6d3787b..be2ce88a4 100644 --- a/dist/lib/UI/pages/admin/reports/traffic/ByAffiliate.html +++ b/dist/lib/UI/pages/admin/reports/traffic/ByAffiliate.html @@ -16,248 +16,6 @@ @_UI_STD_HEAD_@ - - - - - - - - - - - - - +[traffic-report] -[perl tables=affiliate] - - my $file = $Config->{TrackFile}; - unless (-f $file) { - return ''; - } - - $Scratch->{$file} = 1; - - %opts = ( - rf => [ 0 .. 6 ], - hs => 0, - fi => $file, - ml => 999999, - ); - - unless($file =~ m{^/}) { - $opts{bd} = '.'; - } - - %names = qw/ - 01 January - 02 February - 03 March - 04 April - 05 May - 06 June - 07 July - 08 August - 09 September - 10 October - 11 November - 12 December - /; - if($Session->{arg}) { - my $beg = $CGI->{ui_begin_date}; - $opts{dl} = $beg++; - $opts{de} = $beg; - } - elsif ($CGI->{ui_begin_date}) { - for (qw/ ui_begin_date ui_end_date /) { - $CGI->{$_} = $Tag->filter( { - op => 'date_change', - body => $CGI->{$_} - }); - } - my $end; - if( $end = $CGI->{ui_end_date}) { - $end++; - $opts{de} = $end; - } - $opts{dl} = $CGI->{ui_begin_date}; - } - - if ($CGI->{affiliate}) { - $opts{sf} = [ 5 ]; - $opts{se} = [ $CGI->{affiliate} ]; - } - else { - $opts{ra} = 1; - } - - my $ary = $TextSearch->array(\%opts); - my $timeout = '__VISIT_TIMEOUT__' || (30 * 10); - - my $by_day = $CGI->{ui_by_day}; - my $len; - $len = $by_day ? 8 : 6; - - $prev = substr($ary->[0][0], 0, $len); - $break_check = sub { - return if $_[0] eq $prev; - $prev = $_[0]; - return 1; - }; - - BREAK: { - my %action_by_tag = (); - my %action_by_visit = (); - my %action_by_visit_number = (); - my %actions_per_visit_boolean = (); - my $hits; - my %hits_by_item = (); - my %hits_by_page = (); - my %hits_by_session = (); - my $interval_count = 0; - my $interval_total = 0; - my %last_access = (); - my $max_interval = 0; - my $min_interval = 9999999; - my $out = ''; - my %session_by_order = (); - my %session_by_page = (); - my %visit_by_aff = (); - my %visit_by_ip = (); - my %visit_by_session = (); - my %visit_by_user = (); - my %visit_number = (); - my $visits; - COUNT: - while ($_ = shift @$ary) { - - my $per = substr($_->[0], 0, $len); - $break_check->($per) - and do { - unshift @$ary, $_; - last COUNT; - }; - my $update_visit; - my $interval; - $hits++; - $hits_by_period{$per}++; - $hits_by_day{$_->[0]}++; - $hits_by_session{$_->[1]}++ - or $update_visit = 1; - - $interval = $_->[4] - $last_access{$_->[1]} - if $last_access{$_->[1]}; - if($interval) { - $max_interval = $interval - if $interval > $max_interval; - $min_interval = $interval - if $interval < $min_interval; - $interval_total += $interval; - $interval_count++; - $update_visit = 1 if $interval > $timeout; - } - $last_access{$_->[1]} = $_->[4]; - - if($update_visit) { - $visits++; - $visit_number = "$_->[1]:" . $visit_by_session{$_->[1]}++; - $visit_by_period{$per}++; - $visit_by_day{$_->[0]}++; - $visit_by_user{$_->[2]}++; - $visit_by_ip{$_->[3]}++; - $visit_by_aff{$_->[5]}++; - $visit_by_aff_by_period{$per}{$_->[5]}++; - $visit_by_aff_by_day{$_->[0]}{$_->[5]}++; - } - - # Leave this at & instead of UrlJoiner because of Vend::Track - my (@items) = split /\&/, $_->[6]; - foreach $it (@items) { - my($tag, $val) = split /=/, $it, 2; - $action_by_visit{$tag}++ - unless $action_by_visit_number{$visit_number}{$tag}++; - $action_by_tag{$tag}{$val}++; - $action_by_aff{$_->[5]}{$tag}++; - $action_by_period{$per}{$tag}++; - $action_by_day{$_->[0]}{$tag}++; - } - } - foreach my $one (sort keys %visit_by_period) { - my ($yr, $mon, $day) = $one =~ /(\d\d\d\d)(\d\d)(\d\d)?/; - my $date; - $date = $day ? "$names{$mon} $day, $yr" : "$names{$mon} $yr"; - $out = < -EOF - my (@number) = grep /\S/, keys %{ $visit_by_aff_by_period{$one} }; - my $count = scalar(@number); - $out .= < -$count - - - -EOF - for(qw/ VIEWPAGE VIEWPROD ADDITEM ORDER /) { - $count = $action_by_period{$one}{$_} || 0; - $pct = ''; - $pct = $action_by_visit{$_} / $visit_by_period{$one} * 100 - if $visit_by_period{$one}; - $pct = $pct <= 0 ? '' : sprintf( "
%.2f%%
", $pct); - $out .= < -$count$pct - -EOF - } - $out .= ''; - } -[comment] - - for(keys %action_by_tag) { - #$out .= "$_: " . $Tag->uneval( { ref => $action_by_tag{$_} }); - $out .= "\n"; - $out .= "Percent of visits with $_: " . $action_by_visit{$_} / $visits * 100; - $out .= "\n"; - } - for(sort keys %visit_by_period) { - $out .= "$_: visits=$visit_by_period{$_}, " ; - $out .= "hits=$hits_by_period{$_}\n" ; - } - $out .= "Minimum interval: $min_interval\n"; - $out .= "Maximum interval: $max_interval\n"; - $out .= "Average interval: " . $interval_total / $interval_count . "\n" - if $interval_count; -[/comment] - push @out, $out; - redo BREAK if scalar (@$ary); - } - return join "\n\n", @out; -[/perl] - - -
- [L]Date[/L] - - [L]Affiliate[/L] - - [L]Visits[/L] - - [L]Hits[/L] - - [L]Pages[/L] - - [L]Prod. Views[/L] - - [L]Items in cart[/L] - - [L]Orders[/L] -
No traffic statistics found
-$date - -$visit_by_period{$one} - -$hits_by_period{$one} -
@_UI_STD_FOOTER_@ diff --git a/lib/Vend/Dispatch.pm b/lib/Vend/Dispatch.pm index b4c2c19ed..854e0057f 100644 --- a/lib/Vend/Dispatch.pm +++ b/lib/Vend/Dispatch.pm @@ -1,6 +1,6 @@ # Vend::Dispatch - Handle Interchange page requests # -# $Id: Dispatch.pm,v 1.27 2003-10-28 17:22:29 mheins Exp $ +# $Id: Dispatch.pm,v 1.28 2003-12-06 22:52:36 mheins Exp $ # # Copyright (C) 2002-2003 Interchange Development Group # Copyright (C) 2002 Mike Heins @@ -26,7 +26,7 @@ package Vend::Dispatch; use vars qw($VERSION); -$VERSION = substr(q$Revision: 1.27 $, 10); +$VERSION = substr(q$Revision: 1.28 $, 10); use POSIX qw(strftime); use Vend::Util; @@ -1353,7 +1353,8 @@ EOF url_history($Vend::FinalPath) if $Vend::Cfg->{History}; # TRACK - $Vend::Track = new Vend::Track; + $Vend::Track = new Vend::Track + unless $Vend::admin and ! $::Variable->{MV_TRACK_ADMIN}; # END TRACK if($Vend::Cfg->{DisplayErrors} and $Global::DisplayErrors) {