mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-18 03:09:45 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
232 lines
6.4 KiB
C#
232 lines
6.4 KiB
C#
using NLog;
|
|
using System.Web;
|
|
|
|
namespace Sandbox.Diagnostics;
|
|
|
|
[StackTraceHidden]
|
|
public class Logger
|
|
{
|
|
private NLog.Logger _log;
|
|
|
|
/// <summary>
|
|
/// Name of this logger.
|
|
/// </summary>
|
|
public string Name { get; protected set; }
|
|
|
|
public Logger( string name )
|
|
{
|
|
Logging.InitializeConfig();
|
|
|
|
Name = name;
|
|
_log = NLog.LogManager.GetLogger( name );
|
|
|
|
Logging.RegisterLogger( Name );
|
|
}
|
|
|
|
internal void DoInfo( FormattableString message ) => WriteToTargets( NLog.LogLevel.Info, null, message );
|
|
internal void DoTrace( FormattableString message ) => WriteToTargets( NLog.LogLevel.Trace, null, message );
|
|
internal void DoWarning( FormattableString message ) => WriteToTargets( NLog.LogLevel.Warn, null, message );
|
|
internal void DoError( FormattableString message ) => WriteToTargets( NLog.LogLevel.Error, null, message );
|
|
|
|
/// <inheritdoc cref="Info(object)"/>
|
|
public void Info( FormattableString message ) => DoInfo( message );
|
|
/// <inheritdoc cref="Trace(object)"/>
|
|
public void Trace( FormattableString message ) => DoTrace( message );
|
|
/// <inheritdoc cref="Warning(object)"/>
|
|
public void Warning( FormattableString message ) => DoWarning( message );
|
|
/// <inheritdoc cref="Error(object)"/>
|
|
public void Error( FormattableString message ) => DoError( message );
|
|
|
|
/// <inheritdoc cref="Error(Exception, object)"/>
|
|
public void Error( Exception exception, FormattableString message ) => WriteToTargets( NLog.LogLevel.Error, exception, message );
|
|
|
|
/// <summary>
|
|
/// Log an exception as an error, with given message override.
|
|
/// </summary>
|
|
/// <param name="exception">The exception to log.</param>
|
|
/// <param name="message">The text to override exceptions' message with in the log.</param>
|
|
public void Error( Exception exception, object message ) => Error( exception, $"{message}" );
|
|
|
|
/// <summary>
|
|
/// Log an exception as an error.
|
|
/// </summary>
|
|
/// <param name="exception">The exception to log.</param>
|
|
public void Error( Exception exception ) => WriteToTargets( NLog.LogLevel.Error, exception, $"{exception.Message}" );
|
|
|
|
/// <inheritdoc cref="Warning(Exception, object)"/>
|
|
public void Warning( Exception exception, FormattableString message ) => WriteToTargets( NLog.LogLevel.Warn, exception, message );
|
|
|
|
/// <summary>
|
|
/// Log an exception as a warning, with given message override.
|
|
/// </summary>
|
|
/// <param name="exception">The exception to log.</param>
|
|
/// <param name="message">The text to override exceptions' message with in the log.</param>
|
|
public void Warning( Exception exception, object message ) => Warning( exception, $"{message}" );
|
|
|
|
/// <summary>
|
|
/// Log some information. This is the default log severity level.
|
|
/// </summary>
|
|
/// <param name="message">The information to log.</param>
|
|
public void Info( object message )
|
|
{
|
|
if ( message is Exception ex )
|
|
{
|
|
Warning( ex, ex.Message );
|
|
return;
|
|
}
|
|
|
|
Info( $"{message}" );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Log some information. This is least severe log level.
|
|
/// </summary>
|
|
/// <param name="message">The information to log.</param>
|
|
public void Trace( object message )
|
|
{
|
|
if ( message is Exception ex )
|
|
{
|
|
Warning( ex, ex.Message );
|
|
return;
|
|
}
|
|
|
|
Trace( $"{message}" );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Log a warning. This is the second most severe log level.
|
|
/// </summary>
|
|
/// <param name="message">The warning to log.</param>
|
|
public void Warning( object message )
|
|
{
|
|
if ( message is Exception ex )
|
|
{
|
|
Warning( ex, ex.Message );
|
|
return;
|
|
}
|
|
|
|
Warning( $"{message}" );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Log an error. This is the most severe log level.
|
|
/// </summary>
|
|
/// <param name="message">The error to log.</param>
|
|
public void Error( object message )
|
|
{
|
|
if ( message is Exception ex )
|
|
{
|
|
Error( ex, ex.Message );
|
|
return;
|
|
}
|
|
|
|
Error( $"{message}" );
|
|
}
|
|
|
|
internal void WriteToTargets( NLog.LogLevel nlogLevel, Exception ex, FormattableString message, string name = null )
|
|
{
|
|
name ??= Name;
|
|
|
|
LogLevel level = nlogLevel.Ordinal switch
|
|
{
|
|
0 => LogLevel.Trace,
|
|
1 => LogLevel.Trace,
|
|
2 => LogLevel.Info,
|
|
3 => LogLevel.Warn,
|
|
4 => LogLevel.Error,
|
|
5 => LogLevel.Error,
|
|
_ => LogLevel.Info,
|
|
};
|
|
|
|
if ( !Logging.ShouldLog( name, level ) )
|
|
return;
|
|
|
|
var defaultMessage = message.ToString();
|
|
var arguments = new List<object>();
|
|
|
|
var htmlMessage = (string)WrapObject( message, arguments );
|
|
|
|
// Only show the first line in the console, but inspecting that line will show the rest
|
|
|
|
var firstLineBreakIndex = htmlMessage.IndexOf( "\n", StringComparison.Ordinal );
|
|
if ( firstLineBreakIndex > -1 )
|
|
{
|
|
htmlMessage = htmlMessage.Substring( 0, firstLineBreakIndex ).TrimEnd();
|
|
}
|
|
|
|
var logEvent = LogEventInfo.Create( nlogLevel, name, defaultMessage );
|
|
|
|
if ( ex != null )
|
|
{
|
|
logEvent.Exception = ex;
|
|
}
|
|
else
|
|
{
|
|
var stackTrace = new StackTrace( 0, true );
|
|
logEvent.SetStackTrace( stackTrace, 0 );
|
|
}
|
|
|
|
_log.Log( logEvent );
|
|
|
|
string stacktrace = null;
|
|
|
|
if ( logEvent.Exception != null )
|
|
{
|
|
stacktrace = GameLog.WriteExceptionDetails( logEvent.Exception );
|
|
}
|
|
|
|
if ( stacktrace == null && logEvent.StackTrace != null )
|
|
{
|
|
stacktrace = logEvent.StackTrace.ToString();
|
|
}
|
|
|
|
var e = new LogEvent
|
|
{
|
|
Level = level,
|
|
Logger = logEvent.LoggerName,
|
|
Message = defaultMessage,
|
|
Exception = ex,
|
|
HtmlMessage = htmlMessage,
|
|
Stack = stacktrace,
|
|
Time = DateTime.Now,
|
|
Arguments = arguments.ToArray()
|
|
};
|
|
|
|
Logging.Write( e );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Wrap / escape an object for html log messages. Inspectable objects
|
|
/// will be wrapped in a link, and added to <paramref name="outArgs"/>.
|
|
/// The link will index into <paramref name="outArgs"/>. <see cref="FormattableString"/>s
|
|
/// will recurse into <see cref="WrapObject"/>, so their arguments can also be inspected.
|
|
/// </summary>
|
|
/// <param name="o">Object to wrap</param>
|
|
/// <param name="outArgs">Inspectable objects will be added here</param>
|
|
/// <returns>Html-wrapped object. Either a string or a primitive.</returns>
|
|
static object WrapObject( object o, List<object> outArgs )
|
|
{
|
|
if ( o == null ) return "null";
|
|
|
|
if ( o is FormattableString formattable )
|
|
{
|
|
var wrappedArgs = formattable.GetArguments()
|
|
.Select( x => WrapObject( x, outArgs ) )
|
|
.ToArray();
|
|
|
|
return string.Format( formattable.Format, wrappedArgs );
|
|
}
|
|
|
|
if ( o is string ) return HttpUtility.HtmlEncode( o );
|
|
|
|
var t = o.GetType();
|
|
if ( t.IsPrimitive ) return o;
|
|
|
|
var index = outArgs.Count;
|
|
outArgs.Add( o );
|
|
|
|
return $"<a href=\"arg:{index}\" style=\"\">{HttpUtility.HtmlEncode( o.ToString() )}</a>";
|
|
}
|
|
|
|
}
|