fix(query): anchor=latest follows the newest sample of any level, not just the 1m rows [CI]
This commit is contained in:
1 parent
d95acc6575
commit
e1ec7c9b04
3 files changed
+21
-2
No files matched your search
@@ -213,6 +213,9 @@ public interface IMetricStore
|
|||||||
/// <summary>这条序列在某一层里最早的窗口起点;没有数据返回 null。</summary>
|
/// <summary>这条序列在某一层里最早的窗口起点;没有数据返回 null。</summary>
|
||||||
ValueTask<long?> EarliestAsync(MetricLevel level, NodeId agentId, string series, CancellationToken ct);
|
ValueTask<long?> EarliestAsync(MetricLevel level, NodeId agentId, string series, CancellationToken ct);
|
||||||
|
|
||||||
|
/// <summary>这条序列在某一层里最晚的窗口起点;没有数据返回 null。</summary>
|
||||||
|
ValueTask<long?> LatestAsync(MetricLevel level, NodeId agentId, string series, CancellationToken ct);
|
||||||
|
|
||||||
ValueTask<IReadOnlyList<MetricRow>> ReadAgentsAsync(MetricLevel level, IReadOnlyCollection<NodeId> agentIds, string series, long fromMs, long toMs, CancellationToken ct);
|
ValueTask<IReadOnlyList<MetricRow>> ReadAgentsAsync(MetricLevel level, IReadOnlyCollection<NodeId> agentIds, string series, long fromMs, long toMs, CancellationToken ct);
|
||||||
|
|
||||||
ValueTask<int> DeleteOlderThanAsync(MetricLevel level, long cutoffMs, CancellationToken ct);
|
ValueTask<int> DeleteOlderThanAsync(MetricLevel level, long cutoffMs, CancellationToken ct);
|
||||||
|
|||||||
@@ -45,8 +45,19 @@ public sealed class RowLoader
|
|||||||
return at + 1000;
|
return at + 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
IReadOnlyList<MetricRow> rows = await _metrics.ReadAsync(MetricLevel.M1, agent, series, nowMs - (7 * Steps.Day), nowMs + 60_000, ct);
|
// 热层空了(Backend 刚重启、热层还没攒起来)就看持久层:各层里最晚的窗口取最大。只看 1 分钟层会落后——它比 5 分钟层更新得慢时,
|
||||||
return rows.Count == 0 ? null : rows.Max(r => r.WindowStart) + 60_000;
|
// 窗口就被定在好几个小时以前,页面显示的全是旧数据。
|
||||||
|
long? latest = null;
|
||||||
|
foreach (MetricLevel level in new[] { MetricLevel.S10, MetricLevel.M1, MetricLevel.M5 })
|
||||||
|
{
|
||||||
|
if (await _metrics.LatestAsync(level, agent, series, ct) is { } start)
|
||||||
|
{
|
||||||
|
long end = Math.Min(start + level.WidthMs(), nowMs);
|
||||||
|
latest = latest is null ? end : Math.Max(latest.Value, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -90,6 +90,11 @@ public sealed class SqliteMetricStore : IMetricStore
|
|||||||
c => c.Query($"SELECT MIN(window_start) FROM {level.TableName()} WHERE agent_id = @a AND series = @s", r => r.NullableLong(0), ("@a", agentId.Value), ("@s", series)).FirstOrDefault(),
|
c => c.Query($"SELECT MIN(window_start) FROM {level.TableName()} WHERE agent_id = @a AND series = @s", r => r.NullableLong(0), ("@a", agentId.Value), ("@s", series)).FirstOrDefault(),
|
||||||
ct);
|
ct);
|
||||||
|
|
||||||
|
public ValueTask<long?> LatestAsync(MetricLevel level, NodeId agentId, string series, CancellationToken ct) =>
|
||||||
|
_db.ReadAsync(
|
||||||
|
c => c.Query($"SELECT MAX(window_start) FROM {level.TableName()} WHERE agent_id = @a AND series = @s", r => r.NullableLong(0), ("@a", agentId.Value), ("@s", series)).FirstOrDefault(),
|
||||||
|
ct);
|
||||||
|
|
||||||
public ValueTask<IReadOnlyList<MetricRow>> ReadAgentsAsync(MetricLevel level, IReadOnlyCollection<NodeId> agentIds, string series, long fromMs, long toMs, CancellationToken ct) =>
|
public ValueTask<IReadOnlyList<MetricRow>> ReadAgentsAsync(MetricLevel level, IReadOnlyCollection<NodeId> agentIds, string series, long fromMs, long toMs, CancellationToken ct) =>
|
||||||
_db.ReadAsync<IReadOnlyList<MetricRow>>(
|
_db.ReadAsync<IReadOnlyList<MetricRow>>(
|
||||||
c =>
|
c =>
|
||||||
|
|||||||
Reference in new issue
Block a user