Improve device traffic dashboard and domain attribution metrics
This commit is contained in:
@@ -21,6 +21,7 @@ test('domain traffic accumulates connection deltas by device, service and source
|
||||
let response = { connections: [
|
||||
connection('youtube', 'tproxy/tproxy-in', 'r1.googlevideo.com', 10, 100),
|
||||
connection('chatgpt', 'mixed/mixed-in', 'www.chatgpt.com.', 20, 200),
|
||||
connection('hostless', 'tproxy/tproxy-in', '', 5, 50),
|
||||
connection('diagnostics', 'mixed/diagnostics-vpn-in', 'example.com', 30, 300),
|
||||
connection('unknown-device', 'tproxy/tproxy-in', 'example.net', 40, 400, '192.168.50.99'),
|
||||
] };
|
||||
@@ -34,6 +35,7 @@ test('domain traffic accumulates connection deltas by device, service and source
|
||||
response = { connections: [
|
||||
connection('youtube', 'tproxy/tproxy-in', 'r1.googlevideo.com', 15, 130),
|
||||
connection('chatgpt', 'mixed/mixed-in', 'www.chatgpt.com.', 22, 260),
|
||||
connection('hostless', 'tproxy/tproxy-in', '', 7, 70),
|
||||
] };
|
||||
observedAt = new Date('2026-08-08T10:00:02.000Z');
|
||||
await service.refresh();
|
||||
@@ -56,7 +58,20 @@ test('domain traffic accumulates connection deltas by device, service and source
|
||||
uploadBytes: '15',
|
||||
downloadBytes: '130',
|
||||
},
|
||||
{
|
||||
deviceId: id,
|
||||
domain: '_unknown',
|
||||
service: 'Не распознано',
|
||||
source: 'gateway',
|
||||
uploadBytes: '7',
|
||||
downloadBytes: '70',
|
||||
},
|
||||
]);
|
||||
assert.deepEqual(service.snapshot().attributionEvents, {
|
||||
unresolved_host: '1',
|
||||
unknown_device: '1',
|
||||
unsupported_source: '1',
|
||||
});
|
||||
assert.equal(service.snapshot().observedAt, observedAt.toISOString());
|
||||
assert.equal(service.snapshot().source.error, null);
|
||||
|
||||
@@ -65,6 +80,38 @@ test('domain traffic accumulates connection deltas by device, service and source
|
||||
assert.equal(service.snapshot().series[1].downloadBytes, '130');
|
||||
});
|
||||
|
||||
test('a hostless connection can become classified without counting its bytes twice', async () => {
|
||||
let response = { connections: [
|
||||
connection('video', 'tproxy/tproxy-in', '', 10, 100),
|
||||
] };
|
||||
const service = createDomainTrafficService({
|
||||
observe: async () => response,
|
||||
devices: () => [device],
|
||||
});
|
||||
|
||||
await service.refresh();
|
||||
response = { connections: [
|
||||
connection('video', 'tproxy/tproxy-in', 'r2.googlevideo.com', 15, 130),
|
||||
] };
|
||||
await service.refresh();
|
||||
|
||||
assert.deepEqual(
|
||||
Object.fromEntries(service.snapshot().series.map((series) => [series.domain, {
|
||||
uploadBytes: series.uploadBytes,
|
||||
downloadBytes: series.downloadBytes,
|
||||
}])),
|
||||
{
|
||||
_unknown: { uploadBytes: '10', downloadBytes: '100' },
|
||||
'googlevideo.com': { uploadBytes: '5', downloadBytes: '30' },
|
||||
},
|
||||
);
|
||||
assert.deepEqual(service.snapshot().attributionEvents, {
|
||||
unresolved_host: '1',
|
||||
unknown_device: '0',
|
||||
unsupported_source: '0',
|
||||
});
|
||||
});
|
||||
|
||||
test('domain traffic is bounded and keeps the last good snapshot on source failure', async () => {
|
||||
let fail = false;
|
||||
const service = createDomainTrafficService({
|
||||
|
||||
Reference in New Issue
Block a user