9.0 KiB
9.0 KiB
Network log in-app pane — Tech spec
Companion to PRODUCT.md in this directory; refer there for user-visible behavior.
Context
app/src/server/network_logging.rs—init(..)registers HTTP clientset_before_request_fn/set_after_response_fnhooks that pushNetworkLogItems into a boundedasync_channel(size 100). A background task writes items tolog_file_path()(warp_network.log), truncating and reopening after every 50 items.pub fn log_file_path()is exposed for the tail workflow.app/src/server/server_api.rs (1214-1222)—ServerApiProvider::newinvokesnetwork_logging::initwhenContextFlag::NetworkLogConsole.is_enabled().app/src/workflows/local_workflows.rs (213-229)—network_logging_workflow()builds a hardcodedWorkflowSource::Appworkflow whose command istail -f <log>. Injected intoapp_workflows().app/src/settings_view/privacy_page.rs—NetworkLogWidgetrenders the "View network logging" link and dispatchesPrivacyPageAction::LaunchNetworkLogging→ bubbles toSettingsViewEvent::LaunchNetworkLogging.app/src/terminal/input.rs (1754-1760, 7302-7332, 13749)—input:insert_network_logging_workflowbinding ("Show Warp network log") →InputAction::InsertNetworkLoggingWorkflow→Input::insert_network_logging_workflowopens the tail workflow info box.app/src/workspace/view.rs (12646-12648, 12769-12793)—launch_network_logging_workflow_in_active_tabclears the active input and runs the workflow.- Pane plumbing:
app/src/pane_group/pane/mod.rs (133-153, 432-504)—IPaneTypeenum,PaneId::from_*_pane_ctx/viewhelpers,PaneId::renderarms.execution_profile_editor_pane.rsis the closest minimal template.AIFactManager/ExecutionProfileEditorManagerdemonstrate singleton "one pane per window" managers. CodeEditorView(app/src/code/editor/view.rs) supportsbuffer: None,reset(InitialBufferState, ctx), andset_interaction_state(InteractionState::ReadOnly, ctx); its model is defined inapp/src/code/editor/model.rs.app/src/app_state.rs (118-139)—LeafContentsenum.app/src/pane_group/mod.rs (1770-1939)— restore match; panes we don't restore returnErr(anyhow!(..)).
Proposed changes
In-memory model
- Add
NetworkLogModelinapp/src/server/network_logging.rs: singleton entity with aVecDeque<NetworkLogItem>capped atNETWORK_LOGGING_MAX_ITEMS = 50(matches current file-rotation threshold).push(item, ctx)pops the front when over capacity;snapshot_text(&self) -> Stringjoins items with\n. pub(crate)onNetworkLogItem; keep itsDisplayimpl and the existing timestamp +{:?}request/response format so pane output matches whatwarp_network.logused to contain.- Rewrite
init(..)to take theModelContext<ServerApiProvider>. Keep the bounded channel and client hooks unchanged. Replace the disk-writing background task withctx.spawn_stream_local(rx, |_, item, ctx| NetworkLogModel::handle(ctx).update(ctx, |m, ctx| m.push(item, ctx)), |_, _| {}). This mirrors the existingevent_receiverpattern inServerApiProvider::new. - Delete
truncate_and_restart_log,log_file_path(), theWARP_LOGS_DIRbranch, and thelocal_fscfg split. Remove deadwarp_core::paths/PathBufimports. - Register the singleton in
app/src/lib.rs::initialize_app(beforeServerApiProvider):ctx.add_singleton_model(|_| NetworkLogModel::default()).
View, pane, and manager
app/src/server/network_log_view.rs:NetworkLogViewowns aViewHandle<CodeEditorView>and aModelHandle<PaneConfiguration>titled "Network log". Onnew, buildCodeEditorViewwithbuffer: None+ defaultCodeEditorRenderOptions, seed withNetworkLogModel::as_ref(ctx).snapshot_text()viaeditor.reset(InitialBufferState::plain_text(text), ctx), and callset_interaction_state(InteractionState::ReadOnly, ctx). No subscription to the model — single snapshot per open.BackingViewimpl: default header/chrome, no toolbelt, no overflow menu.focus(ctx)forwards to the editor.app/src/pane_group/pane/network_log_pane.rs:NetworkLogPanemirroringExecutionProfileEditorPane.snapshot() -> LeafContents::NetworkLog(new unit variant).attachregisters withNetworkLogPaneManager;detachderegisters.shareable_link()→ShareableLink::Base.app/src/pane_group/pane/mod.rs: addIPaneType::NetworkLog(+Display),PaneId::from_network_log_pane_ctx/..._view, and aChildView<PaneView<NetworkLogView>>arm inPaneId::render.pub(super) mod network_log_pane;+ re-export.app/src/server/network_log_pane_manager.rs:NetworkLogPaneManager(singleton) withHashMap<WindowId, PaneViewLocator>andfind_pane/register_pane/deregister_pane(pattern copied fromExecutionProfileEditorManager). Register ininitialize_app.app/src/app_state.rs:LeafContents::NetworkLog(unit).app/src/pane_group/mod.rs: restore arm returnsErr(anyhow!("Network log panes are not restored")).app/src/persistence/sqlite.rs: add a round-trippable tag for the new variant only if the serde mapping requires it; no restore path needed.
Wiring and cleanup
app/src/workspace/view.rs: addopen_network_log_pane(&mut self, ctx)followingopen_execution_profile_editor_pane: find-existing via the manager and focus, else constructNetworkLogPane::new(ctx)andadd_pane_with_direction(Direction::Right, pane, true, ctx). Replace the body oflaunch_network_logging_workflow_in_active_tabwith a call toopen_network_log_pane(and rename the method + its single caller at12647).app/src/terminal/input.rs: deleteInput::insert_network_logging_workflowand the matchingInputAction::InsertNetworkLoggingWorkflowarm. Repoint theinput:insert_network_logging_workflowbinding (keep id + "Show Warp network log" description, keep theNetworkLogConsoleenablement gate) to a newWorkspaceAction::OpenNetworkLogPanethat the workspace handles by callingopen_network_log_pane. Using aWorkspaceActionavoids adding a one-offInputevent just to bubble it up.app/src/workflows/local_workflows.rs: deletenetwork_logging_workflowand remove its call inapp_workflows(); the prompt-chip dogfood workflow stays.- Privacy page: no copy changes;
PrivacyPageAction::LaunchNetworkLoggingkeeps bubbling upSettingsViewEvent::LaunchNetworkLogging, which now callsopen_network_log_pane.
Testing and validation
Behavior numbers below reference PRODUCT.md.
- Unit test in
network_logging.rs: push > 50 items intoNetworkLogModel, assert len capped at 50,snapshot_textcontains the newest 50 in chronological order. Covers invariants 1, 2, 7. - Unit test:
NetworkLogModel::default()+snapshot_text()returns""; used to validate invariant 9 (empty open) at the model layer. - Grep + build verification that no code under
app/srcorcrates/still referenceswarp_network.log,log_file_path, ornetwork_logging_workflow. Covers invariants 1, 14. - Manual validation (dogfood build,
NetworkLogConsoleenabled by default):- Open Privacy settings → "View network logging" → pane opens as right-split with snapshot. Close and reopen; new requests appear after reopen. Covers invariants 4, 7, 8, 10, 11, 12.
- Trigger the
Show Warp network logkeybinding → same pane opens / focuses. Open from both entrypoints consecutively → only one pane exists per window. Covers invariants 5, 6. - Disable
ContextFlag::NetworkLogConsole(e.g. warp-home-link-only mode) → settings link hidden, keybinding unavailable. Covers invariant 3. - Confirm the pane is read-only: attempted typing produces no edits; find, select, copy still work. Covers invariant 10.
- Open pane, quit app, relaunch → pane is absent, in-memory log starts empty. Covers invariant 13.
- Search command palette and workflow list for "Tail Warp network log" → no results. Covers invariant 14.
- Presubmit:
./script/presubmit(coverscargo fmt+cargo clippy --workspace --all-targets --all-features --tests -- -D warnings+cargo nextest). Must pass before PR, per repo rules. - WASM build:
cargo check --target wasm32-unknown-unknown -p warp(or the repo's standard wasm command) to confirm the removedlocal_fscfg split didn't leave wasm-only gaps.
Risks and mitigations
- Log items can leak sensitive tokens into memory and into the pane UI. The formatting path is unchanged from the existing on-disk log, so redaction behavior is inherited — not improved. Flag as follow-up if stronger redaction is desired.
- Pane type addition touches
LeafContentsand the restore match. Missing an arm is caught at compile time thanks to exhaustive matching, but the sqlite serde tag must round-trip so existing snapshots keep loading. Verify by restoring an app-state snapshot that contains non-network-log panes after the change. - Keybinding id
input:insert_network_logging_workflowis retained for backwards compat with user custom keybindings even though the handler no longer inserts a workflow. Acceptable trade-off; renaming would break users' customized bindings.