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
@@ -32,8 +32,8 @@ public sealed class ModelAndTestEvaluatorTests
|
||||
[Fact]
|
||||
public void Fingerprint_ChangesWhenTheOpChanges()
|
||||
{
|
||||
var a = Metric.Counter("x", ["udp_echo.msg"], Ops.Gap(GapOutput.Count, "rate_hz", 100), "x", "x", new MetricExport("x", Stat.Count, Unit.Count));
|
||||
var b = Metric.Counter("x", ["udp_echo.msg"], Ops.Gap(GapOutput.Count, "rate_hz", 200), "x", "x", new MetricExport("x", Stat.Count, Unit.Count));
|
||||
var a = Metric.Counter("x", ["quic_ping.msg"], Ops.Gap(GapOutput.Count, "rate_hz", 100), "x", "x", new MetricExport("x", Stat.Count, Unit.Count));
|
||||
var b = Metric.Counter("x", ["quic_ping.msg"], Ops.Gap(GapOutput.Count, "rate_hz", 200), "x", "x", new MetricExport("x", Stat.Count, Unit.Count));
|
||||
Assert.NotEqual(a.Fingerprint, b.Fingerprint);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public sealed class OpTests
|
||||
[Fact]
|
||||
public void Rtt_RemovesAgentProcessingTime()
|
||||
{
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "udp_echo", T0, 100, 100, _ => new EchoPacket(false, false, 20_000, 30_000, ProcessUs: 5_000));
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "quic_ping", T0, 100, 100, _ => new EchoPacket(false, false, 20_000, 30_000, ProcessUs: 5_000));
|
||||
var rtt = (HistogramAcc)EvaluateOneBucket(chunk, "rtt").Items["rtt"];
|
||||
Assert.Equal(100UL, rtt.Count);
|
||||
Assert.InRange(rtt.Quantile(0.5)!.Value, 50 * 0.955, 50 * 1.045);
|
||||
@@ -37,8 +37,8 @@ public sealed class OpTests
|
||||
static EchoPacket At(int i) => new(LostUp: i % 20 < 2, LostDown: false, i % 10 < 2 ? 100_000 : 20_000, 20_000);
|
||||
|
||||
// 每 100 ms 一个包,每个权重 1;对照:只取偶数行,每 200 ms 一个包,每个权重 2——代表同样长的时间
|
||||
RawChunk dense = ChunkFactory.Echo(s_agent, "udp_echo", T0, 100, 100, At);
|
||||
RawChunk sparse = ChunkFactory.Echo(s_agent, "udp_echo", T0, 50, 200, i => At(i * 2), weight: _ => 2);
|
||||
RawChunk dense = ChunkFactory.Echo(s_agent, "quic_ping", T0, 100, 100, At);
|
||||
RawChunk sparse = ChunkFactory.Echo(s_agent, "quic_ping", T0, 50, 200, i => At(i * 2), weight: _ => 2);
|
||||
|
||||
MetricSet d = EvaluateOneBucket(dense, "rtt", "loss.up", "loss.total");
|
||||
MetricSet s = EvaluateOneBucket(sparse, "rtt", "loss.up", "loss.total");
|
||||
@@ -54,7 +54,7 @@ public sealed class OpTests
|
||||
public void Loss_SeparatesUpAndDown()
|
||||
{
|
||||
RawChunk chunk = ChunkFactory.Echo(
|
||||
s_agent, "udp_echo", T0, 100, 100,
|
||||
s_agent, "quic_ping", T0, 100, 100,
|
||||
i => new EchoPacket(LostUp: i < 10, LostDown: i is >= 10 and < 15, 20_000, 20_000));
|
||||
MetricSet set = EvaluateOneBucket(chunk, "loss.up", "loss.down", "loss.total");
|
||||
|
||||
@@ -77,7 +77,7 @@ public sealed class OpTests
|
||||
public void Jitter_OnlyOneDirectionVaries_IsAttributedToThatDirection()
|
||||
{
|
||||
// 下行时延每隔一个包多 20 ms
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "udp_echo", T0, 100, 100, i => new EchoPacket(false, false, 20_000, 20_000 + (i % 2 == 0 ? 20_000 : 0)));
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "quic_ping", T0, 100, 100, i => new EchoPacket(false, false, 20_000, 20_000 + (i % 2 == 0 ? 20_000 : 0)));
|
||||
MetricSet set = EvaluateOneBucket(chunk, "jitter.up", "jitter.down");
|
||||
Assert.True(((HistogramAcc)set.Items["jitter.up"]).Quantile(0.95) < 0.5);
|
||||
Assert.InRange(((HistogramAcc)set.Items["jitter.down"]).Quantile(0.95)!.Value, 15, 25);
|
||||
@@ -95,7 +95,7 @@ public sealed class OpTests
|
||||
public void LossRuns_ReportsConsecutiveLosses()
|
||||
{
|
||||
bool[] lost = [false, true, true, true, false, true, false, false, true, true];
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "udp_echo", T0, lost.Length, 100, i => new EchoPacket(false, lost[i], 20_000, 20_000));
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "quic_ping", T0, lost.Length, 100, i => new EchoPacket(false, lost[i], 20_000, 20_000));
|
||||
var runs = (RunLengthAcc)EvaluateOneBucket(chunk, "loss.run").Items["loss.run"];
|
||||
Assert.Equal(3UL, runs.Runs);
|
||||
Assert.Equal(3, runs.Max);
|
||||
@@ -105,7 +105,7 @@ public sealed class OpTests
|
||||
[Fact]
|
||||
public void LossRuns_TrailingRunIsReported()
|
||||
{
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "udp_echo", T0, 4, 100, i => new EchoPacket(false, i >= 2, 20_000, 20_000));
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "quic_ping", T0, 4, 100, i => new EchoPacket(false, i >= 2, 20_000, 20_000));
|
||||
Assert.Equal(2, ((RunLengthAcc)EvaluateOneBucket(chunk, "loss.run").Items["loss.run"]).Max);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public sealed class OpTests
|
||||
{
|
||||
bool[] upLost = [false, true, true, false, false, false, true, true];
|
||||
bool[] downLost = [false, false, true, true, false, true, false, true];
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "udp_echo", T0, upLost.Length, 100,
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "quic_ping", T0, upLost.Length, 100,
|
||||
i => new EchoPacket(upLost[i], downLost[i], 20_000, 20_000));
|
||||
|
||||
MetricSet set = EvaluateOneBucket(chunk, "loss.run.up", "loss.run.down");
|
||||
@@ -135,7 +135,7 @@ public sealed class OpTests
|
||||
public void Reorder_CountsLateArrivals_AndIgnoresDuplicates()
|
||||
{
|
||||
// 包 3 的回复比包 4 晚到
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "udp_echo", T0, 6, 100, i => new EchoPacket(false, false, 20_000, i == 3 ? 150_000 : 20_000));
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "quic_ping", T0, 6, 100, i => new EchoPacket(false, false, 20_000, i == 3 ? 150_000 : 20_000));
|
||||
MetricSet set = EvaluateOneBucket(chunk, "reorder", "dup");
|
||||
Assert.Equal(1UL, ((CounterAcc)set.Items["reorder"]).Value);
|
||||
Assert.False(set.Items.ContainsKey("dup"));
|
||||
@@ -146,7 +146,7 @@ public sealed class OpTests
|
||||
{
|
||||
// 第 40 个包之后的 10 个包被队头阻塞,全部在 2540 ms 之后几乎同时到达
|
||||
RawChunk chunk = ChunkFactory.Echo(
|
||||
s_agent, "tcp_echo", T0, 100, 50,
|
||||
s_agent, "tcp_ping", T0, 100, 50,
|
||||
i => new EchoPacket(false, false, 20_000, i is >= 40 and < 50 ? ((2540 + (i - 40) - (50 * i) - 20) * 1000) - 50 : 20_000));
|
||||
MetricSet set = EvaluateOneBucket(chunk, "tcp.stall", "tcp.stall_max");
|
||||
Assert.Equal(1UL, ((CounterAcc)set.Items["tcp.stall"]).Value);
|
||||
@@ -156,7 +156,7 @@ public sealed class OpTests
|
||||
[Fact]
|
||||
public void Stall_SteadyArrivals_AreNotStalls()
|
||||
{
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 100, 50, _ => new EchoPacket(false, false, 20_000, 20_000));
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 100, 50, _ => new EchoPacket(false, false, 20_000, 20_000));
|
||||
MetricSet set = EvaluateOneBucket(chunk, "tcp.stall");
|
||||
Assert.False(set.Items.ContainsKey("tcp.stall"));
|
||||
}
|
||||
@@ -166,7 +166,7 @@ public sealed class OpTests
|
||||
{
|
||||
// 基线 50 ms(单程 25 ms),阈值 = max(90, 50 + max(15, 17.5)) = 90 ms;第 10、20、30 个回显的 RTT 是 200 ms
|
||||
RawChunk chunk = ChunkFactory.Echo(
|
||||
s_agent, "tcp_echo", T0, 100, 50,
|
||||
s_agent, "tcp_ping", T0, 100, 50,
|
||||
i => new EchoPacket(false, false, 25_000, i % 10 == 0 && i > 0 && i < 40 ? 175_000 : 25_000, ProcessUs: 0));
|
||||
var slow = (RatioAcc)EvaluateOneBucket(chunk, "tcp.slow").Items["tcp.slow"];
|
||||
Assert.Equal(100UL, slow.Denominator);
|
||||
@@ -176,10 +176,10 @@ public sealed class OpTests
|
||||
[Fact]
|
||||
public void Slow_ASteadyConnection_HasNoLongTail_AndTooFewSamplesGiveNoObservation()
|
||||
{
|
||||
RawChunk steady = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 100, 50, _ => new EchoPacket(false, false, 25_000, 25_000));
|
||||
RawChunk steady = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 100, 50, _ => new EchoPacket(false, false, 25_000, 25_000));
|
||||
Assert.Equal(0UL, ((RatioAcc)EvaluateOneBucket(steady, "tcp.slow").Items["tcp.slow"]).Numerator);
|
||||
|
||||
RawChunk few = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 10, 50, i => new EchoPacket(false, false, 25_000, i == 5 ? 500_000 : 25_000));
|
||||
RawChunk few = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 10, 50, i => new EchoPacket(false, false, 25_000, i == 5 ? 500_000 : 25_000));
|
||||
Assert.False(EvaluateOneBucket(few, "tcp.slow").Items.ContainsKey("tcp.slow"));
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ public sealed class OpTests
|
||||
{
|
||||
// 1000 个回显,其中 5 个 1 s 的长尾:p50 约 50 ms,p99 仍在 50 ms 附近,p99.9 落在长尾上
|
||||
RawChunk chunk = ChunkFactory.Echo(
|
||||
s_agent, "tcp_echo", T0, 1000, 10,
|
||||
s_agent, "tcp_ping", T0, 1000, 10,
|
||||
i => new EchoPacket(false, false, 25_000, i % 200 == 0 && i > 0 ? 975_000 : 25_000, ProcessUs: 0), durationMs: 20_000);
|
||||
var rtt = (HistogramAcc)EvaluateOneBucket(chunk, "tcp.rtt").Items["tcp.rtt"];
|
||||
MetricDef def = TcpMetrics.Rtt;
|
||||
@@ -213,7 +213,7 @@ public sealed class OpTests
|
||||
(baseUs + 1_000_000, 0, 40_000u, 2u, 300u),
|
||||
(baseUs + 2_000_000, 0, 40_000u, 2u, 500u),
|
||||
]);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 10, 100, _ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [info]);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 10, 100, _ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [info]);
|
||||
var retrans = (RatioAcc)EvaluateOneBucket(chunk, "tcp.retrans").Items["tcp.retrans"];
|
||||
Assert.Equal(2UL, retrans.Numerator);
|
||||
Assert.Equal(400UL, retrans.Denominator);
|
||||
@@ -224,7 +224,7 @@ public sealed class OpTests
|
||||
{
|
||||
long baseUs = ChunkFactory.DialerUs(0);
|
||||
RawStream info = ChunkFactory.TcpInfo([(baseUs, 0, 1u, 10u, 100u), (baseUs + 1_000_000, 0, 1u, 0u, 50u), (baseUs + 2_000_000, 0, 1u, 1u, 150u)]);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 10, 100, _ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [info]);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 10, 100, _ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [info]);
|
||||
var retrans = (RatioAcc)EvaluateOneBucket(chunk, "tcp.retrans").Items["tcp.retrans"];
|
||||
Assert.Equal(1UL, retrans.Numerator);
|
||||
Assert.Equal(100UL, retrans.Denominator);
|
||||
@@ -234,12 +234,12 @@ public sealed class OpTests
|
||||
public void Retrans_InterleavedConnections_DoNotCreateFalseRetransmissions()
|
||||
{
|
||||
long ts = ChunkFactory.DialerUs(0);
|
||||
var builder = new StreamBuilder(Kinds.TcpEcho.FindStream("tcp_info")!);
|
||||
var builder = new StreamBuilder(Kinds.TcpPing.FindStream("tcp_info")!);
|
||||
builder.Add(ts, 0, 40_000, 0, 10, 10, 1000, 0, 1);
|
||||
builder.Add(ts + 1_000_000, 0, 40_000, 0, 10, 20, 1100, 0, 2);
|
||||
builder.Add(ts + 2_000_000, 0, 40_000, 0, 10, 11, 1100, 0, 1);
|
||||
builder.Add(ts + 3_000_000, 0, 40_000, 0, 10, 21, 1200, 0, 2);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 10, 100,
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 10, 100,
|
||||
_ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [builder.Build()]);
|
||||
var retrans = (RatioAcc)EvaluateOneBucket(chunk, "tcp.retrans").Items["tcp.retrans"];
|
||||
Assert.Equal(2UL, retrans.Numerator);
|
||||
@@ -256,7 +256,7 @@ public sealed class OpTests
|
||||
(ts + 1_000_000, 0, 40_000u, 1u, 200u),
|
||||
(ts + 3_000_000, 0, 40_000u, 3u, 400u),
|
||||
]);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 10, 100,
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 10, 100,
|
||||
_ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [info]);
|
||||
var retrans = (RatioAcc)EvaluateOneBucket(chunk, "tcp.retrans").Items["tcp.retrans"];
|
||||
Assert.Equal(3UL, retrans.Numerator);
|
||||
@@ -267,12 +267,12 @@ public sealed class OpTests
|
||||
public void Retrans_EqualConnectionIdsOnDifferentSides_AreIndependent()
|
||||
{
|
||||
long ts = ChunkFactory.DialerUs(0);
|
||||
var builder = new StreamBuilder(Kinds.TcpEcho.FindStream("tcp_info")!);
|
||||
var builder = new StreamBuilder(Kinds.TcpPing.FindStream("tcp_info")!);
|
||||
builder.Add(ts, 0, 40_000, 0, 10, 10, 1000, 0, 1);
|
||||
builder.Add(ts, 1, 40_000, 0, 10, 100, 2000, 0, 1);
|
||||
builder.Add(ts + 1_000_000, 0, 40_000, 0, 10, 11, 1100, 0, 1);
|
||||
builder.Add(ts + 1_000_000, 1, 40_000, 0, 10, 102, 2200, 0, 1);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 10, 100,
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 10, 100,
|
||||
_ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [builder.Build()]);
|
||||
var retrans = (RatioAcc)EvaluateOneBucket(chunk, "tcp.retrans").Items["tcp.retrans"];
|
||||
Assert.Equal(3UL, retrans.Numerator);
|
||||
@@ -283,12 +283,12 @@ public sealed class OpTests
|
||||
public void Retrans_ForwardAndReturnAreSplitBySide()
|
||||
{
|
||||
long ts = ChunkFactory.DialerUs(0);
|
||||
var builder = new StreamBuilder(Kinds.TcpEcho.FindStream("tcp_info")!);
|
||||
var builder = new StreamBuilder(Kinds.TcpPing.FindStream("tcp_info")!);
|
||||
builder.Add(ts, 0, 40_000, 0, 10, 10, 1000, 0, 1);
|
||||
builder.Add(ts, 1, 40_000, 0, 10, 100, 2000, 0, 1);
|
||||
builder.Add(ts + 1_000_000, 0, 40_000, 0, 10, 11, 1100, 0, 1);
|
||||
builder.Add(ts + 1_000_000, 1, 40_000, 0, 10, 102, 2200, 0, 1);
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_echo", T0, 10, 100,
|
||||
RawChunk chunk = ChunkFactory.Echo(s_agent, "tcp_ping", T0, 10, 100,
|
||||
_ => new EchoPacket(false, false, 20_000, 20_000), extraStreams: [builder.Build()]);
|
||||
var forward = (RatioAcc)EvaluateOneBucket(chunk, "tcp.retrans.up").Items["tcp.retrans.up"];
|
||||
var back = (RatioAcc)EvaluateOneBucket(chunk, "tcp.retrans.down").Items["tcp.retrans.down"];
|
||||
@@ -322,9 +322,9 @@ public sealed class OpTests
|
||||
// 10 秒的块,按 1 秒分桶:每个桶 10 个包
|
||||
RawChunk chunk = ChunkFactory.UdpEchoClean(s_agent, T0);
|
||||
var buckets = new SortedDictionary<long, MetricSet>();
|
||||
WindowEvaluator.Default.Evaluate(chunk, 1000, buckets, new HashSet<string> { "n.udp_echo" });
|
||||
WindowEvaluator.Default.Evaluate(chunk, 1000, buckets, new HashSet<string> { "n.quic_ping" });
|
||||
Assert.Equal(10, buckets.Count);
|
||||
Assert.All(buckets.Values, set => Assert.Equal(10UL, ((CounterAcc)set.Items["n.udp_echo"]).Value));
|
||||
Assert.All(buckets.Values, set => Assert.Equal(10UL, ((CounterAcc)set.Items["n.quic_ping"]).Value));
|
||||
Assert.Equal(T0, buckets.Keys.First());
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user