fix(logging): add adaptive rate-limited DNS query logging, flush pending DNS logs on shutdown, and enhance email delivery logging
This commit is contained in:
@@ -1,5 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-02-21 - 7.4.3 - fix(logging)
|
||||||
|
add adaptive rate-limited DNS query logging, flush pending DNS logs on shutdown, and enhance email delivery logging
|
||||||
|
|
||||||
|
- Introduce adaptive DNS logging: allow up to 2 individual DNS query logs per second, then aggregate further queries and emit a batched summary (dnsLogWindow, dnsBatchCount, dnsBatchTimer) with a 5s flush.
|
||||||
|
- Flush pending DNS batch on stop() and log final DNS batch count during shutdown.
|
||||||
|
- Enhance email observability by logging deliveryStart, deliverySuccess, deliveryFailed and bounceProcessed events alongside existing MetricsManager tracking.
|
||||||
|
- Dependency bump: @design.estate/dees-catalog updated from ^3.43.1 to ^3.43.2.
|
||||||
|
- Non-breaking change; intended as a patch release.
|
||||||
|
|
||||||
## 2026-02-21 - 7.4.2 - fix(monitoring,remoteingress,web)
|
## 2026-02-21 - 7.4.2 - fix(monitoring,remoteingress,web)
|
||||||
Prune old metrics buckets periodically, clear metrics caches on shutdown, simplify edge disconnect handling, and optimize network view data updates
|
Prune old metrics buckets periodically, clear metrics caches on shutdown, simplify edge disconnect handling, and optimize network view data updates
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
"@api.global/typedserver": "^8.3.0",
|
"@api.global/typedserver": "^8.3.0",
|
||||||
"@api.global/typedsocket": "^4.1.0",
|
"@api.global/typedsocket": "^4.1.0",
|
||||||
"@apiclient.xyz/cloudflare": "^7.1.0",
|
"@apiclient.xyz/cloudflare": "^7.1.0",
|
||||||
"@design.estate/dees-catalog": "^3.43.1",
|
"@design.estate/dees-catalog": "^3.43.2",
|
||||||
"@design.estate/dees-element": "^2.1.6",
|
"@design.estate/dees-element": "^2.1.6",
|
||||||
"@push.rocks/projectinfo": "^5.0.2",
|
"@push.rocks/projectinfo": "^5.0.2",
|
||||||
"@push.rocks/qenv": "^6.1.3",
|
"@push.rocks/qenv": "^6.1.3",
|
||||||
|
|||||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -24,8 +24,8 @@ importers:
|
|||||||
specifier: ^7.1.0
|
specifier: ^7.1.0
|
||||||
version: 7.1.0
|
version: 7.1.0
|
||||||
'@design.estate/dees-catalog':
|
'@design.estate/dees-catalog':
|
||||||
specifier: ^3.43.1
|
specifier: ^3.43.2
|
||||||
version: 3.43.1(@tiptap/pm@2.27.2)
|
version: 3.43.2(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-element':
|
'@design.estate/dees-element':
|
||||||
specifier: ^2.1.6
|
specifier: ^2.1.6
|
||||||
version: 2.1.6
|
version: 2.1.6
|
||||||
@@ -351,8 +351,8 @@ packages:
|
|||||||
'@configvault.io/interfaces@1.0.17':
|
'@configvault.io/interfaces@1.0.17':
|
||||||
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
|
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
|
||||||
|
|
||||||
'@design.estate/dees-catalog@3.43.1':
|
'@design.estate/dees-catalog@3.43.2':
|
||||||
resolution: {integrity: sha512-WAWOV8dIgdKfAbS4Ciek8oDVIWC0OSPODhpQdLlsGBXERcFaBPaYxcpywmrjXB/TFeoAQPxBxhS7jb9/p2Rprg==}
|
resolution: {integrity: sha512-7pU+K+B70SxqR4DrBkpc/xvQGLDkxAV2jH7Qyh0TYgkCoxxjsxCuTMKM9JguA38wm6bEgBJVTvyg5S3wCwxm4Q==}
|
||||||
|
|
||||||
'@design.estate/dees-comms@1.0.30':
|
'@design.estate/dees-comms@1.0.30':
|
||||||
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
||||||
@@ -4334,7 +4334,7 @@ snapshots:
|
|||||||
'@api.global/typedrequest-interfaces': 3.0.19
|
'@api.global/typedrequest-interfaces': 3.0.19
|
||||||
'@api.global/typedsocket': 4.1.0(@push.rocks/smartserve@2.0.1)
|
'@api.global/typedsocket': 4.1.0(@push.rocks/smartserve@2.0.1)
|
||||||
'@cloudflare/workers-types': 4.20260210.0
|
'@cloudflare/workers-types': 4.20260210.0
|
||||||
'@design.estate/dees-catalog': 3.43.1(@tiptap/pm@2.27.2)
|
'@design.estate/dees-catalog': 3.43.2(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-comms': 1.0.30
|
'@design.estate/dees-comms': 1.0.30
|
||||||
'@push.rocks/lik': 6.2.2
|
'@push.rocks/lik': 6.2.2
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
@@ -4932,7 +4932,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@api.global/typedrequest-interfaces': 3.0.19
|
'@api.global/typedrequest-interfaces': 3.0.19
|
||||||
|
|
||||||
'@design.estate/dees-catalog@3.43.1(@tiptap/pm@2.27.2)':
|
'@design.estate/dees-catalog@3.43.2(@tiptap/pm@2.27.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@design.estate/dees-domtools': 2.3.8
|
'@design.estate/dees-domtools': 2.3.8
|
||||||
'@design.estate/dees-element': 2.1.6
|
'@design.estate/dees-element': 2.1.6
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '7.4.2',
|
version: '7.4.3',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,6 +212,11 @@ export class DcRouter {
|
|||||||
public remoteIngressManager?: RemoteIngressManager;
|
public remoteIngressManager?: RemoteIngressManager;
|
||||||
public tunnelManager?: TunnelManager;
|
public tunnelManager?: TunnelManager;
|
||||||
|
|
||||||
|
// DNS query logging rate limiter state
|
||||||
|
private dnsLogWindow: number[] = [];
|
||||||
|
private dnsBatchCount: number = 0;
|
||||||
|
private dnsBatchTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
// Certificate status tracking from SmartProxy events (keyed by domain)
|
// Certificate status tracking from SmartProxy events (keyed by domain)
|
||||||
public certificateStatusMap = new Map<string, {
|
public certificateStatusMap = new Map<string, {
|
||||||
status: 'valid' | 'failed';
|
status: 'valid' | 'failed';
|
||||||
@@ -855,6 +860,17 @@ export class DcRouter {
|
|||||||
public async stop() {
|
public async stop() {
|
||||||
logger.log('info', 'Stopping DcRouter services...');
|
logger.log('info', 'Stopping DcRouter services...');
|
||||||
|
|
||||||
|
// Flush pending DNS batch log
|
||||||
|
if (this.dnsBatchTimer) {
|
||||||
|
clearTimeout(this.dnsBatchTimer);
|
||||||
|
if (this.dnsBatchCount > 0) {
|
||||||
|
logger.log('info', `DNS: ${this.dnsBatchCount} queries processed (rate limited, final flush)`, { zone: 'dns' });
|
||||||
|
}
|
||||||
|
this.dnsBatchTimer = null;
|
||||||
|
this.dnsBatchCount = 0;
|
||||||
|
this.dnsLogWindow = [];
|
||||||
|
}
|
||||||
|
|
||||||
await this.opsServer.stop();
|
await this.opsServer.stop();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1002,21 +1018,25 @@ export class DcRouter {
|
|||||||
// Start the server
|
// Start the server
|
||||||
await this.emailServer.start();
|
await this.emailServer.start();
|
||||||
|
|
||||||
// Wire delivery events to MetricsManager for time-series tracking
|
// Wire delivery events to MetricsManager and logger
|
||||||
if (this.metricsManager && this.emailServer.deliverySystem) {
|
if (this.metricsManager && this.emailServer.deliverySystem) {
|
||||||
this.emailServer.deliverySystem.on('deliveryStart', (item: any) => {
|
this.emailServer.deliverySystem.on('deliveryStart', (item: any) => {
|
||||||
this.metricsManager.trackEmailReceived(item?.from);
|
this.metricsManager.trackEmailReceived(item?.from);
|
||||||
|
logger.log('info', `Email delivery started: ${item?.from} → ${item?.to}`, { zone: 'email' });
|
||||||
});
|
});
|
||||||
this.emailServer.deliverySystem.on('deliverySuccess', (item: any) => {
|
this.emailServer.deliverySystem.on('deliverySuccess', (item: any) => {
|
||||||
this.metricsManager.trackEmailSent(item?.to);
|
this.metricsManager.trackEmailSent(item?.to);
|
||||||
|
logger.log('info', `Email delivered to ${item?.to}`, { zone: 'email' });
|
||||||
});
|
});
|
||||||
this.emailServer.deliverySystem.on('deliveryFailed', (item: any, error: any) => {
|
this.emailServer.deliverySystem.on('deliveryFailed', (item: any, error: any) => {
|
||||||
this.metricsManager.trackEmailFailed(item?.to, error?.message);
|
this.metricsManager.trackEmailFailed(item?.to, error?.message);
|
||||||
|
logger.log('warn', `Email delivery failed to ${item?.to}: ${error?.message}`, { zone: 'email' });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (this.metricsManager && this.emailServer) {
|
if (this.metricsManager && this.emailServer) {
|
||||||
this.emailServer.on('bounceProcessed', () => {
|
this.emailServer.on('bounceProcessed', () => {
|
||||||
this.metricsManager.trackEmailBounced();
|
this.metricsManager.trackEmailBounced();
|
||||||
|
logger.log('warn', 'Email bounce processed', { zone: 'email' });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1203,9 +1223,18 @@ export class DcRouter {
|
|||||||
await this.dnsServer.start();
|
await this.dnsServer.start();
|
||||||
logger.log('info', `DNS server started on UDP ${vmIpAddress}:53`);
|
logger.log('info', `DNS server started on UDP ${vmIpAddress}:53`);
|
||||||
|
|
||||||
// Wire DNS query events to MetricsManager for time-series tracking
|
// Wire DNS query events to MetricsManager and logger with adaptive rate limiting
|
||||||
if (this.metricsManager && this.dnsServer) {
|
if (this.metricsManager && this.dnsServer) {
|
||||||
|
const flushDnsBatch = () => {
|
||||||
|
if (this.dnsBatchCount > 0) {
|
||||||
|
logger.log('info', `DNS: ${this.dnsBatchCount} queries processed (rate limited)`, { zone: 'dns' });
|
||||||
|
this.dnsBatchCount = 0;
|
||||||
|
}
|
||||||
|
this.dnsBatchTimer = null;
|
||||||
|
};
|
||||||
|
|
||||||
this.dnsServer.on('query', (event: plugins.smartdns.dnsServerMod.IDnsQueryCompletedEvent) => {
|
this.dnsServer.on('query', (event: plugins.smartdns.dnsServerMod.IDnsQueryCompletedEvent) => {
|
||||||
|
// Metrics tracking
|
||||||
for (const question of event.questions) {
|
for (const question of event.questions) {
|
||||||
this.metricsManager.trackDnsQuery(
|
this.metricsManager.trackDnsQuery(
|
||||||
question.type,
|
question.type,
|
||||||
@@ -1215,6 +1244,21 @@ export class DcRouter {
|
|||||||
event.answered,
|
event.answered,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adaptive logging: individual logs up to 2/sec, then batch
|
||||||
|
const now = Date.now();
|
||||||
|
this.dnsLogWindow = this.dnsLogWindow.filter(t => now - t < 1000);
|
||||||
|
|
||||||
|
if (this.dnsLogWindow.length < 2) {
|
||||||
|
this.dnsLogWindow.push(now);
|
||||||
|
const summary = event.questions.map(q => `${q.type} ${q.name}`).join(', ');
|
||||||
|
logger.log('info', `DNS query: ${summary} (${event.responseTimeMs}ms, ${event.answered ? 'answered' : 'unanswered'})`, { zone: 'dns' });
|
||||||
|
} else {
|
||||||
|
this.dnsBatchCount++;
|
||||||
|
if (!this.dnsBatchTimer) {
|
||||||
|
this.dnsBatchTimer = setTimeout(flushDnsBatch, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '7.4.2',
|
version: '7.4.3',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user