mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Made execution ID an ambient context property in recipe logging.
This commit is contained in:
@@ -90,7 +90,6 @@
|
|||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="recipes-file" type="Orchard.Logging.OrchardFileAppender">
|
<appender name="recipes-file" type="Orchard.Logging.OrchardFileAppender">
|
||||||
<!-- Sends ERROR and FATAL log messages to a file in App_Data. -->
|
|
||||||
<file value="App_Data/Logs/orchard-recipes" />
|
<file value="App_Data/Logs/orchard-recipes" />
|
||||||
<appendToFile value="true" />
|
<appendToFile value="true" />
|
||||||
<!-- Immediate flush on error log, to avoid data loss with sudden termination. -->
|
<!-- Immediate flush on error log, to avoid data loss with sudden termination. -->
|
||||||
@@ -101,7 +100,7 @@
|
|||||||
<!-- Prevents Orchard.exe from displaying locking debug messages. -->
|
<!-- Prevents Orchard.exe from displaying locking debug messages. -->
|
||||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date [%thread] %logger - %P{Tenant} - %level% %message%newline" />
|
<conversionPattern value="%date %logger - %P{Tenant} - %level% %message [ExecutionId=%P{ExecutionId}]%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,9 @@
|
|||||||
<Reference Include="Autofac">
|
<Reference Include="Autofac">
|
||||||
<HintPath>..\..\..\..\lib\autofac\Autofac.dll</HintPath>
|
<HintPath>..\..\..\..\lib\autofac\Autofac.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="log4net">
|
||||||
|
<HintPath>..\..\..\..\lib\log4net\log4net.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Orchard.Recipes.Providers.RecipeHandlers {
|
|||||||
var recipeExecutionContext = new RecipeExecutionContext {ExecutionId = recipeContext.ExecutionId, RecipeStep = recipeContext.RecipeStep};
|
var recipeExecutionContext = new RecipeExecutionContext {ExecutionId = recipeContext.ExecutionId, RecipeStep = recipeContext.RecipeStep};
|
||||||
|
|
||||||
if (executionStep != null) {
|
if (executionStep != null) {
|
||||||
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId);
|
Logger.Information("Executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
|
||||||
executionStep.Execute(recipeExecutionContext);
|
executionStep.Execute(recipeExecutionContext);
|
||||||
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
|
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
|
||||||
recipeContext.Executed = true;
|
recipeContext.Executed = true;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using log4net;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Recipes.Events;
|
using Orchard.Recipes.Events;
|
||||||
@@ -36,19 +37,26 @@ namespace Orchard.Recipes.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var executionId = Guid.NewGuid().ToString("n");
|
var executionId = Guid.NewGuid().ToString("n");
|
||||||
Logger.Information("Executing recipe '{0}' using ExecutionId {1}.", recipe.Name, executionId);
|
ThreadContext.Properties["ExecutionId"] = executionId;
|
||||||
_recipeExecuteEventHandler.ExecutionStart(executionId, recipe);
|
|
||||||
|
|
||||||
foreach (var recipeStep in recipe.RecipeSteps) {
|
try {
|
||||||
_recipeStepQueue.Enqueue(executionId, recipeStep);
|
Logger.Information("Executing recipe '{0}'.", recipe.Name);
|
||||||
_recipeStepResultRecordRepository.Create(new RecipeStepResultRecord() {
|
_recipeExecuteEventHandler.ExecutionStart(executionId, recipe);
|
||||||
ExecutionId = executionId,
|
|
||||||
StepName = recipeStep.Name
|
foreach (var recipeStep in recipe.RecipeSteps) {
|
||||||
});
|
_recipeStepQueue.Enqueue(executionId, recipeStep);
|
||||||
|
_recipeStepResultRecordRepository.Create(new RecipeStepResultRecord() {
|
||||||
|
ExecutionId = executionId,
|
||||||
|
StepName = recipeStep.Name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_recipeScheduler.ScheduleWork(executionId);
|
||||||
|
|
||||||
|
return executionId;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
ThreadContext.Properties["ExecutionId"] = null;
|
||||||
}
|
}
|
||||||
_recipeScheduler.ScheduleWork(executionId);
|
|
||||||
|
|
||||||
return executionId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using log4net;
|
||||||
using Orchard.Environment.Configuration;
|
using Orchard.Environment.Configuration;
|
||||||
using Orchard.Environment.Descriptor;
|
using Orchard.Environment.Descriptor;
|
||||||
using Orchard.Environment.State;
|
using Orchard.Environment.State;
|
||||||
@@ -42,15 +43,21 @@ namespace Orchard.Recipes.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteWork(string executionId) {
|
public void ExecuteWork(string executionId) {
|
||||||
Logger.Information("Executing next step of recipe {0}.", executionId);
|
ThreadContext.Properties["ExecutionId"] = executionId;
|
||||||
// todo: this callback should be guarded against concurrency by the IProcessingEngine
|
try {
|
||||||
var scheduleMore = _recipeStepExecutor.Value.ExecuteNextStep(executionId);
|
Logger.Information("Executing next step of recipe.");
|
||||||
if (scheduleMore)
|
// todo: this callback should be guarded against concurrency by the IProcessingEngine
|
||||||
ScheduleWork(executionId);
|
var scheduleMore = _recipeStepExecutor.Value.ExecuteNextStep(executionId);
|
||||||
else
|
if (scheduleMore)
|
||||||
// https://github.com/OrchardCMS/Orchard/issues/3672
|
ScheduleWork(executionId);
|
||||||
// Because recipes execute in their own workcontext, we need to restart the shell, as signaling a cache won't work across workcontexts.
|
else
|
||||||
_events.Changed(_shellDescriptorManager.GetShellDescriptor(), _shellSettings.Name);
|
// https://github.com/OrchardCMS/Orchard/issues/3672
|
||||||
|
// Because recipes execute in their own workcontext, we need to restart the shell, as signaling a cache won't work across workcontexts.
|
||||||
|
_events.Changed(_shellDescriptorManager.GetShellDescriptor(), _shellSettings.Name);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
ThreadContext.Properties["ExecutionId"] = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ namespace Orchard.Recipes.Services {
|
|||||||
public bool ExecuteNextStep(string executionId) {
|
public bool ExecuteNextStep(string executionId) {
|
||||||
var nextRecipeStep = _recipeStepQueue.Dequeue(executionId);
|
var nextRecipeStep = _recipeStepQueue.Dequeue(executionId);
|
||||||
if (nextRecipeStep == null) {
|
if (nextRecipeStep == null) {
|
||||||
Logger.Information("Recipe execution {0} completed.", executionId);
|
Logger.Information("Recipe execution completed.");
|
||||||
_recipeExecuteEventHandler.ExecutionComplete(executionId);
|
_recipeExecuteEventHandler.ExecutionComplete(executionId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -49,14 +49,14 @@ namespace Orchard.Recipes.Services {
|
|||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
UpdateStepResultRecord(executionId, nextRecipeStep.Name, isSuccessful: false, errorMessage: ex.Message);
|
UpdateStepResultRecord(executionId, nextRecipeStep.Name, isSuccessful: false, errorMessage: ex.Message);
|
||||||
Logger.Error(ex, "Recipe execution {0} failed because the step '{1}' failed.", executionId, nextRecipeStep.Name);
|
Logger.Error(ex, "Recipe execution failed because the step '{0}' failed.", nextRecipeStep.Name);
|
||||||
while (_recipeStepQueue.Dequeue(executionId) != null);
|
while (_recipeStepQueue.Dequeue(executionId) != null);
|
||||||
var message = T("Recipe execution with ID {0} failed because the step '{1}' failed to execute. The following exception was thrown:\n{2}\nRefer to the error logs for more information.", executionId, nextRecipeStep.Name, ex.Message);
|
var message = T("Recipe execution with ID {0} failed because the step '{1}' failed to execute. The following exception was thrown:\n{2}\nRefer to the error logs for more information.", executionId, nextRecipeStep.Name, ex.Message);
|
||||||
throw new OrchardCoreException(message);
|
throw new OrchardCoreException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recipeContext.Executed) {
|
if (!recipeContext.Executed) {
|
||||||
Logger.Error("Recipe execution {0} failed because no matching handler for recipe step '{1}' was found.", executionId, recipeContext.RecipeStep.Name);
|
Logger.Error("Recipe execution failed because no matching handler for recipe step '{0}' was found.", recipeContext.RecipeStep.Name);
|
||||||
while (_recipeStepQueue.Dequeue(executionId) != null);
|
while (_recipeStepQueue.Dequeue(executionId) != null);
|
||||||
var message = T("Recipe execution with ID {0} failed because no matching handler for recipe step '{1}' was found. Refer to the error logs for more information.", executionId, nextRecipeStep.Name);
|
var message = T("Recipe execution with ID {0} failed because no matching handler for recipe step '{1}' was found. Refer to the error logs for more information.", executionId, nextRecipeStep.Name);
|
||||||
throw new OrchardCoreException(message);
|
throw new OrchardCoreException(message);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Orchard.Recipes.Services {
|
|||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public void Enqueue(string executionId, RecipeStep step) {
|
public void Enqueue(string executionId, RecipeStep step) {
|
||||||
Logger.Information("Enqueuing step '{0}' for recipe {1}.", step.Name, executionId);
|
Logger.Information("Enqueuing recipe step '{0}'.", step.Name);
|
||||||
var recipeStepElement = new XElement("RecipeStep");
|
var recipeStepElement = new XElement("RecipeStep");
|
||||||
recipeStepElement.Add(new XElement("Name", step.Name));
|
recipeStepElement.Add(new XElement("Name", step.Name));
|
||||||
recipeStepElement.Add(step.Step);
|
recipeStepElement.Add(step.Step);
|
||||||
@@ -41,7 +41,7 @@ namespace Orchard.Recipes.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public RecipeStep Dequeue(string executionId) {
|
public RecipeStep Dequeue(string executionId) {
|
||||||
Logger.Information("Dequeuing steps for recipe {0}.", executionId);
|
Logger.Information("Dequeuing recipe steps.");
|
||||||
if (!_appDataFolder.DirectoryExists(Path.Combine(_recipeQueueFolder, executionId))) {
|
if (!_appDataFolder.DirectoryExists(Path.Combine(_recipeQueueFolder, executionId))) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ namespace Orchard.Recipes.Services {
|
|||||||
// string to xelement
|
// string to xelement
|
||||||
var stepElement = XElement.Parse(_appDataFolder.ReadFile(stepPath));
|
var stepElement = XElement.Parse(_appDataFolder.ReadFile(stepPath));
|
||||||
var stepName = stepElement.Element("Name").Value;
|
var stepName = stepElement.Element("Name").Value;
|
||||||
Logger.Information("Dequeuing step '{0}' for recipe {1}.", stepName, executionId);
|
Logger.Information("Dequeuing recipe step '{0}'.", stepName);
|
||||||
recipeStep = new RecipeStep {
|
recipeStep = new RecipeStep {
|
||||||
Name = stepName,
|
Name = stepName,
|
||||||
Step = stepElement.Element(stepName)
|
Step = stepElement.Element(stepName)
|
||||||
|
|||||||
Reference in New Issue
Block a user