Refactor VPN proxy client implementation
Build and Deploy Gateway / build-and-push (push) Failing after 2s
Build and Deploy Gateway / deploy (push) Has been skipped

This commit is contained in:
2026-08-09 00:41:52 +03:00
parent 32be4380a3
commit 34d8b681ad
190 changed files with 20064 additions and 9761 deletions
+177
View File
@@ -0,0 +1,177 @@
import type { ServerResponse } from 'node:http';
const COUNTER_PATTERN = /^\d+$/;
const labelValue = (value: unknown) => String(value ?? '')
.replaceAll('\\', '\\\\')
.replaceAll('\n', '\\n')
.replaceAll('"', '\\"');
const labels = (values: Record<string, unknown>) => Object.entries(values)
.map(([key, value]) => `${key}="${labelValue(value)}"`)
.join(',');
function record(value: unknown): Record<string, unknown> {
return value && typeof value === 'object' && !Array.isArray(value)
? value as Record<string, unknown>
: {};
}
function counter(value: unknown) {
const decimal = String(value ?? '');
if (!COUNTER_PATTERN.test(decimal)) throw new Error(`Invalid Prometheus counter: ${decimal}`);
return decimal;
}
function timestamp(value: unknown) {
const milliseconds = Date.parse(String(value ?? ''));
return Number.isFinite(milliseconds) ? String(milliseconds / 1000) : null;
}
function metric(
lines: string[],
name: string,
metricLabels: Record<string, unknown>,
value: unknown,
) {
lines.push(`${name}{${labels(metricLabels)}} ${value}`);
}
export function renderPrometheusMetrics(value: unknown) {
const snapshot = record(value);
const traffic = record(snapshot.traffic);
const lines = [
'# HELP harbor_traffic_bytes_total Total traffic accounted by Harbor.',
'# TYPE harbor_traffic_bytes_total counter',
];
metric(lines, 'harbor_traffic_bytes_total', { source: 'gateway' }, counter(traffic.gatewayBytes));
metric(lines, 'harbor_traffic_bytes_total', { source: 'proxy' }, counter(traffic.proxyBytes));
const globalFreshness = [
['gateway', traffic.gatewayObservedAt],
['proxy', traffic.proxyObservedAt],
].map(([source, observedAt]) => [source, timestamp(observedAt)] as const).filter(([, observedAt]) => observedAt);
if (globalFreshness.length) {
lines.push(
'# HELP harbor_traffic_last_observed_timestamp_seconds Unix timestamp of the last successful Harbor traffic observation.',
'# TYPE harbor_traffic_last_observed_timestamp_seconds gauge',
);
for (const [source, observedAt] of globalFreshness) {
metric(lines, 'harbor_traffic_last_observed_timestamp_seconds', { source }, observedAt);
}
}
const devices = Array.isArray(snapshot.devices) ? snapshot.devices.map(record) : [];
if (devices.length) {
lines.push(
'# HELP harbor_device_info Current Harbor device identity metadata.',
'# TYPE harbor_device_info gauge',
);
for (const device of devices) {
metric(lines, 'harbor_device_info', {
device_id: device.id,
name: device.alias || device.hostname || device.ip || device.id,
ip: device.ip || '',
}, '1');
}
}
const deviceTraffic = devices.flatMap((device) => [
timestamp(device.trafficObservedAt)
? { device, source: 'gateway', observedAt: timestamp(device.trafficObservedAt), uploadBytes: device.uploadBytes, downloadBytes: device.downloadBytes }
: null,
timestamp(device.proxyTrafficObservedAt)
? { device, source: 'proxy', observedAt: timestamp(device.proxyTrafficObservedAt), uploadBytes: device.proxyUploadBytes, downloadBytes: device.proxyDownloadBytes }
: null,
].filter((entry): entry is NonNullable<typeof entry> => entry !== null));
if (deviceTraffic.length) {
lines.push(
'# HELP harbor_device_traffic_bytes_total Total traffic accounted by Harbor for a device.',
'# TYPE harbor_device_traffic_bytes_total counter',
);
for (const { device, source, uploadBytes, downloadBytes } of deviceTraffic) {
metric(lines, 'harbor_device_traffic_bytes_total', {
device_id: device.id,
source,
direction: 'download',
}, counter(downloadBytes));
metric(lines, 'harbor_device_traffic_bytes_total', {
device_id: device.id,
source,
direction: 'upload',
}, counter(uploadBytes));
}
lines.push(
'# HELP harbor_device_traffic_last_observed_timestamp_seconds Unix timestamp of the last successful device traffic observation.',
'# TYPE harbor_device_traffic_last_observed_timestamp_seconds gauge',
);
for (const { device, source, observedAt } of deviceTraffic) {
metric(lines, 'harbor_device_traffic_last_observed_timestamp_seconds', {
device_id: device.id,
source,
}, observedAt);
}
}
const domainTraffic = record(snapshot.domainTraffic);
const domainSeries = Array.isArray(domainTraffic.series) ? domainTraffic.series.map(record) : [];
if (domainSeries.length) {
lines.push(
'# HELP harbor_device_domain_traffic_bytes_total Traffic observed by sing-box for a device and domain.',
'# TYPE harbor_device_domain_traffic_bytes_total counter',
);
for (const series of domainSeries) {
for (const [direction, value] of [
['download', series.downloadBytes],
['upload', series.uploadBytes],
]) {
metric(lines, 'harbor_device_domain_traffic_bytes_total', {
device_id: series.deviceId,
domain: series.domain,
service: series.service,
source: series.source,
direction,
}, counter(value));
}
}
}
const domainObservedAt = timestamp(domainTraffic.observedAt);
if (domainObservedAt) {
lines.push(
'# HELP harbor_domain_traffic_last_observed_timestamp_seconds Unix timestamp of the last successful sing-box connection observation.',
'# TYPE harbor_domain_traffic_last_observed_timestamp_seconds gauge',
);
lines.push(`harbor_domain_traffic_last_observed_timestamp_seconds ${domainObservedAt}`);
}
if (domainTraffic.overflowConnections != null) {
lines.push(
'# HELP harbor_domain_traffic_overflow_connections_total Connections aggregated after the domain series limit was reached.',
'# TYPE harbor_domain_traffic_overflow_connections_total counter',
);
lines.push(`harbor_domain_traffic_overflow_connections_total ${counter(domainTraffic.overflowConnections)}`);
}
const attributionEvents = record(domainTraffic.attributionEvents);
if (domainTraffic.attributionEvents) {
lines.push(
'# HELP harbor_domain_traffic_attribution_events_total Connections with incomplete Harbor domain attribution.',
'# TYPE harbor_domain_traffic_attribution_events_total counter',
);
for (const outcome of ['unresolved_host', 'unknown_device', 'unsupported_source']) {
metric(
lines,
'harbor_domain_traffic_attribution_events_total',
{ outcome },
counter(attributionEvents[outcome]),
);
}
}
return `${lines.join('\n')}\n`;
}
export function sendPrometheusMetrics(res: ServerResponse, snapshot: unknown) {
const body = renderPrometheusMetrics(snapshot);
res.writeHead(200, { 'content-type': 'text/plain; version=0.0.4; charset=utf-8' });
res.end(body);
}