You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CrowdControl/Assets/3rd/StompyRobot/SRDebugger/Scripts/Services/Implementation/StandardConsoleService.cs

210 lines
5.9 KiB
C#

3 months ago
using System;
namespace SRDebugger.Services.Implementation
{
using SRF.Service;
using UnityEngine;
[Service(typeof (IConsoleService))]
public class StandardConsoleService : IConsoleService, IDisposable
{
private readonly bool _collapseEnabled;
private bool _hasCleared;
private readonly CircularBuffer<ConsoleEntry> _allConsoleEntries;
private CircularBuffer<ConsoleEntry> _consoleEntries;
private readonly object _threadLock = new object();
private ILogHandler _expectedLogHandler;
public StandardConsoleService()
{
Application.logMessageReceivedThreaded += UnityLogCallback;
_expectedLogHandler = Debug.unityLogger.logHandler;
SRServiceManager.RegisterService<IConsoleService>(this);
_collapseEnabled = Settings.Instance.CollapseDuplicateLogEntries;
_allConsoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
}
public void Dispose()
{
Application.logMessageReceivedThreaded -= UnityLogCallback;
if (_consoleEntries != null)
{
_consoleEntries.Clear();
}
_allConsoleEntries.Clear();
}
public int ErrorCount { get; private set; }
public int WarningCount { get; private set; }
public int InfoCount { get; private set; }
public event ConsoleUpdatedEventHandler Updated;
public event ConsoleUpdatedEventHandler Error;
public bool LoggingEnabled
{
get { return Debug.unityLogger.logEnabled; }
set { Debug.unityLogger.logEnabled = value; }
}
public bool LogHandlerIsOverriden
{
get
{
return Debug.unityLogger.logHandler != _expectedLogHandler;
}
}
public IReadOnlyList<ConsoleEntry> Entries
{
get
{
if (!_hasCleared)
{
return _allConsoleEntries;
}
return _consoleEntries;
}
}
public IReadOnlyList<ConsoleEntry> AllEntries
{
get { return _allConsoleEntries; }
}
public void Clear()
{
lock (_threadLock)
{
_hasCleared = true;
if (_consoleEntries == null)
{
_consoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
}
else
{
_consoleEntries.Clear();
}
ErrorCount = WarningCount = InfoCount = 0;
}
OnUpdated();
}
protected void OnEntryAdded(ConsoleEntry entry)
{
if (_hasCleared)
{
// Decrement counters if adding this entry will push another
// entry from the buffer.
if (_consoleEntries.IsFull)
{
AdjustCounter(_consoleEntries.Front().LogType, -1);
_consoleEntries.PopFront();
}
_consoleEntries.PushBack(entry);
}
else
{
if (_allConsoleEntries.IsFull)
{
AdjustCounter(_allConsoleEntries.Front().LogType, -1);
_allConsoleEntries.PopFront();
}
}
_allConsoleEntries.PushBack(entry);
OnUpdated();
}
protected void OnEntryDuplicated(ConsoleEntry entry)
{
entry.Count++;
OnUpdated();
// If has cleared, add this entry again for the current list
if (_hasCleared && _consoleEntries.Count == 0)
{
OnEntryAdded(new ConsoleEntry(entry) {Count = 1});
}
}
private void OnUpdated()
{
if (Updated != null)
{
try
{
Updated(this);
}
catch {}
}
}
private void UnityLogCallback(string condition, string stackTrace, LogType type)
{
//if (condition.StartsWith("[SRConsole]"))
// return;
lock (_threadLock)
{
var prevMessage = _collapseEnabled && _allConsoleEntries.Count > 0
? _allConsoleEntries[_allConsoleEntries.Count - 1]
: null;
AdjustCounter(type, 1);
if (prevMessage != null && prevMessage.LogType == type && prevMessage.Message == condition &&
prevMessage.StackTrace == stackTrace)
{
OnEntryDuplicated(prevMessage);
}
else
{
var newEntry = new ConsoleEntry
{
LogType = type,
StackTrace = stackTrace,
Message = condition
};
OnEntryAdded(newEntry);
}
}
}
private void AdjustCounter(LogType type, int amount)
{
switch (type)
{
case LogType.Assert:
case LogType.Error:
case LogType.Exception:
ErrorCount += amount;
if (Error != null)
{
Error.Invoke(this);
}
break;
case LogType.Warning:
WarningCount += amount;
break;
case LogType.Log:
InfoCount += amount;
break;
}
}
}
}