@serve.zone/dcrouter 7.3.0 → 7.4.1
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 +592 -592
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.js +50 -104
- package/dist_ts/logger.d.ts +2 -0
- package/dist_ts/logger.js +3 -3
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +9 -2
- package/dist_ts/monitoring/classes.metricsmanager.js +23 -8
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +5 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +43 -2
- package/dist_ts/opsserver/handlers/stats.handler.js +3 -1
- package/dist_ts_interfaces/data/stats.d.ts +7 -0
- package/dist_ts_interfaces/requests/logs.d.ts +7 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.js +51 -1
- package/dist_ts_web/elements/ops-view-logs.d.ts +1 -0
- package/dist_ts_web/elements/ops-view-logs.js +31 -7
- package/dist_ts_web/elements/ops-view-overview.d.ts +1 -0
- package/dist_ts_web/elements/ops-view-overview.js +12 -3
- package/dist_ts_web/plugins.d.ts +2 -1
- package/dist_ts_web/plugins.js +4 -2
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +54 -107
- package/ts/logger.ts +2 -2
- package/ts/monitoring/classes.metricsmanager.ts +25 -9
- package/ts/opsserver/handlers/logs.handler.ts +47 -2
- package/ts/opsserver/handlers/stats.handler.ts +4 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +61 -0
- package/ts_web/elements/ops-view-logs.ts +28 -5
- package/ts_web/elements/ops-view-overview.ts +12 -2
- package/ts_web/plugins.ts +5 -1
package/ts_web/appstate.ts
CHANGED
|
@@ -1075,6 +1075,55 @@ export const toggleRemoteIngressAction = remoteIngressStatePart.createAction<{
|
|
|
1075
1075
|
}
|
|
1076
1076
|
});
|
|
1077
1077
|
|
|
1078
|
+
// ============================================================================
|
|
1079
|
+
// TypedSocket Client for Real-time Log Streaming
|
|
1080
|
+
// ============================================================================
|
|
1081
|
+
|
|
1082
|
+
let socketClient: plugins.typedsocket.TypedSocket | null = null;
|
|
1083
|
+
const socketRouter = new plugins.domtools.plugins.typedrequest.TypedRouter();
|
|
1084
|
+
|
|
1085
|
+
// Register handler for pushed log entries from the server
|
|
1086
|
+
socketRouter.addTypedHandler(
|
|
1087
|
+
new plugins.domtools.plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PushLogEntry>(
|
|
1088
|
+
'pushLogEntry',
|
|
1089
|
+
async (dataArg) => {
|
|
1090
|
+
const current = logStatePart.getState();
|
|
1091
|
+
const updated = [...current.recentLogs, dataArg.entry];
|
|
1092
|
+
// Cap at 2000 entries
|
|
1093
|
+
if (updated.length > 2000) {
|
|
1094
|
+
updated.splice(0, updated.length - 2000);
|
|
1095
|
+
}
|
|
1096
|
+
logStatePart.setState({ ...current, recentLogs: updated });
|
|
1097
|
+
return {};
|
|
1098
|
+
}
|
|
1099
|
+
)
|
|
1100
|
+
);
|
|
1101
|
+
|
|
1102
|
+
async function connectSocket() {
|
|
1103
|
+
if (socketClient) return;
|
|
1104
|
+
try {
|
|
1105
|
+
socketClient = await plugins.typedsocket.TypedSocket.createClient(
|
|
1106
|
+
socketRouter,
|
|
1107
|
+
plugins.typedsocket.TypedSocket.useWindowLocationOriginUrl(),
|
|
1108
|
+
);
|
|
1109
|
+
await socketClient.setTag('role', 'ops_dashboard');
|
|
1110
|
+
} catch (err) {
|
|
1111
|
+
console.error('TypedSocket connection failed:', err);
|
|
1112
|
+
socketClient = null;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
async function disconnectSocket() {
|
|
1117
|
+
if (socketClient) {
|
|
1118
|
+
try {
|
|
1119
|
+
await socketClient.stop();
|
|
1120
|
+
} catch {
|
|
1121
|
+
// ignore disconnect errors
|
|
1122
|
+
}
|
|
1123
|
+
socketClient = null;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1078
1127
|
// Combined refresh action for efficient polling
|
|
1079
1128
|
async function dispatchCombinedRefreshAction() {
|
|
1080
1129
|
const context = getActionContext();
|
|
@@ -1237,9 +1286,21 @@ let currentRefreshRate = 1000; // Track current refresh rate to avoid unnecessar
|
|
|
1237
1286
|
if (state.isLoggedIn !== previousIsLoggedIn) {
|
|
1238
1287
|
previousIsLoggedIn = state.isLoggedIn;
|
|
1239
1288
|
startAutoRefresh();
|
|
1289
|
+
|
|
1290
|
+
// Connect/disconnect TypedSocket based on login state
|
|
1291
|
+
if (state.isLoggedIn) {
|
|
1292
|
+
connectSocket();
|
|
1293
|
+
} else {
|
|
1294
|
+
disconnectSocket();
|
|
1295
|
+
}
|
|
1240
1296
|
}
|
|
1241
1297
|
});
|
|
1242
1298
|
|
|
1243
1299
|
// Initial start
|
|
1244
1300
|
startAutoRefresh();
|
|
1301
|
+
|
|
1302
|
+
// Connect TypedSocket if already logged in (e.g., persistent session)
|
|
1303
|
+
if (loginStatePart.getState().isLoggedIn) {
|
|
1304
|
+
connectSocket();
|
|
1305
|
+
}
|
|
1245
1306
|
})();
|
|
@@ -29,6 +29,8 @@ export class OpsViewLogs extends DeesElement {
|
|
|
29
29
|
@state()
|
|
30
30
|
accessor filterLimit: number = 100;
|
|
31
31
|
|
|
32
|
+
private lastPushedCount = 0;
|
|
33
|
+
|
|
32
34
|
constructor() {
|
|
33
35
|
super();
|
|
34
36
|
const subscription = appstate.logStatePart
|
|
@@ -110,7 +112,11 @@ export class OpsViewLogs extends DeesElement {
|
|
|
110
112
|
|
|
111
113
|
async connectedCallback() {
|
|
112
114
|
super.connectedCallback();
|
|
113
|
-
this.
|
|
115
|
+
this.lastPushedCount = 0;
|
|
116
|
+
// Only fetch if state is empty (streaming will handle new entries)
|
|
117
|
+
if (this.logState.recentLogs.length === 0) {
|
|
118
|
+
this.fetchLogs();
|
|
119
|
+
}
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
async updated(changedProperties: Map<string, any>) {
|
|
@@ -127,10 +133,27 @@ export class OpsViewLogs extends DeesElement {
|
|
|
127
133
|
// Ensure the chart element has finished its own initialization
|
|
128
134
|
await chartLog.updateComplete;
|
|
129
135
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
// Wait for xterm terminal to finish initializing (CDN load)
|
|
137
|
+
if (!chartLog.terminalReady) {
|
|
138
|
+
await new Promise<void>((resolve) => {
|
|
139
|
+
const check = () => {
|
|
140
|
+
if (chartLog.terminalReady) { resolve(); return; }
|
|
141
|
+
setTimeout(check, 50);
|
|
142
|
+
};
|
|
143
|
+
check();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const allEntries = this.getMappedLogEntries();
|
|
148
|
+
if (this.lastPushedCount === 0 && allEntries.length > 0) {
|
|
149
|
+
// Initial load: push all entries
|
|
150
|
+
chartLog.updateLog(allEntries);
|
|
151
|
+
this.lastPushedCount = allEntries.length;
|
|
152
|
+
} else if (allEntries.length > this.lastPushedCount) {
|
|
153
|
+
// Incremental: only push new entries
|
|
154
|
+
const newEntries = allEntries.slice(this.lastPushedCount);
|
|
155
|
+
chartLog.updateLog(newEntries);
|
|
156
|
+
this.lastPushedCount = allEntries.length;
|
|
134
157
|
}
|
|
135
158
|
}
|
|
136
159
|
|
|
@@ -133,8 +133,8 @@ export class OpsViewOverview extends DeesElement {
|
|
|
133
133
|
.logEntries=${this.getRecentEventEntries()}
|
|
134
134
|
></dees-chart-log>
|
|
135
135
|
<dees-chart-log
|
|
136
|
-
.label=${'
|
|
137
|
-
.logEntries=${this.
|
|
136
|
+
.label=${'DNS Queries'}
|
|
137
|
+
.logEntries=${this.getDnsQueryEntries()}
|
|
138
138
|
></dees-chart-log>
|
|
139
139
|
</div>
|
|
140
140
|
`}
|
|
@@ -395,6 +395,16 @@ export class OpsViewOverview extends DeesElement {
|
|
|
395
395
|
}));
|
|
396
396
|
}
|
|
397
397
|
|
|
398
|
+
private getDnsQueryEntries(): Array<{ timestamp: string; level: 'debug' | 'info' | 'warn' | 'error' | 'success'; message: string; source?: string }> {
|
|
399
|
+
const queries: any[] = (this.statsState.dnsStats as any)?.recentQueries || [];
|
|
400
|
+
return queries.map((q: any) => ({
|
|
401
|
+
timestamp: new Date(q.timestamp).toISOString(),
|
|
402
|
+
level: q.answered ? 'info' as const : 'warn' as const,
|
|
403
|
+
message: `${q.type} ${q.domain} (${q.responseTimeMs}ms)`,
|
|
404
|
+
source: 'dns',
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
407
|
+
|
|
398
408
|
private getEmailTrafficSeries(): Array<{ name: string; color: string; data: Array<{ x: number; y: number }> }> {
|
|
399
409
|
const ts = this.statsState.emailStats?.timeSeries;
|
|
400
410
|
if (!ts) return [];
|
package/ts_web/plugins.ts
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
import * as deesElement from '@design.estate/dees-element';
|
|
3
3
|
import * as deesCatalog from '@design.estate/dees-catalog';
|
|
4
4
|
|
|
5
|
+
// TypedSocket for real-time push communication
|
|
6
|
+
import * as typedsocket from '@api.global/typedsocket';
|
|
7
|
+
|
|
5
8
|
export {
|
|
6
9
|
deesElement,
|
|
7
|
-
deesCatalog
|
|
10
|
+
deesCatalog,
|
|
11
|
+
typedsocket,
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
// domtools gives us TypedRequest and other utilities
|