summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--foostats.pl207
1 files changed, 207 insertions, 0 deletions
diff --git a/foostats.pl b/foostats.pl
index 7512c82..a78ef23 100644
--- a/foostats.pl
+++ b/foostats.pl
@@ -821,6 +821,12 @@ package Foostats::Reporter {
}
$report_content .= "
";
+
+ # Add link to monthly report
+ $report_content .= "## Related Reports\n\n";
+ my $today = localtime;
+ my $current_month = $today->strftime('%Y%m%d');
+ $report_content .= "=> ./30day_summary_$current_month.gmi 30-Day Summary Report\n\n";
my $report_path = "$stats_dir/$date.gmi";
say "Writing report to $report_path";
@@ -829,6 +835,9 @@ package Foostats::Reporter {
# Generate 30-day summary report
generate_30day_report($stats_dir, %merged);
+
+ # Generate yearly report
+ generate_yearly_report($stats_dir, %merged);
}
sub generate_30day_report {
@@ -998,11 +1007,209 @@ package Foostats::Reporter {
";
}
+ # Add link to yearly report
+ $report_content .= "\n## Related Reports\n\n";
+ my $year = $today->strftime('%Y');
+ $report_content .= "=> ./yearly_summary_$year.gmi Yearly Summary Report\n";
+
# Write the 30-day report
my $report_path = "$stats_dir/30day_summary_$report_date.gmi";
say "Writing 30-day summary report to $report_path";
FileHelper::write( $report_path, $report_content );
}
+
+ sub generate_yearly_report {
+ my ( $stats_dir, %merged ) = @_;
+
+ # Get all available dates
+ my @all_dates = sort { $a cmp $b } keys %merged;
+
+ # Filter to only dates that have data
+ @all_dates = grep { exists $merged{$_} && $merged{$_}->{count} } @all_dates;
+
+ return unless @all_dates; # No data available
+
+ my $today = localtime;
+ my $current_year = $today->strftime('%Y');
+
+ # Count total days with data
+ my $total_days = scalar @all_dates;
+
+ my $report_content = "# Yearly Summary Report\n";
+ $report_content .= "## Generated on " . $today->strftime('%Y-%m-%d') . "\n\n";
+ $report_content .= "## Report covers $total_days days of data\n\n";
+
+ # Monthly aggregation
+ my %monthly_stats;
+
+ for my $date (@all_dates) {
+ my $stats = $merged{$date};
+ next unless $stats->{count};
+
+ my ( $year, $month, $day ) = $date =~ /(\d{4})(\d{2})(\d{2})/;
+ my $month_key = "$year-$month";
+
+ # Initialize monthly stats
+ $monthly_stats{$month_key} //= {
+ total_requests => 0,
+ filtered => 0,
+ gemini => 0,
+ web => 0,
+ ipv4 => 0,
+ ipv6 => 0,
+ feed_total => 0,
+ gem_feed => 0,
+ gem_atom => 0,
+ web_feed => 0,
+ web_atom => 0,
+ days => 0
+ };
+
+ my $ms = $monthly_stats{$month_key};
+ $ms->{days}++;
+
+ # Aggregate counts
+ $ms->{total_requests} += ($stats->{count}{gemini} // 0) + ($stats->{count}{web} // 0);
+ $ms->{filtered} += $stats->{count}{filtered} // 0;
+ $ms->{gemini} += $stats->{count}{gemini} // 0;
+ $ms->{web} += $stats->{count}{web} // 0;
+ $ms->{ipv4} += $stats->{count}{IPv4} // 0;
+ $ms->{ipv6} += $stats->{count}{IPv6} // 0;
+
+ # Aggregate feed stats
+ if ($stats->{feed_ips}) {
+ $ms->{feed_total} += $stats->{feed_ips}{'Total'} // 0;
+ $ms->{gem_feed} += $stats->{feed_ips}{'Gemini Gemfeed'} // 0;
+ $ms->{gem_atom} += $stats->{feed_ips}{'Gemini Atom'} // 0;
+ $ms->{web_feed} += $stats->{feed_ips}{'Web Gemfeed'} // 0;
+ $ms->{web_atom} += $stats->{feed_ips}{'Web Atom'} // 0;
+ }
+ }
+
+ # Summary section - monthly evolution
+ $report_content .= "## Monthly Summary Evolution\n\n";
+ $report_content .= "### Total Requests by Month\n\n```\n";
+
+ my @summary_rows;
+ for my $month (sort keys %monthly_stats) {
+ my $ms = $monthly_stats{$month};
+ push @summary_rows, [
+ $month,
+ $ms->{days},
+ $ms->{total_requests},
+ $ms->{filtered},
+ $ms->{gemini},
+ $ms->{web},
+ $ms->{ipv4},
+ $ms->{ipv6}
+ ];
+ }
+
+ $report_content .= format_table(
+ [ 'Month', 'Days', 'Total', 'Filtered', 'Gemini', 'Web', 'IPv4', 'IPv6' ],
+ \@summary_rows
+ );
+ $report_content .= "\n```\n\n";
+
+ # Feed statistics by month
+ $report_content .= "### Feed Statistics by Month\n\n```\n";
+
+ my @feed_rows;
+ for my $month (sort keys %monthly_stats) {
+ my $ms = $monthly_stats{$month};
+ push @feed_rows, [
+ $month,
+ $ms->{feed_total},
+ $ms->{gem_feed},
+ $ms->{gem_atom},
+ $ms->{web_feed},
+ $ms->{web_atom}
+ ];
+ }
+
+ $report_content .= format_table(
+ [ 'Month', 'Total', 'Gem Feed', 'Gem Atom', 'Web Feed', 'Web Atom' ],
+ \@feed_rows
+ );
+ $report_content .= "\n```\n\n";
+
+ # Aggregate hosts and URLs for entire period
+ my %all_hosts;
+ my %all_urls;
+
+ for my $date (@all_dates) {
+ my $stats = $merged{$date};
+ next unless $stats->{page_ips};
+
+ # Aggregate hosts
+ while (my ($host, $count) = each %{$stats->{page_ips}{hosts}}) {
+ $all_hosts{$host} //= 0;
+ $all_hosts{$host} += $count;
+ }
+
+ # Aggregate URLs
+ while (my ($url, $count) = each %{$stats->{page_ips}{urls}}) {
+ $all_urls{$url} //= 0;
+ $all_urls{$url} += $count;
+ }
+ }
+
+ # Top 50 hosts
+ $report_content .= "## Top 50 Hosts (Yearly Total)\n\n```\n";
+
+ my @host_rows;
+ my @sorted_hosts = sort { $all_hosts{$b} <=> $all_hosts{$a} } keys %all_hosts;
+ @sorted_hosts = @sorted_hosts[0..49] if @sorted_hosts > 50;
+
+ for my $host (@sorted_hosts) {
+ push @host_rows, [ $host, $all_hosts{$host} ];
+ }
+
+ $report_content .= format_table(
+ [ 'Host', 'Total Unique Visitors' ],
+ \@host_rows
+ );
+ $report_content .= "\n```\n\n";
+
+ # Top 50 URLs
+ $report_content .= "## Top 50 URLs (Yearly Total)\n\n```\n";
+
+ my @url_rows;
+ my @sorted_urls = sort { $all_urls{$b} <=> $all_urls{$a} } keys %all_urls;
+ @sorted_urls = @sorted_urls[0..49] if @sorted_urls > 50;
+
+ for my $url (@sorted_urls) {
+ push @url_rows, [ $url, $all_urls{$url} ];
+ }
+
+ $report_content .= format_table(
+ [ 'URL', 'Total Unique Visitors' ],
+ \@url_rows
+ );
+ $report_content .= "\n```\n\n";
+
+ # Links to monthly reports
+ $report_content .= "## Monthly Reports\n\n";
+
+ # Get list of all 30-day summary reports
+ my @monthly_reports = glob "$stats_dir/30day_summary_*.gmi";
+ @monthly_reports = sort { $b cmp $a } @monthly_reports;
+
+ for my $report_path (@monthly_reports) {
+ my ($date) = $report_path =~ /30day_summary_(\d{8})\.gmi$/;
+ next unless $date;
+
+ my ( $year, $month, $day ) = $date =~ /(\d{4})(\d{2})(\d{2})/;
+ my $formatted_date = "$year-$month-$day";
+
+ $report_content .= "=> ./30day_summary_$date.gmi 30-Day Summary for $formatted_date\n";
+ }
+
+ # Write the yearly report
+ my $report_path = "$stats_dir/yearly_summary_$current_year.gmi";
+ say "Writing yearly summary report to $report_path";
+ FileHelper::write( $report_path, $report_content );
+ }
}