add proper logger, saves to file as well
This commit is contained in:
parent
a2e27effff
commit
239c4fca32
|
@ -1,101 +0,0 @@
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace AscNet.Common.Util
|
|
||||||
{
|
|
||||||
// TODO: Extend, add file logging, correct some behavior, ensure proper formatting
|
|
||||||
public class Logger
|
|
||||||
{
|
|
||||||
public static readonly Logger c = new(nameof(AscNet), ConsoleColor.DarkRed);
|
|
||||||
private readonly string _name;
|
|
||||||
private readonly bool TraceOnError;
|
|
||||||
private readonly ConsoleColor _color;
|
|
||||||
|
|
||||||
public Logger(string name, ConsoleColor color = ConsoleColor.Cyan, bool traceOnError = true)
|
|
||||||
{
|
|
||||||
_name = name;
|
|
||||||
_color = color;
|
|
||||||
TraceOnError = traceOnError;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(params string[] message)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
Console.Write(DateTime.Now.ToString("HH:mm:ss "));
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("<");
|
|
||||||
Console.ForegroundColor = _color;
|
|
||||||
Console.Write(_name);
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("> ");
|
|
||||||
Console.WriteLine(string.Join("\t", message));
|
|
||||||
Console.ResetColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Warn(params string[] message)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
Console.Write(DateTime.Now.ToString("HH:mm:ss "));
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("<");
|
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
||||||
Console.Write(_name);
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("> ");
|
|
||||||
Console.WriteLine(string.Join("\t", message));
|
|
||||||
Console.ResetColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Trail(params string[] msg)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
|
||||||
Console.WriteLine($"\t└── {string.Join(' ', msg)}");
|
|
||||||
Console.ResetColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Error(params string[] message)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
Console.Write(DateTime.Now.ToString("HH:mm:ss "));
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("<");
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Console.Write(_name);
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("> ");
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
if (TraceOnError)
|
|
||||||
Console.BackgroundColor = ConsoleColor.DarkRed;
|
|
||||||
Console.WriteLine(string.Join("\t", message));
|
|
||||||
Console.ResetColor();
|
|
||||||
#if DEBUG
|
|
||||||
StackTrace trace = new(true);
|
|
||||||
if (TraceOnError)
|
|
||||||
Trail(trace.ToString());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Debug(params string[] message)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
Console.Write(DateTime.Now.ToString("HH:mm:ss "));
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("<");
|
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
|
||||||
Console.Write(_name);
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.Write("> ");
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
Console.BackgroundColor = ConsoleColor.DarkMagenta;
|
|
||||||
Console.WriteLine(string.Join("\t", message));
|
|
||||||
Console.ResetColor();
|
|
||||||
Console.BackgroundColor = ConsoleColor.Black;
|
|
||||||
|
|
||||||
StackTrace trace = new(true);
|
|
||||||
if (TraceOnError)
|
|
||||||
Trail(trace.ToString());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\AscNet.Common\AscNet.Common.csproj" />
|
<ProjectReference Include="..\AscNet.Common\AscNet.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\AscNet.Logging\AscNet.Logging.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using AscNet.Common.Util;
|
using AscNet.Logging;
|
||||||
using MessagePack;
|
using MessagePack;
|
||||||
|
|
||||||
namespace AscNet.GameServer
|
namespace AscNet.GameServer
|
||||||
|
@ -92,7 +92,9 @@ namespace AscNet.GameServer
|
||||||
public static class PacketFactory
|
public static class PacketFactory
|
||||||
{
|
{
|
||||||
public static readonly Dictionary<string, RequestPacketHandlerDelegate> ReqHandlers = new();
|
public static readonly Dictionary<string, RequestPacketHandlerDelegate> ReqHandlers = new();
|
||||||
static readonly Logger c = new("Factory", ConsoleColor.Yellow);
|
|
||||||
|
// TODO: Configure based on session?
|
||||||
|
static readonly Logger log = new(typeof(PacketFactory), LogLevel.DEBUG, LogLevel.DEBUG);
|
||||||
|
|
||||||
public static void LoadPacketHandlers()
|
public static void LoadPacketHandlers()
|
||||||
{
|
{
|
||||||
|
@ -101,7 +103,7 @@ namespace AscNet.GameServer
|
||||||
|
|
||||||
private static void LoadRequestPacketHandlers()
|
private static void LoadRequestPacketHandlers()
|
||||||
{
|
{
|
||||||
c.Log("Loading Packet Handlers...");
|
log.Info("Loading Packet Handlers...");
|
||||||
|
|
||||||
IEnumerable<Type> classes = from t in Assembly.GetExecutingAssembly().GetTypes()
|
IEnumerable<Type> classes = from t in Assembly.GetExecutingAssembly().GetTypes()
|
||||||
select t;
|
select t;
|
||||||
|
@ -112,11 +114,11 @@ namespace AscNet.GameServer
|
||||||
if (attr == null || ReqHandlers.ContainsKey(attr.Name)) continue;
|
if (attr == null || ReqHandlers.ContainsKey(attr.Name)) continue;
|
||||||
ReqHandlers.Add(attr.Name, (RequestPacketHandlerDelegate)Delegate.CreateDelegate(typeof(RequestPacketHandlerDelegate), method));
|
ReqHandlers.Add(attr.Name, (RequestPacketHandlerDelegate)Delegate.CreateDelegate(typeof(RequestPacketHandlerDelegate), method));
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
c.Log($"Loaded {method.Name}");
|
log.Info($"Loaded {method.Name}");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Log("Finished Loading Packet Handlers");
|
log.Info("Finished Loading Packet Handlers");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RequestPacketHandlerDelegate? GetRequestPacketHandler(string name)
|
public static RequestPacketHandlerDelegate? GetRequestPacketHandler(string name)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using AscNet.Common.Util;
|
using AscNet.Logging;
|
||||||
|
|
||||||
namespace AscNet.GameServer
|
namespace AscNet.GameServer
|
||||||
{
|
{
|
||||||
public class Server
|
public class Server
|
||||||
{
|
{
|
||||||
public static readonly Logger c = new(nameof(GameServer), ConsoleColor.Cyan);
|
public static Logger log;
|
||||||
public readonly Dictionary<string, Session> Sessions = new();
|
public readonly Dictionary<string, Session> Sessions = new();
|
||||||
private static Server? _instance;
|
private static Server? _instance;
|
||||||
private readonly TcpListener listener;
|
private readonly TcpListener listener;
|
||||||
|
@ -21,6 +21,10 @@ namespace AscNet.GameServer
|
||||||
|
|
||||||
public Server()
|
public Server()
|
||||||
{
|
{
|
||||||
|
// TODO: add loglevel based on appsettings
|
||||||
|
LogLevel logLevel = LogLevel.DEBUG;
|
||||||
|
LogLevel fileLogLevel = LogLevel.DEBUG;
|
||||||
|
log = new(typeof(Server), logLevel, fileLogLevel);
|
||||||
listener = new(IPAddress.Parse("0.0.0.0"), Common.Common.config.GameServer.Port);
|
listener = new(IPAddress.Parse("0.0.0.0"), Common.Common.config.GameServer.Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,21 +35,21 @@ namespace AscNet.GameServer
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
listener.Start();
|
listener.Start();
|
||||||
c.Log($"{nameof(GameServer)} started and listening on port {Common.Common.config.GameServer.Port}");
|
log.Info($"{nameof(GameServer)} started and listening on port {Common.Common.config.GameServer.Port}");
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
TcpClient tcpClient = listener.AcceptTcpClient();
|
TcpClient tcpClient = listener.AcceptTcpClient();
|
||||||
string id = tcpClient.Client.RemoteEndPoint!.ToString()!;
|
string id = tcpClient.Client.RemoteEndPoint!.ToString()!;
|
||||||
|
|
||||||
c.Warn($"{id} connected");
|
log.Warn($"{id} connected");
|
||||||
Sessions.Add(id, new Session(id, tcpClient));
|
Sessions.Add(id, new Session(id, tcpClient));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
c.Error("TCP listener error: " + ex.Message);
|
log.Error("TCP listener error: " + ex.Message);
|
||||||
c.Log("Waiting 3 seconds before restarting...");
|
log.Info("Waiting 3 seconds before restarting...");
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using AscNet.Common;
|
using AscNet.Common;
|
||||||
using AscNet.Common.Util;
|
using AscNet.Common.Util;
|
||||||
|
using AscNet.Logging;
|
||||||
using MessagePack;
|
using MessagePack;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Logger = AscNet.Logging.Logger;
|
||||||
|
|
||||||
namespace AscNet.GameServer
|
namespace AscNet.GameServer
|
||||||
{
|
{
|
||||||
|
@ -11,7 +13,7 @@ namespace AscNet.GameServer
|
||||||
{
|
{
|
||||||
public readonly string id;
|
public readonly string id;
|
||||||
public readonly TcpClient client;
|
public readonly TcpClient client;
|
||||||
public readonly Logger c;
|
public readonly Logger log;
|
||||||
private long lastPacketTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
private long lastPacketTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||||
private ushort packetNo = 0;
|
private ushort packetNo = 0;
|
||||||
private readonly MessagePackSerializerOptions lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4Block);
|
private readonly MessagePackSerializerOptions lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4Block);
|
||||||
|
@ -20,7 +22,8 @@ namespace AscNet.GameServer
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
client = tcpClient;
|
client = tcpClient;
|
||||||
c = new(id, ConsoleColor.DarkGray);
|
// TODO: add session based configuration? maybe from database?
|
||||||
|
log = new(typeof(Session), LogLevel.DEBUG, LogLevel.DEBUG);
|
||||||
|
|
||||||
Task.Run(ClientLoop);
|
Task.Run(ClientLoop);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +65,7 @@ namespace AscNet.GameServer
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
c.Error("Failed to deserialize packet: " + BitConverter.ToString(packet).Replace("-", ""));
|
log.Error("Failed to deserialize packet: " + BitConverter.ToString(packet).Replace("-", ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,34 +84,37 @@ namespace AscNet.GameServer
|
||||||
RequestPacketHandlerDelegate? requestPacketHandler = PacketFactory.GetRequestPacketHandler(request.Name);
|
RequestPacketHandlerDelegate? requestPacketHandler = PacketFactory.GetRequestPacketHandler(request.Name);
|
||||||
if (requestPacketHandler is not null)
|
if (requestPacketHandler is not null)
|
||||||
{
|
{
|
||||||
|
// TODO: with new logger this will be unnecessary
|
||||||
if (Common.Common.config.VerboseLevel > VerboseLevel.Silent)
|
if (Common.Common.config.VerboseLevel > VerboseLevel.Silent)
|
||||||
c.Log($"{request.Name}{(Common.Common.config.VerboseLevel >= VerboseLevel.Debug ? (", " + JsonConvert.SerializeObject(MessagePackSerializer.Typeless.Deserialize(request.Content))) : "")}");
|
log.Info($"{request.Name}{(Common.Common.config.VerboseLevel >= VerboseLevel.Debug ? (", " + JsonConvert.SerializeObject(MessagePackSerializer.Typeless.Deserialize(request.Content))) : "")}");
|
||||||
requestPacketHandler.Invoke(this, request);
|
requestPacketHandler.Invoke(this, request);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Common.Common.config.VerboseLevel > VerboseLevel.Silent)
|
if (Common.Common.config.VerboseLevel > VerboseLevel.Silent)
|
||||||
c.Warn($"{request.Name} handler not found!{(Common.Common.config.VerboseLevel >= VerboseLevel.Debug ? (", " + JsonConvert.SerializeObject(MessagePackSerializer.Typeless.Deserialize(request.Content))) : "")}");
|
log.Warn($"{request.Name} handler not found!{(Common.Common.config.VerboseLevel >= VerboseLevel.Debug ? (", " + JsonConvert.SerializeObject(MessagePackSerializer.Typeless.Deserialize(request.Content))) : "")}");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Packet.ContentType.Push:
|
case Packet.ContentType.Push:
|
||||||
Packet.Push push = MessagePackSerializer.Deserialize<Packet.Push>(packet.Content);
|
Packet.Push push = MessagePackSerializer.Deserialize<Packet.Push>(packet.Content);
|
||||||
debugContent = push.Content;
|
debugContent = push.Content;
|
||||||
c.Log(push.Name);
|
log.Info(push.Name);
|
||||||
throw new NotImplementedException($"Packet push handlers not implemented ({push.Name})");
|
throw new NotImplementedException($"Packet push handlers not implemented ({push.Name})");
|
||||||
break;
|
|
||||||
case Packet.ContentType.Exception:
|
case Packet.ContentType.Exception:
|
||||||
Packet.Exception exception = MessagePackSerializer.Deserialize<Packet.Exception>(packet.Content);
|
Packet.Exception exception = MessagePackSerializer.Deserialize<Packet.Exception>(packet.Content);
|
||||||
c.Error($"Exception packet received: {exception.Code}, {exception.Message}");
|
log.Error($"Exception packet received: {exception.Code}, {exception.Message}");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
c.Error($"Unknown packet received: {packet}");
|
log.Error($"Unknown packet received: {packet}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
c.Error("Failed to invoke handler: " + ex.Message + $", Raw {packet.Type} packet: " + BitConverter.ToString(debugContent).Replace("-", ""));
|
log.Error("Failed to invoke handler: " + ex.Message + $", Raw {packet.Type} packet: " + BitConverter.ToString(debugContent).Replace("-", ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +146,7 @@ namespace AscNet.GameServer
|
||||||
Type = Packet.ContentType.Push,
|
Type = Packet.ContentType.Push,
|
||||||
Content = MessagePackSerializer.Serialize(packet)
|
Content = MessagePackSerializer.Serialize(packet)
|
||||||
});
|
});
|
||||||
c.Log(packet.Name);
|
log.Info(packet.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendPush(string name, byte[] push)
|
public void SendPush(string name, byte[] push)
|
||||||
|
@ -156,7 +162,7 @@ namespace AscNet.GameServer
|
||||||
Type = Packet.ContentType.Push,
|
Type = Packet.ContentType.Push,
|
||||||
Content = MessagePackSerializer.Serialize(packet)
|
Content = MessagePackSerializer.Serialize(packet)
|
||||||
});
|
});
|
||||||
c.Log(packet.Name);
|
log.Info(packet.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendResponse<T>(T response, int clientSeq = 0)
|
public void SendResponse<T>(T response, int clientSeq = 0)
|
||||||
|
@ -173,7 +179,7 @@ namespace AscNet.GameServer
|
||||||
Type = Packet.ContentType.Response,
|
Type = Packet.ContentType.Response,
|
||||||
Content = MessagePackSerializer.Serialize(packet)
|
Content = MessagePackSerializer.Serialize(packet)
|
||||||
});
|
});
|
||||||
c.Log(packet.Name);
|
log.Info(packet.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Send(Packet packet)
|
private void Send(Packet packet)
|
||||||
|
@ -194,7 +200,7 @@ namespace AscNet.GameServer
|
||||||
if (Server.Instance.Sessions.GetValueOrDefault(id) is null)
|
if (Server.Instance.Sessions.GetValueOrDefault(id) is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
c.Warn($"{id} disconnected");
|
log.Warn($"{id} disconnected");
|
||||||
client.Close();
|
client.Close();
|
||||||
Server.Instance.Sessions.Remove(id);
|
Server.Instance.Sessions.Remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace AscNet.Logging
|
||||||
|
{
|
||||||
|
public interface ILogger
|
||||||
|
{
|
||||||
|
void Debug(string message, string memberName = "");
|
||||||
|
|
||||||
|
void Error(string message, Exception ex = null, string memberName = "");
|
||||||
|
|
||||||
|
void Fatal(string message, Exception ex = null, string memberName = "");
|
||||||
|
|
||||||
|
void Info(string message, string memberName = "");
|
||||||
|
|
||||||
|
void Dispose();
|
||||||
|
|
||||||
|
void Warn(string message, Exception ex = null, string memberName = "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace AscNet.Logging
|
||||||
|
{
|
||||||
|
public enum LogLevel : byte
|
||||||
|
{
|
||||||
|
OFF = 0,
|
||||||
|
FATAL = 8,
|
||||||
|
ERROR = 16,
|
||||||
|
WARN = 32,
|
||||||
|
INFO = 64,
|
||||||
|
DEBUG = 128,
|
||||||
|
ALL = 255
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
namespace AscNet.Logging
|
||||||
|
{
|
||||||
|
public class Logger : ILogger
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
private readonly string _logFilePath = "log.log";
|
||||||
|
private readonly string _loggerName = "DefaultLogger";
|
||||||
|
private readonly LogLevel _logLevel = LogLevel.ALL;
|
||||||
|
private readonly LogLevel _fileLogLevel = LogLevel.ALL;
|
||||||
|
private bool _disposed;
|
||||||
|
private Type _loggerType;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Instantiation
|
||||||
|
|
||||||
|
public Logger(string logFilePath)
|
||||||
|
{
|
||||||
|
_logFilePath = logFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger(string logFilePath, LogLevel logLevel) : this(logFilePath) => _logLevel = logLevel;
|
||||||
|
|
||||||
|
public Logger(Type loggerType, string logFilePath, LogLevel logLevel) : this(logFilePath, logLevel)
|
||||||
|
{
|
||||||
|
_loggerType = loggerType;
|
||||||
|
_loggerName = loggerType.Namespace.RemoveBefore('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger(Type loggerType, LogLevel logLevel, LogLevel fileLogLevel)
|
||||||
|
{
|
||||||
|
_logLevel = logLevel;
|
||||||
|
_fileLogLevel = fileLogLevel;
|
||||||
|
_loggerType = loggerType;
|
||||||
|
_loggerName = loggerType.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger(Type loggerType, string loggerName, LogLevel logLevel, LogLevel fileLogLevel)
|
||||||
|
{
|
||||||
|
_logLevel = logLevel;
|
||||||
|
_fileLogLevel = fileLogLevel;
|
||||||
|
_loggerType = loggerType;
|
||||||
|
_loggerName = loggerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public void Debug(string message, string memberName = "")
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
|
Append(message, memberName, LogLevel.DEBUG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Error(string message, Exception ex = null, string memberName = "")
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
|
if (ex == null)
|
||||||
|
{
|
||||||
|
Append(message, memberName, LogLevel.ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(message + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, memberName,
|
||||||
|
LogLevel.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fatal(string message, Exception ex = null, string memberName = "")
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
|
if (ex == null)
|
||||||
|
{
|
||||||
|
Append(message, memberName, LogLevel.FATAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(message + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, memberName,
|
||||||
|
LogLevel.FATAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Info(string message, string memberName = "")
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
|
Append(message, memberName, LogLevel.INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trace(string message, Exception ex)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warn(string message, Exception ex = null, string memberName = "")
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
|
if (ex == null)
|
||||||
|
{
|
||||||
|
Append(message, memberName, LogLevel.WARN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(message + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, memberName,
|
||||||
|
LogLevel.WARN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
ThreadSafeStreamWriter.Instance.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_loggerType = null;
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Append(string message, string memberName, LogLevel logLevel)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(memberName))
|
||||||
|
{
|
||||||
|
AppendToConsole($"[{memberName}][{_loggerName}]: {message}", logLevel);
|
||||||
|
AppendToFile($"[{memberName}][{_loggerName}]: {message}", logLevel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppendToConsole($"[{_loggerName}]: {message}", logLevel);
|
||||||
|
AppendToFile($"[{_loggerName}]: {message}", logLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppendToConsole(string message, LogLevel logLevel)
|
||||||
|
{
|
||||||
|
if (logLevel <= _logLevel)
|
||||||
|
{
|
||||||
|
switch (logLevel)
|
||||||
|
{
|
||||||
|
case LogLevel.DEBUG:
|
||||||
|
Console.ForegroundColor = ConsoleColor.Magenta;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogLevel.INFO:
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogLevel.WARN:
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogLevel.ERROR:
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogLevel.FATAL:
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}][{logLevel}]{message}");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppendToFile(string message, LogLevel logLevel)
|
||||||
|
{
|
||||||
|
if (logLevel <= _fileLogLevel)
|
||||||
|
{
|
||||||
|
ThreadSafeStreamWriter.Instance.AppendLine($"[{DateTime.Now:dd.MM.yyyy HH:mm:ss.fff}][{_loggerType.Namespace}][{_loggerName}][{logLevel}]{message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace AscNet.Logging
|
||||||
|
{
|
||||||
|
public static class LoggerFactory
|
||||||
|
{
|
||||||
|
public static ILogger Logger { get; set; }
|
||||||
|
|
||||||
|
public static void Debug(string message, [CallerMemberName] string memberName = "") => Logger.Debug(message, memberName);
|
||||||
|
|
||||||
|
public static void Error(string message, Exception ex = null, [CallerMemberName] string memberName = "") => Logger.Error(message, ex, memberName);
|
||||||
|
|
||||||
|
public static void Fatal(string message, Exception ex = null, [CallerMemberName] string memberName = "") => Logger.Fatal(message, ex, memberName);
|
||||||
|
|
||||||
|
public static void Info(string message, [CallerMemberName] string memberName = "") => Logger.Info(message, memberName);
|
||||||
|
|
||||||
|
public static void Warn(string message, Exception ex = null, [CallerMemberName] string memberName = "") => Logger.Warn(message, ex, memberName);
|
||||||
|
|
||||||
|
public static void Dispose() => Logger.Dispose();
|
||||||
|
|
||||||
|
public static void InitializeLogger(ILogger log) => Logger = log;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace AscNet.Logging
|
||||||
|
{
|
||||||
|
public static class LoggingExtensions
|
||||||
|
{
|
||||||
|
public static string RemoveBefore(this string value, char character)
|
||||||
|
{
|
||||||
|
int index = value.LastIndexOf(character);
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
value = value[(index + 1)..];
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
namespace AscNet.Logging
|
||||||
|
{
|
||||||
|
public class ThreadSafeStreamWriter : IDisposable
|
||||||
|
{
|
||||||
|
private static ThreadSafeStreamWriter? _instance;
|
||||||
|
|
||||||
|
private static StreamWriter _writer;
|
||||||
|
|
||||||
|
private bool disposedValue;
|
||||||
|
|
||||||
|
// TODO: add support for configuring
|
||||||
|
private string _logFilePath = "log.log";
|
||||||
|
|
||||||
|
private object _lock = new object();
|
||||||
|
|
||||||
|
public ThreadSafeStreamWriter()
|
||||||
|
{
|
||||||
|
_writer = new StreamWriter(_logFilePath, true);
|
||||||
|
#if !RELEASE
|
||||||
|
_writer.AutoFlush = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ThreadSafeStreamWriter Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _instance ??= new ThreadSafeStreamWriter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AppendLine(string line)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_writer.WriteLine(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!disposedValue)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_writer.Flush();
|
||||||
|
_writer.Close();
|
||||||
|
_writer.Dispose();
|
||||||
|
}
|
||||||
|
disposedValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(disposing: true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\AscNet.Common\AscNet.Common.csproj" />
|
<ProjectReference Include="..\AscNet.Common\AscNet.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\AscNet.Logging\AscNet.Logging.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace AscNet.SDKServer.Controllers
|
||||||
remoteConfigs.AddConfig("PcPayCallbackList", $"{Common.Common.config.GameServer.Host}/api/XPay/KuroPayResult");
|
remoteConfigs.AddConfig("PcPayCallbackList", $"{Common.Common.config.GameServer.Host}/api/XPay/KuroPayResult");
|
||||||
|
|
||||||
string serializedObject = TsvTool.SerializeObject(remoteConfigs);
|
string serializedObject = TsvTool.SerializeObject(remoteConfigs);
|
||||||
SDKServer.c.Log(serializedObject);
|
SDKServer.log.Info(serializedObject);
|
||||||
return serializedObject;
|
return serializedObject;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -61,13 +61,13 @@ namespace AscNet.SDKServer.Controllers
|
||||||
Title = "NOTICE"
|
Title = "NOTICE"
|
||||||
};
|
};
|
||||||
string serializedObject = JsonConvert.SerializeObject(notice);
|
string serializedObject = JsonConvert.SerializeObject(notice);
|
||||||
SDKServer.c.Log(serializedObject);
|
SDKServer.log.Info(serializedObject);
|
||||||
return serializedObject;
|
return serializedObject;
|
||||||
});
|
});
|
||||||
|
|
||||||
app.MapPost("/feedback", (HttpContext ctx) =>
|
app.MapPost("/feedback", (HttpContext ctx) =>
|
||||||
{
|
{
|
||||||
SDKServer.c.Log("1");
|
SDKServer.log.Info("1");
|
||||||
return "1";
|
return "1";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ namespace AscNet.SDKServer.Controllers
|
||||||
Token = token
|
Token = token
|
||||||
};
|
};
|
||||||
string serializedObject = JsonConvert.SerializeObject(gate);
|
string serializedObject = JsonConvert.SerializeObject(gate);
|
||||||
SDKServer.c.Log(serializedObject);
|
SDKServer.log.Info(serializedObject);
|
||||||
return serializedObject;
|
return serializedObject;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
using AscNet.Logging;
|
||||||
|
|
||||||
namespace AscNet.SDKServer
|
namespace AscNet.SDKServer
|
||||||
{
|
{
|
||||||
public class SDKServer
|
public class SDKServer
|
||||||
{
|
{
|
||||||
public static readonly Common.Util.Logger c = new(nameof(SDKServer), ConsoleColor.Green);
|
public static readonly Logger log = new(typeof(SDKServer), Logging.LogLevel.DEBUG, Logging.LogLevel.DEBUG);
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
@ -25,14 +27,14 @@ namespace AscNet.SDKServer
|
||||||
{
|
{
|
||||||
controller.GetMethod(nameof(IRegisterable.Register))!.Invoke(null, new object[] { app });
|
controller.GetMethod(nameof(IRegisterable.Register))!.Invoke(null, new object[] { app });
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
c.Log($"Registered HTTP controller '{controller.Name}'");
|
log.Info($"Registered HTTP controller '{controller.Name}'");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseMiddleware<RequestLoggingMiddleware>();
|
app.UseMiddleware<RequestLoggingMiddleware>();
|
||||||
|
|
||||||
new Thread(() => app.Run()).Start();
|
new Thread(() => app.Run()).Start();
|
||||||
c.Log($"{nameof(SDKServer)} started in port {string.Join(", ", app.Urls.Select(x => x.Split(':').Last()))}!");
|
log.Info($"{nameof(SDKServer)} started in port {string.Join(", ", app.Urls.Select(x => x.Split(':').Last()))}!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RequestLoggingMiddleware
|
private class RequestLoggingMiddleware
|
||||||
|
@ -53,7 +55,7 @@ namespace AscNet.SDKServer
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
c.Log($"{context.Response.StatusCode} {context.Request.Method.ToUpper()} {context.Request.Path + context.Request.QueryString}");
|
log.Info($"{context.Response.StatusCode} {context.Request.Method.ToUpper()} {context.Request.Path + context.Request.QueryString}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AscNet.SDKServer", "AscNet.
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AscNet.GameServer", "AscNet.GameServer\AscNet.GameServer.csproj", "{EB20C0CB-7CA1-459F-8410-7A27CC99F98C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AscNet.GameServer", "AscNet.GameServer\AscNet.GameServer.csproj", "{EB20C0CB-7CA1-459F-8410-7A27CC99F98C}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AscNet.Test", "AscNet.Test\AscNet.Test.csproj", "{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AscNet.Test", "AscNet.Test\AscNet.Test.csproj", "{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AscNet.Logging", "AscNet.Logging\AscNet.Logging.csproj", "{1DFF24B2-A3E1-4E5B-A1E4-3FE7022828EF}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -39,6 +41,10 @@ Global
|
||||||
{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}.Release|Any CPU.Build.0 = Release|Any CPU
|
{DD4C8BB1-2422-4AA4-A12C-9B3A25873887}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1DFF24B2-A3E1-4E5B-A1E4-3FE7022828EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1DFF24B2-A3E1-4E5B-A1E4-3FE7022828EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1DFF24B2-A3E1-4E5B-A1E4-3FE7022828EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1DFF24B2-A3E1-4E5B-A1E4-3FE7022828EF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using AscNet.Common.Util;
|
using AscNet.GameServer;
|
||||||
using AscNet.GameServer;
|
using AscNet.Logging;
|
||||||
|
|
||||||
namespace AscNet
|
namespace AscNet
|
||||||
{
|
{
|
||||||
|
@ -7,15 +7,16 @@ namespace AscNet
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
Logger.c.Log("Starting...");
|
// TODO: Add loglevel parsing from appsettings file
|
||||||
|
LoggerFactory.InitializeLogger(new Logger(typeof(Program), LogLevel.DEBUG, LogLevel.DEBUG));
|
||||||
|
LoggerFactory.Logger.Info("Starting...");
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (Common.Common.config.VerboseLevel < Common.VerboseLevel.Debug)
|
if (Common.Common.config.VerboseLevel < Common.VerboseLevel.Debug)
|
||||||
Common.Common.config.VerboseLevel = Common.VerboseLevel.Debug;
|
Common.Common.config.VerboseLevel = Common.VerboseLevel.Debug;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PacketFactory.LoadPacketHandlers();
|
PacketFactory.LoadPacketHandlers();
|
||||||
Task.Run(GameServer.Server.Instance.Start);
|
Task.Run(Server.Instance.Start);
|
||||||
SDKServer.SDKServer.Main(args);
|
SDKServer.SDKServer.Main(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue