Skip to content

Commit

Permalink
Merge pull request #21 from smellilac/feature-logger
Browse files Browse the repository at this point in the history
Feature logger (Serilog)
  • Loading branch information
HEJOK254 authored Aug 26, 2024
2 parents 82e74db + 3fdc42d commit 64bc013
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 84 deletions.
24 changes: 13 additions & 11 deletions Commands/InteractionServiceHandler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Discord;
using Discord;
using Discord.Interactions;
using Discord.WebSocket;
using Serilog;

namespace QuickEdit.Commands;
public class InteractionServiceHandler
Expand All @@ -23,9 +24,9 @@ public static async Task InitAsync()
// So the event has to be used to handle the result
_interactionService.SlashCommandExecuted += OnSlashCommandExecutedAsync;
}
catch
catch (Exception e)
{
await Program.LogAsync("InteractionServiceHandler", "Error initializing InteractionService", LogSeverity.Critical);
Log.Fatal($"Error initializing InteractionService: {e.Message}");
throw;
}
}
Expand All @@ -38,7 +39,7 @@ public static async Task RegisterModulesAsync()
// The service might not have been initialized yet
if (_interactionService == null)
{
await Program.LogAsync("InteractionServiceManager.RegisterModulesAsync()", "InteractionService not initialized yet", LogSeverity.Error);
Log.Error("Failed to register modules: InteractionService not initialized.");
throw new InvalidOperationException("InteractionService not initialized while trying to register commands");
}

Expand All @@ -52,11 +53,11 @@ public static async Task RegisterModulesAsync()

await _interactionService.RegisterCommandsGloballyAsync();
_client!.InteractionCreated += OnInteractionCreatedAsync;
await Program.LogAsync("InteractionServiceManager", "Modules registered successfully", LogSeverity.Info);
Log.Information("Modules registered successfully");
}
catch (Exception e)
{
await Program.LogAsync("InteractionServiceManager", $"Error registering modules. ({e})", LogSeverity.Critical);
Log.Fatal($"Error registering modules: {(Program.config != null && Program.config.debug ? e : e.Message)}");
throw;
}
}
Expand All @@ -66,7 +67,7 @@ public static async Task OnInteractionCreatedAsync(SocketInteraction interaction
// The service might not have been initialized yet
if (_interactionService == null)
{
await Program.LogAsync("InteractionServiceManager.OnInteractionCreatedAsync()", "InteractionService not initialized yet", LogSeverity.Error);
Log.Error("Error handling interaction: InteractionService not initialized.");
return;
}

Expand All @@ -79,7 +80,7 @@ public static async Task OnInteractionCreatedAsync(SocketInteraction interaction
}
catch (Exception e)
{
await Program.LogAsync("InteractionServiceManager", $"Error handling interaction. {e.Message}", LogSeverity.Error);
Log.Error($"Error handling interaction: {e.Message}");

if (interaction.Type is InteractionType.ApplicationCommand)
{
Expand All @@ -90,19 +91,20 @@ public static async Task OnInteractionCreatedAsync(SocketInteraction interaction
}
}

public static async Task OnSlashCommandExecutedAsync(SlashCommandInfo commandInfo, IInteractionContext interactionContext, IResult result) {
public static async Task OnSlashCommandExecutedAsync(SlashCommandInfo commandInfo, IInteractionContext interactionContext, IResult result)
{
// Only trying to handle errors lol
if (result.IsSuccess)
return;

try
{
await Program.LogAsync("InteractionServiceManager", $"Error handling interaction: {result.Error}", LogSeverity.Error);
Log.Error($"Error handling interaction: {result.Error}");
await interactionContext.Interaction.FollowupAsync("An error occurred while executing the command.", ephemeral: true);
}
catch (Exception e)
{
await Program.LogAsync("InteractionServiceManager", $"Error handling interaction exception bruh: {e.ToString()}", LogSeverity.Error);
Log.Error($"Error handling interaction exception bruh: {e.ToString()}");
throw;
}
}
Expand Down
16 changes: 11 additions & 5 deletions Commands/Modules/VideoUtils.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Discord;
using Discord.Interactions;
using FFMpegCore;
using Serilog;
using System.Text.RegularExpressions;

namespace QuickEdit.Commands.Modules;
Expand Down Expand Up @@ -40,20 +41,25 @@ public async Task TrimVideoAsync(
// Get TimeSpans
TimeSpan trimStart = TimeSpan.Zero;
TimeSpan trimEnd = TimeSpan.Zero;
try {
try
{
// Avoid invalid format exceptions
if (!string.IsNullOrEmpty(trimStartString)) trimStart = TimeSpanFromHMS(trimStartString);
if (!string.IsNullOrEmpty(trimEndString)) trimEnd = TimeSpanFromHMS(trimEndString);
} catch (Exception e) {
}
catch (Exception e)
{
if (e is ArgumentException)
{
await FollowupAsync("Invalid time format. Please provide a valid time format (XXh XXm XXs XXms).", ephemeral: true);
} else {
}
else
{
throw;
}
return;
}

// Make sure the times are not negative | https://stackoverflow.com/a/1018659/17003609 (comment)
trimStart = trimStart.Duration();
trimEnd = trimEnd.Duration();
Expand All @@ -69,7 +75,7 @@ public async Task TrimVideoAsync(
if (!Directory.Exists("./tmp"))
{
Directory.CreateDirectory("./tmp");
await Program.LogAsync("VideoUtils", "TMP directory not found. Created it automatically.", LogSeverity.Info);
Log.Information("TMP directory not found. Created it automatically");
}

await DownloadVideoAsync(video.Url, videoInputPath);
Expand Down
9 changes: 5 additions & 4 deletions ConfigManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Discord;
using Discord;
using Newtonsoft.Json;
using Serilog;

namespace QuickEdit;
public class Config
Expand All @@ -14,17 +15,17 @@ public class Config
string path = "./config.json";
if (!File.Exists(path))
{
Program.LogAsync("Config", $"Config file not found at: {path}", LogSeverity.Critical);
Log.Fatal($"Config file not found at: {Path.GetFullPath(path)}");
return null;
}

try
{
return JsonConvert.DeserializeObject<Config>(File.ReadAllText(path))!;
}
catch
catch (Exception e)
{
Program.LogAsync("Config", "Failed to parse config file.", LogSeverity.Critical);
Log.Fatal($"Failed to parse config file: {e.Message}");
return null;
}
}
Expand Down
21 changes: 12 additions & 9 deletions Discord QuickEdit.csproj
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>QuickEdit</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>quickedit</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>QuickEdit</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>quickedit</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.15.2" />
<PackageReference Include="FFMpegCore" Version="5.1.0" />
<PackageReference Include="Discord.Net" Version="3.15.2" />
<PackageReference Include="FFMpegCore" Version="5.1.0" />
<PackageReference Include="Serilog" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
</ItemGroup>

<Target Name="Date" BeforeTargets="CoreCompile">
Expand Down
27 changes: 27 additions & 0 deletions Logger/AutoLog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Discord;
using Serilog;
using Serilog.Events;

namespace QuickEdit.Logger;

public class AutoLog
{
// LogMessage does not run asynchronously, so we can ignore the DeepSource error
// skipcq: CS-R1073
public static Task LogMessage(LogMessage message)
{
var logLevel = message.Severity switch
{
LogSeverity.Critical => LogEventLevel.Fatal,
LogSeverity.Error => LogEventLevel.Error,
LogSeverity.Warning => LogEventLevel.Warning,
LogSeverity.Info => LogEventLevel.Information,
LogSeverity.Verbose => LogEventLevel.Verbose,
LogSeverity.Debug => LogEventLevel.Debug,
_ => LogEventLevel.Information
};

Log.Write(logLevel, message.Exception, "{Source}: {Message}", message.Source, message.Message);
return Task.CompletedTask;
}
}
27 changes: 27 additions & 0 deletions Logger/SerilogConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Serilog;

namespace QuickEdit.Logger;

public class SerilogConfiguration
{

public static void ConfigureLogger()
{
var logDirectory = "logs";

Directory.CreateDirectory(logDirectory);

var logPath = Path.Combine(logDirectory, "quickedit-.log");

var loggerConfig = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File(logPath, rollingInterval: RollingInterval.Day);

if (Program.config != null && Program.config.debug)
loggerConfig.MinimumLevel.Debug();
else
loggerConfig.MinimumLevel.Information();

Log.Logger = loggerConfig.CreateLogger();
}
}
66 changes: 11 additions & 55 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using Discord;
using Discord;
using Discord.WebSocket;
using FFMpegCore;
using FFMpegCore.Helpers;
using QuickEdit.Commands;
using System.Reflection;
using QuickEdit.Logger;
using Serilog;

namespace QuickEdit;
class Program

internal class Program
{
public static DiscordSocketClient? client;
public static Config? config = Config.GetConfig();
Expand All @@ -16,6 +18,10 @@ class Program

public async Task MainAsync()
{
SerilogConfiguration.ConfigureLogger();

AppDomain.CurrentDomain.ProcessExit += (s, e) => Log.CloseAndFlush();

ShowStartMessage();

// If the config is null, we can't continue as the bot won't have a token to login with
Expand All @@ -24,7 +30,7 @@ public async Task MainAsync()

client = new DiscordSocketClient(socketConfig);

client.Log += LogAsync;
client.Log += AutoLog.LogMessage;
client.Ready += OnReadyAsync;

await client.LoginAsync(TokenType.Bot, config.token);
Expand Down Expand Up @@ -60,59 +66,9 @@ private async Task OnReadyAsync()
}
catch
{
await LogAsync("Program", "Exiting", LogSeverity.Info);
Log.Fatal("Program is exiting due to an error in InteractionServiceHandler.");
// The program cannot continue without the InteractionService, so terminate it. Nothing important should be running at this point.
Environment.Exit(1); // skipcq: CS-W1005
}
}

public Task LogAsync(LogMessage message)
{
string msg = $"[{DateTime.UtcNow.ToString("HH.mm.ss")}] {message.Source}: {message.Message}";
Console.WriteLine(msg + " " + message.Exception);
return Task.CompletedTask;
}

public static Task LogAsync(string source, string message, LogSeverity severity = LogSeverity.Info)
{
string msg = $"[{DateTime.UtcNow.ToString("HH.mm.ss")}] {source}: {message}";

// Change color / display based on severity
// TODO: Maybe use ANSI escape codes instead?
switch (severity)
{
case LogSeverity.Warning:
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(msg);
Console.ResetColor();
break;
case LogSeverity.Critical:
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine(msg);
Console.ResetColor();
break;

case LogSeverity.Error:
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg);
Console.ResetColor();
break;

case LogSeverity.Verbose:
// Verbose logs are only displayed if the debug flag is set to true in the config
if (config == null || !config.debug) break;

Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine(msg);
Console.ResetColor();
break;

default:
// All other severities should have the default color of the console
Console.ResetColor();
Console.WriteLine(msg);
break;
}
return Task.CompletedTask;
}
}

0 comments on commit 64bc013

Please sign in to comment.