using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using Object = UnityEngine.Object; public class CompositeLogger : ILogger, IDisposable { public ILogHandler logHandler { get; set; } public bool logEnabled { get; set; } public LogType filterLogType { get; set; } private ILogger _oldLogger; private readonly List _additiveLoggers = new(); public void Initialize(ILogger additiveLogger = null) { _oldLogger = Debug.unityLogger; logHandler = _oldLogger.logHandler; logEnabled = true; filterLogType = _oldLogger.filterLogType; if (additiveLogger != null) _additiveLoggers.Add(additiveLogger); } public void AddLogger(ILogger additiveLogger) { if (additiveLogger == null) throw new ArgumentNullException(nameof(additiveLogger)); _additiveLoggers.Add(additiveLogger); } public void AddLoggers(params ILogger[] additiveLoggers) { if (additiveLoggers == null) throw new ArgumentNullException(nameof(additiveLoggers)); foreach (var logger in additiveLoggers) { if (logger != null) _additiveLoggers.Add(logger); } } public void RemoveLogger(ILogger additiveLogger) { _additiveLoggers.Remove(additiveLogger); } public void RemoveLoggers(params ILogger[] additiveLoggers) { _additiveLoggers.RemoveAll(additiveLoggers.Contains); } public bool IsLogTypeAllowed(LogType logType) { return _oldLogger.IsLogTypeAllowed(logType) || _additiveLoggers.Any(logger => logger.IsLogTypeAllowed(logType)); } #region Ilogger Implementation public void LogFormat(LogType logType, string format, params object[] args) { _oldLogger.LogFormat(logType, format, args); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogFormat(logType, format, args); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void LogFormat(LogType logType, Object context, string format, params object[] args) { _oldLogger.LogFormat(logType, context, format, args); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogFormat(logType, context, format, args); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void LogException(Exception exception) { _oldLogger.LogException(exception); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogException(exception); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void LogException(Exception exception, Object context) { _oldLogger.LogException(exception, context); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogException(exception, context); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(object message) { _oldLogger.Log(message); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(message); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(LogType logType, object message) { _oldLogger.Log(logType, message); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(logType, message); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(LogType logType, object message, GameObject gameObject) { _oldLogger.Log(logType, message, gameObject); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(logType, message, gameObject); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(LogType logType, object message, Object context) { _oldLogger.Log(logType, message, context); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(logType, message, context); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(LogType logType, string tag, object message, Object context) { _oldLogger.Log(logType, tag, message, context); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(logType, tag, message, context); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(LogType logType, string tag, object message) { _oldLogger.Log(tag, message); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(tag, message); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(string tag, object message) { _oldLogger.Log(tag, message); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(tag, message); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void Log(string tag, object message, Object context) { _oldLogger.Log(tag, message, context); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.Log(tag, message, context); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void LogWarning(string tag, object message) { _oldLogger.LogWarning(tag, message); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogWarning(tag, message); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void LogWarning(string tag, object message, Object context) { _oldLogger.LogWarning(tag, message, context); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogWarning(tag, message, context); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void LogError(string tag, object message) { _oldLogger.LogError(tag, message); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogError(tag, message); } catch (Exception ex) { _oldLogger.LogException(ex); } } } public void LogError(string tag, object message, Object context) { _oldLogger.LogError(tag, message, context); foreach (ILogger additiveLogger in _additiveLoggers) { try { additiveLogger.LogError(tag, message, context); } catch (Exception ex) { _oldLogger.LogException(ex); } } } #endregion public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!disposing) return; lock (_additiveLoggers) { foreach (ILogger additiveLogger in _additiveLoggers.ToArray()) { try { if (additiveLogger is IDisposable disposableLogger) disposableLogger.Dispose(); } catch (Exception ex) { try { _oldLogger?.LogException(ex); } catch { /* ignore */ } } } _additiveLoggers.Clear(); } } ~CompositeLogger() { Dispose(); } }