Better boot fail error reporting
This commit is contained in:
@@ -105,6 +105,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
_state.Level = RuntimeLevel.BootFailed;
|
||||
var bfe = e as BootFailedException ?? new BootFailedException("Boot failed.", e);
|
||||
_state.BootFailedException = bfe;
|
||||
bootTimer.Fail(exception: bfe); // be sure to log the exception - even if we repeat ourselves
|
||||
|
||||
// throwing here can cause w3wp to hard-crash and we want to avoid it.
|
||||
|
||||
@@ -7,6 +7,11 @@ namespace Umbraco.Core.Exceptions
|
||||
/// </summary>
|
||||
public class BootFailedException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the default boot failed exception message.
|
||||
/// </summary>
|
||||
public const string DefaultMessage = "Boot failed: Umbraco cannot run. Sad. See Umbraco's log file for more details.";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Exception"/> class with a specified error message.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using LightInject;
|
||||
|
||||
namespace Umbraco.Core
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Semver;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core
|
||||
@@ -55,5 +56,10 @@ namespace Umbraco.Core
|
||||
/// Gets the runtime level of execution.
|
||||
/// </summary>
|
||||
RuntimeLevel Level { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception that caused the boot to fail.
|
||||
/// </summary>
|
||||
BootFailedException BootFailedException { get; }
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.Web;
|
||||
using Semver;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
@@ -87,7 +88,7 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public RuntimeLevel Level
|
||||
{
|
||||
get { return _level; }
|
||||
get => _level;
|
||||
internal set { _level = value; if (value == RuntimeLevel.Run) _runLevel.Set(); }
|
||||
}
|
||||
|
||||
@@ -113,5 +114,10 @@ namespace Umbraco.Core
|
||||
{
|
||||
return _runLevel.WaitHandle.WaitOne(timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception that caused the boot to fail.
|
||||
/// </summary>
|
||||
public BootFailedException BootFailedException { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using LightInject;
|
||||
@@ -504,7 +505,31 @@ namespace Umbraco.Web
|
||||
if (Core.Composing.Current.RuntimeState.Level == RuntimeLevel.BootFailed)
|
||||
{
|
||||
// there's nothing we can do really
|
||||
app.BeginRequest += (sender, args) => throw new BootFailedException("Boot failed. Umbraco cannot run. Umbraco's log file contains details about what caused the boot to fail.");
|
||||
app.BeginRequest += (sender, args) =>
|
||||
{
|
||||
// would love to avoid throwing, and instead display a customized Umbraco 500
|
||||
// page - however if we don't throw here, something else might go wrong, and
|
||||
// it's this later exception that would be reported. could not figure out how
|
||||
// to prevent it, either with httpContext.Response.End() or .ApplicationInstance
|
||||
// .CompleteRequest()
|
||||
|
||||
// also, if something goes wrong with our DI setup, the logging subsystem may
|
||||
// not even kick in, so here we try to give as much detail as possible
|
||||
|
||||
Exception e = Core.Composing.Current.RuntimeState.BootFailedException;
|
||||
if (e == null)
|
||||
throw new BootFailedException(BootFailedException.DefaultMessage);
|
||||
var m = new StringBuilder();
|
||||
m.Append(BootFailedException.DefaultMessage);
|
||||
while (e != null)
|
||||
{
|
||||
m.Append($"\n\n-> {e.GetType().FullName}: {e.Message}");
|
||||
if (string.IsNullOrWhiteSpace(e.StackTrace) == false)
|
||||
m.Append($"\n{e.StackTrace}");
|
||||
e = e.InnerException;
|
||||
}
|
||||
throw new BootFailedException(m.ToString());
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -548,14 +573,15 @@ namespace Umbraco.Web
|
||||
app.EndRequest += (sender, args) =>
|
||||
{
|
||||
var httpContext = ((HttpApplication) sender).Context;
|
||||
|
||||
if (UmbracoContext.Current != null && UmbracoContext.Current.IsFrontEndUmbracoRequest)
|
||||
{
|
||||
Logger.Debug<UmbracoModule>($"End Request. ({DateTime.Now.Subtract(UmbracoContext.Current.ObjectCreated).TotalMilliseconds}ms)");
|
||||
}
|
||||
|
||||
OnEndRequest(new UmbracoRequestEventArgs(UmbracoContext.Current, new HttpContextWrapper(httpContext)));
|
||||
OnEndRequest(new UmbracoRequestEventArgs(UmbracoContext.Current, new HttpContextWrapper(httpContext)));
|
||||
|
||||
DisposeHttpContextItems(httpContext);
|
||||
DisposeHttpContextItems(httpContext);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user