diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs
index a763b22e36..a9a468319e 100644
--- a/src/Umbraco.Core/Composing/Current.cs
+++ b/src/Umbraco.Core/Composing/Current.cs
@@ -58,6 +58,7 @@ namespace Umbraco.Core.Composing
// resets *everything* that is 'current'
internal static void Reset()
{
+ _container?.Dispose();
_container = null;
_shortStringHelper = null;
diff --git a/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs b/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs
index 1aa5594fad..d1bde55306 100644
--- a/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs
+++ b/src/Umbraco.Core/Logging/DebugDiagnosticsLogger.cs
@@ -7,6 +7,9 @@ namespace Umbraco.Core.Logging
///
public class DebugDiagnosticsLogger : ILogger
{
+ public bool IsEnabled(Type reporting, LogLevel level)
+ => true;
+
///
public void Fatal(Type reporting, Exception exception, string message)
{
@@ -26,15 +29,15 @@ namespace Umbraco.Core.Logging
}
///
- public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] args)
+ public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, args) + Environment.NewLine + exception, reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
}
///
- public void Fatal(Type reporting, string messageTemplate, params object[] args)
+ public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(messageTemplate, args);
+ System.Diagnostics.Debug.WriteLine(messageTemplate, propertyValues);
}
///
@@ -56,27 +59,27 @@ namespace Umbraco.Core.Logging
}
///
- public void Error(Type reporting, Exception exception, string messageTemplate, params object[] args)
+ public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, args) + Environment.NewLine + exception, reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
}
///
- public void Error(Type reporting, string messageTemplate, params object[] args)
+ public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(messageTemplate, args);
+ System.Diagnostics.Debug.WriteLine(messageTemplate, propertyValues);
}
///
- public void Warn(Type reporting, string format)
+ public void Warn(Type reporting, string message)
{
- System.Diagnostics.Debug.WriteLine(format, reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(message, reporting.FullName);
}
-
+
///
- public void Warn(Type reporting, string format, params object[] args)
+ public void Warn(Type reporting, string message, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(format, args), reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message, propertyValues), reporting.FullName);
}
///
@@ -86,9 +89,9 @@ namespace Umbraco.Core.Logging
}
///
- public void Warn(Type reporting, Exception exception, string format, params object[] args)
+ public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(format + Environment.NewLine + exception, args), reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message + Environment.NewLine + exception, propertyValues), reporting.FullName);
}
///
@@ -98,9 +101,9 @@ namespace Umbraco.Core.Logging
}
///
- public void Info(Type reporting, string format, params object[] args)
+ public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(format, args), reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
}
///
@@ -110,9 +113,9 @@ namespace Umbraco.Core.Logging
}
///
- public void Debug(Type reporting, string format, params object[] args)
+ public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(format, args), reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
}
///
@@ -122,9 +125,9 @@ namespace Umbraco.Core.Logging
}
///
- public void Verbose(Type reporting, string format, params object[] args)
+ public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
{
- System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(format, args), reporting.FullName);
- }
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
+ }
}
}
diff --git a/src/Umbraco.Core/Logging/DisposableTimer.cs b/src/Umbraco.Core/Logging/DisposableTimer.cs
index 869ca2cd44..db530e5339 100644
--- a/src/Umbraco.Core/Logging/DisposableTimer.cs
+++ b/src/Umbraco.Core/Logging/DisposableTimer.cs
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Logging
public class DisposableTimer : DisposableObjectSlim
{
private readonly ILogger _logger;
- private readonly LogType? _logType;
+ private readonly LogLevel _level;
private readonly Type _loggerType;
private readonly int _thresholdMilliseconds;
private readonly IDisposable _profilerStep;
@@ -19,22 +19,14 @@ namespace Umbraco.Core.Logging
private bool _failed;
private readonly string _timingId;
- internal enum LogType
- {
- Debug, Info
- }
-
// internal - created by profiling logger
- internal DisposableTimer(ILogger logger, LogType logType, IProfiler profiler, Type loggerType,
+ internal DisposableTimer(ILogger logger, LogLevel level, IProfiler profiler, Type loggerType,
string startMessage, string endMessage, string failMessage = null,
int thresholdMilliseconds = 0)
{
- if (logger == null) throw new ArgumentNullException(nameof(logger));
- if (loggerType == null) throw new ArgumentNullException(nameof(loggerType));
-
- _logger = logger;
- _logType = logType;
- _loggerType = loggerType;
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _level = level;
+ _loggerType = loggerType ?? throw new ArgumentNullException(nameof(loggerType));
_endMessage = endMessage;
_failMessage = failMessage;
_thresholdMilliseconds = thresholdMilliseconds < 0 ? 0 : thresholdMilliseconds;
@@ -42,16 +34,16 @@ namespace Umbraco.Core.Logging
if (thresholdMilliseconds == 0)
{
- switch (logType)
+ switch (_level)
{
- case LogType.Debug:
+ case LogLevel.Debug:
logger.Debug(loggerType, "[Timing {TimingId}] {StartMessage}", _timingId, startMessage);
break;
- case LogType.Info:
+ case LogLevel.Information:
logger.Info(loggerType, "[Timing {TimingId}] {StartMessage}", _timingId, startMessage);
break;
default:
- throw new ArgumentOutOfRangeException(nameof(logType));
+ throw new ArgumentOutOfRangeException(nameof(level));
}
}
@@ -87,19 +79,19 @@ namespace Umbraco.Core.Logging
_profilerStep?.Dispose();
if ((Stopwatch.ElapsedMilliseconds >= _thresholdMilliseconds || _failed)
- && _logType.HasValue && _loggerType != null && _logger != null
+ && _loggerType != null && _logger != null
&& (_endMessage.IsNullOrWhiteSpace() == false || _failed))
{
if (_failed)
{
_logger.Error(_loggerType, _failException, "[Timing {TimingId}] {FailMessage} ({TimingDuration}ms)", _timingId, _failMessage, Stopwatch.ElapsedMilliseconds);
}
- else switch (_logType)
+ else switch (_level)
{
- case LogType.Debug:
+ case LogLevel.Debug:
_logger.Debug(_loggerType, "[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
break;
- case LogType.Info:
+ case LogLevel.Information:
_logger.Info(_loggerType, "[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
break;
// filtered in the ctor
diff --git a/src/Umbraco.Core/Logging/ILogger.cs b/src/Umbraco.Core/Logging/ILogger.cs
index 2162b10bfe..4f49d0b3b4 100644
--- a/src/Umbraco.Core/Logging/ILogger.cs
+++ b/src/Umbraco.Core/Logging/ILogger.cs
@@ -14,6 +14,13 @@ namespace Umbraco.Core.Logging
///
public interface ILogger
{
+ ///
+ /// Determines if logging is enabled at a specified level, for a reporting type.
+ ///
+ /// The reporting type.
+ /// The level.
+ bool IsEnabled(Type reporting, LogLevel level);
+
///
/// Logs a fatal message with an exception.
///
diff --git a/src/Umbraco.Core/Logging/LogLevel.cs b/src/Umbraco.Core/Logging/LogLevel.cs
new file mode 100644
index 0000000000..f1b65499d6
--- /dev/null
+++ b/src/Umbraco.Core/Logging/LogLevel.cs
@@ -0,0 +1,15 @@
+namespace Umbraco.Core.Logging
+{
+ ///
+ /// Specifies the level of a log event.
+ ///
+ public enum LogLevel
+ {
+ Verbose,
+ Debug,
+ Information,
+ Warning,
+ Error,
+ Fatal
+ }
+}
diff --git a/src/Umbraco.Core/Logging/LoggerExtensions.cs b/src/Umbraco.Core/Logging/LoggerExtensions.cs
index c29bcef4f7..3b105ed888 100644
--- a/src/Umbraco.Core/Logging/LoggerExtensions.cs
+++ b/src/Umbraco.Core/Logging/LoggerExtensions.cs
@@ -8,63 +8,62 @@ namespace Umbraco.Core.Logging
public static class LoggerExtensions
{
///
- /// Logs an error message
+ /// Determines if logging is enabled at a specified level, for a reporting type.
+ ///
+ /// The reporting type.
+ /// The logger.
+ /// The level.
+ public static bool IsEnabled(this ILogger logger, LogLevel level)
+ => logger.IsEnabled(typeof(T), level);
+
+ ///
+ /// Logs an error message with an exception.
///
/// The reporting type.
/// The logger.
/// A message.
/// An exception.
public static void Error(this ILogger logger, Exception exception, string message)
- {
- logger.Error(typeof(T), exception, message);
- }
+ => logger.Error(typeof(T), exception, message);
///
- /// Logs an error message with a structured message template
+ /// Logs an error message with an exception.
///
- /// The reporting type
+ /// The reporting type.
/// The logger.
- /// A structured message template
- /// An exception
- /// Message property values
+ /// An exception.
+ /// A message template.
+ /// Property values.
public static void Error(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
- {
- logger.Error(typeof(T), exception, messageTemplate, propertyValues);
- }
+ => logger.Error(typeof(T), exception, messageTemplate, propertyValues);
///
- /// Logs an error message NOTE: This will log an empty message string
+ /// Logs an error exception.
///
- /// The reporting type
+ /// The reporting type.
/// The logger.
- /// An exception
+ /// An exception.
public static void Error(this ILogger logger, Exception exception)
- {
- logger.Error(typeof(T), exception);
- }
+ => logger.Error(typeof(T), exception);
///
- /// Logs an error message WITHOUT EX
+ /// Logs an error message.
///
- ///
- ///
- ///
- public static void Error(this ILogger logger, string message)
- {
- logger.Error(typeof(T), message);
- }
-
- ///
- /// Logs an error message - using a structured log message
- ///
- /// The reporting type
+ /// The reporting type.
/// The logger.
- /// A structured message template
- /// Message property values
+ /// A message.
+ public static void Error(this ILogger logger, string message)
+ => logger.Error(typeof(T), message);
+
+ ///
+ /// Logs an error message.
+ ///
+ /// The reporting type.
+ /// The logger.
+ /// A message template.
+ /// Property values.
public static void Error(this ILogger logger, string messageTemplate, params object[] propertyValues)
- {
- logger.Error(typeof(T), messageTemplate, propertyValues);
- }
+ => logger.Error(typeof(T), messageTemplate, propertyValues);
///
/// Logs a warning message.
@@ -73,46 +72,38 @@ namespace Umbraco.Core.Logging
/// The logger.
/// A message.
public static void Warn(this ILogger logger, string message)
- {
- logger.Warn(typeof(T), message);
- }
+ => logger.Warn(typeof(T), message);
///
- /// Logs a warning message with a structured message template
+ /// Logs a warning message.
///
- /// The reporting type
+ /// The reporting type.
/// The logger.
- /// A structured message template
- /// Message property values
+ /// A message template.
+ /// Property values.
public static void Warn(this ILogger logger, string messageTemplate, params object[] propertyValues)
- {
- logger.Warn(typeof(T), messageTemplate, propertyValues);
- }
+ => logger.Warn(typeof(T), messageTemplate, propertyValues);
///
- /// Logs a formatted warning message with an exception.
+ /// Logs a warning message with an exception.
///
/// The reporting type.
/// The logger.
/// An exception.
/// A message.
public static void Warn(this ILogger logger, Exception exception, string message)
- {
- logger.Warn(typeof(T), exception, message);
- }
+ => logger.Warn(typeof(T), exception, message);
///
- /// Logs a warning message with an exception with a structured message template
+ /// Logs a warning message with an exception.
///
- /// The reporting type
+ /// The reporting type.
/// The logger.
- /// An exception
- /// A structured message template
- /// Message property values
+ /// An exception.
+ /// A message template.
+ /// Property values.
public static void Warn(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
- {
- logger.Warn(typeof(T), exception, messageTemplate, propertyValues);
- }
+ => logger.Warn(typeof(T), exception, messageTemplate, propertyValues);
///
/// Logs an information message.
@@ -121,21 +112,17 @@ namespace Umbraco.Core.Logging
/// The logger.
/// A message.
public static void Info(this ILogger logger, string message)
- {
- logger.Info(typeof(T), message);
- }
+ => logger.Info(typeof(T), message);
///
- /// Logs a information message with a structured message template
+ /// Logs a information message.
///
/// The reporting type
/// The logger.
- /// A structured message template
- /// Message property values
+ /// A message template.
+ /// Property values.
public static void Info(this ILogger logger, string messageTemplate, params object[] propertyValues)
- {
- logger.Info(typeof(T), messageTemplate, propertyValues);
- }
+ => logger.Info(typeof(T), messageTemplate, propertyValues);
///
/// Logs a debugging message.
@@ -144,21 +131,17 @@ namespace Umbraco.Core.Logging
/// The logger.
/// A message.
public static void Debug(this ILogger logger, string message)
- {
- logger.Debug(typeof(T), message);
- }
+ => logger.Debug(typeof(T), message);
///
- /// Logs a debugging message with a structured message template
+ /// Logs a debugging message.
///
/// The reporting type
/// The logger.
- /// A structured message template
- /// Message property values
+ /// A message template.
+ /// Property values.
public static void Debug(this ILogger logger, string messageTemplate, params object[] propertyValues)
- {
- logger.Debug(typeof(T), messageTemplate, propertyValues);
- }
+ => logger.Debug(typeof(T), messageTemplate, propertyValues);
///
/// Logs a verbose message.
@@ -167,22 +150,17 @@ namespace Umbraco.Core.Logging
/// The logger.
/// A message.
public static void Verbose(this ILogger logger, string message)
- {
- logger.Verbose(typeof(T), message);
- }
+ => logger.Verbose(typeof(T), message);
///
- /// Logs a Verbose message with a structured message template
+ /// Logs a verbose message.
///
- /// The reporting type
+ /// The reporting type.
/// The logger.
- /// A structured message template
- /// Message property values
+ /// A message template.
+ /// Property values.
public static void Verbose(this ILogger logger, string messageTemplate, params object[] propertyValues)
- {
- logger.Verbose(typeof(T), messageTemplate, propertyValues);
- }
-
+ => logger.Verbose(typeof(T), messageTemplate, propertyValues);
///
/// Logs a fatal message.
@@ -192,23 +170,17 @@ namespace Umbraco.Core.Logging
/// An exception.
/// A message.
public static void Fatal(this ILogger logger, Exception exception, string message)
- {
- logger.Fatal(typeof(T), exception, message);
- }
-
+ => logger.Fatal(typeof(T), exception, message);
///
- /// Logs a fatal message with a structured message template
+ /// Logs a fatal message.
///
/// The reporting type.
/// The logger.
/// An exception.
- /// A structured message template
- /// Message property values
+ /// A message template.
+ /// Property values.
public static void Fatal(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
- {
- logger.Fatal(typeof(T), exception, messageTemplate, propertyValues);
- }
-
+ => logger.Fatal(typeof(T), exception, messageTemplate, propertyValues);
}
}
diff --git a/src/Umbraco.Core/Logging/MessageTemplates.cs b/src/Umbraco.Core/Logging/MessageTemplates.cs
index 04e802a61d..194d47c339 100644
--- a/src/Umbraco.Core/Logging/MessageTemplates.cs
+++ b/src/Umbraco.Core/Logging/MessageTemplates.cs
@@ -1,7 +1,6 @@
using System;
using System.Linq;
using Serilog;
-using Umbraco.Core.Logging.SerilogExtensions;
namespace Umbraco.Core.Logging
{
@@ -16,19 +15,19 @@ namespace Umbraco.Core.Logging
// but it only has a pre-release NuGet package. So, we've got to use Serilog's code, which
// means we cannot get rid of Serilog entirely. We may want to revisit this at some point.
- private static readonly Lazy MinimalLogger = new Lazy(() => new LoggerConfiguration().CreateLogger());
+ private static readonly Lazy MinimalLogger = new Lazy(() => new LoggerConfiguration().CreateLogger());
public static string Render(string messageTemplate, params object[] args)
{
// by default, unless initialized otherwise, Log.Logger is SilentLogger which cannot bind message
// templates. Log.Logger is set to a true Logger when initializing Umbraco's logger, but in case
// that has not been done already - use a temp minimal logger (eg for tests).
- var logger = Log.Logger as Serilog.Core.Logger ?? MinimalLogger.Value;
+ var logger = Log.Logger as global::Serilog.Core.Logger ?? MinimalLogger.Value;
var bound = logger.BindMessageTemplate(messageTemplate, args, out var parsedTemplate, out var boundProperties);
if (!bound)
- throw new FormatException($"Could not format message \"{messageTemplate}\" with {args.Length} args.");
+ throw new FormatException($"Could not format message \"{messageTemplate}\" with {args.Length} args.");
return parsedTemplate.Render(boundProperties.ToDictionary(x => x.Name, x => x.Value));
}
diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs
index 28d2494b0d..80560e923a 100644
--- a/src/Umbraco.Core/Logging/ProfilingLogger.cs
+++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs
@@ -13,10 +13,8 @@ namespace Umbraco.Core.Logging
public ProfilingLogger(ILogger logger, IProfiler profiler)
{
- if (logger == null) throw new ArgumentNullException(nameof(logger));
- if (profiler == null) throw new ArgumentNullException(nameof(profiler));
- Logger = logger;
- Profiler = profiler;
+ Logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ Profiler = profiler ?? throw new ArgumentNullException(nameof(profiler));
}
public DisposableTimer TraceDuration(string startMessage)
@@ -26,27 +24,33 @@ namespace Umbraco.Core.Logging
public DisposableTimer TraceDuration(string startMessage, string completeMessage, string failMessage = null)
{
- return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, typeof(T), startMessage, completeMessage, failMessage);
+ return new DisposableTimer(Logger, LogLevel.Information, Profiler, typeof(T), startMessage, completeMessage, failMessage);
}
public DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null)
{
- return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, loggerType, startMessage, completeMessage, failMessage);
+ return new DisposableTimer(Logger, LogLevel.Information, Profiler, loggerType, startMessage, completeMessage, failMessage);
}
public DisposableTimer DebugDuration(string startMessage)
{
- return DebugDuration(startMessage, "Completed.");
+ return Logger.IsEnabled(LogLevel.Debug)
+ ? DebugDuration(startMessage, "Completed.")
+ : null;
}
public DisposableTimer DebugDuration(string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0)
{
- return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, typeof(T), startMessage, completeMessage, failMessage, thresholdMilliseconds);
+ return Logger.IsEnabled(LogLevel.Debug)
+ ? new DisposableTimer(Logger, LogLevel.Debug, Profiler, typeof(T), startMessage, completeMessage, failMessage, thresholdMilliseconds)
+ : null;
}
public DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0)
{
- return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds);
+ return Logger.IsEnabled(loggerType, LogLevel.Debug)
+ ? new DisposableTimer(Logger, LogLevel.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds)
+ : null;
}
}
}
diff --git a/src/Umbraco.Core/Logging/SerilogExtensions/Log4NetLevelMapperEnricher.cs b/src/Umbraco.Core/Logging/Serilog/Log4NetLevelMapperEnricher.cs
similarity index 96%
rename from src/Umbraco.Core/Logging/SerilogExtensions/Log4NetLevelMapperEnricher.cs
rename to src/Umbraco.Core/Logging/Serilog/Log4NetLevelMapperEnricher.cs
index 681f7b4936..1424fa0b55 100644
--- a/src/Umbraco.Core/Logging/SerilogExtensions/Log4NetLevelMapperEnricher.cs
+++ b/src/Umbraco.Core/Logging/Serilog/Log4NetLevelMapperEnricher.cs
@@ -1,7 +1,7 @@
using Serilog.Core;
using Serilog.Events;
-namespace Umbraco.Core.Logging.SerilogExtensions
+namespace Umbraco.Core.Logging.Serilog
{
///
/// This is used to create a new property in Logs called 'Log4NetLevel'
diff --git a/src/Umbraco.Core/Logging/SerilogExtensions/LoggerConfigExtensions.cs b/src/Umbraco.Core/Logging/Serilog/LoggerConfigExtensions.cs
similarity index 97%
rename from src/Umbraco.Core/Logging/SerilogExtensions/LoggerConfigExtensions.cs
rename to src/Umbraco.Core/Logging/Serilog/LoggerConfigExtensions.cs
index 150fb0395c..8861c808df 100644
--- a/src/Umbraco.Core/Logging/SerilogExtensions/LoggerConfigExtensions.cs
+++ b/src/Umbraco.Core/Logging/Serilog/LoggerConfigExtensions.cs
@@ -4,7 +4,7 @@ using Serilog;
using Serilog.Events;
using Serilog.Formatting.Compact;
-namespace Umbraco.Core.Logging.SerilogExtensions
+namespace Umbraco.Core.Logging.Serilog
{
public static class LoggerConfigExtensions
{
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Logging.SerilogExtensions
/// A Serilog LoggerConfiguration
public static LoggerConfiguration MinimalConfiguration(this LoggerConfiguration logConfig)
{
- Serilog.Debugging.SelfLog.Enable(msg => System.Diagnostics.Debug.WriteLine(msg));
+ global::Serilog.Debugging.SelfLog.Enable(msg => System.Diagnostics.Debug.WriteLine(msg));
//Set this environment variable - so that it can be used in external config file
//add key="serilog:write-to:RollingFile.pathFormat" value="%BASEDIR%\logs\log.txt" />
diff --git a/src/Umbraco.Core/Logging/Logger.cs b/src/Umbraco.Core/Logging/Serilog/SerilogLogger.cs
similarity index 57%
rename from src/Umbraco.Core/Logging/Logger.cs
rename to src/Umbraco.Core/Logging/Serilog/SerilogLogger.cs
index 0a20022e93..6d3b2b28b3 100644
--- a/src/Umbraco.Core/Logging/Logger.cs
+++ b/src/Umbraco.Core/Logging/Serilog/SerilogLogger.cs
@@ -2,41 +2,40 @@
using System.IO;
using System.Reflection;
using System.Threading;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.Diagnostics;
using Serilog;
using Serilog.Events;
-using Umbraco.Core.Logging.SerilogExtensions;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Diagnostics;
-namespace Umbraco.Core.Logging
+namespace Umbraco.Core.Logging.Serilog
{
///
/// Implements on top of Serilog.
///
- public class Logger : ILogger
+ public class SerilogLogger : ILogger
{
///
- /// Initialize a new instance of the class with a configuration file.
+ /// Initialize a new instance of the class with a configuration file.
///
///
- public Logger(FileInfo logConfigFile)
+ public SerilogLogger(FileInfo logConfigFile)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings(filePath: AppDomain.CurrentDomain.BaseDirectory + logConfigFile)
.CreateLogger();
}
- public Logger(LoggerConfiguration logConfig)
+ public SerilogLogger(LoggerConfiguration logConfig)
{
//Configure Serilog static global logger with config passed in
Log.Logger = logConfig.CreateLogger();
}
///
- /// Creates a logger with some pre-definied configuration and remainder from config file
+ /// Creates a logger with some pre-defined configuration and remainder from config file
///
/// Used by UmbracoApplicationBase to get its logger.
- public static Logger CreateWithDefaultConfiguration()
+ public static SerilogLogger CreateWithDefaultConfiguration()
{
var loggerConfig = new LoggerConfiguration();
loggerConfig
@@ -46,78 +45,118 @@ namespace Umbraco.Core.Logging
.ReadFromConfigFile()
.ReadFromUserConfigFile();
- return new Logger(loggerConfig);
+ return new SerilogLogger(loggerConfig);
}
+ ///
+ /// Gets a contextualized logger.
+ ///
+ private global::Serilog.ILogger LoggerFor(Type reporting)
+ => Log.Logger.ForContext(reporting);
+
+ ///
+ /// Maps Umbraco's log level to Serilog's.
+ ///
+ private LogEventLevel MapLevel(LogLevel level)
+ {
+ switch (level)
+ {
+ case LogLevel.Debug:
+ return LogEventLevel.Debug;
+ case LogLevel.Error:
+ return LogEventLevel.Error;
+ case LogLevel.Fatal:
+ return LogEventLevel.Fatal;
+ case LogLevel.Information:
+ return LogEventLevel.Information;
+ case LogLevel.Verbose:
+ return LogEventLevel.Verbose;
+ case LogLevel.Warning:
+ return LogEventLevel.Warning;
+ }
+
+ throw new NotSupportedException($"LogLevel \"{level}\" is not supported.");
+ }
+
+ ///
+ public bool IsEnabled(Type reporting, LogLevel level)
+ => LoggerFor(reporting).IsEnabled(MapLevel(level));
+
///
public void Fatal(Type reporting, Exception exception, string message)
{
- Fatal(reporting, exception, message, null);
+ var logger = LoggerFor(reporting);
+ DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref message);
+ logger.Fatal(exception, message);
}
///
public void Fatal(Type reporting, Exception exception)
{
- Fatal(reporting, exception, string.Empty);
+ var logger = LoggerFor(reporting);
+ var message = "Exception.";
+ DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref message);
+ logger.Fatal(exception, message);
}
///
public void Fatal(Type reporting, string message)
{
- //Sometimes we need to throw an error without an ex
- Fatal(reporting, null, message);
+ LoggerFor(reporting).Fatal(message);
}
///
public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
{
- //Log a structured message WITHOUT an ex
- Fatal(reporting, null, messageTemplate, propertyValues);
+ LoggerFor(reporting).Fatal(messageTemplate, propertyValues);
}
///
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
- ErrorOrFatal(Fatal, exception, ref messageTemplate);
- var logger = Log.Logger;
- logger?.ForContext(reporting).Fatal(exception, messageTemplate, propertyValues);
+ var logger = LoggerFor(reporting);
+ DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref messageTemplate);
+ logger.Fatal(exception, messageTemplate, propertyValues);
}
///
public void Error(Type reporting, Exception exception, string message)
{
- Error(reporting, exception, message, null);
+ var logger = LoggerFor(reporting);
+ DumpThreadAborts(logger, LogEventLevel.Error, exception, ref message);
+ logger.Error(exception, message);
}
///
public void Error(Type reporting, Exception exception)
{
- Error(reporting, exception, string.Empty);
+ var logger = LoggerFor(reporting);
+ var message = "Exception";
+ DumpThreadAborts(logger, LogEventLevel.Error, exception, ref message);
+ logger.Error(exception, message);
}
///
public void Error(Type reporting, string message)
{
- //Sometimes we need to throw an error without an ex
- Error(reporting, null, message);
+ LoggerFor(reporting).Error(message);
}
///
public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
{
- //Log a structured message WITHOUT an ex
- Error(reporting, null, messageTemplate, propertyValues);
+ LoggerFor(reporting).Error(messageTemplate, propertyValues);
}
///
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
- ErrorOrFatal(Error, exception, ref messageTemplate);
- var logger = Log.Logger;
- logger?.ForContext(reporting).Error(exception, messageTemplate, propertyValues);
+ var logger = LoggerFor(reporting);
+ DumpThreadAborts(logger, LogEventLevel.Error, exception, ref messageTemplate);
+ logger.Error(exception, messageTemplate, propertyValues);
}
- private static void ErrorOrFatal(Action logAction, Exception exception, ref string messageTemplate)
+ private static void DumpThreadAborts(global::Serilog.ILogger logger, LogEventLevel level, Exception exception, ref string messageTemplate)
{
var dump = false;
@@ -143,8 +182,10 @@ namespace Umbraco.Core.Logging
}
catch (Exception ex)
{
+ messageTemplate += "\r\nFailed to create a minidump";
+
//Log a new entry (as opposed to appending to same log entry)
- logAction(ex.GetType(), ex, "Failed to create a minidump at App_Data/MiniDump ({ExType}: {ExMessage}",
+ logger.Write(level, ex, "Failed to create a minidump ({ExType}: {ExMessage})",
new object[]{ ex.GetType().FullName, ex.Message });
}
}
@@ -174,69 +215,63 @@ namespace Umbraco.Core.Logging
}
///
- public void Warn(Type reporting, string format)
+ public void Warn(Type reporting, string message)
{
- Warn(reporting, null, format);
+ LoggerFor(reporting).Warning(message);
}
///
- public void Warn(Type reporting, string messageTemplate, params object[] propertyValues)
+ public void Warn(Type reporting, string message, params object[] propertyValues)
{
- Warn(reporting, null, messageTemplate, propertyValues);
+ LoggerFor(reporting).Warning(message, propertyValues);
}
///
public void Warn(Type reporting, Exception exception, string message)
{
- Warn(reporting, exception, message, Array.Empty
protected virtual ILogger GetLogger()
{
- return Logger.CreateWithDefaultConfiguration();
+ return SerilogLogger.CreateWithDefaultConfiguration();
}
// events - in the order they trigger
@@ -161,13 +160,6 @@ namespace Umbraco.Core
_runtime = null;
}
- // dispose the container and everything
- // but first, capture the looger!
- var logger = Current.Logger;
- Current.Reset();
-
- if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted) return;
-
// try to log the detailed shutdown message (typical asp.net hack: http://weblogs.asp.net/scottgu/433194)
try
{
@@ -185,7 +177,7 @@ namespace Umbraco.Core
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
null, runtime, null);
- logger.Info("Application shutdown. Details: {ShutdownReason}\r\n\r\n_shutDownMessage={ShutdownMessage}\r\n\r\n_shutDownStack={ShutdownStack}",
+ Current.Logger.Info("Application shutdown. Details: {ShutdownReason}\r\n\r\n_shutDownMessage={ShutdownMessage}\r\n\r\n_shutDownStack={ShutdownStack}",
HostingEnvironment.ShutdownReason,
shutDownMessage,
shutDownStack);
@@ -193,20 +185,19 @@ namespace Umbraco.Core
catch (Exception)
{
//if for some reason that fails, then log the normal output
- logger.Info("Application shutdown. Reason: {ShutdownReason}", HostingEnvironment.ShutdownReason);
+ Current.Logger.Info("Application shutdown. Reason: {ShutdownReason}", HostingEnvironment.ShutdownReason);
}
+
+ // dispose the container and everything
+ Current.Reset();
}
// called by ASP.NET (auto event wireup) once per app domain
// sender is System.Web.HttpApplicationFactory, evargs is EventArgs.Empty
protected void Application_End(object sender, EventArgs evargs)
{
- HandleApplicationEnd();
OnApplicationEnd(sender, evargs);
-
- //Not sure if we need to do this - as my POC approach I never had to deal with this
- //As the LightInject container when tearing down will dispose of Serilog AFAIK
- Log.CloseAndFlush();
+ HandleApplicationEnd();
}
#endregion
diff --git a/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs b/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs
index 2026386e8a..a3e36db363 100644
--- a/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs
+++ b/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs
@@ -5,6 +5,9 @@ namespace Umbraco.Tests.TestHelpers
{
public class ConsoleLogger : ILogger
{
+ public bool IsEnabled(Type reporting, LogLevel level)
+ => true;
+
public void Fatal(Type reporting, Exception exception, string message)
{
Console.WriteLine("FATAL {0} - {1}", reporting.Name, message);
@@ -22,15 +25,15 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("FATAL {0} - {1}", reporting.Name, message);
}
- public void Fatal(Type reporting, Exception exception, string format, params object[] args)
+ public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
- Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
Console.WriteLine(exception);
}
- public void Fatal(Type reporting, string format, params object[] args)
+ public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
{
- Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Error(Type reporting, Exception exception, string message)
@@ -50,15 +53,15 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("ERROR {0} - {1}", reporting.Name, message);
}
- public void Error(Type reporting, Exception exception, string format, params object[] args)
+ public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
- Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
Console.WriteLine(exception);
}
- public void Error(Type reporting, string format, params object[] args)
+ public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
{
- Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Warn(Type reporting, string message)
@@ -66,9 +69,9 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("WARN {0} - {1}", reporting.Name, message);
}
- public void Warn(Type reporting, string format, params object[] args)
+ public void Warn(Type reporting, string message, params object[] propertyValues)
{
- Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(message, propertyValues));
}
public void Warn(Type reporting, Exception exception, string message)
@@ -77,15 +80,15 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine(exception);
}
- public void Warn(Type reporting, Exception exception, string format, params object[] args)
+ public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues)
{
- Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(message, propertyValues));
Console.WriteLine(exception);
}
- public void Info(Type reporting, string format, params object[] args)
+ public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
{
- Console.WriteLine("INFO {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("INFO {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Info(Type reporting, string message)
@@ -98,9 +101,9 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("DEBUG {0} - {1}", reporting.Name, message);
}
- public void Debug(Type reporting, string format, params object[] args)
+ public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
{
- Console.WriteLine("DEBUG {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("DEBUG {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Verbose(Type reporting, string message)
@@ -108,9 +111,9 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, message);
}
- public void Verbose(Type reporting, string format, params object[] args)
+ public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
{
- Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, MessageTemplates.Render(format, args));
+ Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
}
}
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index 3e40a7c3f7..ee521a7119 100644
--- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
+++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
@@ -17,6 +17,7 @@ using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.IO.MediaPathSchemes;
using Umbraco.Core.Logging;
+using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Manifest;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence;
@@ -167,7 +168,7 @@ namespace Umbraco.Tests.Testing
}
else if (option == UmbracoTestOptions.Logger.Serilog)
{
- Container.RegisterSingleton(f => new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config"))));
+ Container.RegisterSingleton(f => new SerilogLogger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config"))));
Container.RegisterSingleton(f => new LogProfiler(f.GetInstance()));
}
diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs
index 1e5e909bde..5ca195849b 100644
--- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs
@@ -1,15 +1,10 @@
-using Moq;
-using System.IO;
-using LightInject;
+using System.IO;
using NUnit.Framework;
-using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
-using Umbraco.Core.Persistence.Mappers;
-using Umbraco.Core.Profiling;
+using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Strings;
using Umbraco.Tests.TestHelpers;
-using Umbraco.Examine;
namespace Umbraco.Tests.UmbracoExamine
{
@@ -19,18 +14,12 @@ namespace Umbraco.Tests.UmbracoExamine
[OneTimeSetUp]
public void InitializeFixture()
{
- var logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config")));
+ var logger = new SerilogLogger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config")));
_profilingLogger = new ProfilingLogger(logger, new LogProfiler(logger));
}
private ProfilingLogger _profilingLogger;
- protected override ProfilingLogger ProfilingLogger
- {
- get
- {
- return _profilingLogger;
- }
- }
+ protected override ProfilingLogger ProfilingLogger => _profilingLogger;
///
/// sets up resolvers before resolution is frozen