diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs
index d0025c0c8b..49bb44db47 100644
--- a/src/Umbraco.Core/Composing/Current.cs
+++ b/src/Umbraco.Core/Composing/Current.cs
@@ -57,6 +57,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 a8ca9b6c31..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(string.Format(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(string.Format(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(string.Format(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(string.Format(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(string.Format(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(string.Format(format, args), reporting.FullName);
+ System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
}
///
@@ -122,10 +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(string.Format(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
new file mode 100644
index 0000000000..194d47c339
--- /dev/null
+++ b/src/Umbraco.Core/Logging/MessageTemplates.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Linq;
+using Serilog;
+
+namespace Umbraco.Core.Logging
+{
+ ///
+ /// Provides tools to support message templates.
+ ///
+ public static class MessageTemplates
+ {
+ // Umbraco now uses Message Templates (https://messagetemplates.org/) for logging, which means
+ // we cannot plainly use string.Format() to format them. There is a work-in-progress C# lib,
+ // derived from Serilog, which should help (https://github.com/messagetemplates/messagetemplates-csharp)
+ // 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());
+
+ 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 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.");
+
+ 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();
}
///
@@ -170,13 +169,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
{
@@ -194,7 +186,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);
@@ -202,20 +194,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/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs
index 6fdda7c1ff..278d8408a0 100644
--- a/src/Umbraco.Tests/Models/VariationTests.cs
+++ b/src/Umbraco.Tests/Models/VariationTests.cs
@@ -429,14 +429,15 @@ namespace Umbraco.Tests.Models
Assert.IsTrue(content.IsCultureAvailable(langUk));
Assert.IsFalse(content.IsCulturePublished(langUk));
Assert.IsNull(content.GetPublishName(langUk));
- Assert.IsNull(content.GetPublishDate(langUk)); // not published
- Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
+ Assert.IsNull(content.GetPublishDate(langUk)); // not published
Assert.IsFalse(content.IsCultureAvailable(langEs));
+ Assert.IsFalse(content.IsCultureEdited(langEs)); // not avail, so... not edited
Assert.IsFalse(content.IsCulturePublished(langEs));
+
+ // not published!
Assert.IsNull(content.GetPublishName(langEs));
- Assert.IsNull(content.GetPublishDate(langEs)); // not published!
- Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
+ Assert.IsNull(content.GetPublishDate(langEs));
// cannot test IsCultureEdited here - as that requires the content service and repository
// see: ContentServiceTests.Can_SaveRead_Variations
diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs
index 6edf85718d..7be52c7212 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs
@@ -45,7 +45,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Assert
Assert.That(language, Is.Not.Null);
Assert.That(language.HasIdentity, Is.True);
- Assert.That(language.CultureName, Is.EqualTo("en-US"));
+ Assert.That(language.CultureName, Is.EqualTo("English (United States)"));
Assert.That(language.IsoCode, Is.EqualTo("en-US"));
}
}
@@ -222,7 +222,7 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var scope = provider.CreateScope())
{
var repository = CreateRepository(provider);
-
+
var languageBR = (ILanguage)new Language("pt-BR") { CultureName = "pt-BR", IsDefaultVariantLanguage = true, Mandatory = true };
repository.Save(languageBR);
var languageEN = new Language("en-AU") { CultureName = "en-AU" };
diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs
index d321e9f5e7..2f1cb74e80 100644
--- a/src/Umbraco.Tests/Services/ContentServiceTests.cs
+++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs
@@ -2621,9 +2621,9 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, false), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, false), (langDe, false));
- // not published => must be edited
- AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
- AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
+ // not published => must be edited, if available
+ AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
+ AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
// act
@@ -2663,8 +2663,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
// fr and uk, published without changes, not edited
- AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
- AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
+ AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, false));
+ AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
@@ -2723,8 +2723,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
// we have changed values so now fr and uk are edited
- AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
- AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
+ AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
+ AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
@@ -2767,8 +2767,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// and so, fr has to be edited
- AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
- AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
+ AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
+ AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
@@ -2814,8 +2814,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// and so, fr has to be edited - uk still is
- AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
- AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
+ AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
+ AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
@@ -2856,8 +2856,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// no change, back to published
- AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
- AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
+ AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
+ AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
@@ -2879,8 +2879,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// now, uk is no more edited
- AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
- AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
+ AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, false));
+ AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
diff --git a/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs b/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs
index 9caa4b2aa1..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, string.Format(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, string.Format(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, string.Format(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, string.Format(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, string.Format(format, args));
+ Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(message, propertyValues));
}
public void Warn(Type reporting, Exception exception, string message)
@@ -76,16 +79,16 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("WARN {0} - {1}", reporting.Name, message);
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, string.Format(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, string.Format(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, string.Format(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, string.Format(format, args));
+ Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
}
}
diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
index 7dcb1df77c..1fe814e4c6 100644
--- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
@@ -127,6 +127,11 @@ namespace Umbraco.Tests.TestHelpers
{
if (!(expected is string) && expected is IEnumerable)
{
+ // sort property collection by alias, not by property ids
+ // on members, built-in properties don't have ids (always zero)
+ if (expected is PropertyCollection)
+ sorter = e => ((PropertyCollection) e).OrderBy(x => x.Alias);
+
// compare lists
AssertListsAreEqual(property, (IEnumerable) actual, (IEnumerable) expected, sorter, dateDeltaMilliseconds);
}
@@ -168,6 +173,8 @@ namespace Umbraco.Tests.TestHelpers
private static void AssertListsAreEqual(PropertyInfo property, IEnumerable expected, IEnumerable actual, Func sorter = null, int dateDeltaMilliseconds = 0)
{
+
+
if (sorter == null)
{
// this is pretty hackerific but saves us some code to write
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index 7d0f53d404..5951a87d77 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;
@@ -164,7 +165,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 d512e53b9c..5ca195849b 100644
--- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs
+++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs
@@ -1,8 +1,8 @@
using System.IO;
using NUnit.Framework;
-using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
+using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Strings;
using Umbraco.Tests.TestHelpers;
@@ -14,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