using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using JD.Collections.Extensions; using JD.Kernel.Classes; using JD.Kernel.StaticHelpers; using JD.Kernel.Structs; namespace JD.LogService { /// /// A is used to aggregate message, warnings and errors in a list. /// public class LoggingContext : ILogger { #region Inner Types /// /// An add-only list. /// private class List : Collection where T : LogEvent { #region Variables private readonly LoggingContext m_parent; #endregion #region Constructor public List(LoggingContext parent) { m_parent = parent; } #endregion #region Methods /// /// The function invoked when the user inserts an item in the list, it will be handled by our parent. /// /// /// protected override void InsertItem(int index, T item) { m_parent.Log(item); } protected override void ClearItems() { throw new InvalidOperationException("Can only add items to the list."); } protected override void RemoveItem(int index) { throw new InvalidOperationException("Can only add items to the list."); } protected override void SetItem(int index, T item) { throw new InvalidOperationException("Can only add items to the list."); } /// /// Function invoked when the parent inserts an item in the list, it simply insert the item. /// public void AddInternal(T item) { ICollection baseCollection = this; lock (baseCollection.SyncRoot) { base.InsertItem(Count, item); } } #endregion } /// /// Accompanies the BeforeEventLogged event. /// public class BeforeEventLoggedEventArgs : CancelEventArgs { #region Variables private LogEvent m_event; #endregion #region Constructors /// /// Ctor. /// /// public BeforeEventLoggedEventArgs(LogEvent @event) { m_event = @event; } #endregion #region Properties /// /// The event beeing logged (can be swapped). /// public LogEvent Event { get { return m_event; } set { Throw.IfNull(value, "value"); m_event = value; } } #endregion } #endregion #region Variables private readonly List m_log; private readonly List m_errors; private readonly List m_warnings; private readonly List m_messages; #endregion #region Constructor /// /// Constructor. /// public LoggingContext() { m_errors = new List(this); m_warnings = new List(this); m_messages = new List(this); m_log = new List(this); } #endregion #region Properties /// /// Accesses the collection of errors. /// public IList Errors { get { return m_errors; } } /// /// Accesses the collection of warnings (non critical errors). /// public IList Warnings { get { return m_warnings; } } /// /// Accesses the collection of messages. /// public IList Messages { get { return m_messages; } } /// /// Accesses the entire collection of all the log events. /// public IList FullLog { get { return m_log; } } #endregion #region Events /// /// Triggered when an error is added in . /// public event EventHandler> ErrorAdded; /// /// Triggers the event. /// /// Event Args. protected virtual void OnErrorAdded(ItemEventArgs e) { ErrorAdded?.Invoke(this, e); } /// /// Triggered when a warning is added in . /// public event EventHandler> WarningAdded; /// /// Triggers the event. /// /// Event Args. protected virtual void OnWarningAdded(ItemEventArgs e) { WarningAdded?.Invoke(this, e); } /// /// Triggered when a message is added in . /// public event EventHandler> MessageAdded; /// /// Triggers the event. /// /// Event Args. protected virtual void OnMessageAdded(ItemEventArgs e) { MessageAdded?.Invoke(this, e); } /// /// Triggered when a item is logged in . /// public event EventHandler> EventLogged; /// /// Triggers the event. /// /// Event Args. protected virtual void OnEventLogged(ItemEventArgs e) { EventLogged?.Invoke(this, e); } /// /// Triggered before an item is logged in . /// public event EventHandler BeforeEventLogged; /// /// Triggers the event. /// /// Event Args. protected virtual void OnBeforeEventLogged(BeforeEventLoggedEventArgs e) { BeforeEventLogged?.Invoke(this, e); } #endregion #region ILogger Members /// /// Log an event in the logger. /// /// /// The event will be dispatched in the correct collection. public void Log(LogEvent @event) { Throw.IfNull(@event, "event"); BeforeEventLoggedEventArgs args = new BeforeEventLoggedEventArgs(@event); OnBeforeEventLogged(args); if (args.Cancel) { return; } @event = args.Event; m_log.AddInternal(@event); OnEventLogged(new ItemEventArgs(@event)); switch (@event.Category) { case LogCategory.Message: Message message = @event as Message; Trace.Assert(message != null); m_messages.AddInternal(message); OnMessageAdded(new ItemEventArgs(message)); break; case LogCategory.Warning: Error warning = @event as Error; Trace.Assert(warning != null); m_warnings.AddInternal(warning); OnWarningAdded(new ItemEventArgs(warning)); break; case LogCategory.Error: Error error = @event as Error; Trace.Assert(error != null); m_errors.AddInternal(error); OnErrorAdded(new ItemEventArgs(error)); break; } } #endregion #region Static methods /// /// Creates a logging context that redirects all its inputs to the given logger. /// /// Logger to redirect to. /// public static LoggingContext FromLogger(ILogger logger) { LoggingContext context = new LoggingContext(); context.EventLogged += delegate(object sender, ItemEventArgs e) { logger.Log(e.Item); }; return context; } /// /// Creates a logger that logs to the console. /// public static LoggingContext CreateConsoleLogger() { LoggingContext result = new LoggingContext(); ILogger consoleLogger = Logger.CreateConsoleLogger(); result.EventLogged += (sender, e) => consoleLogger.Log(e.Item); return result; } #endregion #region Logging Helper /// /// Log an event in the logger. /// /// /// /// [Obsolete("Use the extension methods on ILogger instead (LogError, LogWarning, LogMessage).")] // 2011.01 public LogEvent Log(LogCategory category, string message, params object[] args) { LogEvent @event = LogEvent.Formatted(category, message, args); Log(@event); return @event; } /// /// Log an event in the logger. /// /// /// /// /// [Obsolete("Use the extension methods on ILogger instead (LogError, LogWarning, LogMessage).")] // 2011.01 public LogEvent Log(LogCategory category, FileLocation origin, string message, params object[] args) { LogEvent @event = LogEvent.Formatted(category, origin, message, args); Log(@event); return @event; } /// /// Logs the content of the given logging context into this one. /// /// public void Log(LoggingContext log) { log.FullLog.ForEach(Log); } #endregion } }