using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using UnityEngine; using Debug = UnityEngine.Debug; namespace Jovian.Logger { internal class LoggerSettingsData { public bool enableGlobalLogging = true; public Filters[] globalFilters = Array.Empty(); public LoggerColors loggerColors = new(); public bool isLoaded = false; #if UNITY_EDITOR public List LocalFilters { get; set; } = new(); #endif } internal static class InternalLogger { private static readonly LoggerSettingsData loggerSettingsData = new(); private static bool enableGlobalLogging = true; internal static bool IsMainThread => LoggerUtility.IsMainThread; internal static void LoadSettings() { var loggerSettings = LoggerUtility.LoadCustomLoggerSettings(); if(!loggerSettings) { return; } var colors = loggerSettings.loggerColors; loggerSettingsData.globalFilters = loggerSettings.globalFilters; enableGlobalLogging = loggerSettings.enableGlobalLogging; loggerSettingsData.loggerColors.infoColor = colors.infoColor; loggerSettingsData.loggerColors.warningColor = colors.warningColor; loggerSettingsData.loggerColors.errorColor = colors.errorColor; loggerSettingsData.loggerColors.assertColor = colors.assertColor; loggerSettingsData.loggerColors.exceptionColor = colors.exceptionColor; loggerSettingsData.loggerColors.spamColor = colors.spamColor; #if UNITY_EDITOR if(!Environment.CommandLine.Contains("-batchmode")) { loggerSettingsData.LocalFilters = loggerSettings.LocalFilters; } else { loggerSettings.LocalFilters.Clear(); } Debug.Log("[CustomLogger] Local Filters: " + loggerSettingsData.LocalFilters.Count); #endif loggerSettingsData.isLoaded = true; Debug.Log("[CustomLogger] Global Filters: " + loggerSettingsData.globalFilters.Length); Debug.Log("[CustomLogger] Settings loaded"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void LogInternal(JovianLogType jovianLogType, LogCategory logcat, string classType, string msg, Color color, string args = "", UnityEngine.Object reference = null) { if(!enableGlobalLogging) { return; } if(!loggerSettingsData.isLoaded && IsMainThread) { LoadSettings(); } // Check if any filters are present and apply filters foreach(var filter in loggerSettingsData.globalFilters) { if(filter == null) { continue; } if((filter.jovianLogType < jovianLogType || !filter.logCategory.HasFlag(logcat)) || !FilterCaller(filter.callerNames, filter.callerListingType)) { return; } } #if UNITY_EDITOR if(!Environment.CommandLine.Contains("-batchmode")) { foreach(var filter in loggerSettingsData.LocalFilters) { if(filter == null) { continue; } if((filter.jovianLogType < jovianLogType || !filter.logCategory.HasFlag(logcat)) || !FilterCaller(filter.callerNames, filter.callerListingType)) { return; } } } else { if(jovianLogType == JovianLogType.Spam) { return; } } #endif StringBuilder sb = new(500); switch(jovianLogType) { case JovianLogType.Spam: sb.Append("SPAM -> "); break; case JovianLogType.Info: sb.Append("INFO -> "); break; case JovianLogType.Warning: sb.Append("WARNING -> "); break; case JovianLogType.Error: sb.Append("ERROR -> "); break; case JovianLogType.Assert: sb.Append("ASSERT -> "); break; case JovianLogType.Exception: sb.Append("EXCEPTION -> "); break; default: return; } var isFrameCountEnabled = LoggerUtility.IsFrameCountEnabled; // As exceptions can be reported to Unity Exception tracking, we do not want frame numbers in the message. It will prevent Unity from grouping reports var logTypeShouldIncludeFrameCount = jovianLogType != JovianLogType.Exception; if(isFrameCountEnabled && logTypeShouldIncludeFrameCount) { sb.Append("F:"); sb.Append(LoggerUtility.FrameCount); sb.Append(" |"); } sb.Append(" ["); sb.Append(logcat); sb.Append("] "); sb.Append("["); sb.Append(classType); sb.Append("] "); sb.Append(msg); var message = sb.ToString(); LoggerUtility.FormattedLogCallback?.Invoke((jovianLogType, logcat, message)); #if UNITY_EDITOR //remove the color when not in the editor to avoid cluttering the log files if(!Environment.CommandLine.Contains("-batchmode") && IsMainThread) { message = $"{message}"; } #endif Debug.unityLogger.Log(LoggerUtility.GetLogType(jovianLogType), (object)message, reference); return; bool FilterCaller(List filterCallerNames, CallerListingType filterCallerListingType) { foreach(var caller in filterCallerNames) { if(!string.IsNullOrEmpty(caller)) { switch(filterCallerListingType) { case CallerListingType.Blacklist_Caller: return !classType.Contains(caller); case CallerListingType.Whitelist_Caller: return classType.Contains(caller); } } } return true; } } [Conditional("UNITY_EDITOR")] [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void LogSpam(string caller, string msg, LogCategory logcat, UnityEngine.Object reference = null) { LogInternal(JovianLogType.Spam, logcat, caller, msg, loggerSettingsData.loggerColors.spamColor, "spam", reference); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void LogInfo(string caller, string msg, LogCategory logcat, UnityEngine.Object reference = null) { LogInternal(JovianLogType.Info, logcat, caller, msg, loggerSettingsData.loggerColors.infoColor, "", reference); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void LogWarning(string classType, string msg, LogCategory logcat, UnityEngine.Object reference = null) { LogInternal(JovianLogType.Warning, logcat, classType, msg, loggerSettingsData.loggerColors.warningColor, "", reference); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void LogError(string caller, string msg, LogCategory logcat, UnityEngine.Object reference = null) { LogInternal(JovianLogType.Error, logcat, caller, msg, loggerSettingsData.loggerColors.errorColor, "", reference); } internal static void LogException(string caller, string msg, LogCategory logcat, UnityEngine.Object reference = null) { LogInternal(JovianLogType.Exception, logcat, caller, msg, loggerSettingsData.loggerColors.exceptionColor, "", reference); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void LogAssert(string caller, string msg, LogCategory logcat, UnityEngine.Object reference = null) { LogInternal(JovianLogType.Assert, logcat, caller, msg, loggerSettingsData.loggerColors.assertColor, "", reference); } } }