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
@@ -1,4 +1,4 @@
|
||||
# Monitor Agent
|
||||
# MoShiro Agent
|
||||
|
||||
Agent 是部署在 VPS 或其他可达网络节点上的采集进程。它向 Backend 注册并保持连接,接受 Probe 的测量会话,执行线路任务中的 Agent 侧工作,再将两端数据合并后上报。
|
||||
|
||||
@@ -18,14 +18,14 @@ Probe ──TLS 控制 / UDP、TCP 测量──> Agent ──长连接与数据
|
||||
|
||||
```sh
|
||||
cd backend
|
||||
dotnet build agent/src/Monitor.Agent -c Release
|
||||
dotnet build agent/src/MoShiro.Agent -c Release
|
||||
dotnet build fleet/tools/fleet-enroll -c Release
|
||||
```
|
||||
|
||||
发布 NativeAOT 程序需要对应平台的 C/C++ 工具链;`<RID>` 应与构建环境和目标平台匹配:
|
||||
|
||||
```sh
|
||||
dotnet publish agent/src/Monitor.Agent -c Release -r <RID> -p:PublishAot=true
|
||||
dotnet publish agent/src/MoShiro.Agent -c Release -r <RID> -p:PublishAot=true
|
||||
dotnet publish fleet/tools/fleet-enroll -c Release -r <RID> -p:PublishAot=true
|
||||
```
|
||||
|
||||
@@ -36,7 +36,7 @@ dotnet publish fleet/tools/fleet-enroll -c Release -r <RID> -p:PublishAot=true
|
||||
先在管理端创建加入令牌,然后在 Agent 主机上运行一次性注册工具:
|
||||
|
||||
```sh
|
||||
fleet-enroll --server https://<backend> --join <token> --name <agent-name> --identity-dir /etc/monitor
|
||||
fleet-enroll --server https://<backend> --join <token> --name <agent-name> --identity-dir /etc/moshiro
|
||||
```
|
||||
|
||||
注册工具会在身份目录写入节点身份和证书。准备本地 `agent.json`,其中 `fleet.server` 指向 Backend,`fleet.identity_dir` 指向上述目录;`listen`、`limits` 和 `reporting` 可按节点环境调整。配置文件不会由 Backend 修改。限制目标网段和测量预算时,应按实际网络与机器能力配置;`allowed_target_cidrs` 默认为空,不允许 Agent 执行目标探测任务。
|
||||
@@ -44,12 +44,12 @@ fleet-enroll --server https://<backend> --join <token> --name <agent-name> --ide
|
||||
启动 Agent:
|
||||
|
||||
```sh
|
||||
monitor-agent --config /etc/monitor/agent.json
|
||||
moshiro-agent --config /etc/moshiro/agent.json
|
||||
```
|
||||
|
||||
容器节点的运行方式(podman + systemd)和宿主机更新器见 [`../../docs/deployment.md`](../../docs/deployment.md)。也可使用 OCI 镜像 `registry.oeo.one/monitor/monitor-agent:<version>`,自动选择 Linux amd64 或 arm64 镜像。镜像同时包含 `fleet-enroll`;可通过 `--entrypoint /usr/local/bin/fleet-enroll` 执行首次注册。容器默认读取命名 volume 中的 `/etc/monitor/agent.json` 与身份文件;建议使用宿主网络,并按 ICMP 测量需求添加 `NET_RAW` 能力。镜像以 UID/GID 1654 运行,新命名 volume 由引擎按镜像目录初始化权限。
|
||||
容器节点的运行方式(podman + systemd)和宿主机更新器见 [`../../docs/deployment.md`](../../docs/deployment.md)。也可使用 OCI 镜像 `registry.oeo.one/moshiro/moshiro-agent:<version>`,自动选择 Linux amd64 或 arm64 镜像。镜像同时包含 `fleet-enroll`;可通过 `--entrypoint /usr/local/bin/fleet-enroll` 执行首次注册。容器默认读取命名 volume 中的 `/etc/moshiro/agent.json` 与身份文件;建议使用宿主网络,并按 ICMP 测量需求添加 `NET_RAW` 能力。镜像以 UID/GID 1654 运行,新命名 volume 由引擎按镜像目录初始化权限。
|
||||
|
||||
不传 `--config` 时默认读取 `/etc/monitor/agent.json`。Agent 默认监听控制端口 `7443/tcp`,数据端口 `7443/udp` 和 `7444/tcp`;防火墙和面板中的节点端口配置需与本地配置一致。`reporting.host_stats` 可关闭主机状态上报;启用时只上报资源使用等汇总数据,不包含主机名、进程或 IP。
|
||||
不传 `--config` 时默认读取 `/etc/moshiro/agent.json`。Agent 默认监听控制端口 `7443/tcp`,数据端口 `7443/udp` 和 `7444/tcp`;防火墙和面板中的节点端口配置需与本地配置一致。`reporting.host_stats` 可关闭主机状态上报;启用时只上报资源使用等汇总数据,不包含主机名、进程或 IP。
|
||||
|
||||
## 设计说明
|
||||
|
||||
|
||||
+26
-26
@@ -4,15 +4,15 @@ using Fleet.Core;
|
||||
using Fleet.Hosting;
|
||||
using Fleet.Link;
|
||||
using Fleet.Rpc;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>Agent 的组装点:数据面、点对点监听、与 Backend 的链路都在这里接起来。没有全局状态,测试可以在同一进程里启动多个。</summary>
|
||||
public sealed class AgentApp : IDisposable
|
||||
{
|
||||
public const string Version = Monitor.Protocol.BuildInfo.Version;
|
||||
public const string Version = MoShiro.Protocol.BuildInfo.Version;
|
||||
|
||||
private readonly AgentConfig _config;
|
||||
private readonly LoadedNodeIdentity _identity;
|
||||
@@ -35,7 +35,7 @@ public sealed class AgentApp : IDisposable
|
||||
private readonly TestRunner _tests;
|
||||
private readonly FleetLink _link;
|
||||
|
||||
/// <param name="dataDirectory">配置目录(容器里的 <c>/etc/monitor</c>):宿主机更新器和节点在这里交换清单、请求和状态。</param>
|
||||
/// <param name="dataDirectory">配置目录(容器里的 <c>/etc/moshiro</c>):宿主机更新器和节点在这里交换清单、请求和状态。</param>
|
||||
public AgentApp(AgentConfig config, LoadedNodeIdentity identity, string dataDirectory, TimeProvider time, INodeLog log)
|
||||
{
|
||||
_update = new UpdateBridge(dataDirectory, new ConfigStore(dataDirectory).Write, log);
|
||||
@@ -185,48 +185,48 @@ public sealed class AgentApp : IDisposable
|
||||
HashSet<string>? allowed = _config.Policy.AllowMethods is { } list ? [.. list] : null;
|
||||
bool Allow(string method) => allowed is null || allowed.Contains(method);
|
||||
|
||||
if (Allow(MonitorMethods.TestRun))
|
||||
if (Allow(MoShiroMethods.TestRun))
|
||||
{
|
||||
router.On(
|
||||
MonitorMethods.TestRun,
|
||||
MonitorJsonContext.Default.TestRunParams,
|
||||
MonitorJsonContext.Default.TestRunResult,
|
||||
MoShiroMethods.TestRun,
|
||||
MoShiroJsonContext.Default.TestRunParams,
|
||||
MoShiroJsonContext.Default.TestRunResult,
|
||||
(_, run, _) => ValueTask.FromResult(_tests.Start(run)));
|
||||
}
|
||||
|
||||
if (Allow(MonitorMethods.TestCancel))
|
||||
if (Allow(MoShiroMethods.TestCancel))
|
||||
{
|
||||
router.On(
|
||||
MonitorMethods.TestCancel,
|
||||
MonitorJsonContext.Default.TestCancelParams,
|
||||
MonitorJsonContext.Default.TestRunResult,
|
||||
MoShiroMethods.TestCancel,
|
||||
MoShiroJsonContext.Default.TestCancelParams,
|
||||
MoShiroJsonContext.Default.TestRunResult,
|
||||
(_, cancel, _) => ValueTask.FromResult(Result<TestRunResult>.Ok(new TestRunResult { Accepted = _tests.Cancel(cancel.TestId) })));
|
||||
}
|
||||
|
||||
if (Allow(MonitorMethods.UpdateOffer))
|
||||
if (Allow(MoShiroMethods.UpdateOffer))
|
||||
{
|
||||
router.OnNotify(MonitorMethods.UpdateOffer, MonitorJsonContext.Default.UpdateOfferParams, (_, offer, _) =>
|
||||
router.OnNotify(MoShiroMethods.UpdateOffer, MoShiroJsonContext.Default.UpdateOfferParams, (_, offer, _) =>
|
||||
{
|
||||
_update.WriteOffer(offer);
|
||||
return ValueTask.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
if (Allow(MonitorMethods.UpdateApply))
|
||||
if (Allow(MoShiroMethods.UpdateApply))
|
||||
{
|
||||
router.OnNotify(MonitorMethods.UpdateApply, MonitorJsonContext.Default.UpdateOfferParams, (_, _, _) =>
|
||||
router.OnNotify(MoShiroMethods.UpdateApply, MoShiroJsonContext.Default.UpdateOfferParams, (_, _, _) =>
|
||||
{
|
||||
_update.RequestApply();
|
||||
return ValueTask.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
if (Allow(MonitorMethods.ProbeDisconnect))
|
||||
if (Allow(MoShiroMethods.ProbeDisconnect))
|
||||
{
|
||||
router.On(
|
||||
MonitorMethods.ProbeDisconnect,
|
||||
MonitorJsonContext.Default.ProbeDisconnectParams,
|
||||
MonitorJsonContext.Default.TestRunResult,
|
||||
MoShiroMethods.ProbeDisconnect,
|
||||
MoShiroJsonContext.Default.ProbeDisconnectParams,
|
||||
MoShiroJsonContext.Default.TestRunResult,
|
||||
async (_, request, _) => Result<TestRunResult>.Ok(new TestRunResult { Accepted = await _hub.DisconnectAsync(request.ProbeId.Value) }));
|
||||
}
|
||||
|
||||
@@ -236,11 +236,11 @@ public sealed class AgentApp : IDisposable
|
||||
Identity = _identity.Identity,
|
||||
NodeId = _identity.NodeId,
|
||||
NodeVersion = Version,
|
||||
Capabilities = [MonitorCapabilities.Base, MonitorCapabilities.KindsPrefix + string.Join(',', BlockCatalog.AgentKinds)],
|
||||
Capabilities = [MoShiroCapabilities.Base, MoShiroCapabilities.KindsPrefix + string.Join(',', BlockCatalog.AgentKinds)],
|
||||
HelloMeta = HelloMeta,
|
||||
HeartbeatExtra = HeartbeatExtra,
|
||||
};
|
||||
var link = new FleetLink(options, router, [new StateHandler<TaskSet>(TaskSet.StateType, MonitorJsonContext.Default.TaskSet, _tasks.ApplyAsync)], _outbox, _time, _log);
|
||||
var link = new FleetLink(options, router, [new StateHandler<TaskSet>(TaskSet.StateType, MoShiroJsonContext.Default.TaskSet, _tasks.ApplyAsync)], _outbox, _time, _log);
|
||||
|
||||
// 链路重新连上之后补报:在线的 Probe 都告诉 Backend(Backend 重启或链路抖动期间错过了 probe_connected)
|
||||
link.OnConnected = async (_, _) =>
|
||||
@@ -257,7 +257,7 @@ public sealed class AgentApp : IDisposable
|
||||
{
|
||||
var meta = new AgentHelloMeta
|
||||
{
|
||||
Platform = Monitor.Measurement.PlatformDetector.Detect(),
|
||||
Platform = MoShiro.Measurement.PlatformDetector.Detect(),
|
||||
TlsSpki = _identity.File.TlsSpki,
|
||||
ProbeTcpPort = ControlPort,
|
||||
ProbeUdpPorts = [.. UdpPorts],
|
||||
@@ -269,7 +269,7 @@ public sealed class AgentApp : IDisposable
|
||||
MaxConcurrentTests = _config.Limits.MaxConcurrentTests,
|
||||
},
|
||||
};
|
||||
return JsonSerializer.SerializeToElement(meta, MonitorJsonContext.Default.AgentHelloMeta);
|
||||
return JsonSerializer.SerializeToElement(meta, MoShiroJsonContext.Default.AgentHelloMeta);
|
||||
}
|
||||
|
||||
private long _lastIn;
|
||||
@@ -296,6 +296,6 @@ public sealed class AgentApp : IDisposable
|
||||
_lastIn = packetsIn;
|
||||
_lastOut = packetsOut;
|
||||
_lastAtMs = nowMs;
|
||||
return JsonSerializer.SerializeToElement(extra, MonitorJsonContext.Default.AgentHeartbeatExtra);
|
||||
return JsonSerializer.SerializeToElement(extra, MoShiroJsonContext.Default.AgentHeartbeatExtra);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>
|
||||
/// <c>agent.json</c>:节点本地配置,面板无法修改。其中 <c>limits</c> 是本地硬上限:期望任务集超出这些范围时,
|
||||
@@ -40,7 +40,7 @@ public sealed class FleetSection
|
||||
public string Server { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("identity_dir")]
|
||||
public string IdentityDir { get; set; } = "/etc/monitor";
|
||||
public string IdentityDir { get; set; } = "/etc/moshiro";
|
||||
}
|
||||
|
||||
public sealed class ListenSection
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
using Fleet.Core;
|
||||
using Fleet.Link;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>
|
||||
/// Probe 的列块到达之后:找到对应的流 → 与 Agent 在数据面记录的列合并 → 盖章(块头、时钟锚点)→ 编码 → 放进发件箱(通道 16)。
|
||||
@@ -70,6 +70,6 @@ public sealed class ChunkAssembler
|
||||
/// <summary>Agent 自己采集的块(目标任务)直接发出。</summary>
|
||||
public void Emit(RawChunk chunk)
|
||||
{
|
||||
_outbox.Enqueue(MonitorChannels.RawChunk, chunk.Header.ChunkId.Value, RawChunkCodec.Encode(chunk));
|
||||
_outbox.Enqueue(MoShiroChannels.RawChunk, chunk.Header.ChunkId.Value, RawChunkCodec.Encode(chunk));
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -4,10 +4,10 @@ using System.Net.Sockets;
|
||||
using Fleet.Core;
|
||||
using Fleet.Link;
|
||||
using Fleet.Rpc;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>进程内计数(只有计数,没有主机信息):用于心跳和面板上的节点状态。数据面的包计数由共享的 <see cref="DataPlaneCounters"/> 提供。</summary>
|
||||
public sealed class AgentCounters
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
using System.Globalization;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>
|
||||
/// 主机资源占用的只读快照:CPU 占用、内存、根分区、网卡累计流量与瞬时网速、系统运行时长。
|
||||
+4
-4
@@ -4,8 +4,8 @@
|
||||
Condition="'$(UseAotAnywhere)' == 'true'" />
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>monitor-agent</AssemblyName>
|
||||
<RootNamespace>Monitor.Agent</RootNamespace>
|
||||
<AssemblyName>moshiro-agent</AssemblyName>
|
||||
<RootNamespace>MoShiro.Agent</RootNamespace>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
@@ -15,10 +15,10 @@
|
||||
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Monitor.Backend.Tests" />
|
||||
<InternalsVisibleTo Include="MoShiro.Backend.Tests" />
|
||||
<ProjectReference Include="..\..\..\fleet\src\Fleet.Link\Fleet.Link.csproj" />
|
||||
<ProjectReference Include="..\..\..\fleet\src\Fleet.Hosting\Fleet.Hosting.csproj" />
|
||||
<ProjectReference Include="..\..\..\shared\Monitor.Measurement\Monitor.Measurement.csproj" />
|
||||
<ProjectReference Include="..\..\..\shared\MoShiro.Measurement\MoShiro.Measurement.csproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||
<Import Project="Sdk.targets" Sdk="StuDev.AotAnywhere"
|
||||
+11
-11
@@ -2,10 +2,10 @@ using System.Text.Json;
|
||||
using Fleet.Core;
|
||||
using Fleet.Link;
|
||||
using Fleet.Rpc;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>Agent → Backend 的上行:事件和测试状态是尽力而为的通知(链路断开时丢弃;列块走发件箱,不会丢)。</summary>
|
||||
public sealed class BackendUplink
|
||||
@@ -31,7 +31,7 @@ public sealed class BackendUplink
|
||||
}
|
||||
|
||||
var parameters = new AgentEventParams { Kind = kind, AtUtcMs = _time.GetUtcNow().ToUnixTimeMilliseconds(), Detail = detail, Probe = probe };
|
||||
await SafeAsync(() => session.NotifyAsync(MonitorMethods.Event, parameters, MonitorJsonContext.Default.AgentEventParams, CancellationToken.None));
|
||||
await SafeAsync(() => session.NotifyAsync(MoShiroMethods.Event, parameters, MoShiroJsonContext.Default.AgentEventParams, CancellationToken.None));
|
||||
}
|
||||
|
||||
public async ValueTask SendHostAsync(HostSnapshot snapshot)
|
||||
@@ -42,7 +42,7 @@ public sealed class BackendUplink
|
||||
return;
|
||||
}
|
||||
|
||||
await SafeAsync(() => session.NotifyAsync(MonitorMethods.Host, snapshot, MonitorJsonContext.Default.HostSnapshot, CancellationToken.None));
|
||||
await SafeAsync(() => session.NotifyAsync(MoShiroMethods.Host, snapshot, MoShiroJsonContext.Default.HostSnapshot, CancellationToken.None));
|
||||
}
|
||||
|
||||
public async ValueTask SendTestStatusAsync(TestId test, string status, int? phase = null, string? errorCode = null)
|
||||
@@ -54,7 +54,7 @@ public sealed class BackendUplink
|
||||
}
|
||||
|
||||
var parameters = new TestStatusParams { TestId = test, Status = status, Phase = phase, ErrorCode = errorCode };
|
||||
await SafeAsync(() => session.NotifyAsync(MonitorMethods.TestStatus, parameters, MonitorJsonContext.Default.TestStatusParams, CancellationToken.None));
|
||||
await SafeAsync(() => session.NotifyAsync(MoShiroMethods.TestStatus, parameters, MoShiroJsonContext.Default.TestStatusParams, CancellationToken.None));
|
||||
}
|
||||
|
||||
private static async ValueTask SafeAsync(Func<ValueTask> send)
|
||||
@@ -115,7 +115,7 @@ public sealed class PeerHub
|
||||
var order = new Queue<Guid>();
|
||||
rpc.OnBinary = async (frame, token) =>
|
||||
{
|
||||
if (!OutboxFrame.TryParse(frame, out byte channel, out Guid id, out ReadOnlyMemory<byte> payload) || channel != MonitorChannels.ColumnBlock)
|
||||
if (!OutboxFrame.TryParse(frame, out byte channel, out Guid id, out ReadOnlyMemory<byte> payload) || channel != MoShiroChannels.ColumnBlock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -251,7 +251,7 @@ public sealed class PeerHub
|
||||
{
|
||||
Type = LineTaskSet.StateType,
|
||||
Version = set.Version,
|
||||
Doc = JsonSerializer.SerializeToElement(set, MonitorJsonContext.Default.LineTaskSet),
|
||||
Doc = JsonSerializer.SerializeToElement(set, MoShiroJsonContext.Default.LineTaskSet),
|
||||
};
|
||||
try
|
||||
{
|
||||
@@ -270,8 +270,8 @@ public sealed class PeerHub
|
||||
private static RpcRouter<PeerContext> BuildRouter() =>
|
||||
new RpcRouter<PeerContext>()
|
||||
.On(
|
||||
MonitorMethods.Clock,
|
||||
MonitorJsonContext.Default.ClockParams,
|
||||
MonitorJsonContext.Default.ClockResult,
|
||||
MoShiroMethods.Clock,
|
||||
MoShiroJsonContext.Default.ClockParams,
|
||||
MoShiroJsonContext.Default.ClockResult,
|
||||
(context, _, _) => ValueTask.FromResult(Result<ClockResult>.Ok(new ClockResult { AgentMonoUs = context.Clock.NowUs() })));
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
using Fleet.Core;
|
||||
using Fleet.Hosting;
|
||||
using Monitor.Agent;
|
||||
using MoShiro.Agent;
|
||||
|
||||
TimeProvider time = TimeProvider.System;
|
||||
INodeLog log = new ConsoleNodeLog(time);
|
||||
@@ -11,7 +11,7 @@ if (PlatformCheck.VerifyCrypto() is { } problem)
|
||||
return 1;
|
||||
}
|
||||
|
||||
string configPath = "/etc/monitor/agent.json";
|
||||
string configPath = "/etc/moshiro/agent.json";
|
||||
for (int i = 0; i < args.Length - 1; i++)
|
||||
{
|
||||
if (args[i] == "--config")
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Fleet.Core;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>
|
||||
/// 目标任务(Agent 自己探测一个地址,没有对端):用和线路任务同一套积木(<see cref="BlockCatalog"/> 里的拨号方,例如 icmp_echo、connect),
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
using System.Text.Json;
|
||||
using Fleet.Core;
|
||||
using Fleet.Rpc;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>
|
||||
/// 期望任务集(<c>task_set</c>)的调和器:每个任务先经过 <see cref="BudgetGuard"/>(参数校验 + 本地硬上限)。
|
||||
+17
-17
@@ -1,15 +1,15 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Fleet.Core;
|
||||
using Fleet.Rpc;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Agent;
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>
|
||||
/// 按需测试的编排(<c>monitor.test.run</c>):Agent 是时间的主人。每个阶段:
|
||||
/// 登记数据面的流 → <c>monitor.test.phase</c>(Probe 准备好自己一侧的角色)→ 运行(单向数据流由 Agent 发包,回显类等待 Probe 发包)
|
||||
/// → <c>monitor.test.phase_end</c>(Probe 收尾,回复它交出的列块个数)→ 等所有列块合并上传 → <c>phase_done</c>。
|
||||
/// 按需测试的编排(<c>moshiro.test.run</c>):Agent 是时间的主人。每个阶段:
|
||||
/// 登记数据面的流 → <c>moshiro.test.phase</c>(Probe 准备好自己一侧的角色)→ 运行(单向数据流由 Agent 发包,回显类等待 Probe 发包)
|
||||
/// → <c>moshiro.test.phase_end</c>(Probe 收尾,回复它交出的列块个数)→ 等所有列块合并上传 → <c>phase_done</c>。
|
||||
/// 同一时间只能运行 <c>max_concurrent_tests</c> 个测试;Probe 掉线或被取消时测试中止,已经上传的阶段数据保留。
|
||||
/// </summary>
|
||||
public sealed class TestRunner
|
||||
@@ -43,17 +43,17 @@ public sealed class TestRunner
|
||||
|
||||
public int Running => _running.Count;
|
||||
|
||||
/// <summary>校验并接受一个测试(立即返回),实际运行在后台进行,状态通过 <c>monitor.test.status</c> 回报。</summary>
|
||||
/// <summary>校验并接受一个测试(立即返回),实际运行在后台进行,状态通过 <c>moshiro.test.status</c> 回报。</summary>
|
||||
public Result<TestRunResult> Start(TestRunParams run)
|
||||
{
|
||||
if (_sessions.Get(run.ProbeId.Value) is not { } probe)
|
||||
{
|
||||
return Result<TestRunResult>.Fail(MonitorErrors.ProbeOffline, $"probe {run.ProbeId.Value} is not connected to this agent");
|
||||
return Result<TestRunResult>.Fail(MoShiroErrors.ProbeOffline, $"probe {run.ProbeId.Value} is not connected to this agent");
|
||||
}
|
||||
|
||||
if (run.Phases.Count == 0)
|
||||
{
|
||||
return Result<TestRunResult>.Fail(MonitorErrors.ValidationFailed, "a test needs at least one phase");
|
||||
return Result<TestRunResult>.Fail(MoShiroErrors.ValidationFailed, "a test needs at least one phase");
|
||||
}
|
||||
|
||||
var resolved = new List<(TestPhase Phase, TaskDecision Decision)>();
|
||||
@@ -64,7 +64,7 @@ public sealed class TestRunner
|
||||
if (!decision.Accepted)
|
||||
{
|
||||
return Result<TestRunResult>.Fail(
|
||||
decision.Reason == RejectReasons.Unsupported ? FleetErrors.Unsupported : MonitorErrors.BudgetExceeded,
|
||||
decision.Reason == RejectReasons.Unsupported ? FleetErrors.Unsupported : MoShiroErrors.BudgetExceeded,
|
||||
$"phase {phase.Kind} refused: {decision.Reason}");
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public sealed class TestRunner
|
||||
if (_running.Count >= _maxConcurrent || !_running.TryAdd(run.TestId.Value, running))
|
||||
{
|
||||
running.Dispose();
|
||||
return Result<TestRunResult>.Fail(MonitorErrors.TestBusy, "this agent is already running a test");
|
||||
return Result<TestRunResult>.Fail(MoShiroErrors.TestBusy, "this agent is already running a test");
|
||||
}
|
||||
|
||||
_ = Task.Run(() => RunAsync(run.TestId, resolved, running), CancellationToken.None);
|
||||
@@ -154,7 +154,7 @@ public sealed class TestRunner
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
finalStatus = running.Lost ? TestStatuses.Failed : TestStatuses.Aborted;
|
||||
errorCode = running.Lost ? MonitorErrors.ProbeOffline.Value : null;
|
||||
errorCode = running.Lost ? MoShiroErrors.ProbeOffline.Value : null;
|
||||
await TryAbortProbeAsync(running.Probe, test);
|
||||
}
|
||||
catch (TestFailure failure)
|
||||
@@ -183,7 +183,7 @@ public sealed class TestRunner
|
||||
_streams.Add(stream);
|
||||
try
|
||||
{
|
||||
RpcSession<PeerContext> rpc = probe.Rpc ?? throw new TestFailure(MonitorErrors.ProbeOffline.Value);
|
||||
RpcSession<PeerContext> rpc = probe.Rpc ?? throw new TestFailure(MoShiroErrors.ProbeOffline.Value);
|
||||
var start = new TestPhaseStartParams
|
||||
{
|
||||
TestId = test,
|
||||
@@ -194,7 +194,7 @@ public sealed class TestRunner
|
||||
DurationSeconds = durationSeconds,
|
||||
Port = stream.Port,
|
||||
};
|
||||
Result<TestPhaseStartResult> accepted = await rpc.RequestAsync(MonitorMethods.TestPhase, start, MonitorJsonContext.Default.TestPhaseStartParams, MonitorJsonContext.Default.TestPhaseStartResult, ct);
|
||||
Result<TestPhaseStartResult> accepted = await rpc.RequestAsync(MoShiroMethods.TestPhase, start, MoShiroJsonContext.Default.TestPhaseStartParams, MoShiroJsonContext.Default.TestPhaseStartResult, ct);
|
||||
if (!accepted.TryGet(out TestPhaseStartResult? started, out FleetError? error) || !started.Accepted)
|
||||
{
|
||||
throw new TestFailure(error?.Code.Value ?? FleetErrors.Unsupported.Value);
|
||||
@@ -209,7 +209,7 @@ public sealed class TestRunner
|
||||
}
|
||||
catch (BlockFaultException)
|
||||
{
|
||||
throw new TestFailure(MonitorErrors.ProbeOffline.Value);
|
||||
throw new TestFailure(MoShiroErrors.ProbeOffline.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -219,7 +219,7 @@ public sealed class TestRunner
|
||||
|
||||
long sent = stream.Running.Block.Produced;
|
||||
var end = new TestPhaseEndParams { TestId = test, Phase = index, StreamId = stream.Id, SentCount = sent };
|
||||
Result<TestPhaseEndResult> ended = await rpc.RequestAsync(MonitorMethods.TestPhaseEnd, end, MonitorJsonContext.Default.TestPhaseEndParams, MonitorJsonContext.Default.TestPhaseEndResult, ct, s_phaseSlack);
|
||||
Result<TestPhaseEndResult> ended = await rpc.RequestAsync(MoShiroMethods.TestPhaseEnd, end, MoShiroJsonContext.Default.TestPhaseEndParams, MoShiroJsonContext.Default.TestPhaseEndResult, ct, s_phaseSlack);
|
||||
if (!ended.TryGet(out TestPhaseEndResult? finished, out FleetError? endError))
|
||||
{
|
||||
throw new TestFailure(endError.Code.Value);
|
||||
@@ -254,7 +254,7 @@ public sealed class TestRunner
|
||||
|
||||
try
|
||||
{
|
||||
await rpc.NotifyAsync(MonitorMethods.TestAbort, new TestAbortParams { TestId = test }, MonitorJsonContext.Default.TestAbortParams, CancellationToken.None);
|
||||
await rpc.NotifyAsync(MoShiroMethods.TestAbort, new TestAbortParams { TestId = test }, MoShiroJsonContext.Default.TestAbortParams, CancellationToken.None);
|
||||
}
|
||||
catch (Exception ex) when (ex is ObjectDisposedException or InvalidOperationException or IOException)
|
||||
{
|
||||
Reference in new issue
Block a user