Metrics.pm 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package Trog::Log::Metrics;
  2. use 5.040;
  3. use re '/aasx';
  4. use warnings FATAL => 'all';
  5. use Trog::SQLite;
  6. use Trog::Log;
  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. =head2 requests_per(ENUM period{second,minute,hour,day,month,year}, INTEGER num_periods, [TIME_T before], INTEGER[] @codes)
  12. Returns a data structure of the following form
  13. {
  14. labels => [TIME_STR, TIME_STR, ...],
  15. data => [INT, INT,...]
  16. }
  17. Describing the # of requests for the requested $num_periods $period(s) before $before.
  18. 'month' and 'year' are approximations for performance reasons; 30 day and 365 day periods.
  19. Optionally filter by response code(s).
  20. =cut
  21. sub requests_per ( $period, $num_periods, $before, @codes ) {
  22. $before ||= time;
  23. # Build our periods in seconds.
  24. state %period2time = (
  25. second => 1,
  26. minute => 60,
  27. hour => 3600,
  28. day => 86400,
  29. week => 604800,
  30. month => 2592000,
  31. year => 31356000,
  32. );
  33. my $interval = $period2time{$period};
  34. die "Invalid time interval passed." unless $interval;
  35. my @input;
  36. my $whereclause = '';
  37. if (@codes) {
  38. my $bind = join( ',', ( map { '?' } @codes ) );
  39. $whereclause = "WHERE code IN ($bind)";
  40. push( @input, @codes );
  41. }
  42. push( @input, $interval, $before, $num_periods );
  43. ## no critic(ValuesAndExpressions::PreventSQLInjection)
  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;