Updated logger for real time message sending
This commit is contained in:
@@ -2,21 +2,13 @@
|
|||||||
|
|
||||||
public interface ILogger
|
public interface ILogger
|
||||||
{
|
{
|
||||||
public struct FormattedMessage {
|
event Action<ILogMessage>? OnLogReceived;
|
||||||
public string Message;
|
|
||||||
public LogType Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
string LogMessageFormat { get; set; }
|
|
||||||
|
|
||||||
void Log(string message);
|
void Log(string message);
|
||||||
void Log(string message, LogType logType);
|
void Log(string message, LogType logType);
|
||||||
void Log(string message, LogType logType, string format);
|
void Log(string message, LogType logType, string format);
|
||||||
void Log(string message, object Sender);
|
void Log(string message, object sender);
|
||||||
void Log(string message, object Sender, LogType type);
|
void Log(string message, object sender, LogType type);
|
||||||
void LogException(Exception exception, object Sender, bool logFullStack = false);
|
void LogException(Exception exception, object sender, bool logFullStack = false);
|
||||||
|
|
||||||
void SetOutFunction(Action<string,LogType> outFunction);
|
|
||||||
|
|
||||||
string GetLogsHistory();
|
|
||||||
}
|
}
|
||||||
@@ -2,23 +2,15 @@
|
|||||||
|
|
||||||
public sealed class Logger : ILogger
|
public sealed class Logger : ILogger
|
||||||
{
|
{
|
||||||
private FileStream _logFileStream;
|
private readonly string _LogFile;
|
||||||
|
private readonly List<string> _logMessageProperties = typeof(ILogMessage).GetProperties().Select(p => p.Name).ToList();
|
||||||
private readonly List<string> _logMessageProperties = typeof(ILogMessage).GetProperties().Select(p => p.Name).ToList();
|
public event Action<ILogMessage>? OnLogReceived;
|
||||||
private Action<string, LogType>? _outFunction;
|
|
||||||
public string LogMessageFormat { get ; set; }
|
public string LogMessageFormat { get ; set; }
|
||||||
|
|
||||||
public Logger(string logFolder, string logMessageFormat, Action<string, LogType>? outFunction = null)
|
public Logger(string logFolder, string logMessageFormat)
|
||||||
{
|
{
|
||||||
this.LogMessageFormat = logMessageFormat;
|
this.LogMessageFormat = logMessageFormat;
|
||||||
var logFile = Path.Combine(logFolder, $"{DateTime.Now:yyyy-MM-dd}.log");
|
this._LogFile = Path.Combine(logFolder, $"{DateTime.Now:yyyy-MM-dd}.log");
|
||||||
_logFileStream = File.Open(logFile, FileMode.Append, FileAccess.Write, FileShare.Read);
|
|
||||||
this._outFunction = outFunction ?? DefaultLogFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DefaultLogFunction(string message, LogType logType)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"[{logType}] {message}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,15 +30,10 @@ public sealed class Logger : ILogger
|
|||||||
return messageAsString;
|
return messageAsString;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void LogToFile(string message)
|
private async Task LogToFile(string message)
|
||||||
{
|
{
|
||||||
byte[] messageAsBytes = System.Text.Encoding.ASCII.GetBytes(message);
|
await using var streamWriter = new StreamWriter(_LogFile, true);
|
||||||
await _logFileStream.WriteAsync(messageAsBytes, 0, messageAsBytes.Length);
|
await streamWriter.WriteLineAsync(message);
|
||||||
|
|
||||||
byte[] newLine = System.Text.Encoding.ASCII.GetBytes(Environment.NewLine);
|
|
||||||
await _logFileStream.WriteAsync(newLine, 0, newLine.Length);
|
|
||||||
|
|
||||||
await _logFileStream.FlushAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateLogMessage(ILogMessage message, string customFormat)
|
private string GenerateLogMessage(ILogMessage message, string customFormat)
|
||||||
@@ -61,17 +48,17 @@ public sealed class Logger : ILogger
|
|||||||
return messageAsString;
|
return messageAsString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(ILogMessage message, string format)
|
private void Log(ILogMessage message, string format)
|
||||||
{
|
{
|
||||||
string messageAsString = GenerateLogMessage(message, format);
|
string messageAsString = GenerateLogMessage(message, format);
|
||||||
_outFunction?.Invoke(messageAsString, message.LogMessageType);
|
OnLogReceived?.Invoke(message);
|
||||||
LogToFile(messageAsString);
|
LogToFile(messageAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(ILogMessage message)
|
private void Log(ILogMessage message)
|
||||||
{
|
{
|
||||||
string messageAsString = GenerateLogMessage(message);
|
string messageAsString = GenerateLogMessage(message);
|
||||||
_outFunction?.Invoke(messageAsString, message.LogMessageType);
|
OnLogReceived?.Invoke(message);
|
||||||
LogToFile(messageAsString);
|
LogToFile(messageAsString);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -82,22 +69,4 @@ public sealed class Logger : ILogger
|
|||||||
public void Log(string message, object sender) => Log(new LogMessage(message, sender));
|
public void Log(string message, object sender) => Log(new LogMessage(message, sender));
|
||||||
public void Log(string message, object sender, LogType type) => Log(new LogMessage(message, sender, type));
|
public void Log(string message, object sender, LogType type) => Log(new LogMessage(message, sender, type));
|
||||||
public void LogException(Exception exception, object sender, bool logFullStack = false) => Log(LogMessage.CreateFromException(exception, sender, logFullStack));
|
public void LogException(Exception exception, object sender, bool logFullStack = false) => Log(LogMessage.CreateFromException(exception, sender, logFullStack));
|
||||||
|
|
||||||
public void SetOutFunction(Action<string, LogType> outFunction)
|
|
||||||
{
|
|
||||||
this._outFunction = outFunction;
|
|
||||||
}
|
|
||||||
public string GetLogsHistory()
|
|
||||||
{
|
|
||||||
string fileName = _logFileStream.Name;
|
|
||||||
|
|
||||||
//_logFileStream.Flush();
|
|
||||||
_logFileStream.Close();
|
|
||||||
|
|
||||||
string[] logs = File.ReadAllLines(fileName);
|
|
||||||
_logFileStream = File.Open(fileName, FileMode.Append, FileAccess.Write, FileShare.Read);
|
|
||||||
|
|
||||||
return string.Join(Environment.NewLine, logs);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ public static class Initializer
|
|||||||
Directory.CreateDirectory(logFolder);
|
Directory.CreateDirectory(logFolder);
|
||||||
|
|
||||||
ILogger logger = new Logger(logFolder, logFormat);
|
ILogger logger = new Logger(logFolder, logFormat);
|
||||||
logger.SetOutFunction((s, type) => { Console.WriteLine($"[{type}] {s}"); });
|
logger.OnLogReceived += (logMessage) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine(logMessage.Message);
|
||||||
|
};
|
||||||
|
|
||||||
return logger;
|
return logger;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
@page "/"
|
@page "/"
|
||||||
@using DiscordBotCore.Bot
|
@using DiscordBotCore.Bot
|
||||||
|
@using DiscordBotCore.Logging
|
||||||
@using DiscordBotCore.PluginManagement.Loading
|
@using DiscordBotCore.PluginManagement.Loading
|
||||||
@using WebUI.Models
|
@using WebUI.Models
|
||||||
@using WebUI.Services
|
@using WebUI.Services
|
||||||
|
|
||||||
@inject IDiscordBotApplication DiscordBotApplication
|
@inject IDiscordBotApplication DiscordBotApplication
|
||||||
@inject IPluginLoader PluginLoader
|
@inject IPluginLoader PluginLoader
|
||||||
@inject DiscordBotCore.Logging.ILogger Logger
|
@inject ILogger Logger
|
||||||
@inject IJSRuntime JS
|
@inject IJSRuntime JS
|
||||||
@inject NotificationService NotificationService
|
@inject NotificationService NotificationService
|
||||||
|
|
||||||
@rendermode InteractiveServer
|
@rendermode InteractiveServer
|
||||||
<h3>Console Log Viewer</h3>
|
<h3>Console Log Viewer</h3>
|
||||||
|
|
||||||
@@ -16,9 +19,9 @@
|
|||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<h4>Console Log</h4>
|
<h4>Console Log</h4>
|
||||||
<div id="consoleLog" class="border p-3 bg-dark text-white" style="height: 400px; overflow-y: auto; font-family: monospace;">
|
<div id="consoleLog" class="border p-3 bg-dark text-white" style="height: 400px; overflow-y: auto; font-family: monospace;">
|
||||||
@foreach (var line in Logs)
|
@foreach (var line in _Logs)
|
||||||
{
|
{
|
||||||
<div style="@GetLogStyle(line)">@line</div>
|
<div style="@GetLogStyle(line)">@line.Message</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,16 +47,22 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool IsRunning { get; set; }
|
private bool IsRunning { get; set; }
|
||||||
private List<string> Logs { get; set; } = new();
|
private List<ILogMessage> _Logs { get; set; } = new();
|
||||||
private Timer? _logTimer;
|
|
||||||
private int _lastLogCount = 0;
|
|
||||||
private readonly object _logLock = new();
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
IsRunning = DiscordBotApplication.IsReady;
|
IsRunning = DiscordBotApplication.IsReady;
|
||||||
|
Logger.OnLogReceived += LoggerOnLogReceived;
|
||||||
_logTimer = new Timer(async _ => await RefreshLogsAsync(), null, 0, 2000);
|
}
|
||||||
|
|
||||||
|
private void LoggerOnLogReceived(ILogMessage obj)
|
||||||
|
{
|
||||||
|
InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
_Logs.Add(obj);
|
||||||
|
StateHasChanged();
|
||||||
|
await JS.InvokeVoidAsync("scrollToBottom", "consoleLog");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartApplication()
|
private async Task StartApplication()
|
||||||
@@ -62,7 +71,9 @@
|
|||||||
{
|
{
|
||||||
await DiscordBotApplication.StartAsync();
|
await DiscordBotApplication.StartAsync();
|
||||||
Logger.Log("Application started", this);
|
Logger.Log("Application started", this);
|
||||||
|
NotificationService.Notify("Bot Started !", NotificationType.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
IsRunning = DiscordBotApplication.IsReady;
|
IsRunning = DiscordBotApplication.IsReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +83,9 @@
|
|||||||
{
|
{
|
||||||
await DiscordBotApplication.StopAsync();
|
await DiscordBotApplication.StopAsync();
|
||||||
Logger.Log("Application stopped", this);
|
Logger.Log("Application stopped", this);
|
||||||
|
NotificationService.Notify("Bot Stopped !", NotificationType.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
IsRunning = DiscordBotApplication.IsReady;
|
IsRunning = DiscordBotApplication.IsReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,43 +98,15 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetLogStyle(string line)
|
private string GetLogStyle(ILogMessage logMessage)
|
||||||
{
|
{
|
||||||
if (line.Contains("[Error]")) return "color: #ff4d4d;";
|
return logMessage.LogMessageType switch
|
||||||
if (line.Contains("[Warning]")) return "color: #ffa500;";
|
|
||||||
if (line.Contains("[Debug]")) return "color: #88f;";
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RefreshLogsAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var logText = Logger.GetLogsHistory();
|
LogType.Info => "color: white;",
|
||||||
var newLogs = logText.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
|
LogType.Warning => "color: yellow;",
|
||||||
|
LogType.Error => "color: red;",
|
||||||
if (newLogs.Length != _lastLogCount)
|
LogType.Critical => "color: purple;",
|
||||||
{
|
_ => ""
|
||||||
lock (_logLock)
|
};
|
||||||
{
|
|
||||||
Logs = newLogs.ToList();
|
|
||||||
_lastLogCount = newLogs.Length;
|
|
||||||
}
|
|
||||||
await InvokeAsync(async () =>
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
await JS.InvokeVoidAsync("scrollToBottom", "consoleLog");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_logTimer?.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,11 @@
|
|||||||
@using DiscordBotCore.Logging
|
@using DiscordBotCore.Logging
|
||||||
@using DiscordBotCore.PluginManagement
|
@using DiscordBotCore.PluginManagement
|
||||||
@using DiscordBotCore.PluginManagement.Models
|
@using DiscordBotCore.PluginManagement.Models
|
||||||
|
@using WebUI.Models
|
||||||
|
@using WebUI.Services
|
||||||
|
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
|
@inject NotificationService NotificationService
|
||||||
|
|
||||||
@inject IPluginManager PluginManager
|
@inject IPluginManager PluginManager
|
||||||
@inject IConfiguration Configuration
|
@inject IConfiguration Configuration
|
||||||
@@ -67,6 +70,7 @@
|
|||||||
{
|
{
|
||||||
if (!IsValidVersion || selectedFile is null || string.IsNullOrEmpty(selectedFileName))
|
if (!IsValidVersion || selectedFile is null || string.IsNullOrEmpty(selectedFileName))
|
||||||
{
|
{
|
||||||
|
NotificationService.Notify("Invalid field values. Please check the form.", NotificationType.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +79,7 @@
|
|||||||
if (string.IsNullOrEmpty(pluginsFolder))
|
if (string.IsNullOrEmpty(pluginsFolder))
|
||||||
{
|
{
|
||||||
Logger.Log("Plugins folder is not set in the configuration.", this, LogType.Error);
|
Logger.Log("Plugins folder is not set in the configuration.", this, LogType.Error);
|
||||||
|
NotificationService.Notify("Plugins folder is not set in the configuration.", NotificationType.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +91,8 @@
|
|||||||
|
|
||||||
LocalPlugin plugin = new LocalPlugin(pluginModel.Name, pluginModel.Version, filePath, new(), true, pluginModel.IsEnabled);
|
LocalPlugin plugin = new LocalPlugin(pluginModel.Name, pluginModel.Version, filePath, new(), true, pluginModel.IsEnabled);
|
||||||
await PluginManager.AppendPluginToDatabase(plugin);
|
await PluginManager.AppendPluginToDatabase(plugin);
|
||||||
|
|
||||||
|
NotificationService.Notify($"Plugin {pluginModel.Name} uploaded successfully!", NotificationType.Success);
|
||||||
|
|
||||||
Navigation.NavigateTo("/");
|
Navigation.NavigateTo("/");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ else
|
|||||||
if (pluginData is null)
|
if (pluginData is null)
|
||||||
{
|
{
|
||||||
Logger.Log("Plugin data is null.", this, LogType.Error);
|
Logger.Log("Plugin data is null.", this, LogType.Error);
|
||||||
|
NotificationService.Notify("Plugin data is null.", NotificationType.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user