Metrics.pm 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package Trog::Log::Metrics;
  2. use strict;
  3. use warnings;
  4. no warnings 'experimental';
  5. use feature qw{signatures state};
  6. use Trog::SQLite;
  7. =head1 Trog::Log::Metrics
  8. A means for acquiring time-series representations of the data recorded by Trog::Log::DBI,
  9. and for reasoning about the various things that it's Urchin-compatible data can give you.
  10. =cut
  11. sub _dbh {
  12. return Trog::SQLite::dbh( 'schema/log.schema', "logs/log.db" );
  13. }
  14. =head2 requests_per(ENUM period{second,minute,hour,day,month,year}, INTEGER num_periods, [TIME_T before], INTEGER[] @codes)
  15. Returns a data structure of the following form
  16. {
  17. labels => [TIME_STR, TIME_STR, ...],
  18. data => [INT, INT,...]
  19. }
  20. Describing the # of requests for the requested $num_periods $period(s) before $before.
  21. 'month' and 'year' are approximations for performance reasons; 30 day and 365 day periods.
  22. Optionally filter by response code(s).
  23. =cut
  24. sub requests_per ( $period, $num_periods, $before, @codes ) {
  25. $before ||= time;
  26. # Build our periods in seconds.
  27. state %period2time = (
  28. second => 1,
  29. minute => 60,
  30. hour => 3600,
  31. day => 86400,
  32. week => 604800,
  33. month => 2592000,
  34. year => 31356000,
  35. );
  36. my $interval = $period2time{$period};
  37. die "Invalid time interval passed." unless $interval;
  38. my @input;
  39. my $whereclause = '';
  40. if (@codes) {
  41. my $bind = join( ',', ( map { '?' } @codes ) );
  42. $whereclause = "WHERE code IN ($bind)";
  43. push( @input, @codes );
  44. }
  45. push( @input, $interval, $before, $num_periods );
  46. my $query = "SELECT count(*) FROM all_requests $whereclause GROUP BY date / ? HAVING date < ? LIMIT ?";
  47. my @results = map { $_->[0] } @{ _dbh()->selectall_arrayref( $query, undef, @input ) };
  48. my $np = @results < $num_periods ? @results : $num_periods;
  49. my @labels = reverse map { "$_ $period(s) ago" } ( 1 .. $np );
  50. return {
  51. labels => \@labels,
  52. data => \@results,
  53. };
  54. }
  55. 1;