backend: serve single-agent task templates with their status and results, rename the kinds in storage
This commit is contained in:
1 parent
e77880d372
commit
3a9ea46d6f
45 files changed
+763
-216
No files matched your search
@@ -29,7 +29,7 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
{
|
||||
long start = baseMs + (k * 10_000L);
|
||||
RawChunk udp = ChunkFactory.Echo(
|
||||
agent.NodeId, "udp_echo", start, 100, 100,
|
||||
agent.NodeId, "quic_ping", start, 100, 100,
|
||||
i => new EchoPacket(false, lossEvery > 0 && i % lossEvery == 0, (long)(owdMs * 1000), (long)(owdMs * 1000)));
|
||||
Assert.True(await agent.SendChunkAsync(udp));
|
||||
if (tcp)
|
||||
@@ -37,7 +37,7 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
long dialerBase = ChunkFactory.DialerUs(0);
|
||||
RawStream info = ChunkFactory.TcpInfo(Enumerable.Range(0, 10).Select(s => (dialerBase + (s * 1_000_000L), (byte)0, 45_000u, (uint)(s * 2), (uint)(s * 400))));
|
||||
RawChunk tcpChunk = ChunkFactory.Echo(
|
||||
agent.NodeId, "tcp_echo", start, 200, 50, _ => new EchoPacket(false, false, (long)(owdMs * 1000), (long)(owdMs * 1000)), extraStreams: [info]);
|
||||
agent.NodeId, "tcp_ping", start, 200, 50, _ => new EchoPacket(false, false, (long)(owdMs * 1000), (long)(owdMs * 1000)), extraStreams: [info]);
|
||||
Assert.True(await agent.SendChunkAsync(tcpChunk));
|
||||
}
|
||||
}
|
||||
@@ -87,13 +87,13 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
|
||||
// Anchored at now: the last 5 minutes are empty
|
||||
JsonNode atNow = await SeriesAsync(id, "range=5m&step=10s&metrics=loss.total");
|
||||
Assert.Null(atNow["summary"]!["samples"]!["udp_echo"]);
|
||||
Assert.Null(atNow["summary"]!["samples"]!["quic_ping"]);
|
||||
|
||||
// Anchored at the latest sample: the window ends where the data ends and carries all of it
|
||||
JsonNode anchored = await SeriesAsync(id, "range=5m&step=10s&metrics=loss.total&anchor=latest");
|
||||
long to = DateTimeOffset.Parse(anchored["to"]!.GetValue<string>(), System.Globalization.CultureInfo.InvariantCulture).ToUnixTimeMilliseconds();
|
||||
Assert.InRange(to, baseMs + (50 * 1000), baseMs + (80 * 1000));
|
||||
Assert.Equal(600, anchored["summary"]!["samples"]!["udp_echo"]!.GetValue<long>());
|
||||
Assert.Equal(600, anchored["summary"]!["samples"]!["quic_ping"]!.GetValue<long>());
|
||||
Assert.False(anchored["live"]!.GetValue<bool>());
|
||||
|
||||
// 这个窗口是以“最后一个样本”为终点的绝对区间,但线路恢复之后同一个地址的内容就变了:不能被浏览器永久缓存
|
||||
@@ -102,7 +102,7 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
|
||||
// anchor=now is the default behaviour; anything else is rejected
|
||||
JsonNode explicitNow = await SeriesAsync(id, "range=5m&step=10s&metrics=loss.total&anchor=now");
|
||||
Assert.Null(explicitNow["summary"]!["samples"]!["udp_echo"]);
|
||||
Assert.Null(explicitNow["summary"]!["samples"]!["quic_ping"]);
|
||||
using HttpResponseMessage bad = await _backend.Admin.GetAsync($"/api/public/lines/{_backend.Line(id)}/series?range=5m&anchor=yesterday");
|
||||
Assert.Equal(System.Net.HttpStatusCode.BadRequest, bad.StatusCode);
|
||||
}
|
||||
@@ -162,8 +162,8 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
{
|
||||
minute = await SeriesAsync(agent.NodeId.Value, range + "&step=1m");
|
||||
// 窗口会随着后续的块到达而重算:等到 18 个块的样本都计入之后再比较
|
||||
return minute["source"]!.GetValue<string>() == "1m" && minute["summary"]!["samples"]!["udp_echo"]?.GetValue<long>() == 1800
|
||||
&& minute["summary"]!["samples"]!["tcp_echo"]?.GetValue<long>() == 3600;
|
||||
return minute["source"]!.GetValue<string>() == "1m" && minute["summary"]!["samples"]!["quic_ping"]?.GetValue<long>() == 1800
|
||||
&& minute["summary"]!["samples"]!["tcp_ping"]?.GetValue<long>() == 3600;
|
||||
});
|
||||
|
||||
JsonNode hotSummary = hot["summary"]!["metrics"]!;
|
||||
@@ -176,9 +176,9 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
$"{id}: hot={hotSummary[id]} persisted={minuteSummary[id]}");
|
||||
}
|
||||
|
||||
Assert.Equal(1800, hot["summary"]!["samples"]!["udp_echo"]!.GetValue<long>());
|
||||
Assert.Equal(hot["summary"]!["samples"]!["udp_echo"]!.GetValue<long>(), minute["summary"]!["samples"]!["udp_echo"]!.GetValue<long>());
|
||||
Assert.Equal(3600, minute["summary"]!["samples"]!["tcp_echo"]!.GetValue<long>());
|
||||
Assert.Equal(1800, hot["summary"]!["samples"]!["quic_ping"]!.GetValue<long>());
|
||||
Assert.Equal(hot["summary"]!["samples"]!["quic_ping"]!.GetValue<long>(), minute["summary"]!["samples"]!["quic_ping"]!.GetValue<long>());
|
||||
Assert.Equal(3600, minute["summary"]!["samples"]!["tcp_ping"]!.GetValue<long>());
|
||||
|
||||
// RTT = 2 × 20 ms,直方图的相对误差 ≤ 4.5%
|
||||
Assert.InRange(minuteSummary["rtt.p95"]!.GetValue<double>(), 40 * 0.955, 40 * 1.045);
|
||||
@@ -234,7 +234,7 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
Assert.True(goodScore > 90, $"clean line scored {goodScore}");
|
||||
Assert.True(badScore < goodScore - 30, $"lossy line scored {badScore}");
|
||||
Assert.Equal(20.0, lines[badIndex]["summary"]!["metrics"]!["loss.total"]!.GetValue<double>(), 6);
|
||||
Assert.Equal(1200, lines[goodIndex]["summary"]!["samples"]!["udp_echo"]!.GetValue<long>());
|
||||
Assert.Equal(1200, lines[goodIndex]["summary"]!["samples"]!["quic_ping"]!.GetValue<long>());
|
||||
|
||||
// 按指标排序:loss.total 升序时好线路在前
|
||||
JsonNode byLoss = await _backend.GetJsonAsync(_backend.Anonymous, "/api/public/overview?" + range + "&sort=loss.total&order=asc");
|
||||
@@ -372,12 +372,12 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
await using (agent)
|
||||
{
|
||||
string url = $"/api/public/lines/{_backend.Line(agent.NodeId.Value)}/series?from={Iso(baseMs)}&to={Iso(baseMs + Minute)}&step=1m&preset=udp";
|
||||
await BackendFixture.EventuallyAsync(async () => (await _backend.GetJsonAsync(_backend.Admin, url))["summary"]!["samples"]!["udp_echo"]?.GetValue<long>() == 600);
|
||||
await BackendFixture.EventuallyAsync(async () => (await _backend.GetJsonAsync(_backend.Admin, url))["summary"]!["samples"]!["quic_ping"]?.GetValue<long>() == 600);
|
||||
|
||||
// Agent 重连后补传一个迟到的块(落在同一个分钟窗口里)
|
||||
RawChunk late = ChunkFactory.Echo(agent.NodeId, "udp_echo", baseMs + 5_000, 100, 10, _ => new EchoPacket(false, false, 20_000, 20_000));
|
||||
RawChunk late = ChunkFactory.Echo(agent.NodeId, "quic_ping", baseMs + 5_000, 100, 10, _ => new EchoPacket(false, false, 20_000, 20_000));
|
||||
Assert.True(await agent.SendChunkAsync(late));
|
||||
await BackendFixture.EventuallyAsync(async () => (await _backend.GetJsonAsync(_backend.Admin, url))["summary"]!["samples"]!["udp_echo"]?.GetValue<long>() == 700, because: "the late chunk must re-enter the persistent path");
|
||||
await BackendFixture.EventuallyAsync(async () => (await _backend.GetJsonAsync(_backend.Admin, url))["summary"]!["samples"]!["quic_ping"]?.GetValue<long>() == 700, because: "the late chunk must re-enter the persistent path");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
await BackendFixture.EventuallyAsync(async () =>
|
||||
{
|
||||
oneMinute = await SeriesAsync(agent.NodeId.Value, range + "&step=1m");
|
||||
return oneMinute["summary"]!["samples"]!["udp_echo"]?.GetValue<long>() == 3000;
|
||||
return oneMinute["summary"]!["samples"]!["quic_ping"]?.GetValue<long>() == 3000;
|
||||
});
|
||||
|
||||
// 5 分钟层由降采样把 5 个 1 分钟窗口精确合并而来
|
||||
@@ -402,7 +402,7 @@ public sealed class IngestAndQueryTests : IClassFixture<BackendFixture>
|
||||
await BackendFixture.EventuallyAsync(async () =>
|
||||
{
|
||||
fiveMinutes = await SeriesAsync(agent.NodeId.Value, range + "&step=5m");
|
||||
return fiveMinutes["source"]!.GetValue<string>() == "5m" && fiveMinutes["summary"]!["samples"]!["udp_echo"]?.GetValue<long>() == 3000;
|
||||
return fiveMinutes["source"]!.GetValue<string>() == "5m" && fiveMinutes["summary"]!["samples"]!["quic_ping"]?.GetValue<long>() == 3000;
|
||||
});
|
||||
Assert.Equal(oneMinute["summary"]!["metrics"]!["loss.total"]!.GetValue<double>(), fiveMinutes["summary"]!["metrics"]!["loss.total"]!.GetValue<double>(), 9);
|
||||
Assert.Equal(oneMinute["summary"]!["metrics"]!["rtt.p99"]!.GetValue<double>(), fiveMinutes["summary"]!["metrics"]!["rtt.p99"]!.GetValue<double>(), 9);
|
||||
|
||||
Reference in new issue
Block a user