From 6574247428bb10e6eacc7a2e77f843b8c6fdb1d6 Mon Sep 17 00:00:00 2001 From: Sophia Tevosyan Date: Tue, 28 Oct 2025 12:13:29 -0700 Subject: [PATCH 1/3] first commit --- src/DurableTask.Core/TaskOrchestrationContext.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/DurableTask.Core/TaskOrchestrationContext.cs b/src/DurableTask.Core/TaskOrchestrationContext.cs index 0210a10f6..da71eb65f 100644 --- a/src/DurableTask.Core/TaskOrchestrationContext.cs +++ b/src/DurableTask.Core/TaskOrchestrationContext.cs @@ -709,6 +709,15 @@ public void CompleteOrchestration(string result, string details, OrchestrationSt } else { + if (this.continueAsNew != null && orchestrationStatus == OrchestrationStatus.Failed) + { + TraceHelper.TraceSession( + TraceEventType.Warning, + "TaskOrchestrationContext-ContinueAsNewForFailedOrchestration", + OrchestrationInstance.InstanceId, + "Continue as new called for a failed orchestration, orchestration will completed"); + } + if (this.executionCompletedOrTerminated) { return; From b94e9b2145b810998989b9921331c9b0a94d7cf1 Mon Sep 17 00:00:00 2001 From: Sophia Tevosyan Date: Tue, 28 Oct 2025 12:18:26 -0700 Subject: [PATCH 2/3] fixing a typo --- src/DurableTask.Core/TaskOrchestrationContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DurableTask.Core/TaskOrchestrationContext.cs b/src/DurableTask.Core/TaskOrchestrationContext.cs index da71eb65f..88ed83650 100644 --- a/src/DurableTask.Core/TaskOrchestrationContext.cs +++ b/src/DurableTask.Core/TaskOrchestrationContext.cs @@ -715,7 +715,7 @@ public void CompleteOrchestration(string result, string details, OrchestrationSt TraceEventType.Warning, "TaskOrchestrationContext-ContinueAsNewForFailedOrchestration", OrchestrationInstance.InstanceId, - "Continue as new called for a failed orchestration, orchestration will completed"); + "Continue as new called for a failed orchestration, orchestration will complete"); } if (this.executionCompletedOrTerminated) From f7c2e5b04b4c410d56107fac1044e9a165971459 Mon Sep 17 00:00:00 2001 From: Sophia Tevosyan Date: Wed, 29 Oct 2025 13:58:13 -0700 Subject: [PATCH 3/3] addressing PR comment --- ...OrchestrationCompleteOrchestratorAction.cs | 5 ++ src/DurableTask.Core/Logging/EventIds.cs | 2 + src/DurableTask.Core/Logging/LogEvents.cs | 48 +++++++++++++++++++ src/DurableTask.Core/Logging/LogHelper.cs | 17 +++++++ .../Logging/StructuredEventSource.cs | 23 +++++++++ src/DurableTask.Core/OrchestrationTags.cs | 5 ++ .../TaskOrchestrationContext.cs | 15 +++--- .../TaskOrchestrationDispatcher.cs | 4 ++ 8 files changed, 110 insertions(+), 9 deletions(-) diff --git a/src/DurableTask.Core/Command/OrchestrationCompleteOrchestratorAction.cs b/src/DurableTask.Core/Command/OrchestrationCompleteOrchestratorAction.cs index 56551b13e..54abd5225 100644 --- a/src/DurableTask.Core/Command/OrchestrationCompleteOrchestratorAction.cs +++ b/src/DurableTask.Core/Command/OrchestrationCompleteOrchestratorAction.cs @@ -56,5 +56,10 @@ public class OrchestrationCompleteOrchestratorAction : OrchestratorAction /// Gets a list of events that should be carried over when continuing an orchestration as new. /// public IList CarryoverEvents { get; } = new List(); + + /// + /// Gets a collection of tags associated with the completion action. + /// + public IDictionary Tags { get; } = new Dictionary(); } } \ No newline at end of file diff --git a/src/DurableTask.Core/Logging/EventIds.cs b/src/DurableTask.Core/Logging/EventIds.cs index f7386eb99..f23459c79 100644 --- a/src/DurableTask.Core/Logging/EventIds.cs +++ b/src/DurableTask.Core/Logging/EventIds.cs @@ -69,5 +69,7 @@ static class EventIds public const int RenewOrchestrationWorkItemFailed = 72; public const int OrchestrationDebugTrace = 73; + + public const int OrchestrationCompletedWithWarning = 74; } } diff --git a/src/DurableTask.Core/Logging/LogEvents.cs b/src/DurableTask.Core/Logging/LogEvents.cs index fd626d3be..360528638 100644 --- a/src/DurableTask.Core/Logging/LogEvents.cs +++ b/src/DurableTask.Core/Logging/LogEvents.cs @@ -1098,6 +1098,54 @@ void IEventSourceEvent.WriteEventSource() => } #nullable disable + /// + /// Log event representing a warning associated with an orchestration completing. + /// + internal class OrchestrationCompletedWithWarning : StructuredLogEvent, IEventSourceEvent + { + + public OrchestrationCompletedWithWarning( + OrchestrationInstance instance, + string orchestrationStatus, + string warningMessage) + { + this.InstanceId = instance.InstanceId; + this.ExecutionId = instance.ExecutionId; + this.RuntimeStatus = orchestrationStatus; + this.Details = warningMessage; + } + + [StructuredLogField] + public string InstanceId { get; } + + [StructuredLogField] + public string ExecutionId { get; } + + [StructuredLogField] + public string RuntimeStatus { get; } + + [StructuredLogField] + public string Details { get; } + + public override EventId EventId => new EventId( + EventIds.OrchestrationCompletedWithWarning, + nameof(EventIds.OrchestrationCompletedWithWarning)); + + public override LogLevel Level => LogLevel.Warning; + + protected override string CreateLogMessage() => + $"{this.InstanceId}: Orchestration completed with warning: {this.Details}"; + + void IEventSourceEvent.WriteEventSource() => + StructuredEventSource.Log.OrchestrationCompletedWithWarning( + this.InstanceId, + this.ExecutionId, + this.RuntimeStatus, + this.Details, + Utils.AppName, + Utils.PackageVersion); + } + /// /// Log event representing an orchestration aborted event, which can happen if the host is shutting down. /// diff --git a/src/DurableTask.Core/Logging/LogHelper.cs b/src/DurableTask.Core/Logging/LogHelper.cs index 109c14c42..1ae501b79 100644 --- a/src/DurableTask.Core/Logging/LogHelper.cs +++ b/src/DurableTask.Core/Logging/LogHelper.cs @@ -484,6 +484,23 @@ internal void OrchestrationCompleted( } } + /// + /// Logs a warning associated with an orchestration completing. + /// + /// The orchestration instance of the orchestration. + /// The status of the completed orchestration. + /// The warning message to log. + internal void OrchestrationCompletedWithWarning( + OrchestrationInstance instance, + OrchestrationStatus orchestrationStatus, + string warningMessage) + { + if (this.IsStructuredLoggingEnabled) + { + this.WriteStructuredLog(new LogEvents.OrchestrationCompletedWithWarning(instance, orchestrationStatus.ToString(), warningMessage)); + } + } + /// /// Logs that an orchestration execution was aborted. /// diff --git a/src/DurableTask.Core/Logging/StructuredEventSource.cs b/src/DurableTask.Core/Logging/StructuredEventSource.cs index 162a226f2..47a94b1a4 100644 --- a/src/DurableTask.Core/Logging/StructuredEventSource.cs +++ b/src/DurableTask.Core/Logging/StructuredEventSource.cs @@ -579,6 +579,29 @@ internal void OrchestrationCompleted( } } + [Event(EventIds.OrchestrationCompletedWithWarning, Level = EventLevel.Warning, Version = 1)] + internal void OrchestrationCompletedWithWarning( + string InstanceId, + string ExecutionId, + string RuntimeStatus, + string Details, + string AppName, + string ExtensionVersion) + { + if (this.IsEnabled(EventLevel.Warning)) + { + // TODO: Use WriteEventCore for better performance + this.WriteEvent( + EventIds.OrchestrationCompletedWithWarning, + InstanceId, + ExecutionId, + RuntimeStatus, + Details, + AppName, + ExtensionVersion); + } + } + [Event(EventIds.OrchestrationAborted, Level = EventLevel.Warning, Version = 1)] internal void OrchestrationAborted( string InstanceId, diff --git a/src/DurableTask.Core/OrchestrationTags.cs b/src/DurableTask.Core/OrchestrationTags.cs index 00ff3a2b1..c8fba33a1 100644 --- a/src/DurableTask.Core/OrchestrationTags.cs +++ b/src/DurableTask.Core/OrchestrationTags.cs @@ -56,6 +56,11 @@ public static class OrchestrationTags /// public const string CreateTraceForNewOrchestration = "MS_CreateTrace"; + /// + /// The warning logged when an orchestration completes, if any. + /// + public const string CompleteOrchestrationLogWarning = "MS_CompleteOrchestrationLogWarning"; + /// /// Check whether the given tags contain the fire and forget tag /// diff --git a/src/DurableTask.Core/TaskOrchestrationContext.cs b/src/DurableTask.Core/TaskOrchestrationContext.cs index 88ed83650..4972e6fcd 100644 --- a/src/DurableTask.Core/TaskOrchestrationContext.cs +++ b/src/DurableTask.Core/TaskOrchestrationContext.cs @@ -709,15 +709,6 @@ public void CompleteOrchestration(string result, string details, OrchestrationSt } else { - if (this.continueAsNew != null && orchestrationStatus == OrchestrationStatus.Failed) - { - TraceHelper.TraceSession( - TraceEventType.Warning, - "TaskOrchestrationContext-ContinueAsNewForFailedOrchestration", - OrchestrationInstance.InstanceId, - "Continue as new called for a failed orchestration, orchestration will complete"); - } - if (this.executionCompletedOrTerminated) { return; @@ -730,6 +721,12 @@ public void CompleteOrchestration(string result, string details, OrchestrationSt completedOrchestratorAction.Details = details; completedOrchestratorAction.OrchestrationStatus = orchestrationStatus; completedOrchestratorAction.FailureDetails = failureDetails; + + if (this.continueAsNew != null && orchestrationStatus == OrchestrationStatus.Failed) + { + completedOrchestratorAction.Tags[OrchestrationTags.CompleteOrchestrationLogWarning] = + "Continue as new called for a failed orchestration, orchestration will complete."; + } } completedOrchestratorAction.Id = id; diff --git a/src/DurableTask.Core/TaskOrchestrationDispatcher.cs b/src/DurableTask.Core/TaskOrchestrationDispatcher.cs index c19e5bd80..e11330367 100644 --- a/src/DurableTask.Core/TaskOrchestrationDispatcher.cs +++ b/src/DurableTask.Core/TaskOrchestrationDispatcher.cs @@ -964,6 +964,10 @@ internal static bool ReconcileMessagesWithState(TaskOrchestrationWorkItem workIt runtimeState.AddEvent(executionCompletedEvent); + if (completeOrchestratorAction.Tags.TryGetValue(OrchestrationTags.CompleteOrchestrationLogWarning, out string warningMessage)) + { + this.logHelper.OrchestrationCompletedWithWarning(runtimeState.OrchestrationInstance!, completeOrchestratorAction.OrchestrationStatus, warningMessage); + } this.logHelper.OrchestrationCompleted(runtimeState, completeOrchestratorAction); TraceHelper.TraceInstance( runtimeState.OrchestrationStatus == OrchestrationStatus.Failed ? TraceEventType.Warning : TraceEventType.Information,