mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-07 22:08:34 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
216 lines
5.3 KiB
C#
216 lines
5.3 KiB
C#
using NLog;
|
|
using System.Threading.Channels;
|
|
|
|
namespace Sandbox.Diagnostics;
|
|
|
|
internal static partial class Logging
|
|
{
|
|
static bool _initialized;
|
|
internal static void InitializeConfig()
|
|
{
|
|
if ( _initialized )
|
|
return;
|
|
|
|
_initialized = true;
|
|
|
|
var config = new NLog.Config.LoggingConfiguration();
|
|
var game_target = new GameLog();
|
|
|
|
NLog.LogManager.Setup().SetupExtensions( s =>
|
|
{
|
|
s.RegisterLayoutRenderer( "nicestack", ( logEvent ) =>
|
|
{
|
|
var frames = logEvent.StackTrace.GetFrames().Skip( 1 ).Take( 10 ).Where( x => x.GetMethod().DeclaringType.Name != "Logger" );
|
|
var stack = string.Join( "\n", frames.Select( x => $"\t\t{x.GetMethod()?.DeclaringType?.Name}.{x.GetMethod()?.Name} - {x.GetFileName()}:{x.GetFileLineNumber()}" ) );
|
|
if ( stack.StartsWith( "\t\tEngineLoop.Print - " ) ) return "";
|
|
|
|
return $"\n{stack}\n";
|
|
} );
|
|
} );
|
|
|
|
var appName = Process.GetCurrentProcess().ProcessName.Split( '.' )[0];
|
|
|
|
var gamePath = System.Environment.GetEnvironmentVariable( "FACEPUNCH_ENGINE", EnvironmentVariableTarget.User );
|
|
gamePath ??= AppContext.BaseDirectory;
|
|
|
|
var file_target = new NLog.Targets.FileTarget
|
|
{
|
|
FileName = System.IO.Path.Combine( gamePath, $"logs/{appName}.log" ),
|
|
ArchiveOldFileOnStartup = true,
|
|
OpenFileCacheSize = 10,
|
|
MaxArchiveFiles = 10,
|
|
KeepFileOpen = true,
|
|
|
|
|
|
//DeleteOldFileOnStartup = true,
|
|
//Layout = "${date:format=yyyy/MM/dd HH\\:mm\\:ss.ffff}\t[${logger}] ${message}\t${exception:format=ToString}${nicestack}"
|
|
Layout = "${date:format=yyyy/MM/dd HH\\:mm\\:ss.ffff}\t[${logger}] ${message}\t${exception:format=ToString}"
|
|
};
|
|
|
|
//
|
|
// Targets
|
|
//
|
|
config.AddTarget( "file", file_target );
|
|
config.AddTarget( "console", game_target );
|
|
//config.AddTarget( "null", new NLog.Targets.NullTarget() );
|
|
|
|
config.LoggingRules.Clear();
|
|
|
|
//
|
|
// Create a logging rule that captures everything
|
|
//
|
|
{
|
|
var rule = new NLog.Config.LoggingRule( "global" );
|
|
rule.LoggerNamePattern = "*";
|
|
rule.EnableLoggingForLevels( NLog.LogLevel.Trace, NLog.LogLevel.Fatal );
|
|
rule.Targets.Add( file_target );
|
|
rule.Targets.Add( game_target );
|
|
//rule.Filters.Add( new WhenMethodFilter( TestLogFilter ) );
|
|
|
|
config.LoggingRules.Add( rule );
|
|
}
|
|
|
|
NLog.LogManager.Configuration = config;
|
|
|
|
//
|
|
// When we quit, shut nlog down
|
|
//
|
|
AppDomain.CurrentDomain.ProcessExit += ( x, y ) =>
|
|
{
|
|
NLog.LogManager.Shutdown();
|
|
};
|
|
|
|
SetRule( "*", LogLevel.Info );
|
|
}
|
|
|
|
//
|
|
// Garry: I imagine at some point we'll expose rules in a way where we can choose which systems
|
|
// are which levels. Right now that seems like overkill - so I'm just exposing the ability to change
|
|
// verbosity globally. This is complicated by the fact that I want to pull in all the engine logging
|
|
// system too - hence the OnRulesChanged callback, so we can call shit in the sandbox.engine.dll on change.
|
|
//
|
|
|
|
public static LogLevel GetDefaultLevel()
|
|
{
|
|
if ( Rules.TryGetValue( "*", out var r ) )
|
|
return r;
|
|
|
|
return LogLevel.Info;
|
|
}
|
|
|
|
public static void SetRule( string wildcard, LogLevel minimumLevel )
|
|
{
|
|
Rules[wildcard] = minimumLevel;
|
|
RuleCache.Clear();
|
|
}
|
|
|
|
internal static Dictionary<string, LogLevel> Rules = new();
|
|
|
|
static Dictionary<int, bool> RuleCache = new();
|
|
|
|
/// <summary>
|
|
/// Return true if we should print this log entry. Use a cache to avoid craziness.
|
|
/// </summary>
|
|
public static bool ShouldLog( string loggerName, LogLevel level )
|
|
{
|
|
lock ( RuleCache )
|
|
{
|
|
var hash = HashCode.Combine( loggerName, level );
|
|
if ( RuleCache.TryGetValue( hash, out var should ) )
|
|
return should;
|
|
|
|
should = WorkOutShouldLog( loggerName, level );
|
|
RuleCache[hash] = should;
|
|
|
|
return should;
|
|
}
|
|
}
|
|
|
|
static bool WorkOutShouldLog( string loggerName, LogLevel level )
|
|
{
|
|
foreach ( var v in Rules.OrderByDescending( x => x.Key.Length ) )
|
|
{
|
|
if ( loggerName.WildcardMatch( v.Key ) && level >= v.Value )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Todo - turn off logging?
|
|
public static bool Enabled { get; set; } = true;
|
|
internal static bool PrintToConsole { get; set; } = true;
|
|
|
|
internal static event Action<LogEvent> OnMessage;
|
|
internal static Action<Exception> OnException;
|
|
|
|
static Channel<LogEvent> QueuedMessages = Channel.CreateUnbounded<LogEvent>();
|
|
|
|
private static int callDepth = 0;
|
|
|
|
internal static void Write( in LogEvent e )
|
|
{
|
|
if ( ThreadSafe.IsMainThread && callDepth < 3 )
|
|
{
|
|
try
|
|
{
|
|
callDepth++;
|
|
OnMessage?.Invoke( e );
|
|
}
|
|
finally
|
|
{
|
|
callDepth--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
QueuedMessages.Writer.TryWrite( e );
|
|
}
|
|
}
|
|
|
|
internal static void PushQueuedMessages()
|
|
{
|
|
ThreadSafe.AssertIsMainThread();
|
|
|
|
while ( QueuedMessages.Reader.TryRead( out var msg ) )
|
|
{
|
|
try
|
|
{
|
|
OnMessage?.Invoke( msg );
|
|
}
|
|
catch ( System.Exception e )
|
|
{
|
|
Log.Error( e );
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Logger GetLogger( string name = null )
|
|
{
|
|
if ( name == null )
|
|
{
|
|
var frame = new System.Diagnostics.StackFrame( 1, false );
|
|
var method = frame.GetMethod();
|
|
name = method.DeclaringType.Name;
|
|
}
|
|
|
|
return new Logger( name );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Keep a list of loggers
|
|
/// </summary>
|
|
public static HashSet<string> Loggers = new( StringComparer.OrdinalIgnoreCase );
|
|
|
|
internal static void RegisterEngineLogger( int id, string v )
|
|
{
|
|
v = $"engine/{v}";
|
|
Loggers.Add( v );
|
|
}
|
|
|
|
internal static void RegisterLogger( string name )
|
|
{
|
|
Loggers.Add( name );
|
|
}
|
|
}
|