Switched server and client logging to built in logging system.

This commit is contained in:
Harrison Deng 2021-05-26 15:10:17 -05:00
parent 862fbe15ed
commit f459cbdfda
15 changed files with 83 additions and 56 deletions

View File

@ -5,14 +5,18 @@ using System.Net.Http;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;
using MultiShop.Client.Module; using MultiShop.Client.Module;
using MultiShop.Shop.Framework; using MultiShop.Shop.Framework;
using SimpleLogger;
namespace MultiShop.Client namespace MultiShop.Client
{ {
public partial class App public partial class App
{ {
[Inject]
private ILogger<App> Logger {get; set; }
private bool modulesLoaded = false; private bool modulesLoaded = false;
private Dictionary<string, IShop> shops = new Dictionary<string, IShop>(); private Dictionary<string, IShop> shops = new Dictionary<string, IShop>();
@ -31,16 +35,16 @@ namespace MultiShop.Client
string[] dependencyNames = await http.GetFromJsonAsync<string[]>("ShopModule/Dependencies"); string[] dependencyNames = await http.GetFromJsonAsync<string[]>("ShopModule/Dependencies");
Dictionary<Task<byte[]>, string> downloadTasks = new Dictionary<Task<byte[]>, string>(); Dictionary<Task<byte[]>, string> downloadTasks = new Dictionary<Task<byte[]>, string>();
Logger.Log("Beginning to download shop modules..."); Logger.LogInformation("Beginning to download shop modules...");
foreach (string moduleName in moduleNames) foreach (string moduleName in moduleNames)
{ {
Logger.Log($"Downloading shop: {moduleName}", LogLevel.Debug); Logger.LogDebug($"Downloading shop: {moduleName}");
downloadTasks.Add(http.GetByteArrayAsync("shopModule/Modules/" + moduleName), moduleName); downloadTasks.Add(http.GetByteArrayAsync("shopModule/Modules/" + moduleName), moduleName);
} }
Logger.Log("Beginning to download shop module dependencies..."); Logger.LogInformation("Beginning to download shop module dependencies...");
foreach (string depName in dependencyNames) foreach (string depName in dependencyNames)
{ {
Logger.Log($"Downloading shop module dependency: {depName}", LogLevel.Debug); Logger.LogDebug($"Downloading shop module dependency: {depName}");
downloadTasks.Add(http.GetByteArrayAsync("ShopModule/Dependencies/" + depName), depName); downloadTasks.Add(http.GetByteArrayAsync("ShopModule/Dependencies/" + depName), depName);
} }
@ -48,16 +52,16 @@ namespace MultiShop.Client
{ {
Task<byte[]> downloadTask = await Task.WhenAny(downloadTasks.Keys); Task<byte[]> downloadTask = await Task.WhenAny(downloadTasks.Keys);
assemblyData.Add(downloadTasks[downloadTask], await downloadTask); assemblyData.Add(downloadTasks[downloadTask], await downloadTask);
Logger.Log($"Shop module \"{downloadTasks[downloadTask]}\" completed downloading.", LogLevel.Debug); Logger.LogDebug($"Shop module \"{downloadTasks[downloadTask]}\" completed downloading.");
downloadTasks.Remove(downloadTask); downloadTasks.Remove(downloadTask);
} }
Logger.Log($"Downloaded {assemblyData.Count} assemblies in total."); Logger.LogInformation($"Downloaded {assemblyData.Count} assemblies in total.");
ShopModuleLoadContext context = new ShopModuleLoadContext(assemblyData); ShopModuleLoadContext context = new ShopModuleLoadContext(assemblyData);
Logger.Log("Beginning to load shop modules."); Logger.LogInformation("Beginning to load shop modules.");
foreach (string moduleName in moduleNames) foreach (string moduleName in moduleNames)
{ {
Logger.Log($"Attempting to load shop module: \"{moduleName}\"", LogLevel.Debug); Logger.LogDebug($"Attempting to load shop module: \"{moduleName}\"");
Assembly moduleAssembly = context.LoadFromAssemblyName(new AssemblyName(moduleName)); Assembly moduleAssembly = context.LoadFromAssemblyName(new AssemblyName(moduleName));
bool shopLoaded = false; bool shopLoaded = false;
foreach (Type type in moduleAssembly.GetTypes()) foreach (Type type in moduleAssembly.GetTypes())
@ -68,22 +72,22 @@ namespace MultiShop.Client
shopLoaded = true; shopLoaded = true;
shop.Initialize(); shop.Initialize();
shops.Add(shop.ShopName, shop); shops.Add(shop.ShopName, shop);
Logger.Log($"Added shop: {shop.ShopName}", LogLevel.Debug); Logger.LogDebug($"Added shop: {shop.ShopName}");
} }
} }
} }
if (!shopLoaded) { if (!shopLoaded) {
Logger.Log($"Module \"{moduleName}\" was reported to be a shop module, but did not contain a shop interface. Please report this to the site administrator.", LogLevel.Warning); Logger.LogWarning($"Module \"{moduleName}\" was reported to be a shop module, but did not contain a shop interface. Please report this to the site administrator.");
} }
} }
Logger.Log($"Shop module loading complete. Loaded a total of {shops.Count} shops."); Logger.LogInformation($"Shop module loading complete. Loaded a total of {shops.Count} shops.");
modulesLoaded = true; modulesLoaded = true;
foreach (string assemblyName in context.UseCounter.Keys) foreach (string assemblyName in context.UseCounter.Keys)
{ {
int usage = context.UseCounter[assemblyName]; int usage = context.UseCounter[assemblyName];
Logger.Log($"\"{assemblyName}\" was used {usage} times.", LogLevel.Debug); Logger.LogDebug($"\"{assemblyName}\" was used {usage} times.");
if (usage <= 0) { if (usage <= 0) {
Logger.Log($"\"{assemblyName}\" was not used at all.", LogLevel.Warning); Logger.LogWarning($"\"{assemblyName}\" was not used. Please report this to the site administrator.");
} }
} }
} }
@ -93,7 +97,6 @@ namespace MultiShop.Client
foreach (string name in shops.Keys) foreach (string name in shops.Keys)
{ {
shops[name].Dispose(); shops[name].Dispose();
Logger.Log($"Ending lifetime of shop module for \"{name}\".", LogLevel.Debug);
} }
} }
} }

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader; using System.Runtime.Loader;
using SimpleLogger;
namespace MultiShop.Client.Module namespace MultiShop.Client.Module
{ {
@ -16,14 +15,17 @@ namespace MultiShop.Client.Module
{ {
this.rawAssemblies = new Dictionary<string, byte[]>(assemblies); this.rawAssemblies = new Dictionary<string, byte[]>(assemblies);
useCounter = new Dictionary<string, int>(); useCounter = new Dictionary<string, int>();
foreach (string name in rawAssemblies.Keys)
{
useCounter[name] = 0;
}
} }
protected override Assembly Load(AssemblyName assemblyName) protected override Assembly Load(AssemblyName assemblyName)
{ {
Logger.Log("ShopModuleLoadContext is attempting to load assembly: " + assemblyName.FullName, LogLevel.Debug);
if (!rawAssemblies.ContainsKey(assemblyName.FullName)) return null; if (!rawAssemblies.ContainsKey(assemblyName.FullName)) return null;
useCounter[assemblyName.FullName] = useCounter.GetValueOrDefault(assemblyName.FullName) + 1; useCounter[assemblyName.FullName] += 1;
using (MemoryStream stream = new MemoryStream(rawAssemblies[assemblyName.FullName])) using (MemoryStream stream = new MemoryStream(rawAssemblies[assemblyName.FullName]))
{ {

View File

@ -9,13 +9,13 @@
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.5" PrivateAssets="all" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.5" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.5" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.5" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="5.0.0" />
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" /> <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\MultiShop.Shared.csproj" /> <ProjectReference Include="..\Shared\MultiShop.Shared.csproj" />
<ProjectReference Include="..\..\MultiShop.Shop\Framework\MultiShop.Shop.Framework.csproj" /> <ProjectReference Include="..\..\MultiShop.Shop\Framework\MultiShop.Shop.Framework.csproj" />
<ProjectReference Include="..\..\..\SimpleLogger\SimpleLogger.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,11 +1,2 @@
@page "/info" @page "/info"
@using Shop.Framework
<div>
</div>
@code {
[CascadingParameter(Name = "Shops")]
public Dictionary<string, IShop> Shops { get; set; }
}

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
using MultiShop.Shop.Framework;
namespace MultiShop.Client.Pages
{
public partial class Info
{
[CascadingParameter(Name = "Shops")]
public Dictionary<string, IShop> Shops { get; set; }
}
}

View File

@ -2,20 +2,21 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.Logging;
using MultiShop.Client.Extensions; using MultiShop.Client.Extensions;
using MultiShop.Client.Listing; using MultiShop.Client.Listing;
using MultiShop.Shared.Models; using MultiShop.Shared.Models;
using MultiShop.Shop.Framework; using MultiShop.Shop.Framework;
using SimpleLogger;
namespace MultiShop.Client.Pages namespace MultiShop.Client.Pages
{ {
public partial class Search : IAsyncDisposable public partial class Search : IAsyncDisposable
{ {
[Inject]
private ILogger<Search> Logger { get; set; }
[CascadingParameter] [CascadingParameter]
Task<AuthenticationState> AuthenticationStateTask { get; set; } Task<AuthenticationState> AuthenticationStateTask { get; set; }
@ -51,14 +52,12 @@ namespace MultiShop.Client.Pages
}; };
if (authState.User.Identity.IsAuthenticated) { if (authState.User.Identity.IsAuthenticated) {
Logger.Log($"User \"{authState.User.Identity.Name}\" is authenticated. Checking for saved profiles.", LogLevel.Debug); Logger.LogDebug($"User \"{authState.User.Identity.Name}\" is authenticated. Checking for saved profiles.");
HttpResponseMessage searchProfileResponse = await Http.GetAsync("Profile/Search"); HttpResponseMessage searchProfileResponse = await Http.GetAsync("Profile/Search");
if (searchProfileResponse.IsSuccessStatusCode) { if (searchProfileResponse.IsSuccessStatusCode) {
activeSearchProfile = await searchProfileResponse.Content.ReadFromJsonAsync<SearchProfile>(); activeSearchProfile = await searchProfileResponse.Content.ReadFromJsonAsync<SearchProfile>();
Logger.Log("Received: " + await searchProfileResponse.Content.ReadAsStringAsync());
Logger.Log("Serialized then deserialized: " + JsonSerializer.Serialize(activeSearchProfile));
} else { } else {
Logger.Log("Could not load search profile from server. Using default.", LogLevel.Warning); Logger.LogWarning("Could not load search profile from server. Using default.");
activeSearchProfile = new SearchProfile(); activeSearchProfile = new SearchProfile();
} }
@ -66,7 +65,7 @@ namespace MultiShop.Client.Pages
if (resultsProfileResponse.IsSuccessStatusCode) { if (resultsProfileResponse.IsSuccessStatusCode) {
activeResultsProfile = await resultsProfileResponse.Content.ReadFromJsonAsync<ResultsProfile>(); activeResultsProfile = await resultsProfileResponse.Content.ReadFromJsonAsync<ResultsProfile>();
} else { } else {
Logger.Log("Could not load results profile from server.", LogLevel.Debug); Logger.LogWarning("Could not load results profile from server. Using default.");
activeResultsProfile = new ResultsProfile(); activeResultsProfile = new ResultsProfile();
} }
} else { } else {
@ -90,7 +89,7 @@ namespace MultiShop.Client.Pages
if (string.IsNullOrWhiteSpace(query)) return; if (string.IsNullOrWhiteSpace(query)) return;
if (status.Searching) return; if (status.Searching) return;
status.Searching = true; status.Searching = true;
Logger.Log($"Received search request for \"{query}\".", LogLevel.Debug); Logger.LogDebug($"Received search request for \"{query}\".");
resultsChecked = 0; resultsChecked = 0;
listings.Clear(); listings.Clear();
Dictionary<ResultsProfile.Category, List<ProductListingInfo>> greatest = new Dictionary<ResultsProfile.Category, Dictionary<ResultsProfile.Category, List<ProductListingInfo>> greatest = new Dictionary<ResultsProfile.Category,
@ -99,7 +98,7 @@ namespace MultiShop.Client.Pages
{ {
if (activeSearchProfile.ShopStates[shopName]) if (activeSearchProfile.ShopStates[shopName])
{ {
Logger.Log($"Querying \"{shopName}\" for products."); Logger.LogDebug($"Querying \"{shopName}\" for products.");
Shops[shopName].SetupSession(query, activeSearchProfile.Currency); Shops[shopName].SetupSession(query, activeSearchProfile.Currency);
int shopViableResults = 0; int shopViableResults = 0;
await foreach (ProductListing listing in Shops[shopName]) await foreach (ProductListing listing in Shops[shopName])
@ -145,11 +144,11 @@ namespace MultiShop.Client.Pages
shopViableResults += 1; shopViableResults += 1;
if (shopViableResults >= activeSearchProfile.MaxResults) break; if (shopViableResults >= activeSearchProfile.MaxResults) break;
} }
Logger.Log($"\"{shopName}\" has completed. There are {listings.Count} results in total.", LogLevel.Debug); Logger.LogDebug($"\"{shopName}\" has completed. There are {listings.Count} results in total.");
} }
else else
{ {
Logger.Log($"Skipping {shopName} since it's disabled."); Logger.LogDebug($"Skipping {shopName} since it's disabled.");
} }
} }
status.Searching = false; status.Searching = false;

View File

@ -2,13 +2,12 @@ using System;
using System.Net.Http; using System.Net.Http;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using SimpleLogger;
using System.Net.Http.Json; using System.Net.Http.Json;
using Microsoft.Extensions.Logging;
namespace MultiShop.Client namespace MultiShop.Client
{ {
@ -16,18 +15,17 @@ namespace MultiShop.Client
{ {
public static async Task Main(string[] args) public static async Task Main(string[] args)
{ {
Logger.AddLogListener(new ConsoleLogReceiver() {Level = LogLevel.Debug});
var builder = WebAssemblyHostBuilder.CreateDefault(args); var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging"));
builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<App>("#app");
builder.Services.AddHttpClient("MultiShop.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>(); builder.Services.AddHttpClient("MultiShop.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("MultiShop.ServerAPI")); builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("MultiShop.ServerAPI"));
Action<HttpClient> configureClient = client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress); Action<HttpClient> configureClient = client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
builder.Services.AddHttpClient("Public-MultiShop.ServerAPI", configureClient); builder.Services.AddHttpClient("Public-MultiShop.ServerAPI", configureClient);
IReadOnlyDictionary<string, string> webApiConfig = null; IReadOnlyDictionary<string, string> webApiConfig = null;
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
@ -37,6 +35,7 @@ namespace MultiShop.Client
builder.Configuration.AddInMemoryCollection(webApiConfig); builder.Configuration.AddInMemoryCollection(webApiConfig);
builder.Services.AddApiAuthorization(); builder.Services.AddApiAuthorization();
await builder.Build().RunAsync(); await builder.Build().RunAsync();

View File

@ -1,4 +1,3 @@
@using SimpleLogger
@typeparam TItem @typeparam TItem
@inject IJSRuntime JS @inject IJSRuntime JS

View File

@ -9,5 +9,4 @@
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using MultiShop.Client @using MultiShop.Client
@using MultiShop.Client.Shared @using MultiShop.Client.Shared
@using Shop.Framework @using MultiShop.Shop.Framework
@using SimpleLogger

View File

@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"MultiShop": "Debug"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
<div class="my-1 text-muted"> <div class="my-1 text-muted">
Loading app... Loading...
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,10 +2,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using Castle.Core.Logging;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using MultiShop.Server.Options; using MultiShop.Server.Options;
using SimpleLogger;
namespace MultiShop.Server.Controllers namespace MultiShop.Server.Controllers
{ {
@ -13,13 +14,15 @@ namespace MultiShop.Server.Controllers
[Route("[controller]")] [Route("[controller]")]
public class ShopModuleController : ControllerBase public class ShopModuleController : ControllerBase
{ {
private readonly ILogger<ShopModuleController> logger;
private readonly IConfiguration configuration; private readonly IConfiguration configuration;
private IDictionary<string, byte[]> shopModules; private IDictionary<string, byte[]> shopModules;
private IDictionary<string, byte[]> shopModuleDependencies; private IDictionary<string, byte[]> shopModuleDependencies;
public ShopModuleController(IConfiguration configuration) public ShopModuleController(IConfiguration configuration, ILogger<ShopModuleController> logger)
{ {
this.logger = logger;
this.configuration = configuration; this.configuration = configuration;
this.shopModules = new Dictionary<string, byte[]>(); this.shopModules = new Dictionary<string, byte[]>();
this.shopModuleDependencies = new Dictionary<string, byte[]>(); this.shopModuleDependencies = new Dictionary<string, byte[]>();
@ -33,10 +36,10 @@ namespace MultiShop.Server.Controllers
shopModules.Add(assemblyName.FullName, System.IO.File.ReadAllBytes(file)); shopModules.Add(assemblyName.FullName, System.IO.File.ReadAllBytes(file));
} }
catch (BadImageFormatException e) { catch (BadImageFormatException e) {
Logger.Log($"\"{e.FileName}\" is not a valid assembly. Ignoring.", LogLevel.Warning); logger.LogWarning($"\"{e.FileName}\" is not a valid assembly. Ignoring.");
} }
catch (ArgumentException) { catch (ArgumentException) {
Logger.Log($"\"{Path.GetFileName(file)}\" has the same full name as another assembly. Ignoring this one.", LogLevel.Warning); logger.LogWarning($"\"{Path.GetFileName(file)}\" has the same full name as another assembly. Ignoring this one.");
} }
} }
@ -48,10 +51,10 @@ namespace MultiShop.Server.Controllers
shopModuleDependencies.Add(assemblyName.FullName, System.IO.File.ReadAllBytes(file)); shopModuleDependencies.Add(assemblyName.FullName, System.IO.File.ReadAllBytes(file));
} }
catch (BadImageFormatException e) { catch (BadImageFormatException e) {
Logger.Log($"\"{e.FileName}\" is not a valid assembly. Ignoring.", LogLevel.Warning); logger.LogWarning($"\"{e.FileName}\" is not a valid assembly. Ignoring.");
} }
catch (ArgumentException) { catch (ArgumentException) {
Logger.Log($"\"{Path.GetFileName(file)}\" has the same full name as another assembly. Ignoring this one.", LogLevel.Warning); logger.LogWarning($"\"{Path.GetFileName(file)}\" has the same full name as another assembly. Ignoring this one.");
} }
} }
} }

View File

@ -3,7 +3,8 @@
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",
"Microsoft": "Warning", "Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information",
"MultiShop": "Debug"
} }
}, },
"IdentityServer": { "IdentityServer": {