using System; using System.Collections.Generic; namespace BepInEx.Logging { /// /// Handles pub-sub event marshalling across all log listeners and sources. /// public static class Logger { /// /// Collection of all log listeners that receive log events. /// public static ICollection Listeners { get; } = new List(); /// /// Collection of all log source that output log events. /// public static ICollection Sources { get; } = new LogSourceCollection(); private static readonly ManualLogSource InternalLogSource = CreateLogSource("BepInEx"); internal static void InternalLogEvent(object sender, LogEventArgs eventArgs) { foreach (var listener in Listeners) { listener?.LogEvent(sender, eventArgs); } } /// /// Logs an entry to the internal logger instance. /// /// The level of the entry. /// The data of the entry. internal static void Log(LogLevel level, object data) { InternalLogSource.Log(level, data); } internal static void LogFatal(object data) => Log(LogLevel.Fatal, data); internal static void LogError(object data) => Log(LogLevel.Error, data); internal static void LogWarning(object data) => Log(LogLevel.Warning, data); internal static void LogMessage(object data) => Log(LogLevel.Message, data); internal static void LogInfo(object data) => Log(LogLevel.Info, data); internal static void LogDebug(object data) => Log(LogLevel.Debug, data); /// /// Creates a new log source with a name and attaches it to . /// /// Name of the log source to create. /// An instance of that allows to write logs. public static ManualLogSource CreateLogSource(string sourceName) { var source = new ManualLogSource(sourceName); Sources.Add(source); return source; } private class LogSourceCollection : List, ICollection { void ICollection.Add(ILogSource item) { if (item == null) throw new ArgumentNullException(nameof(item), "Log sources cannot be null when added to the source list."); item.LogEvent += InternalLogEvent; base.Add(item); } void ICollection.Clear() { foreach (var item in base.ToArray()) { ((ICollection)this).Remove(item); } } bool ICollection.Remove(ILogSource item) { if (item == null) return false; if (!base.Contains(item)) return false; item.LogEvent -= InternalLogEvent; base.Remove(item); return true; } } } }