mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 19:06:41 +02:00
✨ feat(stats): add user statistics to Prometheus metrics and Grafana
- Add user metrics to mana-core-auth MetricsService: - auth_users_total: Total registered users - auth_users_verified: Email-verified users - auth_users_created_today/this_week/this_month - Create Grafana user-statistics dashboard with: - User overview stats (total, verified, verification rate, new today) - Registration period breakdown (today/week/month) - User growth trends over time - Enhance telegram-stats-bot /users command: - Add yesterday comparison with trends - Add week-over-week comparison - Add mini bar chart for last 7 days registration - Include user stats in daily Telegram report
This commit is contained in:
parent
9fedb7cfdd
commit
0cd2bc858a
6 changed files with 798 additions and 13 deletions
|
|
@ -8,6 +8,14 @@ export interface UserStats {
|
|||
todayNewUsers: number;
|
||||
weekNewUsers: number;
|
||||
monthNewUsers: number;
|
||||
yesterdayNewUsers: number;
|
||||
lastWeekNewUsers: number;
|
||||
dailyRegistrations: DailyRegistration[];
|
||||
}
|
||||
|
||||
export interface DailyRegistration {
|
||||
date: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -43,31 +51,60 @@ export class UsersService implements OnModuleInit {
|
|||
const startOfToday = new Date(now);
|
||||
startOfToday.setHours(0, 0, 0, 0);
|
||||
|
||||
const startOfYesterday = new Date(startOfToday);
|
||||
startOfYesterday.setDate(startOfYesterday.getDate() - 1);
|
||||
|
||||
const startOfWeek = new Date(now);
|
||||
const day = startOfWeek.getDay();
|
||||
const diff = startOfWeek.getDate() - day + (day === 0 ? -6 : 1);
|
||||
startOfWeek.setDate(diff);
|
||||
startOfWeek.setHours(0, 0, 0, 0);
|
||||
|
||||
const startOfLastWeek = new Date(startOfWeek);
|
||||
startOfLastWeek.setDate(startOfLastWeek.getDate() - 7);
|
||||
|
||||
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
|
||||
// Main stats query
|
||||
const [result] = await this.sql`
|
||||
SELECT
|
||||
COUNT(*) as total_users,
|
||||
COUNT(*) FILTER (WHERE email_verified = true) as verified_users,
|
||||
COUNT(*) FILTER (WHERE created_at >= ${startOfToday.toISOString()}) as today_new_users,
|
||||
COUNT(*) FILTER (WHERE created_at >= ${startOfYesterday.toISOString()} AND created_at < ${startOfToday.toISOString()}) as yesterday_new_users,
|
||||
COUNT(*) FILTER (WHERE created_at >= ${startOfWeek.toISOString()}) as week_new_users,
|
||||
COUNT(*) FILTER (WHERE created_at >= ${startOfLastWeek.toISOString()} AND created_at < ${startOfWeek.toISOString()}) as last_week_new_users,
|
||||
COUNT(*) FILTER (WHERE created_at >= ${startOfMonth.toISOString()}) as month_new_users
|
||||
FROM auth.users
|
||||
WHERE deleted_at IS NULL
|
||||
`;
|
||||
|
||||
// Get daily registrations for last 7 days
|
||||
const dailyStats = await this.sql`
|
||||
SELECT
|
||||
DATE(created_at) as date,
|
||||
COUNT(*) as count
|
||||
FROM auth.users
|
||||
WHERE deleted_at IS NULL
|
||||
AND created_at >= ${new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()}
|
||||
GROUP BY DATE(created_at)
|
||||
ORDER BY date DESC
|
||||
`;
|
||||
|
||||
const dailyRegistrations: DailyRegistration[] = dailyStats.map((row) => ({
|
||||
date: new Date(row.date).toISOString().split('T')[0],
|
||||
count: Number(row.count),
|
||||
}));
|
||||
|
||||
return {
|
||||
totalUsers: Number(result.total_users),
|
||||
verifiedUsers: Number(result.verified_users),
|
||||
todayNewUsers: Number(result.today_new_users),
|
||||
yesterdayNewUsers: Number(result.yesterday_new_users),
|
||||
weekNewUsers: Number(result.week_new_users),
|
||||
lastWeekNewUsers: Number(result.last_week_new_users),
|
||||
monthNewUsers: Number(result.month_new_users),
|
||||
dailyRegistrations,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to fetch user stats:', error);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue