PageRenderTime 123ms CodeModel.GetById 90ms RepoModel.GetById 1ms app.codeStats 0ms

/perform/x/perl/lib/Client/Reporter/Traffic.pm

http://guanoo.googlecode.com/
Perl | 269 lines | 194 code | 65 blank | 10 comment | 20 complexity | 0ebb3951cb13e0998bd8280ce70af6cb MD5 | raw file
  1. #!/usr/bin/env perl
  2. =head1 NAME
  3. Client::Reporter::Traffic - Write traffic data to a site's Traffic data table
  4. =head1 VERSION
  5. This document refers to version 1.0 of Client::Reporter::Traffic, released Mar 29, 2008
  6. =head1 DESCRIPTION
  7. Client::Reporter::Traffic writes traffic data to a site's Traffic data table.
  8. =head2 Properties
  9. =over 4
  10. None
  11. =back
  12. =cut
  13. package Client::Reporter::Traffic;
  14. $VERSION = "1.0";
  15. use strict;
  16. use Constants::General;
  17. use Constants::Events;
  18. use Data::Site;
  19. use Utils::Time;
  20. {
  21. # Class static properties
  22. # None
  23. =head2 Class Methods
  24. =over 4
  25. =item new($reporter)
  26. Create a new Client::Reporter::Traffic object
  27. =cut
  28. sub new
  29. {
  30. my ($class, $reporter) = @_;
  31. die "no reporter" unless $reporter;
  32. # Get details from the reporter's site
  33. my $self = {
  34. database => $reporter->{site}->database(),
  35. host => $reporter->{site}->data_server()->{host},
  36. commerce_pages => $reporter->{site}{commerce_pages} || '',
  37. };
  38. bless $self, $class;
  39. }
  40. =item get_channels($visit_data)
  41. Get a list of channels from some visit data
  42. =cut
  43. sub get_channels
  44. {
  45. my ($class, $visit_data) = @_;
  46. return split /,/, $visit_data->{ch};
  47. }
  48. =item get_sequence_events($visit_data)
  49. Get a list of sequence events from some visit data
  50. =cut
  51. sub get_sequence_events
  52. {
  53. my ($class, $visit_data) = @_;
  54. return split /\|/, $visit_data->{sq};
  55. }
  56. =item parse_sequence_event($event)
  57. Parse an event in a sequence from a Traffic record (see "insert" method below)
  58. =cut
  59. sub parse_sequence_event
  60. {
  61. my ($class, $event) = @_;
  62. my $durn = $1 if $event =~ s/^([\d:]+)\s//;
  63. my $refer_id = 0; $refer_id = $1 if $event =~ s/\s(\d+)$//;
  64. my $type_id = 0; $type_id = $1 if $durn =~ s/^(\d+)://;
  65. $durn ||= 1; # minimum of 1 second event duration
  66. $event =~ s/%20/ /g;
  67. return ($type_id, $durn, $event, $refer_id);
  68. }
  69. =back
  70. =head2 Object Methods
  71. =over 4
  72. =item connect()
  73. Connect to a site's data server
  74. =cut
  75. sub connect
  76. {
  77. my ($self) = @_;
  78. my $host = $self->{host} or die "no host";
  79. Data::Site->connect(host => $host);
  80. }
  81. =item disconnect()
  82. Disconnect from a site's data server
  83. =cut
  84. sub disconnect
  85. {
  86. my ($self) = @_;
  87. Data::Site->disconnect();
  88. }
  89. =item delete($start_time)
  90. Delete a day of traffic data from a site's Traffic and TrafficStats data tables
  91. =cut
  92. sub delete
  93. {
  94. my ($self, $start_time) = @_;
  95. my $database = $self->{database} or die "no database";
  96. my $end_time = $start_time + Utils::Time::DAY_SECS;
  97. Data::Site->sql("delete from $database.Traffic where time between $start_time and $end_time");
  98. Data::Site->sql("delete from $database.TrafficStats where time between $start_time and $end_time");
  99. }
  100. =item insert($visit_data)
  101. Insert traffic data to a site's Traffic data table
  102. =cut
  103. sub insert
  104. {
  105. my ($self, $visit_data) = @_;
  106. my $database = $self->{database} or die "no database";
  107. # Get traffic data from visit data
  108. my %stats = ();
  109. my $hits = 0;
  110. my $duration = 0;
  111. my $sequence = '';
  112. my $classes = '';
  113. my $channels = '';
  114. my $commerce = '';
  115. my $i = 1;
  116. while (my $event = $visit_data->{"e$i"})
  117. {
  118. $i++; # next event
  119. my ($channel_id, $type_id, $durn, $name, $refer_id, $class) = split / /, $event;
  120. next unless length $name;
  121. # Measure traffic stats in the content channel and for the whole site
  122. $stats{$channel_id}{"event$type_id"}++;
  123. $stats{$channel_id}{"durn"} += $durn;
  124. if ($channel_id > Constants::General::WHOLE_SITE_CHANNEL_ID)
  125. {
  126. $stats{Constants::General::WHOLE_SITE_CHANNEL_ID}{"event$type_id"}++;
  127. $stats{Constants::General::WHOLE_SITE_CHANNEL_ID}{"durn"} += $durn;
  128. }
  129. # Measure traffic data as a detailed sequence of events
  130. $sequence .= " $refer_id" if $refer_id && $sequence;
  131. $sequence .= '|' if $sequence;
  132. $classes .= ',' if $sequence;
  133. $channels .= ',' if $sequence; # coz zero is false in Perl!
  134. $sequence .= "$type_id:$durn $name";
  135. $classes .= $class || '';
  136. $channels .= $channel_id;
  137. $duration += $durn;
  138. $hits++ if $type_id == Constants::Events::TYPE_PAGE;
  139. $name =~ s/\?.*//; # remove any query string to match commerce pages
  140. if ($self->{commerce_pages} =~ /\Q$name\E/)
  141. {
  142. $commerce .= '|' if $commerce;
  143. $commerce .= $name;
  144. }
  145. }
  146. # Insert the traffic stats into the site's TrafficStats table
  147. while (my ($channel_id, $stats) = each %stats)
  148. {
  149. my $events = '';
  150. my $places = '';
  151. my @values = ();
  152. my $durn = 0;
  153. while (my ($event, $value) = each %{$stats})
  154. {
  155. if ($event eq 'durn') # special case
  156. {
  157. $durn = $value;
  158. next;
  159. }
  160. $events .= "$event,";
  161. $places .= "?,";
  162. push @values, $value;
  163. }
  164. chop $events;
  165. chop $places;
  166. my $sql = "insert into $database.TrafficStats (visit_id, user_id, time, channel_id, duration, $events) values (?, ?, ?, ?, ?, $places)";
  167. eval {
  168. Data::Site->sql($sql, $visit_data->{vi}, $visit_data->{ui}, $visit_data->{tm}, $channel_id, $durn, @values);
  169. }; # just in case
  170. }
  171. # Don't insert hitless traffic data
  172. return unless $hits > 0;
  173. # Insert the traffic data into the site's Traffic data table
  174. eval {
  175. Data::Site->sql("insert into $database.Traffic (visit_id, user_id, time, hits, duration, sequence, classes, channels, campaign, commerce) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $visit_data->{vi}, $visit_data->{ui}, $visit_data->{tm}, $hits, $duration, $sequence, $classes, $channels, $visit_data->{ca}, $commerce);
  176. }; # just in case
  177. }
  178. }1;
  179. =back
  180. =head1 DEPENDENCIES
  181. Data::Site, Utils::Time
  182. =head1 AUTHOR
  183. Kevin Hutchinson <kevin.hutchinson@guanoo.com>
  184. =head1 COPYRIGHT
  185. Copyright (c) 2008 Guanoo, Inc.
  186. This program is free software; you can redistribute it and/or
  187. modify it under the terms of the GNU General Public License
  188. as published by the Free Software Foundation; either version 3
  189. of the License, or (at your option) any later version.
  190. This program is distributed in the hope that it will be useful,
  191. but WITHOUT ANY WARRANTY; without even the implied warranty of
  192. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  193. GNU General Public License for more details.