Add file logging and handle unhandled exceptions (#558)

* add unhandled exception handler

* added file logging

* add option in config

* consolidated console and file log
This commit is contained in:
emmauss 2019-01-31 04:49:15 +02:00 committed by gdkchan
parent c1bdf19061
commit c81abdde4c
6 changed files with 69 additions and 9 deletions

View File

@ -5,6 +5,7 @@ namespace Ryujinx.Common.Logging
Audio, Audio,
Cpu, Cpu,
Font, Font,
Emulation,
Gpu, Gpu,
Hid, Hid,
Kernel, Kernel,

View File

@ -16,6 +16,8 @@ namespace Ryujinx.Common.Logging
public static event EventHandler<LogEventArgs> Updated; public static event EventHandler<LogEventArgs> Updated;
public static bool EnableFileLog { get; set; }
static Logger() static Logger()
{ {
m_EnabledLevels = new bool[Enum.GetNames(typeof(LogLevel)).Length]; m_EnabledLevels = new bool[Enum.GetNames(typeof(LogLevel)).Length];

View File

@ -62,6 +62,8 @@ namespace Ryujinx
} }
} }
Logger.EnableFileLog = Convert.ToBoolean(parser.Value("Enable_File_Log"));
SystemLanguage SetLanguage = Enum.Parse<SystemLanguage>(parser.Value("System_Language")); SystemLanguage SetLanguage = Enum.Parse<SystemLanguage>(parser.Value("System_Language"));
device.System.State.SetLanguage(SetLanguage); device.System.State.SetLanguage(SetLanguage);
@ -118,7 +120,6 @@ namespace Ryujinx
}); });
NpadController = new NpadController( NpadController = new NpadController(
Convert.ToBoolean(parser.Value("GamePad_Enable")), Convert.ToBoolean(parser.Value("GamePad_Enable")),
Convert.ToInt32 (parser.Value("GamePad_Index")), Convert.ToInt32 (parser.Value("GamePad_Index")),
(float)Convert.ToDouble (parser.Value("GamePad_Deadzone"), CultureInfo.InvariantCulture), (float)Convert.ToDouble (parser.Value("GamePad_Deadzone"), CultureInfo.InvariantCulture),

View File

@ -22,7 +22,10 @@ namespace Ryujinx
Config.Read(device); Config.Read(device);
Logger.Updated += ConsoleLog.Log; Logger.Updated += Log.LogMessage;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
if (args.Length == 1) if (args.Length == 1)
{ {
@ -87,6 +90,23 @@ namespace Ryujinx
audioOut.Dispose(); audioOut.Dispose();
} }
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Log.Close();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
Logger.PrintError(LogClass.Emulation, $"Unhandled exception caught: {exception}");
if (e.IsTerminating)
{
Log.Close();
}
}
/// <summary> /// <summary>
/// Picks an <see cref="IAalOutput"/> audio output renderer supported on this machine /// Picks an <see cref="IAalOutput"/> audio output renderer supported on this machine
/// </summary> /// </summary>

View File

@ -22,6 +22,9 @@ Logging_Enable_Error = true
#Filtered log classes, seperated by ", ", eg. `Logging_Filtered_Classes = Loader, ServiceFS` #Filtered log classes, seperated by ", ", eg. `Logging_Filtered_Classes = Loader, ServiceFS`
Logging_Filtered_Classes = Logging_Filtered_Classes =
#Enable file logging
Enable_File_Log = true
#System Language list: https://gist.github.com/HorrorTroll/b6e4a88d774c3c9b3bdf54d79a7ca43b #System Language list: https://gist.github.com/HorrorTroll/b6e4a88d774c3c9b3bdf54d79a7ca43b
#Change System Language #Change System Language
System_Language = AmericanEnglish System_Language = AmericanEnglish

View File

@ -1,22 +1,27 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
namespace Ryujinx namespace Ryujinx
{ {
static class ConsoleLog static class Log
{ {
private static readonly string _path;
private static StreamWriter _logWriter;
private static Thread _messageThread; private static Thread _messageThread;
private static BlockingCollection<LogEventArgs> _messageQueue; private static BlockingCollection<LogEventArgs> _messageQueue;
private static Dictionary<LogLevel, ConsoleColor> _logColors; private static Dictionary<LogLevel, ConsoleColor> _logColors;
static ConsoleLog() static Log()
{ {
_logColors = new Dictionary<LogLevel, ConsoleColor>() _logColors = new Dictionary<LogLevel, ConsoleColor>()
{ {
@ -47,6 +52,13 @@ namespace Ryujinx
} }
}); });
_path = Path.Combine(Environment.CurrentDirectory, "Ryujinx.log");
if (Logger.EnableFileLog)
{
_logWriter = new StreamWriter(File.Open(_path,FileMode.Create, FileAccess.Write));
}
_messageThread.IsBackground = true; _messageThread.IsBackground = true;
_messageThread.Start(); _messageThread.Start();
} }
@ -82,26 +94,47 @@ namespace Ryujinx
} }
} }
string message = sb.ToString();
if (_logColors.TryGetValue(e.Level, out ConsoleColor color)) if (_logColors.TryGetValue(e.Level, out ConsoleColor color))
{ {
Console.ForegroundColor = color; Console.ForegroundColor = color;
Console.WriteLine(sb.ToString()); Console.WriteLine(message);
Console.ResetColor(); Console.ResetColor();
} }
else else
{ {
Console.WriteLine(sb.ToString()); Console.WriteLine(message);
}
if (Logger.EnableFileLog)
{
_logWriter.WriteLine(message);
} }
} }
public static void Log(object sender, LogEventArgs e) public static void LogMessage(object sender, LogEventArgs e)
{ {
if (!_messageQueue.IsAddingCompleted) if (!_messageQueue.IsAddingCompleted)
{ {
_messageQueue.Add(e); _messageQueue.Add(e);
} }
} }
public static void Close()
{
_messageQueue.CompleteAdding();
_messageThread.Join();
if (Logger.EnableFileLog)
{
_logWriter.Flush();
_logWriter.Close();
_logWriter.Dispose();
}
}
} }
} }