[codex] Add Studio server logs module#810
Conversation
|
Paired Core PR: elsa-workflows/elsa-core#7438 |
Greptile SummaryThis PR adds a new
Confidence Score: 3/5Safe to merge in environments where the hub never returns 401, but the unauthorized path is broken and will produce confusing error messages when auth is enforced. The SignalR observer catches UnauthorizedAccessException to handle hub 401s, but SignalR raises HttpRequestException with Unauthorized status code instead. Any backend enforcing read:server-logs permission will surface a raw exception rather than the intended access-denied UI. This is the auth entry-point for the entire live-streaming feature. src/modules/Elsa.Studio.ServerLogs/Services/SignalRServerLogObserver.cs — incorrect exception type for 401 handling in StartAsync.
|
| Filename | Overview |
|---|---|
| src/modules/Elsa.Studio.ServerLogs/Services/SignalRServerLogObserver.cs | SignalR live log observer; catches the wrong exception type for 401 so the Unauthorized state is never set when the hub rejects the connection. |
| src/modules/Elsa.Studio.ServerLogs/UI/Pages/ServerLogs.razor.cs | Main page code-behind; HasActiveFilter always true on load due to non-null default MinimumLevel, and scroll uses eval unnecessarily. Otherwise solid lifecycle and filter management. |
| src/modules/Elsa.Studio.ServerLogs/Services/RemoteServerLogService.cs | HTTP client wrapper for recent logs and sources; gracefully handles 404 and delegates to filter mapper. Looks correct. |
| src/modules/Elsa.Studio.ServerLogs/Services/ServerLogFilterMapper.cs | Stateless filter copier; correctly clamps Take and deep-copies the Levels collection to prevent aliasing. |
| src/modules/Elsa.Studio.ServerLogs/UI/Pages/ServerLogs.razor | Razor template for the log viewer; toolbar, filters, row rendering, and exception display all look correct. |
| src/modules/Elsa.Studio.ServerLogs.Tests/ServerLogFilterMapperTests.cs | Five unit tests covering field mapping, Take clamping, defaults, and Levels copy isolation — all correct. |
| src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDetails.razor.cs | Adds a deep-link from the workflow instance panel to the server logs page with the instance ID URL-encoded; straightforward and correct. |
| src/modules/Elsa.Studio.ServerLogs/Extensions/ServiceCollectionExtensions.cs | DI registration for feature, menu, service, and observer — all scoped, no issues. |
Sequence Diagram
sequenceDiagram
participant Page as ServerLogs Page
participant SLS as RemoteServerLogService
participant Obs as SignalRServerLogObserver
participant API as Backend REST API
participant Hub as Backend SignalR Hub
Page->>SLS: ListSourcesAsync()
SLS->>API: GET /server-logs/sources
API-->>SLS: sources list
SLS-->>Page: sources
Page->>SLS: GetRecentAsync(filter, rowCap)
SLS->>API: POST /server-logs/recent
API-->>SLS: RecentServerLogsResult
SLS-->>Page: recent logs
Page->>Obs: StartAsync(filter)
Obs->>Hub: HubConnection.StartAsync()
Obs->>Hub: SendAsync SubscribeAsync
Hub-->>Obs: ReceiveLogEventAsync
Obs-->>Page: LogReceived event
Hub-->>Obs: ReceiveDroppedEventsAsync
Obs-->>Page: DroppedEventsReceived event
Page->>Obs: DisposeAsync()
Obs->>Hub: SendAsync UnsubscribeAsync
Obs->>Hub: StopAsync and DisposeAsync
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
src/modules/Elsa.Studio.ServerLogs/Services/SignalRServerLogObserver.cs:55-58
**Wrong exception type for 401 Unauthorized**
SignalR's `HubConnection.StartAsync()` does not throw `UnauthorizedAccessException` on an HTTP 401 response — it throws `HttpRequestException` with `StatusCode = HttpStatusCode.Unauthorized`. This catch block will never fire, so a 401 from the hub endpoint will propagate as an unhandled exception and surface as a generic `ErrorMessage` on the page rather than setting the `Unauthorized` connection state. The fix is to match the existing 404 pattern and catch `HttpRequestException e when (e.StatusCode is HttpStatusCode.Unauthorized)`.
### Issue 2 of 3
src/modules/Elsa.Studio.ServerLogs/UI/Pages/ServerLogs.razor.cs:104
`HasActiveFilter` always true on initial load due to non-null default `MinimumLevel`
`ServerLogFilter.MinimumLevel` defaults to `ServerLogLevel.Information` (not `null`), so `HasActiveFilter` evaluates to `true` the moment the page opens. This means the empty-state message will always read "No server logs match the current filters" on first load, even before the user touches any filter — the intended message "No server logs received yet" is never shown.
```suggestion
protected bool HasActiveFilter => !string.IsNullOrWhiteSpace(ViewState.Filter.SourceId) || (ViewState.Filter.MinimumLevel != null && ViewState.Filter.MinimumLevel != ServerLogLevel.Information) || !string.IsNullOrWhiteSpace(ViewState.Filter.Text) || !string.IsNullOrWhiteSpace(ViewState.Filter.WorkflowInstanceId);
```
### Issue 3 of 3
src/modules/Elsa.Studio.ServerLogs/UI/Pages/ServerLogs.razor.cs:380
`eval` used for scroll — unnecessary and fragile
Calling `eval` via JS interop is unnecessary; `scrollTo` can be invoked directly on the element via a lambda. While `LogSurfaceId` is a compile-time constant so there is no injection risk today, using `eval` conflicts with strict CSP policies and makes JS calls harder to audit.
```suggestion
await JS.InvokeVoidAsync("(id) => { const el = document.getElementById(id); if (el) el.scrollTo({ top: el.scrollHeight }); }", LogSurfaceId);
```
Reviews (1): Last reviewed commit: "Merge branch 'main' into 003-live-server..." | Re-trigger Greptile
There was a problem hiding this comment.
Pull request overview
Adds a new Elsa.Studio.ServerLogs module to Elsa Studio, enabling operators to view recent backend log events and subscribe to live log updates via SignalR, with filtering and basic operational controls. The PR also introduces accompanying specifications/Spec Kit workflow assets and wires the module into the bundled/hosted Studio applications.
Changes:
- Introduce
Elsa.Studio.ServerLogsmodule (models, API client, services, SignalR observer, UI page, menu integration, DI registration). - Add workflow-instance deep link to open Server Logs pre-filtered by
workflowInstanceId. - Add Spec Kit specs/tasks/templates/scripts and include new test packages + a small xUnit test project for filter mapping.
Reviewed changes
Copilot reviewed 103 out of 103 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/modules/Elsa.Studio.Workflows/Components/WorkflowInstanceViewer/Components/WorkflowInstanceDetails.razor.cs | Adds a Server Logs deep link from workflow instance details. |
| src/modules/Elsa.Studio.ServerLogs/UI/Pages/ServerLogs.razor.css | Styles for the dense log viewer surface and rows. |
| src/modules/Elsa.Studio.ServerLogs/UI/Pages/ServerLogs.razor | Server Logs page markup (toolbar, filters, rows, empty/error states). |
| src/modules/Elsa.Studio.ServerLogs/UI/Pages/ServerLogs.razor.cs | Page state management, REST backfill, live subscription handling, URL syncing, copy/scroll behaviors. |
| src/modules/Elsa.Studio.ServerLogs/Services/SignalRServerLogObserver.cs | SignalR client connection lifecycle + event dispatch for live logs. |
| src/modules/Elsa.Studio.ServerLogs/Services/ServerLogFilterMapper.cs | Maps UI filter state to REST/live subscription filters; clamps take for backfill. |
| src/modules/Elsa.Studio.ServerLogs/Services/RemoteServerLogService.cs | Refit-backed service for recent logs and source listing. |
| src/modules/Elsa.Studio.ServerLogs/README.md | Module setup + backend requirements + operator workflow docs. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogViewState.cs | Stores local UI state (filter, caps, toggles, connection status). |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogSourceStatus.cs | Source health enum. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogSource.cs | Source metadata model. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogLevel.cs | Log level enum used by UI/API. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogFilter.cs | Filter model for REST and live subscriptions. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogException.cs | Exception payload model for log events. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogEvent.cs | Log event model including source + workflow/tenant metadata. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogDroppedEventSummary.cs | Model for backpressure/dropped event summaries. |
| src/modules/Elsa.Studio.ServerLogs/Models/ServerLogConnectionStatus.cs | Connection state enum for UI messaging. |
| src/modules/Elsa.Studio.ServerLogs/Models/RecentServerLogsResult.cs | DTO for backfill results + dropped count. |
| src/modules/Elsa.Studio.ServerLogs/Menu/ServerLogsMenu.cs | Adds Server Logs menu entry. |
| src/modules/Elsa.Studio.ServerLogs/Feature.cs | Declares a remote-feature-gated module feature (Elsa.ServerLogStreaming). |
| src/modules/Elsa.Studio.ServerLogs/Extensions/ServiceCollectionExtensions.cs | Registers module services (feature, menu, service, observer). |
| src/modules/Elsa.Studio.ServerLogs/Elsa.Studio.ServerLogs.csproj | New Razor SDK module project + SignalR/WebUtilities refs. |
| src/modules/Elsa.Studio.ServerLogs/Contracts/IServerLogService.cs | Contract for backfill + source list. |
| src/modules/Elsa.Studio.ServerLogs/Contracts/IServerLogObserver.cs | Contract for live observer (start/update/reconnect + events). |
| src/modules/Elsa.Studio.ServerLogs/Client/IServerLogsApi.cs | Refit API contract for /server-logs/* endpoints. |
| src/modules/Elsa.Studio.ServerLogs/_Imports.razor | Razor imports for the new module. |
| src/modules/Elsa.Studio.ServerLogs.Tests/ServerLogFilterMapperTests.cs | Unit tests for filter mapping/clamping behavior. |
| src/modules/Elsa.Studio.ServerLogs.Tests/Elsa.Studio.ServerLogs.Tests.csproj | New xUnit test project referencing the module. |
| src/hosts/Elsa.Studio.Host.Wasm/Program.cs | Registers the Server Logs module in the WASM host. |
| src/hosts/Elsa.Studio.Host.Server/Program.cs | Registers the Server Logs module in the Server host. |
| src/bundles/Elsa.Studio/Elsa.Studio.csproj | Bundles the Server Logs module by default. |
| specs/003-live-server-logs/tasks.md | Feature task breakdown for the Server Logs module. |
| specs/003-live-server-logs/spec.md | Feature specification (stories, FRs/SCs, edge cases). |
| specs/003-live-server-logs/research.md | Design decisions and rationale. |
| specs/003-live-server-logs/quickstart.md | Quickstart validation steps. |
| specs/003-live-server-logs/plan.md | Implementation plan + constitution check evidence. |
| specs/003-live-server-logs/data-model.md | Data model definitions and invariants. |
| specs/003-live-server-logs/contracts/signalr-client.md | SignalR client contract documentation. |
| specs/003-live-server-logs/contracts/backend-client.md | REST client contract documentation. |
| specs/003-live-server-logs/checklists/requirements.md | Requirements checklist for the feature. |
| Elsa.Studio.sln | Adds the new module + test project to the solution; adjusts VS version line. |
| Directory.Packages.props | Adds central package versions for xUnit + test SDK. |
| AGENTS.md | Adds Spec Kit marker block for agent context. |
| .specify/workflows/workflow-registry.json | Registers bundled workflow metadata. |
| .specify/workflows/speckit/workflow.yml | Adds the Speckit workflow definition (gates + steps). |
| .specify/templates/tasks-template.md | Adds/updates tasks template. |
| .specify/templates/spec-template.md | Adds/updates spec template. |
| .specify/templates/plan-template.md | Adds/updates plan template. |
| .specify/templates/constitution-template.md | Adds constitution template. |
| .specify/templates/checklist-template.md | Adds checklist template. |
| .specify/scripts/bash/setup-tasks.sh | Adds tasks setup helper script. |
| .specify/scripts/bash/setup-plan.sh | Adds plan setup helper script. |
| .specify/scripts/bash/check-prerequisites.sh | Adds consolidated prerequisites checker script. |
| .specify/memory/constitution.md | Adds Elsa Studio constitution used by Spec Kit. |
| .specify/integrations/speckit.manifest.json | Records speckit integration manifest/version. |
| .specify/integrations/codex.manifest.json | Records codex integration manifest/version. |
| .specify/integration.json | Configures the default Spec Kit integration. |
| .specify/init-options.json | Records Spec Kit init options. |
| .specify/extensions/git/scripts/powershell/initialize-repo.ps1 | Git extension script (PowerShell) for repo init. |
| .specify/extensions/git/scripts/powershell/git-common.ps1 | Git extension shared utilities (PowerShell). |
| .specify/extensions/git/scripts/powershell/auto-commit.ps1 | Git extension auto-commit hook (PowerShell). |
| .specify/extensions/git/scripts/bash/initialize-repo.sh | Git extension script (Bash) for repo init. |
| .specify/extensions/git/scripts/bash/git-common.sh | Git extension shared utilities (Bash). |
| .specify/extensions/git/scripts/bash/auto-commit.sh | Git extension auto-commit hook (Bash). |
| .specify/extensions/git/README.md | Documentation for the git extension behavior/config. |
| .specify/extensions/git/git-config.yml | Default git extension configuration. |
| .specify/extensions/git/extension.yml | Git extension manifest (hooks/commands). |
| .specify/extensions/git/config-template.yml | Git extension config template. |
| .specify/extensions/git/commands/speckit.git.validate.md | Command doc: validate feature branch naming. |
| .specify/extensions/git/commands/speckit.git.remote.md | Command doc: detect git remote. |
| .specify/extensions/git/commands/speckit.git.initialize.md | Command doc: initialize git repo. |
| .specify/extensions/git/commands/speckit.git.feature.md | Command doc: create feature branch. |
| .specify/extensions/git/commands/speckit.git.commit.md | Command doc: auto-commit hook behavior. |
| .specify/extensions/.registry | Registers extensions and their command bindings. |
| .specify/extensions.yml | Enables git extension hooks in Spec Kit. |
| .github/prompts/speckit.git.validate.prompt.md | Prompt stub for git validate agent. |
| .github/prompts/speckit.git.remote.prompt.md | Prompt stub for git remote agent. |
| .github/prompts/speckit.git.initialize.prompt.md | Prompt stub for git initialize agent. |
| .github/prompts/speckit.git.feature.prompt.md | Prompt stub for git feature agent. |
| .github/prompts/speckit.git.commit.prompt.md | Prompt stub for git commit agent. |
| .github/agents/speckit.git.validate.agent.md | Agent definition for git validate. |
| .github/agents/speckit.git.remote.agent.md | Agent definition for git remote. |
| .github/agents/speckit.git.initialize.agent.md | Agent definition for git initialize. |
| .github/agents/speckit.git.feature.agent.md | Agent definition for git feature. |
| .github/agents/speckit.git.commit.agent.md | Agent definition for git commit. |
| .agents/skills/speckit-taskstoissues/SKILL.md | Skill: convert tasks into GitHub issues. |
| .agents/skills/speckit-tasks/SKILL.md | Skill: generate tasks.md from spec/plan artifacts. |
| .agents/skills/speckit-plan/SKILL.md | Skill: create plan/research/contracts artifacts. |
| .agents/skills/speckit-implement/SKILL.md | Skill: implement tasks.md step-by-step. |
| .agents/skills/speckit-git-validate/SKILL.md | Skill wrapper for git validate command doc. |
| .agents/skills/speckit-git-remote/SKILL.md | Skill wrapper for git remote command doc. |
| .agents/skills/speckit-git-initialize/SKILL.md | Skill wrapper for git initialize command doc. |
| .agents/skills/speckit-git-feature/SKILL.md | Skill wrapper for git feature command doc. |
| .agents/skills/speckit-git-commit/SKILL.md | Skill wrapper for git commit command doc. |
| .agents/skills/speckit-constitution/SKILL.md | Skill: update constitution + propagate into templates. |
| .agents/skills/speckit-clarify/SKILL.md | Skill: ask/record targeted spec clarifications. |
| .agents/skills/speckit-analyze/SKILL.md | Skill: read-only cross-artifact consistency analysis. |
* Specify diagnostics structured logs Studio module * Clarify diagnostics structured logs spec * Plan diagnostics structured logs refactor * Create diagnostics structured logs tasks * Refactor Studio server logs to structured diagnostics * Record diagnostics structured logs verification * Update Studio branding version to 3.8 * Update RemoteFeature name and simplify StructuredLogsMenu logic * Fix structured logs response contract
Summary
Adds an
Elsa.Studio.ServerLogsmodule that lets operators inspect backend server logs from Studio. The module loads recent logs through the backend API, opens an authenticated SignalR subscription for live updates, and provides a dense operational log viewer with filters, source selection, copy actions, and workflow-instance deep links.Highlights
/server-logs?workflowInstanceId=....Validation
dotnet build src/modules/Elsa.Studio.ServerLogs/Elsa.Studio.ServerLogs.csproj --no-restore --nologo -v:minimalpassed.dotnet test src/modules/Elsa.Studio.ServerLogs.Tests/Elsa.Studio.ServerLogs.Tests.csproj --nologo -v:minimalpassed, 5 tests.dotnet build Elsa.Studio.sln --no-restorepassed after restore.Existing framework warnings remain in shared Studio projects, including XML documentation, trim analyzer, nullable, and MudBlazor analyzer warnings.