diff --git a/src/Umbraco.Core/Logging/LogHelper.cs b/src/Umbraco.Core/Logging/LogHelper.cs index 9291ffec1d..0513699f4e 100644 --- a/src/Umbraco.Core/Logging/LogHelper.cs +++ b/src/Umbraco.Core/Logging/LogHelper.cs @@ -9,6 +9,7 @@ namespace Umbraco.Core.Logging /// /// Used for logging /// + [Obsolete("Use UmbracoContext.Current.Application.Services.LoggingService instead")] public static class LogHelper { /// diff --git a/src/Umbraco.Core/Services/ILoggingService.cs b/src/Umbraco.Core/Services/ILoggingService.cs new file mode 100644 index 0000000000..6348e2495c --- /dev/null +++ b/src/Umbraco.Core/Services/ILoggingService.cs @@ -0,0 +1,23 @@ +using System; + +namespace Umbraco.Core.Services +{ + /// + /// Interface for logging service. + /// + public interface ILoggingService + { + void Error(Type callingType, string message, Exception exception); + void Warn(Type callingType, string message, params Func[] formatItems); + + void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems); + + void Info(Type callingType, Func generateMessage); + + void Info(Type type, string generateMessageFormat, params Func[] formatItems); + + void Debug(Type callingType, Func generateMessage); + + void Debug(Type type, string generateMessageFormat, params Func[] formatItems); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/LoggingService.cs b/src/Umbraco.Core/Services/LoggingService.cs new file mode 100644 index 0000000000..43cd5b0cba --- /dev/null +++ b/src/Umbraco.Core/Services/LoggingService.cs @@ -0,0 +1,264 @@ +using System; +using System.Linq; +using System.Threading; +using System.Web; +using log4net; + +namespace Umbraco.Core.Services +{ + /// + /// Used for logging + /// + public class LoggingService : ILoggingService + { + /// + /// Returns a logger for the type specified + /// + /// + /// + internal ILog LoggerFor() + { + return LogManager.GetLogger(typeof(T)); + } + + /// + /// Returns a logger for the object's type + /// + /// + /// + internal ILog LoggerFor(object getTypeFromInstance) + { + if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance"); + + return LogManager.GetLogger(getTypeFromInstance.GetType()); + } + + /// + /// Useful if the logger itself is running on another thread + /// + /// + /// + private string PrefixThreadId(string generateMessageFormat) + { + return "[Thread " + Thread.CurrentThread.ManagedThreadId + "] " + generateMessageFormat; + } + + + /// + /// Adds an error log + /// + /// + /// + /// + public void Error(string message, Exception exception) + { + Error(typeof (T), message, exception); + } + + public void Error(Type callingType, string message, Exception exception) + { + var logger = LogManager.GetLogger(callingType); + if (logger != null) + logger.Error(PrefixThreadId(message), exception); + } + + + + public void Warn(Type callingType, string message, params Func[] formatItems) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsWarnEnabled) return; + logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + } + + public void Warn(Type callingType, string message, bool showHttpTrace, params Func[] formatItems) + { + Mandate.ParameterNotNull(callingType, "callingType"); + Mandate.ParameterNotNullOrEmpty(message, "message"); + + if (showHttpTrace && HttpContext.Current != null) + { + HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray())); + } + + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsWarnEnabled) return; + logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + + } + + public void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems) + { + WarnWithException(callingType, message, false, e, formatItems); + } + + public void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func[] formatItems) + { + Mandate.ParameterNotNull(e, "e"); + Mandate.ParameterNotNull(callingType, "callingType"); + Mandate.ParameterNotNullOrEmpty(message, "message"); + + if (showHttpTrace && HttpContext.Current != null) + { + HttpContext.Current.Trace.Warn( + callingType.Name, + string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()), + e); + } + + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsWarnEnabled) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.WarnFormat(PrefixThreadId(message) + ". Exception: " + e, executedParams); + } + + /// + /// Adds a warn log + /// + /// + /// + /// + public void Warn(string message, params Func[] formatItems) + { + Warn(typeof(T), message, formatItems); + } + + public void Warn(string message, bool showHttpTrace, params Func[] formatItems) + { + Warn(typeof(T), message, showHttpTrace, formatItems); + } + + public void WarnWithException(string message, Exception e, params Func[] formatItems) + { + WarnWithException(typeof(T), message, e, formatItems); + } + public void WarnWithException(string message, bool showHttpTrace, Exception e, params Func[] formatItems) + { + WarnWithException(typeof(T), message, showHttpTrace, e, formatItems); + } + + + + + /// + /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The delegate to generate a message. + /// + public void Info(Func generateMessage) + { + Info(typeof(T), generateMessage); + } + + /// + /// Traces if tracing is enabled. + /// + /// + /// + public void Info(Type callingType, Func generateMessage) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsInfoEnabled) return; + logger.Info(PrefixThreadId(generateMessage.Invoke())); + } + + /// + /// Traces if tracing is enabled. + /// + /// The type for the logging namespace. + /// The message format. + /// The format items. + public void Info(Type type, string generateMessageFormat, params Func[] formatItems) + { + var logger = LogManager.GetLogger(type); + if (logger == null || !logger.IsInfoEnabled) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams); + } + + /// + /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The generate message format. + /// The format items. + /// + public void Info(string generateMessageFormat, params Func[] formatItems) + { + Info(typeof(T), generateMessageFormat, formatItems); + } + + + + + /// + /// Debugs a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The delegate to generate a message. + /// + public void Debug(Func generateMessage) + { + Debug(typeof(T), generateMessage); + } + + /// + /// Debugs if tracing is enabled. + /// + /// + /// + public void Debug(Type callingType, Func generateMessage) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsDebugEnabled) return; + logger.Debug(PrefixThreadId(generateMessage.Invoke())); + } + + /// + /// Debugs if tracing is enabled. + /// + /// The type for the logging namespace. + /// The message format. + /// The format items. + public void Debug(Type type, string generateMessageFormat, params Func[] formatItems) + { + var logger = LogManager.GetLogger(type); + if (logger == null || !logger.IsDebugEnabled) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.DebugFormat(PrefixThreadId(generateMessageFormat), executedParams); + } + + /// + /// Debugs a message, only generating the message if debug is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The generate message format. + /// The format items. + /// + public void Debug(string generateMessageFormat, params Func[] formatItems) + { + Debug(typeof(T), generateMessageFormat, formatItems); + } + + /// + /// Debugs a message and also writes to the TraceContext specified, useful for when you would like the debug + /// output also displayed in the Http trace output. + /// + /// + /// + /// + /// + public void Debug(string generateMessageFormat, bool showHttpTrace, params Func[] formatItems) + { + if (showHttpTrace && HttpContext.Current != null) + { + HttpContext.Current.Trace.Write( + typeof(T).Name, + string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray())); + } + Debug(typeof(T), generateMessageFormat, formatItems); + } + + } +} diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 6dabf8b0b6..afd502338f 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Core.Logging; using System.IO; using Umbraco.Core.IO; using Umbraco.Core.Persistence; @@ -15,6 +16,7 @@ namespace Umbraco.Core.Services public class ServiceContext { private Lazy _localizedTextService; + private Lazy _loggingService; private Lazy _tagService; private Lazy _contentService; private Lazy _userService; @@ -56,6 +58,7 @@ namespace Umbraco.Core.Services /// /// /// + /// public ServiceContext( IContentService contentService, IMediaService mediaService, @@ -74,6 +77,7 @@ namespace Umbraco.Core.Services IApplicationTreeService treeService, ITagService tagService, INotificationService notificationService, + INotificationService notificationService, ILoggingService loggingService) ILocalizedTextService localizedTextService) { _localizedTextService = new Lazy(() => localizedTextService); @@ -94,7 +98,7 @@ namespace Umbraco.Core.Services _memberService = new Lazy(() => memberService); _userService = new Lazy(() => userService); _notificationService = new Lazy(() => notificationService); - + _loggingService = new Lazy(() => loggingService); } /// @@ -189,6 +193,10 @@ namespace Umbraco.Core.Services if (_memberGroupService == null) _memberGroupService = new Lazy(() => new MemberGroupService(provider, repositoryFactory.Value)); + + + if (_loggingService== null) + _loggingService = new Lazy(() => new LoggingService()); } @@ -351,6 +359,13 @@ namespace Umbraco.Core.Services { get { return _memberGroupService.Value; } } - + + /// + /// Gets the LoggingService + /// + public ILoggingService LoggingService + { + get { return _loggingService.Value; } + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 5b3a6c6ced..2861c03073 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -318,6 +318,8 @@ + + diff --git a/src/Umbraco.Tests/MockTests.cs b/src/Umbraco.Tests/MockTests.cs index 95c324fd49..5a73dca432 100644 --- a/src/Umbraco.Tests/MockTests.cs +++ b/src/Umbraco.Tests/MockTests.cs @@ -5,6 +5,7 @@ using System.Text; using System.Web; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Services; @@ -57,7 +58,7 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new Mock().Object, - new Mock().Object, + new Mock().Object, new Mock().Object); Mock.Of()); Assert.Pass(); } @@ -104,7 +105,7 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new Mock().Object, - new Mock().Object, + new Mock().Object, new Mock().Object), Mock.Of()), CacheHelper.CreateDisabledCacheHelper());