Files
UnrealEngine/Engine/Source/Programs/Horde/HordeServer.Shared/Utilities/StructuredRpcException.cs
2025-05-18 13:04:45 +08:00

86 lines
2.2 KiB
C#

// Copyright Epic Games, Inc. All Rights Reserved.
using System.Globalization;
using System.Text;
using Grpc.Core;
namespace HordeServer.Utilities
{
/// <summary>
/// Exception class designed to allow logging structured log messages
/// </summary>
public class StructuredRpcException : RpcException
{
/// <summary>
/// The format string with named parameters
/// </summary>
public string Format { get; }
/// <summary>
/// The argument list
/// </summary>
public object[] Args { get; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="statusCode">Status code to return</param>
/// <param name="format">The format string</param>
/// <param name="args">Arguments for the format string</param>
public StructuredRpcException(StatusCode statusCode, string format, params object[] args)
: base(new Status(statusCode, FormatMessage(format, args)))
{
Format = format;
Args = args;
}
/// <summary>
/// Replace named arguments in the format message with their values
/// </summary>
/// <param name="format"></param>
/// <param name="args"></param>
/// <returns></returns>
static string FormatMessage(string format, params object[] args)
{
string newFormat = ConvertToFormatString(format);
return String.Format(CultureInfo.CurrentCulture, newFormat, args);
}
/// <summary>
/// Converts a named parameter format string to a String.Format style string
/// </summary>
/// <param name="format"></param>
/// <returns></returns>
static string ConvertToFormatString(string format)
{
int argIdx = 0;
StringBuilder newFormat = new StringBuilder();
for (int idx = 0; idx < format.Length; idx++)
{
char character = format[idx];
newFormat.Append(character);
if (character == '{' && idx + 1 < format.Length)
{
char nextCharacter = format[idx + 1];
if ((nextCharacter >= 'a' && nextCharacter <= 'z') || (nextCharacter >= 'A' && nextCharacter <= 'Z') || nextCharacter == '_')
{
for (int endIdx = idx + 2; endIdx < format.Length; endIdx++)
{
if (format[endIdx] == ':' || format[endIdx] == '}')
{
newFormat.Append(argIdx++);
idx = endIdx - 1;
break;
}
}
}
}
}
return newFormat.ToString();
}
}
}