Structured Logs
Configure Elsa 3.8.2 structured log capture, Studio diagnostics, redaction, and durable storage.
Elsa's Elsa.Diagnostics.StructuredLogs module captures ILogger events from an Elsa host and makes them available to operators through REST, SignalR, and Elsa Studio. It is a host-diagnostics feature: it is separate from the workflow journal, the Elsa.Logging workflow Log activity, and raw stdout/stderr capture. For raw managed console output, see Console Logs.
Use this module when operators need searchable application logs with workflow, tenant, trace, and source metadata. Use Log Persistence for activity execution history, and Distributed Tracing for spans and metrics.
Choose the packages
The 3.8.2 release separates the server, dashboard contribution, and storage packages:
Elsa.Diagnostics.StructuredLogscapturesILoggerevents, keeps recent events, and exposes the REST and SignalR contracts.Elsa.Diagnostics.StructuredLogs.Dashboardcontributes structured-log status and findings to the Elsa dashboard.Elsa.Diagnostics.StructuredLogs.Persistence.Relationalcontains the provider-neutral relational store and write buffer.Elsa.Diagnostics.StructuredLogs.Persistence.Sqlitesupplies SQLite connection, dialect, migration, and startup-cleanup services.
The default store is in memory and is scoped to one process. Add SQLite when recent logs must survive a restart. The release's relational package is a provider contract; SQLite is the concrete relational provider shipped here.
Enable server diagnostics
For a custom ASP.NET Core host, install the server package and register the feature. UseStructuredLogsDashboard is optional and requires the dashboard package.
using Elsa.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddElsa(elsa =>
{
elsa.UseStructuredLogs(structuredLogs =>
{
structuredLogs.RecentLogCapacity = 5_000;
structuredLogs.MaxRecentLogQuerySize = 1_000;
});
elsa.UseStructuredLogsDashboard();
});
var app = builder.Build();
app.UseRouting();
app.UseStructuredLogs();
app.Run();UseStructuredLogs registers the FastEndpoints assembly and structured-log services. The application-builder call maps the SignalR hub; the REST endpoints are discovered by the feature. Keep the call in the normal endpoint-routing portion of the host pipeline.
The Elsa Server Web sample keeps this feature disabled by default behind a useStructuredLogs switch. Enable the server feature and the corresponding Studio module together when you want the built-in diagnostics page.
Connect Elsa Studio
The Studio side is also modular. A custom Studio host registers the remote API client and the dashboard widget:
The module adds a Structured Logs item under the Diagnostics menu at diagnostics/structured-logs. Studio requests the server's recent-log and source endpoints, then uses the authenticated SignalR hub for live events. The menu and dashboard widget are remote-feature-gated: if the server does not advertise the structured-log feature, Studio does not treat the page as available.
Studio hosts in the 3.8.2 release compose these modules explicitly. The server must still enable the backend feature, and the Studio backend URL and authentication configuration must point to that server.
Inspect the server contract
All REST endpoints use the configured Elsa API prefix and require diagnostics/structured-logs:view:
GETorPOST /diagnostics/structured-logs/recentreturns recent events. The POST form accepts aStructuredLogFilterbody.GET /diagnostics/structured-logs/sourceslists known log sources and their health metadata.GET /diagnostics/structured-logs/storagereports whether a storage provider is present and how many durable writes it has dropped.
The SignalR hub is /elsa/hubs/diagnostics/structured-logs. It requires an authenticated user and exposes SubscribeAsync, UpdateFilterAsync, and UnsubscribeAsync. The hub's authorization attribute is separate from the REST permission; protect the hub and its containing host with the same authentication policy used for the rest of the Elsa API.
The recent-log filter can match:
minimum level or an explicit level set;
category prefix and text across messages, exceptions, properties, and scopes;
tenant, workflow definition, workflow instance, trace, span, correlation, and source IDs; and
timestamp range and maximum result count.
For example:
The in-memory store clamps Take to MaxRecentLogQuerySize (1,000 by default). Filters are applied to the event timestamp, not the time the host received the event.
Understand captured events
The provider is an ordinary ILoggerProvider. Each captured event includes the category, event ID and name, rendered message, message template, exception, scopes, structured properties, timestamps, source ID, and any available trace, span, correlation, tenant, workflow-definition, and workflow-instance IDs.
The module excludes its own Elsa.Diagnostics.StructuredLogs categories by default. Set IncludeStructuredLogsInternalLogs only when diagnosing the diagnostics subsystem itself; enabling it can increase noise quickly.
Sources are tracked from the events they receive. A source becomes stale after SourceHeartbeatTimeout (30 seconds by default), which helps distinguish a quiet source from a source that has stopped reporting. Source metadata is provider-owned and can include the host/container identity gathered by the runtime.
Redact before buffering or streaming
Redaction runs before an event is stored or sent to a live subscriber. The default sensitive property-name fragments include authorization, token, password, secret, api-key, cookie, and connection-string variants. The default text patterns redact bearer tokens, common name=value secrets, and Azure AccountKey/SharedAccessKey values.
Add application-specific names and patterns through the feature configuration:
Redaction is a safety net, not a substitute for avoiding secrets in log messages and properties. Review custom patterns and test representative log payloads before granting operators access.
Add SQLite persistence
Register SQLite from the structured-log feature when log history should survive process restarts:
SQLite migrations run at startup by default. Set RunMigrationsOnStartup to false when deployment tooling owns schema migration, and create the StructuredLogEvents table before the application starts.
Relational writes pass through a bounded queue. The defaults are a capacity of 10,000 queued events, batches of 100, a one-second flush interval, and a 10-second shutdown flush timeout. When the queue is full, new writes are dropped. A failed or timed-out flush can also increase the dropped-write counter. Inspect /diagnostics/structured-logs/storage during operations and alert on a non-zero dropped-write count.
Retention is opt-in. MaxAge deletes records older than the configured age; MaxRows deletes rows beyond the configured maximum. The SQLite startup service performs cleanup only when CleanupOnStartup is true. Choose limits based on the log volume and the size of message, exception, scope, and property JSON stored in each row.
The default SQLite filename is local to the process. It is suitable for a single host or development, not as a shared multi-node log store. For a cluster, use a relational provider that supplies its own connection factory, SQL dialect, migration runner, and shared database topology; the 3.8.2 core relational package does not provision those services automatically.
Structured Logs versus the other logging features
Use the feature that matches the data you need:
Elsa.Diagnostics.StructuredLogscaptures hostILoggerevents for Studio diagnostics and optional durable storage.Elsa.Loggingfromelsa-extensionsadds the workflowLogactivity and routes its entries to configured sinks. It is not theILoggerprovider described on this page.Elsa.Diagnostics.ConsoleLogscaptures raw stdout/stderr lines. It does not turn those lines into structuredILoggerevents.The workflow journal and activity execution records describe workflow execution state, not the complete host application log stream.
These features can be enabled together, but they have separate packages, permissions, buffers, and retention behavior.
Troubleshooting checklist
Confirm the server package is installed and
UseStructuredLogsis present.Confirm
app.UseStructuredLogs()runs after routing is configured.Confirm the caller has
diagnostics/structured-logs:viewfor REST requests and is authenticated for SignalR.Confirm custom Studio hosts register both
AddStructuredLogsModuleandAddStructuredLogsDashboardModule.Emit an
ILoggerevent from the host.Console.WriteLineis covered by Console Logs, not Structured Logs.Check the source list for stale sources and the storage endpoint for dropped durable writes.
If SQLite is enabled, verify the connection string, schema migration mode, file permissions, and whether the write queue is flushing successfully.
Release source
This page is validated against release/3.8.2: Core 33181ae3048f628f591a0155b5665a8e4d1bcea2, Studio 1c72dc02c837919059b60efe5df2ed57ff2db2d9, and Extensions e7d05ef930dfde2aa85bf9dcaf841e5a6ede0a1e.
Last updated