@serve.zone/dcrouter 7.0.1 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_serve/bundle.js +528 -587
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.js +18 -1
- package/dist_ts/logger.d.ts +2 -0
- package/dist_ts/logger.js +6 -1
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +37 -0
- package/dist_ts/monitoring/classes.metricsmanager.js +101 -1
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +2 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +70 -25
- package/dist_ts/opsserver/handlers/stats.handler.js +25 -1
- package/dist_ts_interfaces/data/stats.d.ts +23 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/ops-view-logs.d.ts +7 -2
- package/dist_ts_web/elements/ops-view-logs.js +78 -102
- package/dist_ts_web/elements/ops-view-overview.d.ts +6 -0
- package/dist_ts_web/elements/ops-view-overview.js +82 -8
- package/dist_ts_web/elements/ops-view-security.js +42 -36
- package/package.json +2 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +19 -1
- package/ts/logger.ts +7 -0
- package/ts/monitoring/classes.metricsmanager.ts +123 -3
- package/ts/opsserver/handlers/logs.handler.ts +77 -28
- package/ts/opsserver/handlers/stats.handler.ts +27 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/ops-view-logs.ts +72 -108
- package/ts_web/elements/ops-view-overview.ts +80 -6
- package/ts_web/elements/ops-view-security.ts +47 -36
|
@@ -291,6 +291,10 @@ let OpsViewSecurity = (() => {
|
|
|
291
291
|
renderOverview(metrics) {
|
|
292
292
|
const threatLevel = this.calculateThreatLevel(metrics);
|
|
293
293
|
const threatScore = this.getThreatScore(metrics);
|
|
294
|
+
// Derive active sessions from recent successful auth events (last hour)
|
|
295
|
+
const allEvents = metrics.recentEvents || [];
|
|
296
|
+
const oneHourAgo = Date.now() - 3600000;
|
|
297
|
+
const recentAuthSuccesses = allEvents.filter((evt) => evt.type === 'authentication' && evt.success === true && evt.timestamp >= oneHourAgo).length;
|
|
294
298
|
const tiles = [
|
|
295
299
|
{
|
|
296
300
|
id: 'threatLevel',
|
|
@@ -312,7 +316,7 @@ let OpsViewSecurity = (() => {
|
|
|
312
316
|
{
|
|
313
317
|
id: 'blockedThreats',
|
|
314
318
|
title: 'Blocked Threats',
|
|
315
|
-
value: metrics.blockedIPs
|
|
319
|
+
value: (metrics.blockedIPs?.length || 0) + metrics.spamDetected,
|
|
316
320
|
type: 'number',
|
|
317
321
|
icon: 'lucide:ShieldCheck',
|
|
318
322
|
color: '#ef4444',
|
|
@@ -321,11 +325,11 @@ let OpsViewSecurity = (() => {
|
|
|
321
325
|
{
|
|
322
326
|
id: 'activeSessions',
|
|
323
327
|
title: 'Active Sessions',
|
|
324
|
-
value:
|
|
328
|
+
value: recentAuthSuccesses,
|
|
325
329
|
type: 'number',
|
|
326
330
|
icon: 'lucide:Users',
|
|
327
331
|
color: '#22c55e',
|
|
328
|
-
description: '
|
|
332
|
+
description: 'Authenticated in last hour',
|
|
329
333
|
},
|
|
330
334
|
{
|
|
331
335
|
id: 'authFailures',
|
|
@@ -387,6 +391,10 @@ let OpsViewSecurity = (() => {
|
|
|
387
391
|
`;
|
|
388
392
|
}
|
|
389
393
|
renderAuthentication(metrics) {
|
|
394
|
+
// Derive auth events from recentEvents
|
|
395
|
+
const allEvents = metrics.recentEvents || [];
|
|
396
|
+
const authEvents = allEvents.filter((evt) => evt.type === 'authentication');
|
|
397
|
+
const successfulLogins = authEvents.filter((evt) => evt.success === true).length;
|
|
390
398
|
const tiles = [
|
|
391
399
|
{
|
|
392
400
|
id: 'authFailures',
|
|
@@ -400,13 +408,21 @@ let OpsViewSecurity = (() => {
|
|
|
400
408
|
{
|
|
401
409
|
id: 'successfulLogins',
|
|
402
410
|
title: 'Successful Logins',
|
|
403
|
-
value:
|
|
411
|
+
value: successfulLogins,
|
|
404
412
|
type: 'number',
|
|
405
413
|
icon: 'lucide:Lock',
|
|
406
414
|
color: '#22c55e',
|
|
407
415
|
description: 'Successful logins today',
|
|
408
416
|
},
|
|
409
417
|
];
|
|
418
|
+
// Map auth events to login history table data
|
|
419
|
+
const loginHistory = authEvents.map((evt) => ({
|
|
420
|
+
timestamp: evt.timestamp,
|
|
421
|
+
username: evt.details?.username || 'unknown',
|
|
422
|
+
ipAddress: evt.ipAddress || 'unknown',
|
|
423
|
+
success: evt.success ?? false,
|
|
424
|
+
reason: evt.success ? '' : evt.message || 'Authentication failed',
|
|
425
|
+
}));
|
|
410
426
|
return html `
|
|
411
427
|
<dees-statsgrid
|
|
412
428
|
.tiles=${tiles}
|
|
@@ -417,7 +433,7 @@ let OpsViewSecurity = (() => {
|
|
|
417
433
|
<dees-table
|
|
418
434
|
.heading1=${'Login History'}
|
|
419
435
|
.heading2=${'Recent authentication attempts'}
|
|
420
|
-
.data=${
|
|
436
|
+
.data=${loginHistory}
|
|
421
437
|
.displayFunction=${(item) => ({
|
|
422
438
|
'Time': new Date(item.timestamp).toLocaleString(),
|
|
423
439
|
'Username': item.username,
|
|
@@ -518,45 +534,35 @@ let OpsViewSecurity = (() => {
|
|
|
518
534
|
getThreatScore(metrics) {
|
|
519
535
|
// Simple scoring algorithm
|
|
520
536
|
let score = 100;
|
|
521
|
-
|
|
522
|
-
score -=
|
|
523
|
-
score -= metrics.
|
|
524
|
-
score -= metrics.
|
|
525
|
-
score -= metrics.
|
|
526
|
-
score -= metrics.
|
|
537
|
+
const blockedCount = Array.isArray(metrics.blockedIPs) ? metrics.blockedIPs.length : (metrics.blockedIPs || 0);
|
|
538
|
+
score -= blockedCount * 2;
|
|
539
|
+
score -= (metrics.authenticationFailures || 0) * 1;
|
|
540
|
+
score -= (metrics.spamDetected || 0) * 0.5;
|
|
541
|
+
score -= (metrics.malwareDetected || 0) * 3;
|
|
542
|
+
score -= (metrics.phishingDetected || 0) * 3;
|
|
543
|
+
score -= (metrics.suspiciousActivities || 0) * 2;
|
|
527
544
|
return Math.max(0, Math.min(100, Math.round(score)));
|
|
528
545
|
}
|
|
529
546
|
getSecurityEvents(metrics) {
|
|
530
|
-
|
|
531
|
-
return
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
},
|
|
538
|
-
{
|
|
539
|
-
timestamp: Date.now() - 1000 * 60 * 15,
|
|
540
|
-
event: 'SPF check failed',
|
|
541
|
-
severity: 'medium',
|
|
542
|
-
details: 'Domain: example.com',
|
|
543
|
-
},
|
|
544
|
-
{
|
|
545
|
-
timestamp: Date.now() - 1000 * 60 * 30,
|
|
546
|
-
event: 'IP blocked due to spam',
|
|
547
|
-
severity: 'high',
|
|
548
|
-
details: 'IP: 10.0.0.1',
|
|
549
|
-
},
|
|
550
|
-
];
|
|
547
|
+
const events = metrics.recentEvents || [];
|
|
548
|
+
return events.map((evt) => ({
|
|
549
|
+
timestamp: evt.timestamp,
|
|
550
|
+
event: evt.message,
|
|
551
|
+
severity: evt.level === 'critical' ? 'critical' : evt.level === 'error' ? 'high' : evt.level === 'warn' ? 'warning' : 'info',
|
|
552
|
+
details: evt.ipAddress ? `IP: ${evt.ipAddress}` : evt.domain ? `Domain: ${evt.domain}` : evt.type,
|
|
553
|
+
}));
|
|
551
554
|
}
|
|
552
555
|
async clearBlockedIPs() {
|
|
553
|
-
|
|
556
|
+
// SmartProxy manages IP blocking — not yet exposed via API
|
|
557
|
+
alert('Clearing blocked IPs is not yet supported from the UI.');
|
|
554
558
|
}
|
|
555
559
|
async unblockIP(ip) {
|
|
556
|
-
|
|
560
|
+
// SmartProxy manages IP blocking — not yet exposed via API
|
|
561
|
+
alert(`Unblocking IP ${ip} is not yet supported from the UI.`);
|
|
557
562
|
}
|
|
558
563
|
async saveEmailSecuritySettings() {
|
|
559
|
-
|
|
564
|
+
// Config is read-only from the UI for now
|
|
565
|
+
alert('Email security settings are read-only. Update the dcrouter configuration file to change these settings.');
|
|
560
566
|
}
|
|
561
567
|
static {
|
|
562
568
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
@@ -565,4 +571,4 @@ let OpsViewSecurity = (() => {
|
|
|
565
571
|
return OpsViewSecurity = _classThis;
|
|
566
572
|
})();
|
|
567
573
|
export { OpsViewSecurity };
|
|
568
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BzLXZpZXctc2VjdXJpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c193ZWIvZWxlbWVudHMvb3BzLXZpZXctc2VjdXJpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0sbUJBQW1CLENBQUM7QUFDNUMsT0FBTyxLQUFLLFFBQVEsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQ0wsV0FBVyxFQUNYLGFBQWEsRUFDYixJQUFJLEVBQ0osS0FBSyxFQUNMLEdBQUcsRUFDSCxVQUFVLEdBQ1gsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQW1CLE1BQU0sNkJBQTZCLENBQUM7SUFHakQsZUFBZTs0QkFEM0IsYUFBYSxDQUFDLG1CQUFtQixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7Ozs7K0JBQW5CLFNBQVEsV0FBVzs7OztzQ0FDN0MsS0FBSyxFQUFFO3VDQVdQLEtBQUssRUFBRTtZQVZSLG1MQUFTLFVBQVUsNkJBQVYsVUFBVSwrRkFRakI7WUFHRixzTEFBUyxXQUFXLDZCQUFYLFdBQVcsaUdBQTRFO1lBYmxHLDZLQWtnQkM7Ozs7UUFoZ0JDLGlGQUE0QztZQUMxQyxXQUFXLEVBQUUsSUFBSTtZQUNqQixVQUFVLEVBQUUsSUFBSTtZQUNoQixRQUFRLEVBQUUsSUFBSTtZQUNkLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLFdBQVcsRUFBRSxDQUFDO1lBQ2QsU0FBUyxFQUFFLEtBQUs7WUFDaEIsS0FBSyxFQUFFLElBQUk7U0FDWixFQUFDO1FBUkYsSUFBUyxVQUFVLGdEQVFqQjtRQVJGLElBQVMsVUFBVSxzREFRakI7UUFHRiw0SUFBcUYsVUFBVSxHQUFDO1FBQWhHLElBQVMsV0FBVyxpREFBNEU7UUFBaEcsSUFBUyxXQUFXLHVEQUE0RTtRQUVoRztZQUNF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
|
|
574
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BzLXZpZXctc2VjdXJpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c193ZWIvZWxlbWVudHMvb3BzLXZpZXctc2VjdXJpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0sbUJBQW1CLENBQUM7QUFDNUMsT0FBTyxLQUFLLFFBQVEsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQ0wsV0FBVyxFQUNYLGFBQWEsRUFDYixJQUFJLEVBQ0osS0FBSyxFQUNMLEdBQUcsRUFDSCxVQUFVLEdBQ1gsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQW1CLE1BQU0sNkJBQTZCLENBQUM7SUFHakQsZUFBZTs0QkFEM0IsYUFBYSxDQUFDLG1CQUFtQixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7Ozs7K0JBQW5CLFNBQVEsV0FBVzs7OztzQ0FDN0MsS0FBSyxFQUFFO3VDQVdQLEtBQUssRUFBRTtZQVZSLG1MQUFTLFVBQVUsNkJBQVYsVUFBVSwrRkFRakI7WUFHRixzTEFBUyxXQUFXLDZCQUFYLFdBQVcsaUdBQTRFO1lBYmxHLDZLQTZnQkM7Ozs7UUEzZ0JDLGlGQUE0QztZQUMxQyxXQUFXLEVBQUUsSUFBSTtZQUNqQixVQUFVLEVBQUUsSUFBSTtZQUNoQixRQUFRLEVBQUUsSUFBSTtZQUNkLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLFdBQVcsRUFBRSxDQUFDO1lBQ2QsU0FBUyxFQUFFLEtBQUs7WUFDaEIsS0FBSyxFQUFFLElBQUk7U0FDWixFQUFDO1FBUkYsSUFBUyxVQUFVLGdEQVFqQjtRQVJGLElBQVMsVUFBVSxzREFRakI7UUFHRiw0SUFBcUYsVUFBVSxHQUFDO1FBQWhHLElBQVMsV0FBVyxpREFBNEU7UUFBaEcsSUFBUyxXQUFXLHVEQUE0RTtRQUVoRztZQUNF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
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/dcrouter",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "7.0
|
|
4
|
+
"version": "7.2.0",
|
|
5
5
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@push.rocks/smartfile": "^13.1.2",
|
|
43
43
|
"@push.rocks/smartguard": "^3.1.0",
|
|
44
44
|
"@push.rocks/smartjwt": "^2.2.1",
|
|
45
|
-
"@push.rocks/smartlog": "^3.1
|
|
45
|
+
"@push.rocks/smartlog": "^3.2.1",
|
|
46
46
|
"@push.rocks/smartmetrics": "^3.0.1",
|
|
47
47
|
"@push.rocks/smartmongo": "^5.1.0",
|
|
48
48
|
"@push.rocks/smartmta": "^5.2.2",
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/classes.dcrouter.ts
CHANGED
|
@@ -1055,7 +1055,25 @@ export class DcRouter {
|
|
|
1055
1055
|
|
|
1056
1056
|
// Start the server
|
|
1057
1057
|
await this.emailServer.start();
|
|
1058
|
-
|
|
1058
|
+
|
|
1059
|
+
// Wire delivery events to MetricsManager for time-series tracking
|
|
1060
|
+
if (this.metricsManager && this.emailServer.deliverySystem) {
|
|
1061
|
+
this.emailServer.deliverySystem.on('deliveryStart', (item: any) => {
|
|
1062
|
+
this.metricsManager.trackEmailReceived(item?.from);
|
|
1063
|
+
});
|
|
1064
|
+
this.emailServer.deliverySystem.on('deliverySuccess', (item: any) => {
|
|
1065
|
+
this.metricsManager.trackEmailSent(item?.to);
|
|
1066
|
+
});
|
|
1067
|
+
this.emailServer.deliverySystem.on('deliveryFailed', (item: any, error: any) => {
|
|
1068
|
+
this.metricsManager.trackEmailFailed(item?.to, error?.message);
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
if (this.metricsManager && this.emailServer) {
|
|
1072
|
+
this.emailServer.on('bounceProcessed', () => {
|
|
1073
|
+
this.metricsManager.trackEmailBounced();
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1059
1077
|
logger.log('info', `Email server started on ports: ${emailConfig.ports.join(', ')}`);
|
|
1060
1078
|
}
|
|
1061
1079
|
|
package/ts/logger.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { SmartlogDestinationBuffer } from '@push.rocks/smartlog/destination-buffer';
|
|
3
4
|
|
|
4
5
|
// Map NODE_ENV to valid TEnvironment
|
|
5
6
|
const nodeEnv = process.env.NODE_ENV || 'production';
|
|
@@ -10,6 +11,9 @@ const envMap: Record<string, 'local' | 'test' | 'staging' | 'production'> = {
|
|
|
10
11
|
'production': 'production'
|
|
11
12
|
};
|
|
12
13
|
|
|
14
|
+
// In-memory log buffer for the OpsServer UI
|
|
15
|
+
export const logBuffer = new SmartlogDestinationBuffer({ maxEntries: 2000 });
|
|
16
|
+
|
|
13
17
|
// Default Smartlog instance
|
|
14
18
|
const baseLogger = new plugins.smartlog.Smartlog({
|
|
15
19
|
logContext: {
|
|
@@ -19,6 +23,9 @@ const baseLogger = new plugins.smartlog.Smartlog({
|
|
|
19
23
|
}
|
|
20
24
|
});
|
|
21
25
|
|
|
26
|
+
// Wire the buffer destination so all logs are captured
|
|
27
|
+
baseLogger.addLogDestination(logBuffer);
|
|
28
|
+
|
|
22
29
|
// Extended logger compatible with the original enhanced logger API
|
|
23
30
|
class StandardLogger {
|
|
24
31
|
private defaultContext: Record<string, any> = {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { DcRouter } from '../classes.dcrouter.js';
|
|
3
3
|
import { MetricsCache } from './classes.metricscache.js';
|
|
4
|
+
import { SecurityLogger, SecurityEventType } from '../security/classes.securitylogger.js';
|
|
4
5
|
|
|
5
6
|
export class MetricsManager {
|
|
6
7
|
private logger: plugins.smartlog.Smartlog;
|
|
@@ -37,6 +38,10 @@ export class MetricsManager {
|
|
|
37
38
|
responseTimes: [] as number[], // Track response times in ms
|
|
38
39
|
};
|
|
39
40
|
|
|
41
|
+
// Per-minute time-series buckets for charts
|
|
42
|
+
private emailMinuteBuckets = new Map<number, { sent: number; received: number; failed: number }>();
|
|
43
|
+
private dnsMinuteBuckets = new Map<number, { queries: number }>();
|
|
44
|
+
|
|
40
45
|
// Track security-specific metrics
|
|
41
46
|
private securityMetrics = {
|
|
42
47
|
blockedIPs: 0,
|
|
@@ -227,20 +232,45 @@ export class MetricsManager {
|
|
|
227
232
|
});
|
|
228
233
|
}
|
|
229
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Sync security metrics from the SecurityLogger singleton (last 24h).
|
|
237
|
+
* Called before returning security stats so counters reflect real events.
|
|
238
|
+
*/
|
|
239
|
+
private syncFromSecurityLogger(): void {
|
|
240
|
+
try {
|
|
241
|
+
const securityLogger = SecurityLogger.getInstance();
|
|
242
|
+
const summary = securityLogger.getEventsSummary(86400000); // last 24h
|
|
243
|
+
|
|
244
|
+
this.securityMetrics.spamDetected = summary.byType[SecurityEventType.SPAM] || 0;
|
|
245
|
+
this.securityMetrics.malwareDetected = summary.byType[SecurityEventType.MALWARE] || 0;
|
|
246
|
+
this.securityMetrics.phishingDetected = summary.byType[SecurityEventType.DMARC] || 0; // phishing via DMARC
|
|
247
|
+
this.securityMetrics.authFailures =
|
|
248
|
+
summary.byType[SecurityEventType.AUTHENTICATION] || 0;
|
|
249
|
+
this.securityMetrics.blockedIPs =
|
|
250
|
+
(summary.byType[SecurityEventType.IP_REPUTATION] || 0) +
|
|
251
|
+
(summary.byType[SecurityEventType.REJECTED_CONNECTION] || 0);
|
|
252
|
+
} catch {
|
|
253
|
+
// SecurityLogger may not be initialized yet — ignore
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
230
257
|
// Get security metrics
|
|
231
258
|
public async getSecurityStats() {
|
|
232
259
|
return this.metricsCache.get('securityStats', () => {
|
|
260
|
+
// Sync counters from the real SecurityLogger events
|
|
261
|
+
this.syncFromSecurityLogger();
|
|
262
|
+
|
|
233
263
|
// Get recent incidents (last 20)
|
|
234
264
|
const recentIncidents = this.securityMetrics.incidents.slice(-20);
|
|
235
|
-
|
|
265
|
+
|
|
236
266
|
return {
|
|
237
267
|
blockedIPs: this.securityMetrics.blockedIPs,
|
|
238
268
|
authFailures: this.securityMetrics.authFailures,
|
|
239
269
|
spamDetected: this.securityMetrics.spamDetected,
|
|
240
270
|
malwareDetected: this.securityMetrics.malwareDetected,
|
|
241
271
|
phishingDetected: this.securityMetrics.phishingDetected,
|
|
242
|
-
totalThreatsBlocked: this.securityMetrics.spamDetected +
|
|
243
|
-
this.securityMetrics.malwareDetected +
|
|
272
|
+
totalThreatsBlocked: this.securityMetrics.spamDetected +
|
|
273
|
+
this.securityMetrics.malwareDetected +
|
|
244
274
|
this.securityMetrics.phishingDetected,
|
|
245
275
|
recentIncidents,
|
|
246
276
|
};
|
|
@@ -275,6 +305,7 @@ export class MetricsManager {
|
|
|
275
305
|
// Email event tracking methods
|
|
276
306
|
public trackEmailSent(recipient?: string, deliveryTimeMs?: number): void {
|
|
277
307
|
this.emailMetrics.sentToday++;
|
|
308
|
+
this.incrementEmailBucket('sent');
|
|
278
309
|
|
|
279
310
|
if (recipient) {
|
|
280
311
|
const count = this.emailMetrics.recipients.get(recipient) || 0;
|
|
@@ -311,6 +342,7 @@ export class MetricsManager {
|
|
|
311
342
|
|
|
312
343
|
public trackEmailReceived(sender?: string): void {
|
|
313
344
|
this.emailMetrics.receivedToday++;
|
|
345
|
+
this.incrementEmailBucket('received');
|
|
314
346
|
|
|
315
347
|
this.emailMetrics.recentActivity.push({
|
|
316
348
|
timestamp: Date.now(),
|
|
@@ -326,6 +358,7 @@ export class MetricsManager {
|
|
|
326
358
|
|
|
327
359
|
public trackEmailFailed(recipient?: string, reason?: string): void {
|
|
328
360
|
this.emailMetrics.failedToday++;
|
|
361
|
+
this.incrementEmailBucket('failed');
|
|
329
362
|
|
|
330
363
|
this.emailMetrics.recentActivity.push({
|
|
331
364
|
timestamp: Date.now(),
|
|
@@ -361,6 +394,7 @@ export class MetricsManager {
|
|
|
361
394
|
// DNS event tracking methods
|
|
362
395
|
public trackDnsQuery(queryType: string, domain: string, cacheHit: boolean, responseTimeMs?: number): void {
|
|
363
396
|
this.dnsMetrics.totalQueries++;
|
|
397
|
+
this.incrementDnsBucket();
|
|
364
398
|
|
|
365
399
|
if (cacheHit) {
|
|
366
400
|
this.dnsMetrics.cacheHits++;
|
|
@@ -547,4 +581,90 @@ export class MetricsManager {
|
|
|
547
581
|
};
|
|
548
582
|
}, 200); // Use 200ms cache for more frequent updates
|
|
549
583
|
}
|
|
584
|
+
|
|
585
|
+
// --- Time-series helpers ---
|
|
586
|
+
|
|
587
|
+
private static minuteKey(ts: number = Date.now()): number {
|
|
588
|
+
return Math.floor(ts / 60000) * 60000;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
private incrementEmailBucket(field: 'sent' | 'received' | 'failed'): void {
|
|
592
|
+
const key = MetricsManager.minuteKey();
|
|
593
|
+
let bucket = this.emailMinuteBuckets.get(key);
|
|
594
|
+
if (!bucket) {
|
|
595
|
+
bucket = { sent: 0, received: 0, failed: 0 };
|
|
596
|
+
this.emailMinuteBuckets.set(key, bucket);
|
|
597
|
+
}
|
|
598
|
+
bucket[field]++;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
private incrementDnsBucket(): void {
|
|
602
|
+
const key = MetricsManager.minuteKey();
|
|
603
|
+
let bucket = this.dnsMinuteBuckets.get(key);
|
|
604
|
+
if (!bucket) {
|
|
605
|
+
bucket = { queries: 0 };
|
|
606
|
+
this.dnsMinuteBuckets.set(key, bucket);
|
|
607
|
+
}
|
|
608
|
+
bucket.queries++;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
private pruneOldBuckets(): void {
|
|
612
|
+
const cutoff = Date.now() - 86400000; // 24h
|
|
613
|
+
for (const key of this.emailMinuteBuckets.keys()) {
|
|
614
|
+
if (key < cutoff) this.emailMinuteBuckets.delete(key);
|
|
615
|
+
}
|
|
616
|
+
for (const key of this.dnsMinuteBuckets.keys()) {
|
|
617
|
+
if (key < cutoff) this.dnsMinuteBuckets.delete(key);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Get email time-series data for the last N hours, aggregated per minute.
|
|
623
|
+
*/
|
|
624
|
+
public getEmailTimeSeries(hours: number = 24): {
|
|
625
|
+
sent: Array<{ timestamp: number; value: number }>;
|
|
626
|
+
received: Array<{ timestamp: number; value: number }>;
|
|
627
|
+
failed: Array<{ timestamp: number; value: number }>;
|
|
628
|
+
} {
|
|
629
|
+
this.pruneOldBuckets();
|
|
630
|
+
const cutoff = Date.now() - hours * 3600000;
|
|
631
|
+
const sent: Array<{ timestamp: number; value: number }> = [];
|
|
632
|
+
const received: Array<{ timestamp: number; value: number }> = [];
|
|
633
|
+
const failed: Array<{ timestamp: number; value: number }> = [];
|
|
634
|
+
|
|
635
|
+
const sortedKeys = Array.from(this.emailMinuteBuckets.keys())
|
|
636
|
+
.filter((k) => k >= cutoff)
|
|
637
|
+
.sort((a, b) => a - b);
|
|
638
|
+
|
|
639
|
+
for (const key of sortedKeys) {
|
|
640
|
+
const bucket = this.emailMinuteBuckets.get(key)!;
|
|
641
|
+
sent.push({ timestamp: key, value: bucket.sent });
|
|
642
|
+
received.push({ timestamp: key, value: bucket.received });
|
|
643
|
+
failed.push({ timestamp: key, value: bucket.failed });
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return { sent, received, failed };
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Get DNS time-series data for the last N hours, aggregated per minute.
|
|
651
|
+
*/
|
|
652
|
+
public getDnsTimeSeries(hours: number = 24): {
|
|
653
|
+
queries: Array<{ timestamp: number; value: number }>;
|
|
654
|
+
} {
|
|
655
|
+
this.pruneOldBuckets();
|
|
656
|
+
const cutoff = Date.now() - hours * 3600000;
|
|
657
|
+
const queries: Array<{ timestamp: number; value: number }> = [];
|
|
658
|
+
|
|
659
|
+
const sortedKeys = Array.from(this.dnsMinuteBuckets.keys())
|
|
660
|
+
.filter((k) => k >= cutoff)
|
|
661
|
+
.sort((a, b) => a - b);
|
|
662
|
+
|
|
663
|
+
for (const key of sortedKeys) {
|
|
664
|
+
const bucket = this.dnsMinuteBuckets.get(key)!;
|
|
665
|
+
queries.push({ timestamp: key, value: bucket.queries });
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
return { queries };
|
|
669
|
+
}
|
|
550
670
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
3
|
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
4
|
+
import { logBuffer } from '../../logger.js';
|
|
4
5
|
|
|
5
6
|
export class LogsHandler {
|
|
6
7
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
@@ -64,6 +65,32 @@ export class LogsHandler {
|
|
|
64
65
|
);
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
private static mapLogLevel(smartlogLevel: string): 'debug' | 'info' | 'warn' | 'error' {
|
|
69
|
+
switch (smartlogLevel) {
|
|
70
|
+
case 'silly':
|
|
71
|
+
case 'debug':
|
|
72
|
+
return 'debug';
|
|
73
|
+
case 'warn':
|
|
74
|
+
return 'warn';
|
|
75
|
+
case 'error':
|
|
76
|
+
return 'error';
|
|
77
|
+
default:
|
|
78
|
+
return 'info';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private static deriveCategory(
|
|
83
|
+
zone?: string,
|
|
84
|
+
message?: string
|
|
85
|
+
): 'smtp' | 'dns' | 'security' | 'system' | 'email' {
|
|
86
|
+
const msg = (message || '').toLowerCase();
|
|
87
|
+
if (msg.includes('[security:') || msg.includes('security')) return 'security';
|
|
88
|
+
if (zone === 'email' || msg.includes('email') || msg.includes('smtp') || msg.includes('mta')) return 'email';
|
|
89
|
+
if (zone === 'dns' || msg.includes('dns')) return 'dns';
|
|
90
|
+
if (msg.includes('smtp')) return 'smtp';
|
|
91
|
+
return 'system';
|
|
92
|
+
}
|
|
93
|
+
|
|
67
94
|
private async getRecentLogs(
|
|
68
95
|
level?: 'error' | 'warn' | 'info' | 'debug',
|
|
69
96
|
category?: 'smtp' | 'dns' | 'security' | 'system' | 'email',
|
|
@@ -78,42 +105,64 @@ export class LogsHandler {
|
|
|
78
105
|
message: string;
|
|
79
106
|
metadata?: any;
|
|
80
107
|
}>> {
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
108
|
+
// Compute a timestamp cutoff from timeRange
|
|
109
|
+
let since: number | undefined;
|
|
110
|
+
if (timeRange) {
|
|
111
|
+
const rangeMs: Record<string, number> = {
|
|
112
|
+
'1h': 3600000,
|
|
113
|
+
'6h': 21600000,
|
|
114
|
+
'24h': 86400000,
|
|
115
|
+
'7d': 604800000,
|
|
116
|
+
'30d': 2592000000,
|
|
117
|
+
};
|
|
118
|
+
since = Date.now() - (rangeMs[timeRange] || 86400000);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Map the UI level to smartlog levels for filtering
|
|
122
|
+
const smartlogLevels: string[] | undefined = level
|
|
123
|
+
? level === 'debug'
|
|
124
|
+
? ['debug', 'silly']
|
|
125
|
+
: level === 'info'
|
|
126
|
+
? ['info', 'ok', 'success', 'note', 'lifecycle']
|
|
127
|
+
: [level]
|
|
128
|
+
: undefined;
|
|
129
|
+
|
|
130
|
+
// Fetch a larger batch from buffer, then apply category filter client-side
|
|
131
|
+
const rawEntries = logBuffer.getEntries({
|
|
132
|
+
level: smartlogLevels as any,
|
|
133
|
+
search,
|
|
134
|
+
since,
|
|
135
|
+
limit: limit * 3, // over-fetch to compensate for category filtering
|
|
136
|
+
offset: 0,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Map ILogPackage → UI log format and apply category filter
|
|
140
|
+
const mapped: Array<{
|
|
84
141
|
timestamp: number;
|
|
85
142
|
level: 'debug' | 'info' | 'warn' | 'error';
|
|
86
143
|
category: 'smtp' | 'dns' | 'security' | 'system' | 'email';
|
|
87
144
|
message: string;
|
|
88
145
|
metadata?: any;
|
|
89
146
|
}> = [];
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
mockLogs.push({
|
|
105
|
-
timestamp: now - (i * 60000), // 1 minute apart
|
|
106
|
-
level: mockLevel,
|
|
107
|
-
category: mockCategory,
|
|
108
|
-
message: `Sample log message ${i} from ${mockCategory}`,
|
|
109
|
-
metadata: {
|
|
110
|
-
requestId: plugins.uuid.v4(),
|
|
111
|
-
},
|
|
147
|
+
|
|
148
|
+
for (const pkg of rawEntries) {
|
|
149
|
+
const uiLevel = LogsHandler.mapLogLevel(pkg.level);
|
|
150
|
+
const uiCategory = LogsHandler.deriveCategory(pkg.context?.zone, pkg.message);
|
|
151
|
+
|
|
152
|
+
if (category && uiCategory !== category) continue;
|
|
153
|
+
|
|
154
|
+
mapped.push({
|
|
155
|
+
timestamp: pkg.timestamp,
|
|
156
|
+
level: uiLevel,
|
|
157
|
+
category: uiCategory,
|
|
158
|
+
message: pkg.message,
|
|
159
|
+
metadata: pkg.data,
|
|
112
160
|
});
|
|
161
|
+
|
|
162
|
+
if (mapped.length >= limit) break;
|
|
113
163
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return mockLogs.slice(offset, offset + limit);
|
|
164
|
+
|
|
165
|
+
return mapped;
|
|
117
166
|
}
|
|
118
167
|
|
|
119
168
|
private setupLogStream(
|