Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Исправлен баг `GameManager.NewGame()`: в режиме бесплатной игры (`payment.freeGame = true`) больше не выполняется проверка/списание баланса. - Добавлен явный guard для free-play перед `Balance.CanStartGame()` и `Balance.SpendBalance(...)`, чтобы не было нежелательных списаний. - Устранена ошибка закрытия лог-файла `Cannot access a disposed object`: - `FileLogger` переведен на безопасный паттерн `Dispose(bool)` с идемпотентностью; - добавлена защита от повторного закрытия/записи в уже закрытый поток; - финализатор `FileLogger` больше не выполняет managed-cleanup. - Устранен риск повторной очистки в `CompositeLogger`: - добавлен флаг `_disposed`; - `Dispose(bool)` теперь выполняется только один раз; - финализатор вызывает `Dispose(false)` вместо полного `Dispose()`.
363 lines
10 KiB
C#
363 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace RR.Common.Utility
|
|
{
|
|
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<ILogger> _additiveLoggers = new();
|
|
private bool _disposed;
|
|
|
|
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 (_disposed || !disposing) return;
|
|
|
|
lock (_additiveLoggers)
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
|
|
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();
|
|
_disposed = true;
|
|
}
|
|
}
|
|
|
|
~CompositeLogger()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
}
|
|
}
|