Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Logs
logs
!apps/api/src/domains/logs
!apps/web/src/components/pages/Logs.tsx
*.log
npm-debug.log*
yarn-debug.log*
Expand Down
194 changes: 194 additions & 0 deletions apps/api/src/domains/dashboard/dashboard.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AuthRequest } from '../../middleware/auth';
import logger from '../../utils/logger';
import { DashboardService } from './dashboard.service';
import { GetMetricsQueryDto, GetRecentAlertsQueryDto } from './dto';
import { dashboardAnalyticsService } from './services/dashboard-analytics.service';

const dashboardService = new DashboardService();

Expand Down Expand Up @@ -82,3 +83,196 @@ export const getRecentAlerts = async (
});
}
};

/**
* Get request trend analytics (auto-refresh every 5s)
*/
export const getRequestTrend = async (
req: AuthRequest,
res: Response
): Promise<void> => {
try {
const { interval = 5 } = req.query;
const intervalSeconds = Math.max(5, Math.min(60, Number(interval)));

const trend = await dashboardAnalyticsService.getRequestTrend(intervalSeconds);

res.json({
success: true,
data: trend,
});
} catch (error) {
logger.error('Get request trend error:', error);
res.status(500).json({
success: false,
message: 'Failed to get request trend',
});
}
};

/**
* Get slow requests from performance monitoring
*/
export const getSlowRequests = async (
req: AuthRequest,
res: Response
): Promise<void> => {
try {
const { limit = 10 } = req.query;
const slowRequests = await dashboardAnalyticsService.getSlowRequests(Number(limit));

res.json({
success: true,
data: slowRequests,
});
} catch (error) {
logger.error('Get slow requests error:', error);
res.status(500).json({
success: false,
message: 'Failed to get slow requests',
});
}
};

/**
* Get latest attack statistics (top 5 in 24h)
*/
export const getLatestAttackStats = async (
req: AuthRequest,
res: Response
): Promise<void> => {
try {
const { limit = 5 } = req.query;
const attacks = await dashboardAnalyticsService.getLatestAttacks(Number(limit));

res.json({
success: true,
data: attacks,
});
} catch (error) {
logger.error('Get latest attack stats error:', error);
res.status(500).json({
success: false,
message: 'Failed to get latest attack statistics',
});
}
};

/**
* Get latest security news/events
*/
export const getLatestNews = async (
req: AuthRequest,
res: Response
): Promise<void> => {
try {
const { limit = 20 } = req.query;
const news = await dashboardAnalyticsService.getLatestNews(Number(limit));

res.json({
success: true,
data: news,
});
} catch (error) {
logger.error('Get latest news error:', error);
res.status(500).json({
success: false,
message: 'Failed to get latest news',
});
}
};

/**
* Get request analytics (top IPs by period)
*/
export const getRequestAnalytics = async (
req: AuthRequest,
res: Response
): Promise<void> => {
try {
const { period = 'day' } = req.query;
const validPeriod = ['day', 'week', 'month'].includes(period as string)
? (period as 'day' | 'week' | 'month')
: 'day';

const analytics = await dashboardAnalyticsService.getRequestAnalytics(validPeriod);

res.json({
success: true,
data: analytics,
});
} catch (error) {
logger.error('Get request analytics error:', error);
res.status(500).json({
success: false,
message: 'Failed to get request analytics',
});
}
};

/**
* Get attack vs normal request ratio
*/
export const getAttackRatio = async (
req: AuthRequest,
res: Response
): Promise<void> => {
try {
const ratio = await dashboardAnalyticsService.getAttackRatio();

res.json({
success: true,
data: ratio,
});
} catch (error) {
logger.error('Get attack ratio error:', error);
res.status(500).json({
success: false,
message: 'Failed to get attack ratio',
});
}
};

/**
* Get complete dashboard analytics
*/
export const getDashboardAnalytics = async (
req: AuthRequest,
res: Response
): Promise<void> => {
try {
const [
requestTrend,
slowRequests,
latestAttacks,
latestNews,
requestAnalytics,
attackRatio,
] = await Promise.all([
dashboardAnalyticsService.getRequestTrend(5),
dashboardAnalyticsService.getSlowRequests(10),
dashboardAnalyticsService.getLatestAttacks(5),
dashboardAnalyticsService.getLatestNews(20),
dashboardAnalyticsService.getRequestAnalytics('day'),
dashboardAnalyticsService.getAttackRatio(),
]);

res.json({
success: true,
data: {
requestTrend,
slowRequests,
latestAttacks,
latestNews,
requestAnalytics,
attackRatio,
},
});
} catch (error) {
logger.error('Get dashboard analytics error:', error);
res.status(500).json({
success: false,
message: 'Failed to get dashboard analytics',
});
}
};
22 changes: 22 additions & 0 deletions apps/api/src/domains/dashboard/dashboard.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,26 @@ router.get('/metrics', dashboardController.getSystemMetrics);
// Get recent alerts
router.get('/recent-alerts', dashboardController.getRecentAlerts);

// Dashboard Analytics Endpoints
// Get request trend (auto-refresh every 5s)
router.get('/analytics/request-trend', dashboardController.getRequestTrend);

// Get slow requests
router.get('/analytics/slow-requests', dashboardController.getSlowRequests);

// Get latest attack statistics (top 5 in 24h)
router.get('/analytics/latest-attacks', dashboardController.getLatestAttackStats);

// Get latest security news/events
router.get('/analytics/latest-news', dashboardController.getLatestNews);

// Get request analytics (top IPs by period)
router.get('/analytics/request-analytics', dashboardController.getRequestAnalytics);

// Get attack vs normal request ratio
router.get('/analytics/attack-ratio', dashboardController.getAttackRatio);

// Get complete dashboard analytics (all in one)
router.get('/analytics', dashboardController.getDashboardAnalytics);

export default router;
Loading