# -*- coding: utf-8 -*- # 에디터 로그(Editor.log)를 기준으로 오류를 센다. 콘솔 조회(get_console_logs)는 엔진이 직접 찍는 오류(BatchDrawCommand 등)를 놓쳤다. # python logscan.py mark 지금 로그 크기를 적어 둔다 # python logscan.py scan [이름] 적어 둔 자리부터 끝까지에서 오류 머리줄을 센다 import io, os, re, sys, collections LOG = r"C:\Users\sw\AppData\Local\Unity\Editor\Editor.log" MARK = os.path.join(os.path.dirname(os.path.abspath(__file__)), "logscan.mark") # 도구가 내는 메시지(게임 오류 아님) IGNORE = ("Failed to handle /api/exec request",) def read_from(offset): with open(LOG, "rb") as f: f.seek(offset) return f.read().decode("utf-8", errors="replace") def main(): cmd = sys.argv[1] if len(sys.argv) > 1 else "scan" if cmd == "mark": size = os.path.getsize(LOG) io.open(MARK, "w").write(str(size)) print("mark", size) return offset = int(io.open(MARK).read().strip()) if os.path.exists(MARK) else 0 size = os.path.getsize(LOG) if offset > size: offset = 0 # 에디터가 다시 떠서 로그가 새로 시작됨 text = read_from(offset) lines = text.split("\n") heads = collections.Counter() unloads = 0 for i, l in enumerate(lines): l = l.rstrip("\r") if l.startswith("Unloading ") and "unused Assets" in l: unloads += 1 head = None if l.startswith("A BatchDrawCommand was submitted"): head = "A BatchDrawCommand was submitted with an invalid Batch, Mesh, or Material ID" elif l.startswith(("UnityEngine.Debug:LogError", "UnityEngine.Debug:LogException", "UnityEngine.Debug:LogAssertion", "UnityEngine.Debug:LogErrorFormat")): j = i while j > 0 and not lines[j].startswith("UnityEngine.Debug:ExtractStackTraceNoAlloc"): j -= 1 head = lines[j - 1].strip()[:200] if j > 0 else "?" elif re.match(r"^[A-Za-z_\.]*Exception: ", l) or re.match(r"^[A-Za-z_\.]+Exception$", l.strip()): head = l.strip()[:200] elif l.startswith(("Assertion failed", "Some objects were not cleaned up", "Can't destroy", "Destroying GameObjects immediately")): head = l.strip()[:200] elif "error CS" in l: head = l.strip()[:200] if head is None: continue if any(x in head for x in IGNORE): continue heads[re.sub(r"\d+", "#", head)] += 1 name = sys.argv[2] if len(sys.argv) > 2 else "" total = sum(heads.values()) print("LOGSCAN %s bytes=%d lines=%d unloadUnused=%d errors=%d" % (name, size - offset, len(lines), unloads, total)) for h, c in heads.most_common(20): print(" x%d %s" % (c, h)) main()