feat(remoteingress): add remote ingress performance configuration and expose tunnel transport metrics

This commit is contained in:
2026-04-26 12:14:51 +00:00
parent 49ce265d7e
commit ec5374900c
14 changed files with 194 additions and 18 deletions
@@ -125,6 +125,18 @@ export class OpsViewRemoteIngress extends DeesElement {
color: ${cssManager.bdTheme('#047857', '#34d399')};
border: 1px dashed ${cssManager.bdTheme('#6ee7b7', '#065f46')};
}
.metricStack {
display: flex;
flex-direction: column;
gap: 2px;
font-size: 12px;
line-height: 1.35;
}
.metricMuted {
color: var(--text-muted, #6b7280);
}
`,
];
@@ -226,9 +238,13 @@ export class OpsViewRemoteIngress extends DeesElement {
.displayFunction=${(edge: interfaces.data.IRemoteIngress) => ({
name: edge.name,
status: this.getEdgeStatusHtml(edge),
transport: this.getTransportHtml(edge.id),
publicIp: this.getEdgePublicIp(edge.id),
ports: this.getPortsHtml(edge),
tunnels: this.getEdgeTunnelCount(edge.id),
window: this.getWindowHtml(edge.id),
queues: this.getQueuesHtml(edge.id),
traffic: this.getTrafficHtml(edge.id),
lastHeartbeat: this.getLastHeartbeat(edge.id),
})}
.dataActions=${[
@@ -459,6 +475,46 @@ export class OpsViewRemoteIngress extends DeesElement {
return status?.activeTunnels || 0;
}
private getTransportHtml(edgeId: string): TemplateResult | string {
const status = this.getEdgeStatus(edgeId);
if (!status?.connected) return '-';
const mode = status.transportMode || 'unknown';
const label = mode === 'quic' ? 'QUIC' : mode === 'tcpTls' ? 'TCP/TLS' : mode;
return html`<div class="metricStack"><strong>${label}</strong><span class="metricMuted">${status.fallbackUsed ? 'fallback' : status.performance?.profile || 'default'}</span></div>`;
}
private getWindowHtml(edgeId: string): TemplateResult | string {
const status = this.getEdgeStatus(edgeId);
if (!status?.connected || !status.flowControl) return '-';
if (!status.flowControl.applies) {
return html`<div class="metricStack"><span>native QUIC</span><span class="metricMuted">max ${status.performance?.maxStreamsPerEdge || '-'} streams</span></div>`;
}
return html`
<div class="metricStack">
<span>${this.formatBytes(status.flowControl.currentWindowBytes)} window</span>
<span class="metricMuted">${this.formatBytes(status.flowControl.estimatedInFlightBytes)} est. in-flight</span>
</div>
`;
}
private getQueuesHtml(edgeId: string): TemplateResult | string {
const status = this.getEdgeStatus(edgeId);
if (!status?.connected || !status.queues) return '-';
return html`<div class="metricStack"><span>C ${status.queues.ctrlQueueDepth} / D ${status.queues.dataQueueDepth}</span><span class="metricMuted">S ${status.queues.sustainedQueueDepth}</span></div>`;
}
private getTrafficHtml(edgeId: string): TemplateResult | string {
const status = this.getEdgeStatus(edgeId);
if (!status?.connected || !status.traffic) return '-';
const drops = (status.traffic.rejectedStreams || 0) + (status.udp?.droppedDatagrams || 0);
return html`
<div class="metricStack">
<span>${this.formatBytes(status.traffic.bytesIn)} in / ${this.formatBytes(status.traffic.bytesOut)} out</span>
<span class="metricMuted">${drops} rejected/dropped</span>
</div>
`;
}
private getLastHeartbeat(edgeId: string): string {
const status = this.getEdgeStatus(edgeId);
if (!status?.lastHeartbeat) return '-';
@@ -467,4 +523,16 @@ export class OpsViewRemoteIngress extends DeesElement {
if (ago < 3600000) return `${Math.floor(ago / 60000)}m ago`;
return `${Math.floor(ago / 3600000)}h ago`;
}
private formatBytes(bytes: number): string {
if (!Number.isFinite(bytes) || bytes <= 0) return '0 B';
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let value = bytes;
let unitIndex = 0;
while (value >= 1024 && unitIndex < units.length - 1) {
value = value / 1024;
unitIndex++;
}
return `${value >= 10 || unitIndex === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[unitIndex]}`;
}
}