mirror of
https://github.com/DCFApixels/DragonECS-Unity.git
synced 2025-09-18 01:54:35 +08:00
impl strip console stacktrace
This commit is contained in:
parent
f068c22661
commit
dd328432f1
@ -30,27 +30,6 @@ namespace DCFApixels.DragonECS
|
|||||||
if (Instance.GetType() == typeof(UnityDebugService)) { return; }
|
if (Instance.GetType() == typeof(UnityDebugService)) { return; }
|
||||||
Set<UnityDebugService>();
|
Set<UnityDebugService>();
|
||||||
}
|
}
|
||||||
protected override void OnEnableBaseService(DebugService oldService)
|
|
||||||
{
|
|
||||||
EditorGUI.hyperLinkClicked -= EditorGUI_hyperLinkClicked;
|
|
||||||
EditorGUI.hyperLinkClicked += EditorGUI_hyperLinkClicked;
|
|
||||||
Application.logMessageReceived -= Application_logMessageReceived;
|
|
||||||
Application.logMessageReceived += Application_logMessageReceived;
|
|
||||||
}
|
|
||||||
protected override void OnDisableBaseService(DebugService nextService)
|
|
||||||
{
|
|
||||||
Application.logMessageReceived -= Application_logMessageReceived;
|
|
||||||
EditorGUI.hyperLinkClicked -= EditorGUI_hyperLinkClicked;
|
|
||||||
}
|
|
||||||
private void EditorGUI_hyperLinkClicked(EditorWindow editor, HyperLinkClickedEventArgs args)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
private void Application_logMessageReceived(string logString, string stackTrace, LogType type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected override DebugService CreateThreadInstance()
|
protected override DebugService CreateThreadInstance()
|
||||||
{
|
{
|
||||||
@ -67,6 +46,7 @@ namespace DCFApixels.DragonECS
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
string msg = AutoConvertObjectToString(v);
|
string msg = AutoConvertObjectToString(v);
|
||||||
|
string indexedLink = UnityDebugServiceStorage.NewIndexedLink();
|
||||||
bool hasTag = string.IsNullOrEmpty(tag) == false;
|
bool hasTag = string.IsNullOrEmpty(tag) == false;
|
||||||
if (hasTag)
|
if (hasTag)
|
||||||
{
|
{
|
||||||
@ -75,24 +55,24 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
case "pass":
|
case "pass":
|
||||||
Debug.Log(
|
Debug.Log(
|
||||||
$"[<color=#00ff00>{tag}</color>] {msg}");
|
$"[<color=#00ff00>{tag}</color>] {msg}{indexedLink}");
|
||||||
break;
|
break;
|
||||||
case "warning":
|
case "warning":
|
||||||
Debug.LogWarning(
|
Debug.LogWarning(
|
||||||
$"[<color=#ffff00>{tag}</color>] {msg}");
|
$"[<color=#ffff00>{tag}</color>] {msg}{indexedLink}");
|
||||||
break;
|
break;
|
||||||
case "error":
|
case "error":
|
||||||
Debug.LogError(
|
Debug.LogError(
|
||||||
$"[<color=#ff4028>{tag}</color>] {msg}");
|
$"[<color=#ff4028>{tag}</color>] {msg}{indexedLink}");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.Log(
|
Debug.Log(
|
||||||
$"[{tag}] {msg}");
|
$"[{tag}] {msg}{indexedLink}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Debug.Log(msg);
|
Debug.Log($"{msg}{indexedLink}");
|
||||||
}
|
}
|
||||||
public override void Break()
|
public override void Break()
|
||||||
{
|
{
|
||||||
|
@ -1,17 +1,23 @@
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Unity.Internal
|
namespace DCFApixels.DragonECS.Unity.Internal
|
||||||
{
|
{
|
||||||
internal class UnityDebugServiceStorage : ScriptableSingleton<UnityDebugServiceStorage>
|
using static UnityDebugServiceStorage;
|
||||||
|
using static UnityDebugServiceStorageInitializer;
|
||||||
|
|
||||||
|
[InitializeOnLoad]
|
||||||
|
internal static class UnityDebugServiceStorageInitializer
|
||||||
{
|
{
|
||||||
private static readonly MethodInfo _getLogsCountMethod;
|
private static readonly MethodInfo _getLogsCountMethod;
|
||||||
public static readonly bool IsSupportAutoLingks;
|
public static readonly bool IsSupportAutoLingks;
|
||||||
static UnityDebugServiceStorage()
|
static UnityDebugServiceStorageInitializer()
|
||||||
{
|
{
|
||||||
var logEntriesType = typeof(EditorWindow).Assembly.GetType("UnityEditor.LogEntries");
|
var logEntriesType = typeof(EditorWindow).Assembly.GetType("UnityEditor.LogEntries");
|
||||||
if (logEntriesType != null)
|
if (logEntriesType != null)
|
||||||
@ -23,88 +29,167 @@ namespace DCFApixels.DragonECS.Unity.Internal
|
|||||||
EditorGUI.hyperLinkClicked -= EditorGUI_hyperLinkClicked;
|
EditorGUI.hyperLinkClicked -= EditorGUI_hyperLinkClicked;
|
||||||
Application.logMessageReceived -= Application_logMessageReceived;
|
Application.logMessageReceived -= Application_logMessageReceived;
|
||||||
_consoleLogCounter = -1;
|
_consoleLogCounter = -1;
|
||||||
if (IsSupportAutoLingks)
|
//if (IsSupportAutoLingks)
|
||||||
{
|
{
|
||||||
EditorGUI.hyperLinkClicked += EditorGUI_hyperLinkClicked;
|
EditorGUI.hyperLinkClicked += EditorGUI_hyperLinkClicked;
|
||||||
Application.logMessageReceived += Application_logMessageReceived;
|
Application.logMessageReceived += Application_logMessageReceived;
|
||||||
_consoleLogCounter = GetConsoleLogCount();
|
_consoleLogCounter = GetConsoleLogCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static int GetConsoleLogCount()
|
||||||
|
{
|
||||||
|
return (int)_getLogsCountMethod.Invoke(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal class UnityDebugServiceStorage : ScriptableSingleton<UnityDebugServiceStorage>
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
public UnityDebugServiceStorage() { }
|
public UnityDebugServiceStorage() { }
|
||||||
|
|
||||||
private const int IntervalChecksTicksThreshold = 100;
|
internal const int IntervalChecksTicksThreshold = 100;
|
||||||
private static int _consoleLogCounter;
|
internal static int _consoleLogCounter;
|
||||||
private static int _intervalChecksTicks = 0;
|
internal static int _intervalChecksTicks = 0;
|
||||||
private static StructList<string> _recycledIndexes;
|
internal static StructList<LogEntry> _logEntries = new StructList<LogEntry>(256);
|
||||||
private static StructList<LogEntry> _logEntries;
|
internal static object _lock = new object();
|
||||||
private static object _lock = new object();
|
|
||||||
|
|
||||||
private static void EditorGUI_hyperLinkClicked(EditorWindow window, HyperLinkClickedEventArgs args)
|
internal static void EditorGUI_hyperLinkClicked(EditorWindow window, HyperLinkClickedEventArgs args)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
OnProcessClickData(args.hyperLinkData);
|
||||||
|
}
|
||||||
|
internal static void OnProcessClickData(Dictionary<string, string> infos)
|
||||||
|
{
|
||||||
|
if (infos == null) return;
|
||||||
|
if (!infos.TryGetValue("href", out var path)) return;
|
||||||
|
infos.TryGetValue("line", out var line);
|
||||||
|
|
||||||
|
for (int i = 0; i < _logEntries.Count; i++)
|
||||||
|
{
|
||||||
|
ref var e = ref _logEntries._items[i];
|
||||||
|
if (CheckLogWithIndexedLink(e.LogString))
|
||||||
|
{
|
||||||
|
int indexof = e.LogString.LastIndexOf(INDEXED_LINK_PREV) - 1 + INDEXED_LINK_PREV.Length;// откатываю символ ∆
|
||||||
|
int stringIndexLength = e.LogString.Length - (indexof + INDEXED_LINK_POST.Length);
|
||||||
|
|
||||||
|
if(stringIndexLength == path.Length)
|
||||||
|
{
|
||||||
|
bool isSkip = false;
|
||||||
|
for (int j = 1; j < stringIndexLength; j++)
|
||||||
|
{
|
||||||
|
var pathchar = path[j];
|
||||||
|
var logchar = e.LogString[indexof + j];
|
||||||
|
if (pathchar != logchar) { isSkip = true; break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Application_logMessageReceived(string logString, string stackTrace, LogType type)
|
if (isSkip) { continue; }
|
||||||
|
|
||||||
|
OpenIDE(e);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OpenIDE(LogEntry entry)
|
||||||
|
{
|
||||||
|
var parsed = ParseLastCall(entry.StackTrace);
|
||||||
|
if (string.IsNullOrEmpty(parsed.path)) { return; }
|
||||||
|
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(parsed.path, parsed.line); //TODO
|
||||||
|
}
|
||||||
|
public static (string path, int line) ParseLastCall(string stackTrace)
|
||||||
|
{
|
||||||
|
var debugTypeFullname = typeof(DCFApixels.DragonECS.EcsDebug).FullName;
|
||||||
|
stackTrace = stackTrace.Remove(0, stackTrace.IndexOf(debugTypeFullname));
|
||||||
|
var lines = stackTrace.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
for (int i = 1; i < lines.Length; i++)
|
||||||
|
{
|
||||||
|
var line = lines[i];
|
||||||
|
Match match = Regex.Match(line, @"\(at (?<path>.+?):(?<line>\d+)\)");
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
string filePath = match.Groups["path"].Value;
|
||||||
|
string lineNumber = match.Groups["line"].Value;
|
||||||
|
return (filePath, int.Parse(lineNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal static void Application_logMessageReceived(string logString, string stackTrace, LogType type)
|
||||||
{
|
{
|
||||||
if (_intervalChecksTicks >= IntervalChecksTicksThreshold ||
|
if (_intervalChecksTicks >= IntervalChecksTicksThreshold ||
|
||||||
_logEntries.Count >= _logEntries.Capacity - 1)
|
_logEntries.Count >= _logEntries.Capacity - 1)
|
||||||
{
|
{
|
||||||
CheckConsoleClean();
|
CheckConsoleClean();
|
||||||
_intervalChecksTicks = 0;
|
|
||||||
}
|
}
|
||||||
_logEntries.Add(new LogEntry(logString, stackTrace));
|
_logEntries.Add(new LogEntry(logString, stackTrace));
|
||||||
|
|
||||||
Interlocked.Increment(ref _consoleLogCounter);
|
_consoleLogCounter++;
|
||||||
Interlocked.Increment(ref _intervalChecksTicks);
|
_intervalChecksTicks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static bool CheckConsoleClean()
|
private static bool CheckConsoleClean()
|
||||||
{
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_intervalChecksTicks < IntervalChecksTicksThreshold) { return false; }
|
||||||
int currentCount = GetConsoleLogCount();
|
int currentCount = GetConsoleLogCount();
|
||||||
if (_consoleLogCounter > currentCount)
|
if (_consoleLogCounter > currentCount)
|
||||||
{
|
{
|
||||||
|
var l = _consoleLogCounter - currentCount;
|
||||||
error
|
if(l < _logEntries.Count)
|
||||||
|
{
|
||||||
|
_logEntries.FastRemoveSpan(0, l);
|
||||||
|
}
|
||||||
|
|
||||||
_consoleLogCounter = currentCount;
|
_consoleLogCounter = currentCount;
|
||||||
|
_intervalChecksTicks = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private static int GetConsoleLogCount()
|
|
||||||
{
|
|
||||||
return (int)_getLogsCountMethod.Invoke(null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const string INDEXED_LINK_PREV = "\r\n\r\n<a href=\"∆";
|
||||||
|
private const string INDEXED_LINK_POST = "\">Open line</a>";
|
||||||
private static string CreateIndexedLink(int index)
|
private static string CreateIndexedLink(int index)
|
||||||
{
|
{
|
||||||
return $"<a href=\"{index}\">∆</a> ";
|
return $"{INDEXED_LINK_PREV}{index}{INDEXED_LINK_POST}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//multi thread access.
|
//multi thread access.
|
||||||
public static string GetHyperLink()
|
public static string NewIndexedLink()
|
||||||
{
|
{
|
||||||
return instance.GetHyperLink_Internal();
|
return instance.GetHyperLink_Internal();
|
||||||
}
|
}
|
||||||
|
private static int _hyperLinkIndex = 0;
|
||||||
public string GetHyperLink_Internal()
|
public string GetHyperLink_Internal()
|
||||||
{
|
{
|
||||||
string hyperLink;
|
var index = Interlocked.Increment(ref _hyperLinkIndex);
|
||||||
if (_recycledIndexes.Count > 0)
|
string hyperLink = CreateIndexedLink(index);
|
||||||
{
|
|
||||||
hyperLink = _recycledIndexes.Dequeue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hyperLink = CreateIndexedLink(_logEntries.Count);
|
|
||||||
}
|
|
||||||
return hyperLink;
|
return hyperLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool CheckLogWithIndexedLink(string log)
|
||||||
|
{
|
||||||
|
if (log.Length < INDEXED_LINK_POST.Length) { return false; }
|
||||||
|
for (int i = 0; i < INDEXED_LINK_POST.Length; i++)
|
||||||
|
{
|
||||||
|
char constChar = INDEXED_LINK_POST[i];
|
||||||
|
char logChar = log[log.Length - INDEXED_LINK_POST.Length + i];
|
||||||
|
if (constChar != logChar) { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly struct LogEntry
|
||||||
private readonly struct LogEntry
|
|
||||||
{
|
{
|
||||||
public readonly string LogString;
|
public readonly string LogString;
|
||||||
public readonly string StackTrace;
|
public readonly string StackTrace;
|
||||||
|
@ -154,6 +154,33 @@ namespace DCFApixels.DragonECS.Unity.Internal
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void FastRemoveSpan(int startIndex, int length)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (startIndex < 0) { Throw.ArgumentOutOfRange(); }
|
||||||
|
if (length < 0) { Throw.ArgumentOutOfRange(); }
|
||||||
|
if (startIndex + length > _count) { Throw.Argument("Invalid range specified"); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (length == 0 || _count == 0) { return; }
|
||||||
|
|
||||||
|
int elementsToMove = _count - (startIndex + length);
|
||||||
|
|
||||||
|
if (elementsToMove > 0)
|
||||||
|
{
|
||||||
|
Array.Copy(
|
||||||
|
sourceArray: _items,
|
||||||
|
sourceIndex: startIndex + length,
|
||||||
|
destinationArray: _items,
|
||||||
|
destinationIndex: startIndex,
|
||||||
|
length: elementsToMove
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_count -= length;
|
||||||
|
|
||||||
|
//RuntimeHelpers.IsReferenceOrContainsReferences<T>();
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool RemoveWithOrder(T item)
|
public bool RemoveWithOrder(T item)
|
||||||
{
|
{
|
||||||
int index = IndexOf(item);
|
int index = IndexOf(item);
|
||||||
@ -222,17 +249,17 @@ namespace DCFApixels.DragonECS.Unity.Internal
|
|||||||
self._items[index] = item;
|
self._items[index] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool TryDequeue_MultiAccess<T>(this ref StructList<T> self, T item)
|
// public static bool TryDequeue_MultiAccess<T>(this ref StructList<T> self, T item)
|
||||||
{
|
// {
|
||||||
var index = Interlocked.Increment(ref self._count);
|
// var index = Interlocked.Increment(ref self._count);
|
||||||
|
//
|
||||||
#if DEBUG
|
//#if DEBUG
|
||||||
if (_count <= 0) { Throw.ArgumentOutOfRange(); }
|
// if (_count <= 0) { Throw.ArgumentOutOfRange(); }
|
||||||
#endif
|
//#endif
|
||||||
T result = _items[--_count];
|
// T result = _items[--_count];
|
||||||
_items[_count] = default;
|
// _items[_count] = default;
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,5 +8,13 @@ namespace DCFApixels.DragonECS.Unity.Internal
|
|||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
|
internal static void Argument(string message)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(message);
|
||||||
|
}
|
||||||
|
internal static void Exception()
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user