Browse the archived sessions in the network analyzer page - #922
Open
sven-n wants to merge 1 commit into
Open
Conversation
The last part of the analyzer page: the archive of the observed accounts is browsable next to the live connections, and the observation of an account can be switched on and off while its player is online. * The sidebar lists the archived sessions below the connections, grouped by account, with their date, packet count, duration and size. A session which is still being written is marked with a record dot. * Opening a session shows its packets in the same grid, analyzed with the client version which was recorded in its metadata. A running session is re-read while it's open, so the traffic of an observed player can be followed live - the file is the single source, so there is nothing to merge. * A session can be deleted after a confirmation, and downloaded as one capture file: the parts are concatenated behind a single header line, so the download opens in the analyzer tool as one session. * The download goes through a controller of the admin panel instead of a static file: an archived session contains the login packet of the player in plain text, so it must not be reachable without an authenticated user. It's logged like the other accesses to the archive. * The observation toggle in the header of a game server connection persists the account flag through the player and starts or ends the archived session right away, without a reconnect. The member order of the page was fixed on the way, which removes three StyleCop warnings it had before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pb82LmoaUVdZtBtQs7xrtA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 6 of #895 — the last one. Targets the phase 5 branch of #917, so please review/merge that one first; this PR then rebases onto master automatically. The diff shown here is only the phase 6 part.
The sidebar
Below the live connections, the archive of the observed accounts is listed, grouped by account: date, packet count, duration and size per session. A session which is still being written carries a record dot, because its player is still online.
The list only appears when an
IPacketArchiveis registered, so the page degrades the same way it already does without a capture service.The download is not a static file
NetworkArchiveController(api/network-archive/{**sessionId}) streams the session instead of serving the directory statically — an archived session contains the login packet of the player in plain text. It sits behind the sameRequireAuthorization()as every other controller of the panel, resolves the session throughIPacketArchive(which refuses an id pointing outside the archive), takes the file names from the metadata rather than from the url, and logs the download like the other accesses to the archive.The observation toggle
The header of a game server connection gets an Observe button. It goes through the new
IPacketCaptureService.SetObservationAsync(connectionId, isActive)down toICapturedConnectionInfo.SetObservationAsync, which the game server implements: it setsAccount.IsNetworkObservationActive, persists it through the player (whose context owns that account object — saving it anywhere else would race with the player's own save), and starts or ends the archived session right away, so it needs no reconnect.IsObservedandSetObservationAsyncare default interface members onICapturedConnectionInforeturningfalse: the observation is an account setting, and only a game server connection knows an account. The connect and chat server infos stay untouched.For an offline account the flag is edited in the account editor, where
AutoFormalready renders it since #917.Tests
11 new tests in
MUnique.OpenMU.Web.Tests:ArchiveList: the empty hint, grouping by account, the download link (including the escaping of an account name with a space), select and delete callbacks (deleting must not open the session), and the marker of a running session.The archive tests run against a real
PacketArchivein a temp directory, so they exercise the file format end to end rather than a mock. That also made two async races in the tests visible, which is why they wait for the state instead of asserting right after the click.Verification
dotnet build src/MUnique.OpenMU.sln -p:ci=true→ 0 errors. The page had three StyleCop warnings (member ordering) before this PR; the members were reordered on the way, so it has none now.MUnique.OpenMU.Tests807,Web.Tests74,Network.Tests73 (4 skipped),Network.Packets.Tests588,ChatServer.Tests26,PlugIns.Tests41,Persistence.Initialization.Tests12 (2 skipped),AttributeSystem.Tests44,Pathfinding.Tests9.Web.Testswas run three times in a row for the new async tests.With this, #895 is complete: capture hook, capture service, the page, the deep links (#916), the observation archive (#917) and the browser here.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Pb82LmoaUVdZtBtQs7xrtA
Generated by Claude Code