diff --git a/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs b/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs
index 37b671926c..90498991a4 100644
--- a/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs
+++ b/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs
@@ -2,6 +2,8 @@
// See LICENSE for more details.
using System.ComponentModel;
+using Microsoft.Extensions.Hosting;
+using Umbraco.Cms.Core.Extensions;
namespace Umbraco.Cms.Core.Configuration.Models;
@@ -12,10 +14,28 @@ namespace Umbraco.Cms.Core.Configuration.Models;
public class LoggingSettings
{
internal const string StaticMaxLogAge = "1.00:00:00"; // TimeSpan.FromHours(24);
+ internal const string StaticDirectory = Constants.SystemDirectories.LogFiles;
///
/// Gets or sets a value for the maximum age of a log file.
///
[DefaultValue(StaticMaxLogAge)]
public TimeSpan MaxLogAge { get; set; } = TimeSpan.Parse(StaticMaxLogAge);
+
+ ///
+ /// Gets or sets the folder to use for log files
+ ///
+ [DefaultValue(StaticDirectory)]
+ public string Directory { get; set; } = StaticDirectory;
+
+ public string GetAbsoluteLoggingPath(IHostEnvironment hostEnvironment)
+ {
+ var dir = Directory;
+ if (dir.StartsWith("~/"))
+ {
+ return hostEnvironment.MapPathContentRoot(dir);
+ }
+
+ return dir;
+ }
}
diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs
index 85375390ac..d0e4488e0e 100644
--- a/src/Umbraco.Core/Constants-SystemDirectories.cs
+++ b/src/Umbraco.Core/Constants-SystemDirectories.cs
@@ -60,6 +60,7 @@ public static partial class Constants
///
/// The default folder where Umbraco log files are stored
///
+ [Obsolete("Use LoggingSettings.GetLoggingDirectory() instead, will be removed in Umbraco 13.")]
public const string LogFiles = Umbraco + "/Logs";
[Obsolete("Use PluginIcons instead")]
diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs
index d8c6d1ff8f..59e4eeb105 100644
--- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs
+++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs
@@ -7,6 +7,7 @@ using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Formatting.Compact;
+using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Extensions;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Logging.Serilog.Enrichers;
@@ -21,7 +22,7 @@ namespace Umbraco.Extensions
/// Such as adding ProcessID, Thread, AppDomain etc
/// It is highly recommended that you keep/use this default in your own logging config customizations
///
- [Obsolete("Please use an alternative method.")]
+ [Obsolete("Please use an alternative method. This will be removed in Umbraco 13.")]
public static LoggerConfiguration MinimalConfiguration(
this LoggerConfiguration logConfig,
Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment,
@@ -36,7 +37,7 @@ namespace Umbraco.Extensions
/// Such as adding ProcessID, Thread, AppDomain etc
/// It is highly recommended that you keep/use this default in your own logging config customizations
///
- [Obsolete("Please use an alternative method.")]
+ [Obsolete("Please use an alternative method. This will be removed in Umbraco 13.")]
public static LoggerConfiguration MinimalConfiguration(
this LoggerConfiguration logConfig,
Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment,
@@ -126,6 +127,7 @@ namespace Umbraco.Extensions
///
/// The log level you wish the JSON file to collect - default is Verbose (highest)
/// The number of days to keep log files. Default is set to null which means all logs are kept
+ [Obsolete("Will be removed in Umbraco 13.")]
public static LoggerConfiguration OutputDefaultTextFile(
this LoggerConfiguration logConfig,
Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment,
@@ -144,6 +146,31 @@ namespace Umbraco.Extensions
return logConfig;
}
+ ///
+ /// Outputs a .txt format log at /App_Data/Logs/
+ ///
+ /// A Serilog LoggerConfiguration
+ ///
+ ///
+ /// The log level you wish the JSON file to collect - default is Verbose (highest)
+ public static LoggerConfiguration OutputDefaultTextFile(
+ this LoggerConfiguration logConfig,
+ IHostEnvironment hostEnvironment,
+ LoggingSettings loggingSettings,
+ LogEventLevel minimumLevel = LogEventLevel.Verbose)
+ {
+ //Main .txt logfile - in similar format to older Log4Net output
+ //Ends with ..txt as Date is inserted before file extension substring
+ logConfig.WriteTo.File(
+ Path.Combine(loggingSettings.GetAbsoluteLoggingPath(hostEnvironment), $"UmbracoTraceLog.{Environment.MachineName}..txt"),
+ shared: true,
+ rollingInterval: RollingInterval.Day,
+ restrictedToMinimumLevel: minimumLevel,
+ retainedFileCountLimit: null, //Setting to null means we keep all files - default is 31 days
+ outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}");
+
+ return logConfig;
+ }
///
/// Used in config - If renamed or moved to other assembly the config file also has be updated.
@@ -195,6 +222,7 @@ namespace Umbraco.Extensions
/// The log level you wish the JSON file to collect - default is Verbose (highest)
///
/// The number of days to keep log files. Default is set to null which means all logs are kept
+ [Obsolete("Will be removed in Umbraco 13.")]
public static LoggerConfiguration OutputDefaultJsonFile(
this LoggerConfiguration logConfig,
Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment,
@@ -215,5 +243,33 @@ namespace Umbraco.Extensions
return logConfig;
}
+ ///
+ /// Outputs a CLEF format JSON log at /App_Data/Logs/
+ ///
+ /// A Serilog LoggerConfiguration
+ ///
+ /// The logging configuration
+ /// The log level you wish the JSON file to collect - default is Verbose (highest)
+ /// The number of days to keep log files. Default is set to null which means all logs are kept
+ public static LoggerConfiguration OutputDefaultJsonFile(
+ this LoggerConfiguration logConfig,
+ IHostEnvironment hostEnvironment,
+ LoggingSettings loggingSettings,
+ LogEventLevel minimumLevel = LogEventLevel.Verbose,
+ int? retainedFileCount = null)
+ {
+ // .clef format (Compact log event format, that can be imported into local SEQ & will make searching/filtering logs easier)
+ // Ends with ..txt as Date is inserted before file extension substring
+ logConfig.WriteTo.File(
+ new CompactJsonFormatter(),
+ Path.Combine(loggingSettings.GetAbsoluteLoggingPath(hostEnvironment) ,$"UmbracoTraceLog.{Environment.MachineName}..json"),
+ shared: true,
+ rollingInterval: RollingInterval.Day, // Create a new JSON file every day
+ retainedFileCountLimit: retainedFileCount, // Setting to null means we keep all files - default is 31 days
+ restrictedToMinimumLevel: minimumLevel);
+
+ return logConfig;
+ }
+
}
}
diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
index d8e132440c..bd3fc6849d 100644
--- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
@@ -373,7 +373,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install
{
Message =
"The database configuration failed with the following message: " + ex.Message +
- $"\n Please check log file for additional information (can be found in '{Constants.SystemDirectories.LogFiles}')",
+ $"\n Please check log file for additional information (can be found in '{nameof(LoggingSettings)}.{nameof(LoggingSettings.Directory)}')",
Success = false,
Percentage = "90"
};
diff --git a/src/Umbraco.Web.Common/Extensions/ServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/ServiceCollectionExtensions.cs
index 9a9d606644..a5e30f9011 100644
--- a/src/Umbraco.Web.Common/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/ServiceCollectionExtensions.cs
@@ -82,8 +82,9 @@ public static class ServiceCollectionExtensions
IHostEnvironment hostEnvironment,
IConfiguration configuration)
{
- // TODO: WEBSITE_RUN_FROM_PACKAGE - can't assume this DIR is writable - we have an IConfiguration instance so a later refactor should be easy enough.
- var loggingDir = hostEnvironment.MapPathContentRoot(Constants.SystemDirectories.LogFiles);
+ LoggingSettings loggerSettings = GetLoggerSettings(configuration);
+
+ var loggingDir = loggerSettings.GetAbsoluteLoggingPath(hostEnvironment);
ILoggingConfiguration loggingConfig = new LoggingConfiguration(loggingDir);
var umbracoFileConfiguration = new UmbracoFileConfiguration(configuration);
@@ -146,6 +147,13 @@ public static class ServiceCollectionExtensions
return services;
}
+ private static LoggingSettings GetLoggerSettings(IConfiguration configuration)
+ {
+ var loggerSettings = new LoggingSettings();
+ configuration.GetSection(Constants.Configuration.ConfigLogging).Bind(loggerSettings);
+ return loggerSettings;
+ }
+
///
/// Called to create the to assign to the
///