运维
运维
日志落在哪、每层记什么、错误码怎么读、有哪些命令、指标怎么看,以及这套东西目前的边界。
日志落在哪
<Project>/Saved/Logs/<Project>.log 大厅与客户端
<Project>/Saved/CrossingNet/Logs/instance_<端口>.log 每个房间进程一份
<Project>/Saved/CrossingNet/Settlements.log 结算流水(恢复与幂等)
<Project>/Saved/CrossingNet/Devices.json 设备注册表房间日志按实例端口分开,一个实例一条时间线;大厅日志用层前缀把阶段分开,grep 就能拼出一局的路径。
日志格式统一为:
[Layer] event=EventName k=v k=v ...每层记什么
| 层 | 关键事件 |
|---|---|
Identity | ProviderReady、Assigned、AuthFailed、PlayerStateClassMissing |
Session | SpawnStart、HealthFirstOK、RoomEmpty、RoomReap、SlotReserved、ControlReady、PushHello、SettlementRecorded、SettlementAcked、SettlementAckTimeout、SettlementMissing、ReconnectRegistered、SessionReplaced、WarmPoolSpawn、WarmClaimed、MatchAssignedToInstance、MetricsSnapshot、LogRotated |
Match | MatcherReady、QueueJoin、QueueCancel、MatchTeams、MatchFound、MatchRejected、QueueTimeout、MatchPendingInstance、Waiting(Verbose) |
Ready | ReadyCheckStart、Accept、Passed、Timeout、Failed |
Assign | Assigned、Received、Rejected、Failed、SpectateAssigned、LateJoinAssigned、ReconnectAssigned、ReconnectRejected |
Travel | Pending、Arrived、Start、Failed、Return、ReportFailed |
Room | JoinTokenAccepted / JoinTokenRejected、SeatAssigned、Roster、ReadyChanged、GameStart、GameEnd、Settlement、SettlementAcked、PlayerDisconnected、Reconnected、ReconnectSeated、SurrenderVoteStarted、SurrenderPassed、RemakeTriggered、PlayerAfk、SeriesArmed、RoundEnded、SeriesFinished、SpectatorJoined、LateJoinSeated、BotSpawned、BotReplaced |
Client | Config、RpcThrottled、SpectateArmed、LateJoinArmed、ReconnectArmed |
Lobby | ReturnToLobby |
Config | Summary、Mode、Features、Prod、Warning、ReconnectDisabled |
错误码
错误码按层分段,CrossingError::ToString 给出 "4002 BadToken" 这样的文本:
| 段 | 含义 | 例子 |
|---|---|---|
| 1xxx | 版本 / 构建 | 1001 VersionMismatch、1002 ClientTooOld |
| 2xxx | 网络 / 端口 | 2001 ConnectTimeout、2002 PortUnreachable、2003 ResolveFailed |
| 3xxx | 会话 / 房间 | 3001 RoomNotFound、3002 RoomFull、3003 RoomStarted、3004 BadPassword、3005 RoomClosed |
| 4xxx | 身份 / 权限 | 4001 NotLoggedIn、4002 BadToken、4003 DuplicateLogin、4004 Banned |
| 5xxx | 数据 / 协议 | 5001 MessageTooLarge、5002 DataCorrupt、5003 ChunkFailed、5004 ChunkTimeout、5005 ProfileVersionMismatch |
| 6xxx | 匹配 | 6001 MatchTimeout、6002 MatchCanceled、6003 NoInstance、6004 EloMismatch、6005 TeamSizeInvalid、6006 PenaltyCooldown、6007 ReadyTimeout、6008 ReadyDeclined、6009 ReadyDisconnected |
| 7xxx | 组队 | 7001 PartyNotFound、7002 PartyFull、7003 NotPartyLeader、7004 PartyClosed、7005 PartyPlayerBusy |
| 9xxx | 内部 / 未知 | 9001 Unknown(出现即代表缺码) |
命令
对局与实例
CrossingNet.Status 实例表 + 匹配队列快照
CrossingNet.DebugAssign [Mode] 跳过匹配直接拉起实例并分配
CrossingNet.CloseInstance <id> 关一个实例
CrossingNet.ForceSettle [Team] 强制结算
CrossingNet.ServerLog <path> 指定房间日志路径玩家
CrossingNet.Kick <playerId>
CrossingNet.Ban <playerId> [minutes]
CrossingNet.Unban <playerId>
README.md的「已知限制」里还写着「无踢人/封禁命令」,那是早先的结论;源码里这几个命令都已经注册。
设备
CrossingNet.DeviceBan <deviceKey|playerGuid> [minutes] [reason]
CrossingNet.DeviceUnban <deviceKey>
CrossingNet.DeviceInfo <deviceKey|playerGuid>
CrossingNet.DeviceList [banned]局域网
CrossingNet.LANHost [roomName] [map] [gamePort]
CrossingNet.LANAdvertise [roomName] [map] [gamePort]
CrossingNet.LANDiscover
CrossingNet.LANList
CrossingNet.LANJoin <ip:port>
CrossingNet.LANStop
CrossingNet.LANInfo指标
每 MetricsIntervalSeconds(默认 10 秒)汇总一次:
Session->GetMetricsJson(); // JSON
Session->GetMetricsPrometheus(); // Prometheus 文本看的数:按状态的实例数、队列人数、平均等待、结算重试次数、控制通道超时次数。
日志里对应 [Session] event=MetricsSnapshot。
日志轮转
bEnableLogRotation=True
LogRetentionDays=3
LogRotationMaxBytes=0按天切分、超期清理;房间日志保持稳定路径 instance_<port>.log,方便按实例查。
关掉就交给外部收集器。
排查顺序
1. CrossingNet.Status 实例在不在、状态对不对
2. 大厅 grep [Match] / [Assign] / [Session] 配对、分配、结算
3. 房间 instance_<port>.log 票据、座位、开局、结束
4. 错误码 6xxx 看匹配,4xxx 看票据,5xxx 看档案
5. trace 从 QueueJoin 一路串起来已知边界
| 类别 | 限制 |
|---|---|
| 结算 | ACK 是乐观 ACK;SettlementMissing 只报告,不自动补分 |
| 安全 | 控制面/健康端口明文;票据是 bearer token;LogNet 会打印旅行 URL 里的 token |
| 运维 | 指标只写日志,没有 /metrics HTTP 与告警;没有进程守护 |
| 玩法 | 无换边/自动平衡、暂停;多队系列赛、排行榜未做 |
| 网络 | IPv4;无 NAT 穿透/中继;地址手工配置 |