refactor!: rename the project from Monitor to MoShiro [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful
ci/woodpecker/push/main-amd64-build Pipeline was successful
Namespaces, assemblies, solution, binaries, images, systemd units, config paths, environment variables, protocol methods and the Linux user are all renamed. Breaking: existing databases, node identities and installed units must be recreated.
This commit is contained in:
1 parent
27ac7fb787
commit
2e146d4da7
309 files changed
+1565
-1572
No files matched your search
@@ -0,0 +1,41 @@
|
||||
namespace MoShiro.Backend.Analysis;
|
||||
|
||||
/// <summary>线路基础指标(udp_echo / icmp_echo 的回显流)。新增指标 = 加一行声明。</summary>
|
||||
public static class LinkMetrics
|
||||
{
|
||||
private static readonly string[] s_udpMsg = ["udp_echo.msg"];
|
||||
private static readonly string[] s_udpOrIcmpMsg = ["udp_echo.msg", "icmp_echo.msg"];
|
||||
|
||||
public static readonly MetricDef Rtt = Metric.Histogram(
|
||||
"rtt", s_udpOrIcmpMsg, Ops.Rtt, "RTT", "Round-trip time with the Agent processing time removed.", Unit.Ms,
|
||||
[Stat.P50, Stat.P95, Stat.P99, Stat.Mean], good: 50, poor: 150);
|
||||
|
||||
public static readonly MetricDef LossUp = Metric.Ratio(
|
||||
"loss.up", s_udpMsg, Ops.Loss(Dir.Up), "Loss (up)", "Packets lost between the Probe and the Agent.", good: 0.5, poor: 3);
|
||||
|
||||
public static readonly MetricDef LossDown = Metric.Ratio(
|
||||
"loss.down", s_udpMsg, Ops.Loss(Dir.Down), "Loss (down)", "Replies lost between the Agent and the Probe, among packets that reached the Agent.", good: 0.5, poor: 3);
|
||||
|
||||
public static readonly MetricDef LossTotal = Metric.Ratio(
|
||||
"loss.total", s_udpOrIcmpMsg, Ops.Loss(Dir.Total), "Loss (total)", "Packets whose reply never came back.", good: 0.5, poor: 3);
|
||||
|
||||
public static readonly MetricDef JitterUp = Metric.Histogram(
|
||||
"jitter.up", s_udpMsg, Ops.OwdVar(Dir.Up), "Jitter (up)", "One-way delay variation, offset and drift removed.", Unit.Ms, [Stat.P95], good: 3, poor: 20);
|
||||
|
||||
public static readonly MetricDef JitterDown = Metric.Histogram(
|
||||
"jitter.down", s_udpMsg, Ops.OwdVar(Dir.Down), "Jitter (down)", "One-way delay variation, offset and drift removed.", Unit.Ms, [Stat.P95], good: 3, poor: 20);
|
||||
|
||||
public static readonly MetricDef LossRun = Metric.RunLength(
|
||||
"loss.run", s_udpMsg, Ops.LossRuns, "Loss runs", "Lengths of consecutive lost packets.",
|
||||
new MetricExport("loss.run_max", Stat.Max, Unit.Packets, 2, 10),
|
||||
new MetricExport("loss.run_mean", Stat.Mean, Unit.Packets));
|
||||
|
||||
public static readonly MetricDef Reorder = Metric.Counter(
|
||||
"reorder", s_udpMsg, Ops.Reorder, "Reordered", "Replies that arrived after a higher sequence number.", new MetricExport("reorder", Stat.Count, Unit.Count));
|
||||
|
||||
public static readonly MetricDef Dup = Metric.Counter(
|
||||
"dup", s_udpMsg, Ops.Dup, "Duplicates", "Replies received more than once.", new MetricExport("dup", Stat.Count, Unit.Count));
|
||||
|
||||
public static readonly MetricDef SamplesUdp = Metric.Counter(
|
||||
"n.udp_echo", s_udpMsg, Ops.RowCount, "udp_echo samples", "Number of udp_echo records.", new MetricExport("n.udp_echo", Stat.Count, Unit.Count), Better.None);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
namespace MoShiro.Backend.Analysis;
|
||||
|
||||
public sealed record PresetDef(string Id, string Label, IReadOnlyList<string> MetricIds);
|
||||
|
||||
/// <summary>
|
||||
/// 指标注册表:存储、降采样、API、目录都由它驱动。新增指标时,在对应的 Metrics 文件里加一行声明,
|
||||
/// 再把它放进这里的 <see cref="All"/>(显式注册,AOT 安全,不使用反射)。
|
||||
/// </summary>
|
||||
public static class MetricRegistry
|
||||
{
|
||||
public static readonly IReadOnlyList<MetricDef> All =
|
||||
[
|
||||
LinkMetrics.Rtt, LinkMetrics.LossUp, LinkMetrics.LossDown, LinkMetrics.LossTotal,
|
||||
LinkMetrics.JitterUp, LinkMetrics.JitterDown, LinkMetrics.LossRun, LinkMetrics.Reorder, LinkMetrics.Dup, LinkMetrics.SamplesUdp,
|
||||
TcpMetrics.Rtt, TcpMetrics.Slow, TcpMetrics.Stall, TcpMetrics.StallMax, TcpMetrics.Retrans, TcpMetrics.Srtt, TcpMetrics.BulkRate, TcpMetrics.BulkPeak, TcpMetrics.SamplesTcp,
|
||||
SessionMetrics.ConnectSuccess, SessionMetrics.ConnectTcp, SessionMetrics.ConnectTls,
|
||||
SessionMetrics.FailTimeout, SessionMetrics.FailReset, SessionMetrics.FailTls,
|
||||
SessionMetrics.HoldResets, SessionMetrics.HoldLifetime,
|
||||
SessionMetrics.TrainLoss, SessionMetrics.TrainJitter, SessionMetrics.TrainRate, SessionMetrics.SamplesConnect,
|
||||
];
|
||||
|
||||
/// <summary>指标分组:前端按分组展示,新增指标只需要把它加进分组。</summary>
|
||||
public static readonly IReadOnlyList<PresetDef> Presets =
|
||||
[
|
||||
new("udp", "UDP", ["loss.up", "loss.down", "loss.total", "rtt.p50", "rtt.p95", "rtt.p99", "jitter.up.p95", "jitter.down.p95", "loss.run_max", "reorder", "dup"]),
|
||||
new("tcp", "TCP", ["tcp.rtt.p50", "tcp.rtt.p95", "tcp.rtt.p99", "tcp.rtt.p999", "tcp.rtt.max", "tcp.rtt.tail", "tcp.slow", "tcp.stall.per_min", "tcp.stall_max", "tcp.retrans", "tcp.srtt.p95"]),
|
||||
new("connect", "Connect", ["connect.success", "connect.tcp_ms.p95", "connect.tls_ms.p95", "connect.fail.timeout", "connect.fail.rst", "connect.fail.tls"]),
|
||||
new("session", "Session", ["hold.resets.per_h", "hold.lifetime_max"]),
|
||||
new("scores", "Scores", ["score.base", "score.mc", "score.hy2", "score.reality"]),
|
||||
];
|
||||
|
||||
private static readonly Dictionary<string, MetricDef> s_byId = All.ToDictionary(m => m.Id, StringComparer.Ordinal);
|
||||
|
||||
private static readonly Dictionary<string, (MetricDef Def, MetricExport Export)> s_byExport = BuildExportIndex();
|
||||
|
||||
public static MetricDef? Find(string metricId) => s_byId.GetValueOrDefault(metricId);
|
||||
|
||||
/// <summary>按导出 id(例如 <c>rtt.p95</c>)查找。</summary>
|
||||
public static bool TryFindExport(string exportId, out MetricDef def, out MetricExport export)
|
||||
{
|
||||
if (s_byExport.TryGetValue(exportId, out (MetricDef Def, MetricExport Export) found))
|
||||
{
|
||||
def = found.Def;
|
||||
export = found.Export;
|
||||
return true;
|
||||
}
|
||||
|
||||
def = null!;
|
||||
export = null!;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PresetDef? FindPreset(string id) => Presets.FirstOrDefault(p => p.Id == id);
|
||||
|
||||
public static IEnumerable<(MetricDef Def, MetricExport Export)> AllExports() =>
|
||||
All.SelectMany(def => def.Exports.Select(export => (def, export)));
|
||||
|
||||
private static Dictionary<string, (MetricDef, MetricExport)> BuildExportIndex()
|
||||
{
|
||||
var index = new Dictionary<string, (MetricDef, MetricExport)>(StringComparer.Ordinal);
|
||||
foreach (MetricDef def in All)
|
||||
{
|
||||
foreach (MetricExport export in def.Exports)
|
||||
{
|
||||
if (!index.TryAdd(export.Id, (def, export)))
|
||||
{
|
||||
throw new InvalidOperationException($"duplicate export id {export.Id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
namespace MoShiro.Backend.Analysis;
|
||||
|
||||
/// <summary>连接建立、长连接、UDP 压测(udp_train)的指标。</summary>
|
||||
public static class SessionMetrics
|
||||
{
|
||||
private static readonly string[] s_conn = ["connect.conn"];
|
||||
private static readonly string[] s_hold = ["hold.hold"];
|
||||
private static readonly string[] s_train = ["udp_train.pkt"];
|
||||
|
||||
public static readonly MetricDef ConnectSuccess = new(
|
||||
"connect.success", AccKind.Ratio, s_conn, Ops.OutcomeRatio(ConnectOutcome.Ok), "Connect success", "Share of connection attempts that completed.", Better.Higher,
|
||||
[new MetricExport("connect.success", Stat.Pct, Unit.Pct, 99, 90)]);
|
||||
|
||||
public static readonly MetricDef ConnectTcp = Metric.Histogram(
|
||||
"connect.tcp_ms", s_conn, Ops.PhaseMs("tcp_us"), "TCP connect time", "Time to establish the TCP connection.", Unit.Ms, [Stat.P95], good: 100, poor: 400);
|
||||
|
||||
public static readonly MetricDef ConnectTls = Metric.Histogram(
|
||||
"connect.tls_ms", s_conn, Ops.PhaseMs("tls_us"), "TLS handshake time", "Time for the TLS handshake after TCP is up.", Unit.Ms, [Stat.P95], good: 200, poor: 800);
|
||||
|
||||
public static readonly MetricDef FailTimeout = Metric.Counter(
|
||||
"connect.fail.timeout", s_conn, Ops.OutcomeCount(ConnectOutcome.Timeout), "Connect timeouts", "Attempts that timed out.", new MetricExport("connect.fail.timeout", Stat.Count, Unit.Count));
|
||||
|
||||
public static readonly MetricDef FailReset = Metric.Counter(
|
||||
"connect.fail.rst", s_conn, Ops.OutcomeCount(ConnectOutcome.Reset), "Connect resets", "Attempts answered with a reset.", new MetricExport("connect.fail.rst", Stat.Count, Unit.Count));
|
||||
|
||||
public static readonly MetricDef FailTls = Metric.Counter(
|
||||
"connect.fail.tls", s_conn, Ops.OutcomeCount(ConnectOutcome.TlsAlert), "TLS failures", "Attempts that ended in a TLS alert.", new MetricExport("connect.fail.tls", Stat.Count, Unit.Count));
|
||||
|
||||
public static readonly MetricDef HoldResets = Metric.Counter(
|
||||
"hold.resets", s_hold, Ops.HoldEvents(HoldEvent.Reset), "Held connection resets", "Times the held connection was reset.", new MetricExport("hold.resets.per_h", Stat.PerHour, Unit.PerHour, 0.5, 4));
|
||||
|
||||
public static readonly MetricDef HoldLifetime = Metric.Max(
|
||||
"hold.lifetime", s_hold, Ops.HoldLifetime, "Longest connection lifetime", "Longest observed lifetime of the held connection (ms).", Unit.Ms, "hold.lifetime_max", Better.Higher);
|
||||
|
||||
public static readonly MetricDef TrainLoss = Metric.Ratio(
|
||||
"train.loss", s_train, Ops.TrainLoss, "Train loss", "Loss of a fixed-rate UDP stream.", good: 1, poor: 10);
|
||||
|
||||
public static readonly MetricDef TrainJitter = Metric.Histogram(
|
||||
"train.jitter", s_train, Ops.TrainJitter, "Train jitter", "One-way delay variation of a fixed-rate UDP stream.", Unit.Ms, [Stat.P95], good: 3, poor: 20);
|
||||
|
||||
public static readonly MetricDef TrainRate = Metric.Histogram(
|
||||
"train.rate", s_train, Ops.TrainRate, "Train rate", "Delivered rate of a fixed-rate UDP stream per second.", Unit.Mbps, [Stat.P50, Stat.Mean], Better.Higher);
|
||||
|
||||
public static readonly MetricDef SamplesConnect = Metric.Counter(
|
||||
"n.connect", s_conn, Ops.RowCount, "connect samples", "Number of connection attempts.", new MetricExport("n.connect", Stat.Count, Unit.Count), Better.None);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
namespace MoShiro.Backend.Analysis;
|
||||
|
||||
/// <summary>TCP 指标:回显的 RTT 与卡顿、内核采样的重传、批量传输的吞吐。</summary>
|
||||
public static class TcpMetrics
|
||||
{
|
||||
private static readonly string[] s_tcpMsg = ["tcp_echo.msg"];
|
||||
private static readonly string[] s_tcpInfo = ["tcp_echo.tcp_info", "tcp_bulk.tcp_info"];
|
||||
private static readonly string[] s_bulkBytes = ["tcp_bulk.bytes"];
|
||||
|
||||
public static readonly MetricDef Rtt = Metric.Histogram(
|
||||
"tcp.rtt", s_tcpMsg, Ops.Rtt, "TCP RTT", "Application-level echo round trip over TCP (includes retransmission delay).", Unit.Ms,
|
||||
[Stat.P50, Stat.P95, Stat.P99, Stat.P999, Stat.Max, Stat.Tail], good: 60, poor: 200);
|
||||
|
||||
public static readonly MetricDef Slow = Metric.Ratio(
|
||||
"tcp.slow", s_tcpMsg, Ops.SlowShare(minSamples: 20), "TCP long-tail echoes",
|
||||
"Share of echoes slower than the long-tail threshold: max(1.8 x baseline, baseline + max(15 ms, 0.35 x baseline)), where the baseline is the median RTT of the same 10 s chunk.",
|
||||
good: 1, poor: 5);
|
||||
|
||||
public static readonly MetricDef Stall = Metric.Counter(
|
||||
"tcp.stall", s_tcpMsg, Ops.Gap(GapOutput.Count, "rate_hz", thresholdMs: 100), "TCP stalls",
|
||||
"Arrival gaps longer than the expected interval plus 100 ms (head-of-line blocking).",
|
||||
new MetricExport("tcp.stall.per_min", Stat.PerMin, Unit.PerMin, 0.5, 5));
|
||||
|
||||
public static readonly MetricDef StallMax = Metric.Max(
|
||||
"tcp.stall_max", s_tcpMsg, Ops.Gap(GapOutput.MaxMs, "rate_hz", thresholdMs: 100), "Longest TCP stall", "Longest stall in the period.", Unit.Ms, good: 200, poor: 1000);
|
||||
|
||||
public static readonly MetricDef Retrans = Metric.Ratio(
|
||||
"tcp.retrans", s_tcpInfo, Ops.KernelDelta("retrans_total", "segs_out"), "TCP retransmissions", "Retransmitted segments as a share of segments sent (kernel counters).", good: 0.5, poor: 3);
|
||||
|
||||
public static readonly MetricDef Srtt = Metric.Histogram(
|
||||
"tcp.srtt", s_tcpInfo, Ops.Column("srtt_us", 0.001), "Kernel srtt", "Smoothed RTT sampled from the kernel.", Unit.Ms, [Stat.P95], good: 60, poor: 200);
|
||||
|
||||
public static readonly MetricDef BulkRate = Metric.Histogram(
|
||||
"tcp.bulk.mbps", s_bulkBytes, Ops.BulkRate, "Bulk throughput", "Aggregate throughput of the bulk transfer streams.", Unit.Mbps,
|
||||
[Stat.P50, Stat.Mean, Stat.Max], Better.Higher);
|
||||
|
||||
public static readonly MetricDef BulkPeak = Metric.Histogram(
|
||||
"tcp.bulk.peak", s_bulkBytes, Ops.BulkPeak, "Peak bulk throughput", "Best sustained 1 s throughput of the bulk transfer: how fast this line can go.", Unit.Mbps,
|
||||
[Stat.Max], Better.Higher);
|
||||
|
||||
public static readonly MetricDef SamplesTcp = Metric.Counter(
|
||||
"n.tcp_echo", s_tcpMsg, Ops.RowCount, "tcp_echo samples", "Number of tcp_echo records.", new MetricExport("n.tcp_echo", Stat.Count, Unit.Count), Better.None);
|
||||
}
|
||||
Reference in new issue
Block a user