Compare commits

..

2 Commits

Author SHA1 Message Date
fd36c8deca lm: Handle Tail flag in LogPacket (#4274)
* lm: Handle TailFlag in LogPacket

* Addresses feedback
2023-01-12 07:42:05 +01:00
70638340b3 Ava UI: Move Ava logging to Logger.Debug (#4255)
* Ava: Move Ava logging to Logger.Debug

Since #4231 we currently redirect Avalonia logs to our Logger, which is pretty nice. But since it uses our Logging level too, it now leads to a massive flood in our Log files.
To avoid that, I've included all `AvaLogLevel` to the log message, and make all Ava Logs using `Logger.Debug`.

* Logs errors to Error and other to Debug

* missing level

* keep var
2023-01-11 23:27:26 +01:00
3 changed files with 157 additions and 41 deletions

View File

@ -20,12 +20,12 @@ namespace Ryujinx.Ava.UI.Helpers
{ {
return level switch return level switch
{ {
AvaLogLevel.Verbose => RyuLogger.Trace, AvaLogLevel.Verbose => RyuLogger.Debug,
AvaLogLevel.Debug => RyuLogger.Debug, AvaLogLevel.Debug => RyuLogger.Debug,
AvaLogLevel.Information => RyuLogger.Info, AvaLogLevel.Information => RyuLogger.Debug,
AvaLogLevel.Warning => RyuLogger.Warning, AvaLogLevel.Warning => RyuLogger.Debug,
AvaLogLevel.Error => RyuLogger.Error, AvaLogLevel.Error => RyuLogger.Error,
AvaLogLevel.Fatal => RyuLogger.Notice, AvaLogLevel.Fatal => RyuLogger.Error,
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null) _ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
}; };
} }
@ -37,34 +37,38 @@ namespace Ryujinx.Ava.UI.Helpers
public void Log(AvaLogLevel level, string area, object source, string messageTemplate) public void Log(AvaLogLevel level, string area, object source, string messageTemplate)
{ {
GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(area, messageTemplate, source, null)); GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, null));
} }
public void Log<T0>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0) public void Log<T0>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0)
{ {
GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(area, messageTemplate, source, new object[] { propertyValue0 })); GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0 }));
} }
public void Log<T0, T1>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1) public void Log<T0, T1>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
{ {
GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(area, messageTemplate, source, new object[] { propertyValue0, propertyValue1 })); GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0, propertyValue1 }));
} }
public void Log<T0, T1, T2>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) public void Log<T0, T1, T2>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2)
{ {
GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(area, messageTemplate, source, new object[] { propertyValue0, propertyValue1, propertyValue2 })); GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0, propertyValue1, propertyValue2 }));
} }
public void Log(AvaLogLevel level, string area, object source, string messageTemplate, params object[] propertyValues) public void Log(AvaLogLevel level, string area, object source, string messageTemplate, params object[] propertyValues)
{ {
GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(area, messageTemplate, source, propertyValues)); GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, propertyValues));
} }
private static string Format(string area, string template, object source, object[] v) private static string Format(AvaLogLevel level, string area, string template, object source, object[] v)
{ {
var result = new StringBuilder(); var result = new StringBuilder();
var r = new CharacterReader(template.AsSpan()); var r = new CharacterReader(template.AsSpan());
var i = 0; int i = 0;
result.Append('[');
result.Append(level);
result.Append("] ");
result.Append('['); result.Append('[');
result.Append(area); result.Append(area);

View File

@ -1,6 +1,7 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.LogManager.Types;
using Ryujinx.Horizon.Sdk.Lm; using Ryujinx.Horizon.Sdk.Lm;
using Ryujinx.Horizon.Sdk.Sf; using Ryujinx.Horizon.Sdk.Sf;
using Ryujinx.Horizon.Sdk.Sf.Hipc; using Ryujinx.Horizon.Sdk.Sf.Hipc;
@ -13,13 +14,19 @@ namespace Ryujinx.Horizon.LogManager.Ipc
{ {
partial class LmLogger : ILmLogger partial class LmLogger : ILmLogger
{ {
private const int MessageLengthLimit = 5000;
private readonly LogService _log; private readonly LogService _log;
private readonly ulong _pid; private readonly ulong _pid;
private LogPacket _logPacket;
public LmLogger(LogService log, ulong pid) public LmLogger(LogService log, ulong pid)
{ {
_log = log; _log = log;
_pid = pid; _pid = pid;
_logPacket = new LogPacket();
} }
[CmifCommand(0)] [CmifCommand(0)]
@ -30,7 +37,12 @@ namespace Ryujinx.Horizon.LogManager.Ipc
return Result.Success; return Result.Success;
} }
Logger.Guest?.Print(LogClass.ServiceLm, LogImpl(message)); if (LogImpl(message))
{
Logger.Guest?.Print(LogClass.ServiceLm, _logPacket.ToString());
_logPacket = new LogPacket();
}
return Result.Success; return Result.Success;
} }
@ -60,58 +72,86 @@ namespace Ryujinx.Horizon.LogManager.Ipc
return true; return true;
} }
private static string LogImpl(ReadOnlySpan<byte> message) private bool LogImpl(ReadOnlySpan<byte> message)
{ {
SpanReader reader = new(message); SpanReader reader = new(message);
LogPacketHeader header = reader.Read<LogPacketHeader>(); LogPacketHeader header = reader.Read<LogPacketHeader>();
StringBuilder builder = new();
builder.AppendLine($"Guest Log:\n Log level: {header.Severity}"); bool isHeadPacket = (header.Flags & LogPacketFlags.IsHead) != 0;
bool isTailPacket = (header.Flags & LogPacketFlags.IsTail) != 0;
_logPacket.Severity = header.Severity;
while (reader.Length > 0) while (reader.Length > 0)
{ {
int type = ReadUleb128(ref reader); int type = ReadUleb128(ref reader);
int size = ReadUleb128(ref reader); int size = ReadUleb128(ref reader);
LogDataChunkKey field = (LogDataChunkKey)type; LogDataChunkKey key = (LogDataChunkKey)type;
string fieldStr; if (key == LogDataChunkKey.Start)
if (field == LogDataChunkKey.Start)
{ {
reader.Skip(size); reader.Skip(size);
continue; continue;
} }
else if (field == LogDataChunkKey.Stop) else if (key == LogDataChunkKey.Stop)
{ {
break; break;
} }
else if (field == LogDataChunkKey.Line) else if (key == LogDataChunkKey.Line)
{ {
fieldStr = $"{field}: {reader.Read<int>()}"; _logPacket.Line = reader.Read<int>();
} }
else if (field == LogDataChunkKey.DropCount) else if (key == LogDataChunkKey.DropCount)
{ {
fieldStr = $"{field}: {reader.Read<long>()}"; _logPacket.DropCount = reader.Read<long>();
} }
else if (field == LogDataChunkKey.Time) else if (key == LogDataChunkKey.Time)
{ {
fieldStr = $"{field}: {reader.Read<long>()}s"; _logPacket.Time = reader.Read<long>();
} }
else if (field < LogDataChunkKey.Count) else if (key == LogDataChunkKey.Message)
{ {
fieldStr = $"{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'"; string text = Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd();
if (isHeadPacket && isTailPacket)
{
_logPacket.Message = text;
} }
else else
{ {
fieldStr = $"Field{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'"; _logPacket.Message += text;
if (_logPacket.Message.Length >= MessageLengthLimit)
{
isTailPacket = true;
}
}
}
else if (key == LogDataChunkKey.Filename)
{
_logPacket.Filename = Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd();
}
else if (key == LogDataChunkKey.Function)
{
_logPacket.Function = Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd();
}
else if (key == LogDataChunkKey.Module)
{
_logPacket.Module = Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd();
}
else if (key == LogDataChunkKey.Thread)
{
_logPacket.Thread = Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd();
}
else if (key == LogDataChunkKey.ProgramName)
{
_logPacket.ProgramName = Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd();
}
} }
builder.AppendLine($" {fieldStr}"); return isTailPacket;
}
return builder.ToString();
} }
private static int ReadUleb128(ref SpanReader reader) private static int ReadUleb128(ref SpanReader reader)

View File

@ -0,0 +1,72 @@
using Ryujinx.Horizon.Sdk.Diag;
using System.Text;
namespace Ryujinx.Horizon.LogManager.Types
{
struct LogPacket
{
public string Message;
public int Line;
public string Filename;
public string Function;
public string Module;
public string Thread;
public long DropCount;
public long Time;
public string ProgramName;
public LogSeverity Severity;
public override string ToString()
{
StringBuilder builder = new();
builder.AppendLine($"Guest Log:\n Log level: {Severity}");
if (Time > 0)
{
builder.AppendLine($" Time: {Time}s");
}
if (DropCount > 0)
{
builder.AppendLine($" DropCount: {DropCount}");
}
if (!string.IsNullOrEmpty(ProgramName))
{
builder.AppendLine($" ProgramName: {ProgramName}");
}
if (!string.IsNullOrEmpty(Module))
{
builder.AppendLine($" Module: {Module}");
}
if (!string.IsNullOrEmpty(Thread))
{
builder.AppendLine($" Thread: {Thread}");
}
if (!string.IsNullOrEmpty(Filename))
{
builder.AppendLine($" Filename: {Filename}");
}
if (Line > 0)
{
builder.AppendLine($" Line: {Line}");
}
if (!string.IsNullOrEmpty(Function))
{
builder.AppendLine($" Function: {Function}");
}
if (!string.IsNullOrEmpty(Message))
{
builder.AppendLine($" Message: {Message}");
}
return builder.ToString();
}
}
}