From 87dbc5f3482f88be4460fbce8e0e4ed6a0e3de4b Mon Sep 17 00:00:00 2001 From: InF Date: Sat, 27 Jan 2024 17:50:49 +0500 Subject: [PATCH] Implement Serilog logging (#118) * add serilog * do a little bit more complicated logging setup * delete MigrateDataChore.cs because it's not used * replace console.writeline with serilog log.debug/error --- LightTube/Chores/MigrateDataChore.cs | 49 ----------- LightTube/Chores/QueueChore.cs | 5 +- LightTube/Controllers/SettingsController.cs | 11 +-- LightTube/Database/DatabaseManager.cs | 1 - LightTube/JsCache.cs | 9 +- LightTube/LightTube.csproj | 2 + LightTube/Program.cs | 98 +++++++++++++-------- 7 files changed, 79 insertions(+), 96 deletions(-) delete mode 100644 LightTube/Chores/MigrateDataChore.cs diff --git a/LightTube/Chores/MigrateDataChore.cs b/LightTube/Chores/MigrateDataChore.cs deleted file mode 100644 index c02ab098..00000000 --- a/LightTube/Chores/MigrateDataChore.cs +++ /dev/null @@ -1,49 +0,0 @@ -using LightTube.Database; -using LightTube.Database.Models; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace LightTube.Chores; - -public class MigrateDataChore : IChore -{ - public string Id => "MigrateData"; - - public async Task RunChore(Action updateStatus, Guid id) - { - int migratedUserCount = 0; - int migratedLoginCount = 0; - - updateStatus("Migrating users..."); - IAsyncCursor unmigratedUsers = await DatabaseManager.UserCollection.FindAsync(x => x.SubscribedChannels != null || (x.Email != null && x.UserID == null) || x.LTChannelID == null); - while (await unmigratedUsers.MoveNextAsync()) - { - foreach (DatabaseUser user in unmigratedUsers.Current) - { - user.Migrate(); - await DatabaseManager.UserCollection.FindOneAndReplaceAsync(x => x.PasswordHash == user.PasswordHash, // surely the password hash wouldnt change - user); - migratedUserCount++; - } - } - - updateStatus("Migrating tokens..."); - IMongoCollection tokensCollection = DatabaseManager.Database.GetCollection("tokens"); - IAsyncCursor unmigratedTokens = await tokensCollection.FindAsync(x => true); - while (await unmigratedTokens.MoveNextAsync()) - { - foreach (BsonDocument token in unmigratedTokens.Current.Where(x => x.Contains("Identifier"))) - { - token["_id"] = token["Identifier"]; - token["UserID"] = token["Email"]; - token.Remove("Identifier"); - token.Remove("Email"); - await tokensCollection.DeleteOneAsync(x => x["Token"] == token["Token"]); - await tokensCollection.InsertOneAsync(token); - migratedLoginCount++; - } - } - - return $"migrated\n- {migratedUserCount} users\n- {migratedLoginCount} tokens"; - } -} \ No newline at end of file diff --git a/LightTube/Chores/QueueChore.cs b/LightTube/Chores/QueueChore.cs index a828f3a3..9514a4c1 100644 --- a/LightTube/Chores/QueueChore.cs +++ b/LightTube/Chores/QueueChore.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Serilog; namespace LightTube.Chores; @@ -20,7 +21,7 @@ public QueueChore(Type chore) public void Start() { - Console.WriteLine($"[CHORE] [{Chore.Id}] Chore started"); + Log.Information($"[CHORE] [{Chore.Id}] Chore started"); Running = true; Stopwatch.Start(); Chore.RunChore(s => Status = s, Id) @@ -29,7 +30,7 @@ public void Start() Stopwatch.Stop(); Running = false; Complete = true; - Console.WriteLine($"[CHORE] [{Chore.Id}] Chore complete in {Stopwatch.Elapsed}\n{task.Result}"); + Log.Information($"[CHORE] [{Chore.Id}] Chore complete in {Stopwatch.Elapsed}\n{task.Result}"); ChoreManager.NextChore(); }); } diff --git a/LightTube/Controllers/SettingsController.cs b/LightTube/Controllers/SettingsController.cs index 6ff9f719..8bf70c2b 100644 --- a/LightTube/Controllers/SettingsController.cs +++ b/LightTube/Controllers/SettingsController.cs @@ -4,6 +4,7 @@ using LightTube.Database; using LightTube.Database.Models; using Microsoft.AspNetCore.Mvc; +using Serilog; namespace LightTube.Controllers; @@ -124,7 +125,7 @@ await DatabaseManager.Users.UpdateSubscription(token, id, { Task.WaitAll(channelTasks, TimeSpan.FromSeconds(30)); sp.Stop(); - Console.WriteLine( + Log.Debug( $"Subscribed to {channelTasks.Length} more channels in {sp.Elapsed}."); } catch (Exception) @@ -150,7 +151,7 @@ await DatabaseManager.Users.UpdateSubscription(token, id, } catch (Exception e) { - Console.WriteLine("error/video: " + e.Message); + Log.Error("error/video: " + e.Message); } })) .ToArray(); @@ -159,16 +160,16 @@ await DatabaseManager.Users.UpdateSubscription(token, id, { Task.WaitAll(videoTasks, TimeSpan.FromSeconds(30)); sp.Stop(); - Console.WriteLine( + Log.Debug( $"Got {videoTasks.Length} more videos in {sp.Elapsed}. {videoNexts.Count} success"); } catch (Exception e) { - Console.WriteLine("Error while getting videos\n" + e); + Log.Error("Error while getting videos\n" + e); } } - Console.WriteLine( + Log.Debug( $"From {videos.Length} videos, got {videoNexts.Count} videos."); foreach (ImportedData.Playlist playlist in playlists) diff --git a/LightTube/Database/DatabaseManager.cs b/LightTube/Database/DatabaseManager.cs index a904c77d..7d4ab59a 100644 --- a/LightTube/Database/DatabaseManager.cs +++ b/LightTube/Database/DatabaseManager.cs @@ -34,7 +34,6 @@ public static void Init(string connstr) Oauth2 = new Oauth2Manager(Oauth2TokensCollection); Playlists = new PlaylistManager(PlaylistCollection, VideoCacheCollection); - ChoreManager.QueueChore("MigrateData"); ChoreManager.QueueChore("DatabaseCleanup"); } } \ No newline at end of file diff --git a/LightTube/JsCache.cs b/LightTube/JsCache.cs index 035e17b6..f0ba8c0a 100644 --- a/LightTube/JsCache.cs +++ b/LightTube/JsCache.cs @@ -1,6 +1,7 @@ using System.Security.Cryptography; using System.Text; using System.Web; +using Serilog; namespace LightTube; @@ -19,15 +20,15 @@ public static async Task DownloadLibraries() { HttpClient client = new(); Directory.CreateDirectory("/tmp/lighttube/jsCache"); - Console.WriteLine("[JsCache] Downloading libraries..."); + Log.Information("[JsCache] Downloading libraries..."); foreach ((string? name, Uri? url) in LibraryUrls) { - Console.WriteLine($"[JsCache] Downloading '{name}' from {url}"); + Log.Information($"[JsCache] Downloading '{name}' from {url}"); HttpResponseMessage response = await client.GetAsync(url); string jsData = await response.Content.ReadAsStringAsync(); await File.WriteAllTextAsync($"/tmp/lighttube/jsCache/{name}", jsData); - Console.WriteLine($"[JsCache] Calculating the MD5 hash of {name}..."); + Log.Debug($"[JsCache] Calculating the MD5 hash of {name}..."); using MD5 md5 = MD5.Create(); byte[] inputBytes = Encoding.ASCII.GetBytes(jsData); @@ -36,7 +37,7 @@ public static async Task DownloadLibraries() Hashes[name] = hash; - Console.WriteLine($"[JsCache] Downloaded '{name}'."); + Log.Information($"[JsCache] Downloaded '{name}'."); } CacheUpdateTime = DateTimeOffset.UtcNow; } diff --git a/LightTube/LightTube.csproj b/LightTube/LightTube.csproj index 3c35fc2e..bfad15bb 100644 --- a/LightTube/LightTube.csproj +++ b/LightTube/LightTube.csproj @@ -14,6 +14,8 @@ + + diff --git a/LightTube/Program.cs b/LightTube/Program.cs index 8a8c2468..3dc7d2ff 100644 --- a/LightTube/Program.cs +++ b/LightTube/Program.cs @@ -3,51 +3,79 @@ using LightTube; using LightTube.Chores; using LightTube.Database; +using Serilog; +using Serilog.Events; -WebApplicationBuilder builder = WebApplication.CreateBuilder(args); -// Add services to the container. -builder.Services.AddControllersWithViews().AddNewtonsoftJson(); +Log.Logger = new LoggerConfiguration() + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateBootstrapLogger(); -InnerTubeAuthorization? auth = Configuration.GetInnerTubeAuthorization(); -builder.Services.AddSingleton(new InnerTube.InnerTube(new InnerTubeConfiguration +try { - Authorization = auth, - CacheSize = int.Parse(Configuration.GetVariable("LIGHTTUBE_CACHE_SIZE", "50")!), - CacheExpirationPollingInterval = default -})); -builder.Services.AddSingleton(new HttpClient()); + WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + + builder.Host.UseSerilog((context, services, configuration) => configuration + .ReadFrom.Configuration(context.Configuration) + .ReadFrom.Services(services) + .Enrich.FromLogContext() + .WriteTo.Console()); + +// Add services to the container. + builder.Services.AddControllersWithViews().AddNewtonsoftJson(); + + InnerTubeAuthorization? auth = Configuration.GetInnerTubeAuthorization(); + builder.Services.AddSingleton(new InnerTube.InnerTube(new InnerTubeConfiguration + { + Authorization = auth, + CacheSize = int.Parse(Configuration.GetVariable("LIGHTTUBE_CACHE_SIZE", "50")!), + CacheExpirationPollingInterval = default + })); + builder.Services.AddSingleton(new HttpClient()); -await JsCache.DownloadLibraries(); -ChoreManager.RegisterChores(); -DatabaseManager.Init(Configuration.GetVariable("LIGHTTUBE_MONGODB_CONNSTR")); + await JsCache.DownloadLibraries(); + ChoreManager.RegisterChores(); + DatabaseManager.Init(Configuration.GetVariable("LIGHTTUBE_MONGODB_CONNSTR")); -WebApplication app = builder.Build(); + WebApplication app = builder.Build(); // Configure the HTTP request pipeline. -if (!app.Environment.IsDevelopment()) -{ - app.UseExceptionHandler("/Home/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - app.UseHttpsRedirection(); -} + if (!app.Environment.IsDevelopment()) + { + app.UseExceptionHandler("/Home/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); + app.UseHttpsRedirection(); + } -app.UseStaticFiles(new StaticFileOptions { - OnPrepareResponse = ctx => - { - // Cache static files for 3 days - ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=259200"); - ctx.Context.Response.Headers.Append("Expires", DateTime.UtcNow.AddDays(3).ToString("R", CultureInfo.InvariantCulture)); - } -}); + app.UseStaticFiles(new StaticFileOptions + { + OnPrepareResponse = ctx => + { + // Cache static files for 3 days + ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=259200"); + ctx.Context.Response.Headers.Append("Expires", + DateTime.UtcNow.AddDays(3).ToString("R", CultureInfo.InvariantCulture)); + } + }); -app.UseRouting(); + app.UseRouting(); -app.UseAuthorization(); + app.UseAuthorization(); -app.MapControllerRoute( - name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); + app.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); -app.Run(); \ No newline at end of file + app.Run(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Application terminated unexpectedly"); +} +finally +{ + Log.CloseAndFlush(); +} \ No newline at end of file