Skip to content

Commit

Permalink
tec: Provide statistics as CSV
Browse files Browse the repository at this point in the history
  • Loading branch information
marienfressinaud committed Jan 23, 2024
1 parent 8361c89 commit 578a848
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 22 deletions.
76 changes: 54 additions & 22 deletions src/cli/System.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,32 +84,64 @@ public function show(): Response
/**
* Show statistics of the system.
*
* @request_param string format
* The output format, either `plain` (default) or `csv`.
* @request_param integer year
* The year to display (only for `csv` format), default is current year.
*
* @response 200
*/
public function stats(Request $request): Response
{
$count_users = models\User::count();
$count_users_validated = models\User::countValidated();
$percent_users_validated = intval($count_users_validated * 100 / max(1, $count_users));

return Response::ok('cli/system/stats.txt', [
'count_users' => $count_users,
'percent_users_validated' => $percent_users_validated,
'count_users_week' => models\User::countSince(\Minz\Time::ago(1, 'week')),
'count_users_month' => models\User::countSince(\Minz\Time::ago(1, 'month')),
'count_users_active_month' => models\Session::countUsersActiveSince(\Minz\Time::ago(1, 'month')),
'count_links' => models\Link::countEstimated(),
'count_links_to_fetch' => models\Link::countToFetch(),
'count_collections' => models\Collection::countCollections(),
'count_collections_public' => models\Collection::countCollectionsPublic(),
'count_feeds' => models\Collection::countFeeds(),
'count_feeds_by_hours' => models\Collection::countFeedsByHours(),
'count_requests' => models\FetchLog::countEstimated(),
'count_requests_feeds' => models\FetchLog::countByType('feed'),
'count_requests_links' => models\FetchLog::countByType('link'),
'count_requests_images' => models\FetchLog::countByType('image'),
'count_requests_by_days' => models\FetchLog::countByDays(),
]);
$format = $request->param('format', 'plain');

if ($format === 'csv') {
$current_year = intval(\Minz\Time::now()->format('Y'));
$year = $request->paramInteger('year', $current_year);

$registrations_per_date = models\User::countPerMonth($year);
$active_per_date = models\User::countActivePerMonth($year);

$dates = array_keys(array_merge($registrations_per_date, $active_per_date));

$stats_per_date = [];
foreach ($dates as $date) {
$count_registrations = $registrations_per_date[$date] ?? 0;
$count_active = $active_per_date[$date] ?? 0;

$stats_per_date[$date] = [
'registrations' => $count_registrations,
'active' => $count_active,
];
}

return Response::ok('cli/system/stats.csv.txt', [
'stats_per_date' => $stats_per_date,
]);
} else {
$count_users = models\User::count();
$count_users_validated = models\User::countValidated();
$percent_users_validated = intval($count_users_validated * 100 / max(1, $count_users));

return Response::ok('cli/system/stats.txt', [
'count_users' => $count_users,
'percent_users_validated' => $percent_users_validated,
'count_users_week' => models\User::countSince(\Minz\Time::ago(1, 'week')),
'count_users_month' => models\User::countSince(\Minz\Time::ago(1, 'month')),
'count_users_active_month' => models\Session::countUsersActiveSince(\Minz\Time::ago(1, 'month')),
'count_links' => models\Link::countEstimated(),
'count_links_to_fetch' => models\Link::countToFetch(),
'count_collections' => models\Collection::countCollections(),
'count_collections_public' => models\Collection::countCollectionsPublic(),
'count_feeds' => models\Collection::countFeeds(),
'count_feeds_by_hours' => models\Collection::countFeedsByHours(),
'count_requests' => models\FetchLog::countEstimated(),
'count_requests_feeds' => models\FetchLog::countByType('feed'),
'count_requests_links' => models\FetchLog::countByType('link'),
'count_requests_images' => models\FetchLog::countByType('image'),
'count_requests_by_days' => models\FetchLog::countByDays(),
]);
}
}

/**
Expand Down
69 changes: 69 additions & 0 deletions src/models/dao/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace flusio\models\dao;

use flusio\models;
use Minz\Database;

/**
Expand Down Expand Up @@ -46,6 +47,74 @@ public static function countSince(\DateTimeImmutable $since): int
return intval($statement->fetchColumn());
}

/**
* Return the number of new users per month for the given year.
*
* @return array<string, int>
*/
public static function countPerMonth(int $year): array
{
$sql = <<<'SQL'
SELECT to_char(created_at, 'YYYY-MM') AS date, COUNT(*) FROM users
WHERE id != :support_user_id
AND created_at >= :since
AND created_at <= :until
GROUP BY date
SQL;

$since = new \DateTimeImmutable();
$since = $since->setDate($year, 1, 1);
$since = $since->setTime(0, 0, 0);

$until = $since->setDate($year, 12, 31);
$until = $until->setTime(23, 59, 59);

$database = Database::get();
$statement = $database->prepare($sql);
$statement->execute([
':support_user_id' => models\User::supportUser()->id,
':since' => $since->format(Database\Column::DATETIME_FORMAT),
':until' => $until->format(Database\Column::DATETIME_FORMAT),
]);

return $statement->fetchAll(\PDO::FETCH_KEY_PAIR);
}

/**
* Return the number of active users per month for the given year.
*
* An active user is a user that created a link during a given month.
*
* @return array<string, int>
*/
public static function countActivePerMonth(int $year): array
{
$sql = <<<'SQL'
SELECT to_char(created_at, 'YYYY-MM') AS date, COUNT(DISTINCT user_id) FROM links
WHERE user_id != :support_user_id
AND created_at >= :since
AND created_at <= :until
GROUP BY date
SQL;

$since = new \DateTimeImmutable();
$since = $since->setDate($year, 1, 1);
$since = $since->setTime(0, 0, 0);

$until = $since->setDate($year, 12, 31);
$until = $until->setTime(23, 59, 59);

$database = Database::get();
$statement = $database->prepare($sql);
$statement->execute([
':support_user_id' => models\User::supportUser()->id,
':since' => $since->format(Database\Column::DATETIME_FORMAT),
':until' => $until->format(Database\Column::DATETIME_FORMAT),
]);

return $statement->fetchAll(\PDO::FETCH_KEY_PAIR);
}

/**
* Delete not validated users older than the given date.
*/
Expand Down
6 changes: 6 additions & 0 deletions src/views/cli/system/stats.csv.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php foreach ($stats_per_date as $date => $stats): ?>
<?= $date . '-01;' ?>
<?= $stats['registrations'] . ';' ?>
<?= $stats['active'] . ';' ?>

<?php endforeach; ?>

0 comments on commit 578a848

Please sign in to comment.