From 4d1a00810644a5f5a1fa7e59a25c0c23b7425342 Mon Sep 17 00:00:00 2001 From: PopSlime Date: Fri, 6 Jun 2025 19:32:31 +0800 Subject: [PATCH] feat: Add logs --- Assets/Cryville.EEW.Unity/App.cs | 55 ++++++ .../Map/MapTileBitmapHolderBehaviour.cs | 4 +- Assets/Cryville.EEW.Unity/SoundPlayer.cs | 1 + Assets/Cryville.EEW.Unity/TTSWorker.cs | 7 +- Assets/Cryville.EEW.Unity/Worker.cs | 5 +- Assets/Plugins/Cryville.Common.Logging.dll | Bin 0 -> 10752 bytes .../Plugins/Cryville.Common.Logging.dll.meta | 33 ++++ Assets/Plugins/Cryville.Common.Logging.xml | 185 ++++++++++++++++++ .../Plugins/Cryville.Common.Logging.xml.meta | 7 + 9 files changed, 293 insertions(+), 4 deletions(-) create mode 100644 Assets/Plugins/Cryville.Common.Logging.dll create mode 100644 Assets/Plugins/Cryville.Common.Logging.dll.meta create mode 100644 Assets/Plugins/Cryville.Common.Logging.xml create mode 100644 Assets/Plugins/Cryville.Common.Logging.xml.meta diff --git a/Assets/Cryville.EEW.Unity/App.cs b/Assets/Cryville.EEW.Unity/App.cs index dc1095f..1344699 100644 --- a/Assets/Cryville.EEW.Unity/App.cs +++ b/Assets/Cryville.EEW.Unity/App.cs @@ -1,19 +1,60 @@ using Cryville.Common.Font; +using Cryville.Common.Logging; using Cryville.Common.Unity.UI; using Cryville.Culture; +using System; +using System.Globalization; using System.IO; using System.Text; using System.Xml; using System.Xml.Linq; using UnityEngine; +using Logger = Cryville.Common.Logging.Logger; namespace Cryville.EEW.Unity { class App { + public static string AppDataPath { get; private set; } + + public static Logger MainLogger { get; private set; } + static FileStream _logFileStream; + static StreamLoggerListener _logWriter; + static bool _init; public static void Init() { if (_init) return; _init = true; + AppDataPath = Application.persistentDataPath; + + var logPath = Directory.CreateDirectory(Path.Combine(AppDataPath, "logs")); + _logFileStream = new FileStream( + Path.Combine( + logPath.FullName, + string.Format( + CultureInfo.InvariantCulture, + "{0}.log", + DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmssfff", CultureInfo.InvariantCulture) + ) + ), + FileMode.Create, FileAccess.Write, FileShare.Read + ); + _logWriter = new StreamLoggerListener(_logFileStream) { AutoFlush = true }; + MainLogger = new Logger(); + var listener = new InstantLoggerListener(); + listener.Log += MainLogger.Log; + MainLogger.AddListener(_logWriter); + Application.logMessageReceivedThreaded += OnInternalLog; + + MainLogger.Log(1, "App", null, "App Version: {0}", Application.version); + MainLogger.Log(1, "App", null, "Unity Version: {0}", Application.unityVersion); + MainLogger.Log(1, "App", null, "Operating System: {0}, Unity = {1}, Family = {2}", Environment.OSVersion, SystemInfo.operatingSystem, SystemInfo.operatingSystemFamily); + MainLogger.Log(1, "App", null, "Platform: Build = {0}, Unity = {1}", PlatformConfig.Name, Application.platform); + MainLogger.Log(1, "App", null, "Culture: {0}, UI = {1}, Unity = {2}", SharedCultures.CurrentCulture, SharedCultures.CurrentUICulture, Application.systemLanguage); + MainLogger.Log(1, "App", null, "Device: Model = {0}, Type = {1}", SystemInfo.deviceModel, SystemInfo.deviceType); + MainLogger.Log(1, "App", null, "Graphics: Name = {0}, Type = {1}, Vendor = {2}, Version = {3}", SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceType, SystemInfo.graphicsDeviceVendor, SystemInfo.graphicsDeviceVersion); + MainLogger.Log(1, "App", null, "Processor: Count = {0}, Frequency = {1}MHz, Type = {2}", SystemInfo.processorCount, SystemInfo.processorFrequency, SystemInfo.processorType); + + MainLogger.Log(1, "App", null, "Initializing font manager"); foreach (var res in Resources.LoadAll("cldr/common/validity")) { IdValidity.Load(LoadXmlDocument(res)); } @@ -25,7 +66,10 @@ namespace Cryville.EEW.Unity { }; TMPLocalizedText.DefaultShader = Resources.Load(PlatformConfig.TextShader); + MainLogger.Log(1, "App", null, "Loading config"); SharedSettings.Instance.Init(); + + MainLogger.Log(1, "App", null, "Initialized"); } static readonly Encoding _encoding = new UTF8Encoding(false, true); @@ -40,5 +84,16 @@ namespace Cryville.EEW.Unity { using var reader = XmlReader.Create(stream, _xmlSettings); return XDocument.Load(reader); } + + static void OnInternalLog(string condition, string stackTrace, LogType type) { + var l = type switch { + LogType.Log => 1, + LogType.Assert => 2, + LogType.Warning => 3, + LogType.Error or LogType.Exception => 4, + _ => 1, + }; + MainLogger.Log(l, "Internal", null, "{0}\n{1}", condition, stackTrace); + } } } diff --git a/Assets/Cryville.EEW.Unity/Map/MapTileBitmapHolderBehaviour.cs b/Assets/Cryville.EEW.Unity/Map/MapTileBitmapHolderBehaviour.cs index fc619c6..53b69e5 100644 --- a/Assets/Cryville.EEW.Unity/Map/MapTileBitmapHolderBehaviour.cs +++ b/Assets/Cryville.EEW.Unity/Map/MapTileBitmapHolderBehaviour.cs @@ -40,7 +40,7 @@ namespace Cryville.EEW.Unity.Map { _req.SendWebRequest(); } catch (Exception ex) { - Debug.LogException(ex); + App.MainLogger.Log(4, "Map", null, "An error occurred when loading map tile {0}: {1}", _localFile, ex); } _isReady = false; } @@ -51,7 +51,7 @@ namespace Cryville.EEW.Unity.Map { _sprite = Sprite.Create(_tex, new Rect(0, 0, _tex.width, _tex.height), Vector2.zero, _tex.height, 0, SpriteMeshType.FullRect, Vector4.zero, false); } else { - Debug.LogError(_texHandler.error); + App.MainLogger.Log(4, "Map", null, "An error occurred when loading map tile {0}: {1}", _localFile, _texHandler.error); _localFile.Delete(); } _req.Dispose(); diff --git a/Assets/Cryville.EEW.Unity/SoundPlayer.cs b/Assets/Cryville.EEW.Unity/SoundPlayer.cs index 1e5926c..afdb910 100644 --- a/Assets/Cryville.EEW.Unity/SoundPlayer.cs +++ b/Assets/Cryville.EEW.Unity/SoundPlayer.cs @@ -13,6 +13,7 @@ namespace Cryville.EEW.Unity { }; protected override Stream Open(string path) { + App.MainLogger.Log(0, "Audio", null, "Opening audio file {0}", path); path = Path.Combine(Application.streamingAssetsPath, "Sounds", path + ".ogg"); if (!File.Exists(path)) return null; return new FileStream(path, FileMode.Open, FileAccess.Read); diff --git a/Assets/Cryville.EEW.Unity/TTSWorker.cs b/Assets/Cryville.EEW.Unity/TTSWorker.cs index 7c3e1f3..92575d0 100644 --- a/Assets/Cryville.EEW.Unity/TTSWorker.cs +++ b/Assets/Cryville.EEW.Unity/TTSWorker.cs @@ -9,6 +9,7 @@ namespace Cryville.EEW.Unity { readonly ISpVoice _voice; public TTSWorker() : base(CreateSoundPlayer()) { + App.MainLogger.Log(1, "Audio", null, "Initializing TTS worker"); try { _voice = new SpVoiceClass(); } @@ -16,10 +17,12 @@ namespace Cryville.EEW.Unity { } static SoundPlayer CreateSoundPlayer() { + App.MainLogger.Log(1, "Audio", null, "Creating sound player"); try { return new SoundPlayer(); } - catch (InvalidOperationException) { + catch (InvalidOperationException ex) { + App.MainLogger.Log(3, "Audio", null, "An error occurred when creating sound player: {0}", ex); return null; } } @@ -37,11 +40,13 @@ namespace Cryville.EEW.Unity { (uint)(SpeechVoiceSpeakFlags.SVSFlagsAsync | SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak), out _ ); + App.MainLogger.Log(0, "Audio", null, "TTS ({0}): {1}", culture, content); return Task.CompletedTask; } protected override void StopCurrent() { if (_voice == null) return; + App.MainLogger.Log(0, "Audio", null, "TTS stopping current"); _voice.Skip("SENTENCE", int.MaxValue, out _); } } diff --git a/Assets/Cryville.EEW.Unity/Worker.cs b/Assets/Cryville.EEW.Unity/Worker.cs index 99578c7..04c291b 100644 --- a/Assets/Cryville.EEW.Unity/Worker.cs +++ b/Assets/Cryville.EEW.Unity/Worker.cs @@ -60,6 +60,7 @@ namespace Cryville.EEW.Unity { } void Start() { + App.MainLogger.Log(1, "App", null, "Initializing localized resources manager"); LocalizedResources.Init(new LocalizedResourcesManager()); RegisterViewModelGenerators(_worker); RegisterTTSMessageGenerators(_worker); @@ -73,6 +74,7 @@ namespace Cryville.EEW.Unity { _worker.Reported += OnReported; _grouper.GroupUpdated += OnGroupUpdated; _grouper.GroupRemoved += OnGroupRemoved; + App.MainLogger.Log(1, "App", null, "Worker ready"); Task.Run(() => GatewayVerify(_cancellationTokenSource.Token)).ContinueWith(task => { if (task.IsFaulted) { OnReported(this, new() { Title = task.Exception.Message }); @@ -133,6 +135,7 @@ namespace Cryville.EEW.Unity { bool _verified; void BuildWorkers() { + App.MainLogger.Log(1, "App", null, "Building workers"); #if UNITY_EDITOR _worker.AddWorker(new WolfxWorker(new Uri("ws://localhost:9995/wolfx"))); _worker.AddWorker(new JMAAtomWorker(new Uri("http://localhost:9095/eqvol.xml"))); @@ -215,7 +218,7 @@ namespace Cryville.EEW.Unity { ReportViewModel _latestHistoryReport; void OnReported(object sender, ReportViewModel e) { if (e.Model is Exception && e.Model is not SourceWorkerNetworkException) - Debug.LogError(e); + App.MainLogger.Log(4, "Map", null, "Received an error from {0}: {1}", sender.GetType(), e.Model); _grouper.Report(e); _ongoingReportManager.Report(e); _uiActionQueue.Enqueue(() => { diff --git a/Assets/Plugins/Cryville.Common.Logging.dll b/Assets/Plugins/Cryville.Common.Logging.dll new file mode 100644 index 0000000000000000000000000000000000000000..59183ebb4eb6b1ba76dab29e1891b89c80f7cf2f GIT binary patch literal 10752 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 + + + Cryville.Common.Logging + + + + + A logger. + + + + + Attaches a listener to the logger. + + The logger listener. + + + + Detaches a listener from the logger. + + The logger listener. + + + + Logs to the logger. + + The severity level. + The category. + The format string. + The arguments for formatting. + + + + Logs to the logger. + + The severity level. + The category. + The format provider. + The format string. + The arguments for formatting. + + + + Logs to the logger. + + The severity level. + The category. + The message. + + + + Logs to the logger. + + The severity level. + The category. + An array of containing the message. + + + + Logs to the logger. + + The severity level. + The category. + An array of containing the message. + A zero-based index of the first character of the message within . + The length of the message. + + + + Logs to the logger. + + The severity level. + The category. + A pointer to the first character of the message. + The length of the message. + + + + A logger listener. + + + + + Closes the logger listener and cleans up all the resources. + + Whether to clean up managed resources. + + + + Closes the logger listener. + + + + + Handles an incoming log. + + The severity level. + The category. + The message. + + + + Handles an incoming log. + + The severity level. + The category. + An array of containing the message. + A zero-based index of the first character of the message within . + The length of the message. + + + + Handles an incoming log. + + The severity level. + The category. + A pointer to the first character of the message. + The length of the message. + + + + A that calls a callback function on log. + + + + + Occurs when a log is logged to the logger. + + + + + + + + A that buffers the logs for enumeration. + + + + + + + + Enumerates the buffered logs. + + The callback function to receive the logs. + + + + A that writes logs into a stream. + + The stream. + The encoding. + + + + A that writes logs into a stream. + + The stream. + The encoding. + + + + Creates an instance of the class. + + The stream. + + + + Whether to flush the stream every time a log is written. + + + + + + + + Represents the method that will handle a log. + + The severity level. + The category. + The message. + + + diff --git a/Assets/Plugins/Cryville.Common.Logging.xml.meta b/Assets/Plugins/Cryville.Common.Logging.xml.meta new file mode 100644 index 0000000..2a0c9e9 --- /dev/null +++ b/Assets/Plugins/Cryville.Common.Logging.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 72ded0675457e0348809193a9c1092b5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: