StandardConsoleService.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System;
  2. using System.Collections.Generic;
  3. namespace SRDebugger.Services.Implementation
  4. {
  5. using SRF.Service;
  6. using UnityEngine;
  7. [Service(typeof (IConsoleService))]
  8. public class StandardConsoleService : IConsoleService, IDisposable
  9. {
  10. private readonly bool _collapseEnabled;
  11. private bool _hasCleared;
  12. private readonly CircularBuffer<ConsoleEntry> _allConsoleEntries;
  13. private CircularBuffer<ConsoleEntry> _consoleEntries;
  14. private readonly object _threadLock = new object();
  15. private ILogHandler _expectedLogHandler;
  16. public StandardConsoleService()
  17. {
  18. Application.logMessageReceivedThreaded += UnityLogCallback;
  19. _expectedLogHandler = Debug.unityLogger.logHandler;
  20. SRServiceManager.RegisterService<IConsoleService>(this);
  21. _collapseEnabled = Settings.Instance.CollapseDuplicateLogEntries;
  22. _allConsoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
  23. }
  24. public void Dispose()
  25. {
  26. Application.logMessageReceivedThreaded -= UnityLogCallback;
  27. if (_consoleEntries != null)
  28. {
  29. _consoleEntries.Clear();
  30. }
  31. _allConsoleEntries.Clear();
  32. }
  33. public int ErrorCount { get; private set; }
  34. public int WarningCount { get; private set; }
  35. public int InfoCount { get; private set; }
  36. public event ConsoleUpdatedEventHandler Updated;
  37. public event ConsoleUpdatedEventHandler Error;
  38. public bool LoggingEnabled
  39. {
  40. get { return Debug.unityLogger.logEnabled; }
  41. set { Debug.unityLogger.logEnabled = value; }
  42. }
  43. public bool LogHandlerIsOverriden
  44. {
  45. get
  46. {
  47. return Debug.unityLogger.logHandler != _expectedLogHandler;
  48. }
  49. }
  50. public IReadOnlyList<ConsoleEntry> Entries
  51. {
  52. get
  53. {
  54. if (!_hasCleared)
  55. {
  56. return _allConsoleEntries;
  57. }
  58. return _consoleEntries;
  59. }
  60. }
  61. public IReadOnlyList<ConsoleEntry> AllEntries
  62. {
  63. get { return _allConsoleEntries; }
  64. }
  65. public void Clear()
  66. {
  67. lock (_threadLock)
  68. {
  69. _hasCleared = true;
  70. if (_consoleEntries == null)
  71. {
  72. _consoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
  73. }
  74. else
  75. {
  76. _consoleEntries.Clear();
  77. }
  78. ErrorCount = WarningCount = InfoCount = 0;
  79. }
  80. OnUpdated();
  81. }
  82. protected void OnEntryAdded(ConsoleEntry entry)
  83. {
  84. if (_hasCleared)
  85. {
  86. // Decrement counters if adding this entry will push another
  87. // entry from the buffer.
  88. if (_consoleEntries.IsFull)
  89. {
  90. AdjustCounter(_consoleEntries.Front().LogType, -1);
  91. _consoleEntries.PopFront();
  92. }
  93. _consoleEntries.PushBack(entry);
  94. }
  95. else
  96. {
  97. if (_allConsoleEntries.IsFull)
  98. {
  99. AdjustCounter(_allConsoleEntries.Front().LogType, -1);
  100. _allConsoleEntries.PopFront();
  101. }
  102. }
  103. _allConsoleEntries.PushBack(entry);
  104. OnUpdated();
  105. }
  106. protected void OnEntryDuplicated(ConsoleEntry entry)
  107. {
  108. entry.Count++;
  109. OnUpdated();
  110. // If has cleared, add this entry again for the current list
  111. if (_hasCleared && _consoleEntries.Count == 0)
  112. {
  113. OnEntryAdded(new ConsoleEntry(entry) {Count = 1});
  114. }
  115. }
  116. private void OnUpdated()
  117. {
  118. if (Updated != null)
  119. {
  120. try
  121. {
  122. Updated(this);
  123. }
  124. catch {}
  125. }
  126. }
  127. private void UnityLogCallback(string condition, string stackTrace, LogType type)
  128. {
  129. //if (condition.StartsWith("[SRConsole]"))
  130. // return;
  131. lock (_threadLock)
  132. {
  133. var prevMessage = _collapseEnabled && _allConsoleEntries.Count > 0
  134. ? _allConsoleEntries[_allConsoleEntries.Count - 1]
  135. : null;
  136. AdjustCounter(type, 1);
  137. if (prevMessage != null && prevMessage.LogType == type && prevMessage.Message == condition &&
  138. prevMessage.StackTrace == stackTrace)
  139. {
  140. OnEntryDuplicated(prevMessage);
  141. }
  142. else
  143. {
  144. var newEntry = new ConsoleEntry
  145. {
  146. LogType = type,
  147. StackTrace = stackTrace,
  148. Message = condition
  149. };
  150. OnEntryAdded(newEntry);
  151. }
  152. }
  153. }
  154. private void AdjustCounter(LogType type, int amount)
  155. {
  156. switch (type)
  157. {
  158. case LogType.Assert:
  159. case LogType.Error:
  160. case LogType.Exception:
  161. ErrorCount += amount;
  162. if (Error != null)
  163. {
  164. Error.Invoke(this);
  165. }
  166. break;
  167. case LogType.Warning:
  168. WarningCount += amount;
  169. break;
  170. case LogType.Log:
  171. InfoCount += amount;
  172. break;
  173. }
  174. }
  175. }
  176. }