fix: prevent QUIC heartbeat stalls and isolate TCP retransmission counters [CI] [SKIP TESTS]
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/dev-image Pipeline was successful

This commit is contained in:
justme committed 2026-10-20 18:23:31 +08:00
1 parent 0066a947da
commit 0fd38b2367
14 files changed
+299 -50

No files matched your search

@@ -9,7 +9,7 @@ internal static class TcpInfoTime
side is not null && side.Values[row] == 0 ? view.ProbeToUtcMs(ts.Values[row]) : view.AgentToUtcMs(ts.Values[row]);
}
/// <summary>两次采样之间累计计数的差值(分子)与另一个累计计数的差值(分母),按 side 分别计算。</summary>
/// <summary>两次采样之间累计计数的差值(分子)与另一个累计计数的差值(分母),按 (side, conn) 分别计算;旧数据没有 conn 时按 side 计算。</summary>
internal sealed class KernelDeltaOp : MetricOp
{
private readonly string _field;
@@ -21,12 +21,13 @@ internal sealed class KernelDeltaOp : MetricOp
_over = over;
}
public override string Signature => $"kernel_delta/{_field}/{_over}/1";
public override string Signature => $"kernel_delta/{_field}/{_over}/2";
public override void Evaluate(ChunkView view, RawStream stream, IObservationSink sink)
{
RawColumn? ts = stream.Find("ts");
RawColumn? side = stream.Find("side");
RawColumn? connection = stream.Find("conn");
RawColumn? field = stream.Find(_field);
RawColumn? over = stream.Find(_over);
if (ts is null || field is null || over is null)
@@ -34,21 +35,34 @@ internal sealed class KernelDeltaOp : MetricOp
return;
}
var last = new Dictionary<long, (long Field, long Over)>();
var last = new Dictionary<(long Side, long Connection), (long Ts, long Field, long Over)>();
for (int i = 0; i < stream.Count; i++)
{
long key = side?.Values[i] ?? 0;
if (last.TryGetValue(key, out (long Field, long Over) previous))
if (!ts.IsValid(i) || !field.IsValid(i) || !over.IsValid(i))
{
long dField = Math.Max(0, field.Values[i] - previous.Field);
long dOver = Math.Max(0, over.Values[i] - previous.Over);
if (dOver > 0)
continue;
}
var key = (side?.Values[i] ?? 0, connection?.IsValid(i) == true ? connection.Values[i] : 0);
if (last.TryGetValue(key, out (long Ts, long Field, long Over) previous))
{
// Ignore delayed/duplicate samples without replacing the newer baseline.
if (ts.Values[i] <= previous.Ts)
{
continue;
}
// Either counter falling means reset/wrap: discard the whole
// interval rather than mixing a new numerator with an old denominator.
long dField = field.Values[i] - previous.Field;
long dOver = over.Values[i] - previous.Over;
if (dField >= 0 && dOver > 0)
{
sink.Emit(TcpInfoTime.ToUtcMs(view, ts, side, i), dField, dOver);
}
}
last[key] = (field.Values[i], over.Values[i]);
last[key] = (ts.Values[i], field.Values[i], over.Values[i]);
}
}
}