using System; using System.Globalization; using System.IO; using System.Threading; namespace StardewModdingAPI { /// /// Class to organize logging calls. /// public class Log { private static StreamWriter _logStream; private static string _logPath; /// /// Set up the logging stream /// /// public static void Initialize(string logPath) { _logPath = logPath; var logFile = string.Format("{0}\\MODDED_ProgramLog.Log_LATEST.txt", logPath); try { _logStream = new StreamWriter(logFile, false); } catch (Exception) { // TODO: not use general exception Error("Could not initialize LogStream - Logging is disabled"); } } /// /// Print provided parameters to the console/file as applicable /// /// Desired message /// When true, writes to ONLY console and not the log file. /// Additional params to be added to the message private static void PrintLog(object message, bool disableLogging, params object[] values) { string logOutput = $"[{DateTime.Now.ToLongTimeString()}] {string.Format(message.ToString(), values)}"; Console.WriteLine(logOutput); if (_logStream != null && !disableLogging) { _logStream.WriteLine(logOutput); _logStream.Flush(); } } /// /// Successful message to display to console and logging. /// /// /// public static void Success(object message, params object[] values) { Console.ForegroundColor = ConsoleColor.Green; PrintLog(message?.ToString(), false, values); Console.ForegroundColor = ConsoleColor.Gray; } /// /// Generic comment to display to console and logging. /// /// /// public static void Verbose(object message, params object[] values) { Console.ForegroundColor = ConsoleColor.Gray; PrintLog(message?.ToString(), false, values); Console.ForegroundColor = ConsoleColor.Gray; } /// /// Additional comment to display to console and logging. /// /// /// public static void Comment(object message, params object[] values) { Console.ForegroundColor = ConsoleColor.Yellow; PrintLog(message?.ToString(), false, values); Console.ForegroundColor = ConsoleColor.Gray; } /// /// Message for only console. Does not appear in logging. /// /// /// public static void Info(object message, params object[] values) { Console.ForegroundColor = ConsoleColor.Gray; PrintLog(message?.ToString(), true, values); Console.ForegroundColor = ConsoleColor.Gray; } /// /// Important message indicating an error. /// /// /// public static void Error(object message, params object[] values) { Console.ForegroundColor = ConsoleColor.Red; PrintLog(message?.ToString(), false, values); Console.ForegroundColor = ConsoleColor.Gray; } /// /// A message displayed only while in DEBUG mode /// /// /// public static void Debug(object message, params object[] values) { #if DEBUG Console.ForegroundColor = ConsoleColor.Yellow; Log.PrintLog(message.ToString(), false, values); Console.ForegroundColor = ConsoleColor.Gray; #endif } /// /// Catch unhandled exception from the application /// /// Should be moved out of here if we do more than just log the exception. public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine("An exception has been caught"); File.WriteAllText(_logPath + "\\MODDED_ErrorLog.Log_" + DateTime.UtcNow.Ticks + ".txt", e.ExceptionObject.ToString()); } /// /// Catch thread exception from the application /// /// Should be moved out of here if we do more than just log the exception. public static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { Console.WriteLine("A thread exception has been caught"); File.WriteAllText(_logPath + "\\MODDED_ErrorLog.Log_" + Extensions.Random.Next(100000000, 999999999) + ".txt", e.Exception.ToString()); } // I'm including the following for now because they have a lot of references with different uses. // They should be removed since they do not provide any insight into actual problems, and other log methods should be used. public static void LogValueNotSpecified() { Error(" must be specified"); } public static void LogObjectValueNotSpecified() { Error(" and must be specified"); } public static void LogValueInvalid() { Error(" is invalid"); } public static void LogObjectInvalid() { Error(" is invalid"); } public static void LogValueNotInt32() { Error(" must be a whole number (Int32)"); } } }