feat(smartnetwork): add Rust-powered network diagnostics bridge and IP intelligence lookups

This commit is contained in:
2026-03-26 15:24:43 +00:00
parent e9dcd45acd
commit c3ac9b4f9e
34 changed files with 5499 additions and 3159 deletions

View File

@@ -53,7 +53,7 @@ export class CloudflareSpeed {
const t5 = await measureDownloadParallel(100001000, 1);
downloadTests = [...t1, ...t2, ...t3, ...t4, ...t5];
}
const speedDownload = stats.quartile(downloadTests, 0.9).toFixed(2);
const speedDownload = downloadTests.length > 0 ? stats.quartile(downloadTests, 0.9).toFixed(2) : '0.00';
// lets test the upload speed with configurable parallel streams
const measureUploadParallel = (bytes: number, iterations: number) => {
@@ -84,7 +84,7 @@ export class CloudflareSpeed {
const u3 = await measureUploadParallel(1001000, 8);
uploadTests = [...u1, ...u2, ...u3];
}
const speedUpload = stats.quartile(uploadTests, 0.9).toFixed(2);
const speedUpload = uploadTests.length > 0 ? stats.quartile(uploadTests, 0.9).toFixed(2) : '0.00';
return {
...latency,
@@ -147,8 +147,14 @@ export class CloudflareSpeed {
for (let i = 0; i < iterations; i += 1) {
await this.upload(bytes).then(
async (response) => {
const transferTime = response[6];
measurements.push(await this.measureSpeed(bytes, transferTime));
// Prefer server-timing duration; fall back to client-side transfer time
let transferTime = response[6];
if (!transferTime || !isFinite(transferTime)) {
transferTime = response[5] - response[4]; // ended - ttfb
}
if (transferTime > 0) {
measurements.push(await this.measureSpeed(bytes, transferTime));
}
},
(error) => {
getLogger().error('Error measuring upload chunk:', error);
@@ -164,17 +170,22 @@ export class CloudflareSpeed {
}
public async fetchServerLocations(): Promise<{ [key: string]: string }> {
const res = JSON.parse(await this.get('speed.cloudflare.com', '/locations')) as Array<{
iata: string;
city: string;
}>;
return res.reduce(
(data: Record<string, string>, optionsArg) => {
data[optionsArg.iata] = optionsArg.city;
return data;
},
{} as Record<string, string>,
);
try {
const raw = await this.get('speed.cloudflare.com', '/locations');
const parsed = JSON.parse(raw);
if (!Array.isArray(parsed)) {
return {};
}
return (parsed as Array<{ iata: string; city: string }>).reduce(
(data: Record<string, string>, entry) => {
data[entry.iata] = entry.city;
return data;
},
{} as Record<string, string>,
);
} catch {
return {};
}
}
public async get(hostname: string, path: string): Promise<string> {
@@ -259,7 +270,12 @@ export class CloudflareSpeed {
sslHandshake,
ttfb,
ended,
parseFloat((res.headers['server-timing'] as string).slice(22)),
(() => {
const serverTiming = res.headers['server-timing'] as string | undefined;
if (!serverTiming) return 0;
const match = serverTiming.match(/dur=([\d.]+)/);
return match ? parseFloat(match[1]) : parseFloat(serverTiming.slice(22)) || 0;
})(),
]);
});
});