chore: initial project import

This commit is contained in:
justme committed 2026-10-04 21:46:39 +08:00
commit 3fc4e5ca53
347 files changed
+56172

No files matched your search

@@ -0,0 +1,210 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Fleet.Core;
namespace Monitor.Protocol;
/// <summary>Agent 单调时钟与 UTC 的锚点,以及 Probe 时钟相对 Agent 时钟的偏移估计。</summary>
public sealed class ChunkClock
{
[JsonPropertyName("agent_mono_us")]
public long AgentMonoUs { get; set; }
[JsonPropertyName("utc_ms")]
public long UtcMs { get; set; }
/// <summary>Agent 时钟 − Probe 时钟(微秒)。</summary>
[JsonPropertyName("probe_offset_us")]
public long ProbeOffsetUs { get; set; }
/// <summary>Probe 相对 Agent 的时钟漂移(ppb,十亿分之一)。</summary>
[JsonPropertyName("probe_drift_ppb")]
public long ProbeDriftPpb { get; set; }
}
public sealed class ColumnHeader
{
[JsonPropertyName("name")]
public string Name { get; set; } = "";
/// <summary>u8 | u16 | u32 | u64 | i32 | i64</summary>
[JsonPropertyName("type")]
public string Type { get; set; } = "";
/// <summary>plain | delta</summary>
[JsonPropertyName("enc")]
public string Enc { get; set; } = "plain";
[JsonPropertyName("nullable")]
public bool Nullable { get; set; }
/// <summary>ts_probe | ts_agent | ts_local,其他为空。</summary>
[JsonPropertyName("role")]
public string? Role { get; set; }
}
public sealed class StreamHeader
{
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("count")]
public int Count { get; set; }
[JsonPropertyName("columns")]
public List<ColumnHeader> Columns { get; set; } = [];
}
/// <summary>块头(JSON,自描述):列定义写在块里,新增列或新增 Kind 不需要升级 container_version。</summary>
public sealed class RawChunkHeader
{
[JsonPropertyName("chunk_id")]
public ChunkId ChunkId { get; set; }
[JsonPropertyName("container_version")]
public int ContainerVersion { get; set; } = ProtocolVersion.Container;
[JsonPropertyName("kind")]
public string Kind { get; set; } = "";
[JsonPropertyName("task_id")]
public TaskId? TaskId { get; set; }
[JsonPropertyName("test_id")]
public TestId? TestId { get; set; }
[JsonPropertyName("phase")]
public int? Phase { get; set; }
[JsonPropertyName("agent_id")]
public NodeId AgentId { get; set; }
[JsonPropertyName("probe_id")]
public ProbeId? ProbeId { get; set; }
[JsonPropertyName("target")]
public string? Target { get; set; }
/// <summary>参数的完整快照(包含默认值)。</summary>
[JsonPropertyName("params")]
public Dictionary<string, JsonElement> Params { get; set; } = [];
[JsonPropertyName("port")]
public int Port { get; set; }
[JsonPropertyName("direction")]
public string? Direction { get; set; }
[JsonPropertyName("start_utc_ms")]
public long StartUtcMs { get; set; }
[JsonPropertyName("duration_ms")]
public int DurationMs { get; set; }
/// <summary>Probe 一侧的列没有在宽限期内送达:只有 Agent 一侧的数据。</summary>
[JsonPropertyName("partial")]
public bool Partial { get; set; }
[JsonPropertyName("clock")]
public ChunkClock Clock { get; set; } = new();
[JsonPropertyName("streams")]
public List<StreamHeader> Streams { get; set; } = [];
/// <summary>
/// "line:&lt;probe_id&gt;" 或 "target:&lt;task_id&gt;":存储和分析用的序列标识。
/// 一条线路是一对(Probe,Agent):同一个 Agent 上每个 Probe 的数据各是一个序列,互不混合。
/// </summary>
[JsonIgnore]
public string Series => TaskId is { } id && Target is not null ? "target:" + id.Value : LinePrefix + (ProbeId?.Value ?? "");
public const string LinePrefix = "line:";
}
public sealed class RawColumn
{
public RawColumn(string name, ColumnType type, ColumnEnc enc, bool nullable, ColumnRole role, long[] values, bool[]? valid)
{
Name = name;
Type = type;
Enc = enc;
Nullable = nullable;
Role = role;
Values = values;
Valid = valid;
}
public string Name { get; }
public ColumnType Type { get; }
public ColumnEnc Enc { get; }
public bool Nullable { get; }
public ColumnRole Role { get; }
/// <summary>所有列统一用 long 存放(u64 按位保存)。缺失值对应的位置内容无意义,请先看 <see cref="IsValid"/>。</summary>
public long[] Values { get; }
public bool[]? Valid { get; }
public int Count => Values.Length;
public bool IsValid(int row) => Valid is null || Valid[row];
}
public sealed class RawStream
{
public RawStream(string name, int count, IReadOnlyList<RawColumn> columns)
{
Name = name;
Count = count;
Columns = columns;
}
public string Name { get; }
public int Count { get; }
public IReadOnlyList<RawColumn> Columns { get; }
public RawColumn? Find(string name)
{
foreach (RawColumn column in Columns)
{
if (column.Name == name)
{
return column;
}
}
return null;
}
}
public sealed class RawChunk
{
public RawChunk(RawChunkHeader header, IReadOnlyList<RawStream> streams)
{
Header = header;
Streams = streams;
}
public RawChunkHeader Header { get; }
public IReadOnlyList<RawStream> Streams { get; }
public RawStream? Find(string name)
{
foreach (RawStream stream in Streams)
{
if (stream.Name == name)
{
return stream;
}
}
return null;
}
}