Metrics.pm 1.9 KB

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