diff --git a/src/modules/Elsa.Workflows.Core/Contracts/ILoggerStateGenerator.cs b/src/modules/Elsa.Workflows.Core/Contracts/ILoggerStateGenerator.cs
new file mode 100644
index 000000000..136babbcf
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Core/Contracts/ILoggerStateGenerator.cs
@@ -0,0 +1,14 @@
+namespace Elsa.Workflows.Contracts;
+
+///
+/// Generates logger state for the specified .
+///
+public interface ILoggerStateGenerator
+{
+ ///
+ /// Generates logger state for the specified .
+ ///
+ /// The to generate logger state for.
+ /// A containing the state related to the .
+ Dictionary GenerateLoggerState(TContext context);
+}
diff --git a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs
index 048c657e9..5501a0b5e 100644
--- a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs
+++ b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs
@@ -18,6 +18,7 @@ using Elsa.Workflows.PortResolvers;
using Elsa.Workflows.Serialization.Configurators;
using Elsa.Workflows.Serialization.Helpers;
using Elsa.Workflows.Serialization.Serializers;
+using Elsa.Workflows.Services;
using Elsa.Workflows.UIHints.CheckList;
using Elsa.Workflows.UIHints.Dropdown;
using Elsa.Workflows.UIHints.JsonEditor;
@@ -50,6 +51,12 @@ public class WorkflowsFeature : FeatureBase
/// A handler for committing workflow execution state.
public Func CommitStateHandler { get; set; } = sp => new NoopCommitStateHandler();
+ /// A factory that instantiates a concrete .
+ public Func> WorkflowLoggerStateGenerator { get; set; } = sp => new WorkflowLoggerStateGenerator();
+
+ /// A factory that instantiates a concrete .
+ public Func> ActivityLoggerStateGenerator { get; set; } = sp => new ActivityLoggerStateGenerator();
+
/// A delegate to configure the .
public Action WorkflowExecutionPipeline { get; set; } = builder => builder
.UseExceptionHandling()
@@ -58,9 +65,7 @@ public class WorkflowsFeature : FeatureBase
/// A delegate to configure the .
public Action ActivityExecutionPipeline { get; set; } = builder => builder.UseDefaultActivityInvoker();
- ///
/// Fluent method to set .
- ///
public WorkflowsFeature WithStandardInStreamProvider(Func provider)
{
StandardInStreamProvider = provider;
@@ -79,8 +84,22 @@ public class WorkflowsFeature : FeatureBase
{
IdentityGenerator = generator;
return this;
+ }
+
+ /// Fluent method to set .
+ public WorkflowsFeature WithWorkflowLoggerStateGenerator(Func> generator)
+ {
+ WorkflowLoggerStateGenerator = generator;
+ return this;
}
-
+
+ /// Fluent method to set .
+ public WorkflowsFeature WithActivityLoggerStateGenerator(Func> generator)
+ {
+ ActivityLoggerStateGenerator = generator;
+ return this;
+ }
+
/// Fluent method to configure the .
public WorkflowsFeature WithWorkflowExecutionPipeline(Action setup)
{
@@ -176,7 +195,11 @@ public class WorkflowsFeature : FeatureBase
.AddScoped()
.AddScoped()
- // Logging
+ // Logger state generators
+ .AddSingleton(WorkflowLoggerStateGenerator)
+ .AddSingleton(ActivityLoggerStateGenerator)
+
+ // Logging
.AddLogging();
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs b/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs
index 6139b50f4..a66286462 100644
--- a/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs
@@ -1,20 +1,16 @@
using Elsa.Workflows.Contracts;
using Elsa.Workflows.Options;
+using Microsoft.Extensions.Logging;
namespace Elsa.Workflows;
///
-public class ActivityInvoker : IActivityInvoker
+public class ActivityInvoker(
+ IActivityExecutionPipeline pipeline,
+ ILoggerStateGenerator loggerStateGenerator,
+ ILogger logger)
+ : IActivityInvoker
{
- private readonly IActivityExecutionPipeline _pipeline;
-
- ///
- /// Constructor.
- ///
- public ActivityInvoker(IActivityExecutionPipeline pipeline)
- {
- _pipeline = pipeline;
- }
///
public async Task InvokeAsync(WorkflowExecutionContext workflowExecutionContext, IActivity activity, ActivityInvocationOptions? options = default)
@@ -42,8 +38,11 @@ public class ActivityInvoker : IActivityInvoker
///
public async Task InvokeAsync(ActivityExecutionContext activityExecutionContext)
- {
- // Execute the activity execution pipeline.
- await _pipeline.ExecuteAsync(activityExecutionContext);
+ {
+ var loggerState = loggerStateGenerator.GenerateLoggerState(activityExecutionContext);
+ using var loggingScope = logger.BeginScope(loggerState);
+
+ // Execute the activity execution pipeline.
+ await pipeline.ExecuteAsync(activityExecutionContext);
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Services/ActivityLoggerStateGenerator.cs b/src/modules/Elsa.Workflows.Core/Services/ActivityLoggerStateGenerator.cs
new file mode 100644
index 000000000..2dbe0863f
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Core/Services/ActivityLoggerStateGenerator.cs
@@ -0,0 +1,22 @@
+using Elsa.Workflows.Contracts;
+
+namespace Elsa.Workflows.Services;
+
+///
+/// Generates logger state for the specified .
+///
+public class ActivityLoggerStateGenerator : ILoggerStateGenerator
+{
+ ///
+ /// Generates logger state for the specified .
+ ///
+ /// The to generate logger state for.
+ /// A containing the state related to the .
+ public Dictionary GenerateLoggerState(ActivityExecutionContext activityExecutionContext)
+ {
+ return new Dictionary
+ {
+ ["ActivityInstanceId"] = activityExecutionContext.Id
+ };
+ }
+}
diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowLoggerStateGenerator.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowLoggerStateGenerator.cs
new file mode 100644
index 000000000..4f8c88200
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowLoggerStateGenerator.cs
@@ -0,0 +1,22 @@
+using Elsa.Workflows.Contracts;
+
+namespace Elsa.Workflows.Services;
+
+///
+/// Generates logger state for the specified .
+///
+public class WorkflowLoggerStateGenerator : ILoggerStateGenerator
+{
+ ///
+ /// Generates logger state for the specified .
+ ///
+ /// The to generate logger state for.
+ /// A containing the state related to the .
+ public Dictionary GenerateLoggerState(WorkflowExecutionContext workflowExecutionContext)
+ {
+ return new Dictionary
+ {
+ ["WorkflowInstanceId"] = workflowExecutionContext.Id
+ };
+ }
+}
diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowRunner.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowRunner.cs
index c5d54735d..8918b387a 100644
--- a/src/modules/Elsa.Workflows.Core/Services/WorkflowRunner.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowRunner.cs
@@ -18,7 +18,8 @@ public class WorkflowRunner(
IWorkflowBuilderFactory workflowBuilderFactory,
IWorkflowGraphBuilder workflowGraphBuilder,
IIdentityGenerator identityGenerator,
- INotificationSender notificationSender,
+ INotificationSender notificationSender,
+ ILoggerStateGenerator loggerStateGenerator,
ICommitStateHandler commitStateHandler,
ILogger logger)
: IWorkflowRunner
@@ -163,16 +164,11 @@ public class WorkflowRunner(
return await RunAsync(workflowExecutionContext);
}
-
///
public async Task RunAsync(WorkflowExecutionContext workflowExecutionContext)
{
- var workflowInstanceId = workflowExecutionContext.Id;
- var logContext = new Dictionary
- {
- ["WorkflowInstanceId"] = workflowInstanceId
- };
- using var loggingScope = logger.BeginScope(logContext);
+ var loggerState = loggerStateGenerator.GenerateLoggerState(workflowExecutionContext);
+ using var loggingScope = logger.BeginScope(loggerState);
var workflow = workflowExecutionContext.Workflow;
var cancellationToken = workflowExecutionContext.CancellationToken;