diff --git a/zero/Frontend/ZeroViteModule.cs b/zero/Frontend/ZeroViteModule.cs new file mode 100644 index 00000000..284bf4cd --- /dev/null +++ b/zero/Frontend/ZeroViteModule.cs @@ -0,0 +1,99 @@ +using Microsoft.AspNetCore.Builder; +#if DEBUG +using ViteProxy; +#endif + +namespace zero.Frontend; + +public static class ZeroBuilderExtensions +{ + public static ZeroBuilder AddVite(this ZeroBuilder builder) + { +#if DEBUG + builder.Services.AddViteProxy("Zero:Vite"); +#endif + return builder; + } +} + +public static class ViteProxyApplicationBuilderExtensions +{ + public static IApplicationBuilder UseVite(this IApplicationBuilder app, string path = null, string configName = null) + { +#if DEBUG + app.UseViteStaticFiles(path, configName); +#endif + return app; + } +} + +// internal class ZeroViteModule : ZeroModule +// { +// public override int ConfigureOrder { get; } = -1; +// +// public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) +// { +// #if DEBUG +// services.AddViteProxy(); +// +// services.AddHttpClient("vite-proxy") +// .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler +// { +// UseCookies = false, +// AllowAutoRedirect = false, +// AutomaticDecompression = System.Net.DecompressionMethods.None, +// PooledConnectionLifetime = TimeSpan.FromMinutes(5), +// PooledConnectionIdleTimeout = TimeSpan.FromMinutes(2), +// MaxConnectionsPerServer = 256 +// }); +// #endif +// } +// +// +// public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) +// { +// #if DEBUG +// app.UseViteStaticFiles(); +// #endif +// // +// // app.Use(async (context, next) => +// // { +// // if (context.Request.Path.StartsWithSegments("/@viteproxy", out _)) +// // { +// // var targetUri = new Uri($"http://localhost:5123{context.Request.Path}{context.Request.QueryString}"); +// // +// // var client = context.RequestServices.GetRequiredService() +// // .CreateClient("vite-proxy"); +// // +// // using var requestMessage = new HttpRequestMessage(new HttpMethod(context.Request.Method), targetUri); +// // +// // if (context.Request.ContentLength > 0) +// // requestMessage.Content = new StreamContent(context.Request.Body); +// // +// // if (!string.IsNullOrEmpty(context.Request.ContentType) && requestMessage.Content != null) +// // requestMessage.Content.Headers.TryAddWithoutValidation("Content-Type", context.Request.ContentType); +// // +// // using var responseMessage = await client.SendAsync( +// // requestMessage, +// // HttpCompletionOption.ResponseHeadersRead, +// // context.RequestAborted); +// // +// // context.Response.StatusCode = (int)responseMessage.StatusCode; +// // +// // foreach (var header in responseMessage.Headers) +// // context.Response.Headers[header.Key] = header.Value.ToArray(); +// // +// // foreach (var header in responseMessage.Content.Headers) +// // context.Response.Headers[header.Key] = header.Value.ToArray(); +// // +// // context.Response.Headers.Remove("transfer-encoding"); +// // context.Response.Headers.Remove("connection"); +// // +// // await responseMessage.Content.CopyToAsync(context.Response.Body, context.RequestAborted); +// // return; +// // } +// // +// // await next(); +// // }); +// } +// } \ No newline at end of file diff --git a/zero/Logging/LogLevelOverrides.cs b/zero/Logging/LogLevelOverrides.cs new file mode 100644 index 00000000..b1914f5e --- /dev/null +++ b/zero/Logging/LogLevelOverrides.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using Microsoft.Extensions.Logging; + +namespace zero.Logging; + +public class LogLevelOverrides : Dictionary +{ + public LogLevelOverrides()//IHostEnvironment env) + { + this["zero"] = LogLevel.Debug; + this["zero.Routing"] = LogLevel.Debug; + + // if (env.IsDevelopment()) + // { + // this["zero"] = LogLevel.Debug; + // this["zero.Routing"] = LogLevel.Debug; + // } + // else + // { + // this["zero"] = LogLevel.Debug; + // } + + this["SixLabors"] = LogLevel.Warning; + this["Quartz"] = LogLevel.Warning; + this["Microsoft.AspNetCore"] = LogLevel.Warning; + + string executingAssemblyName = Assembly.GetExecutingAssembly().GetName().Name; + if (executingAssemblyName != null) + { + this[executingAssemblyName] = LogLevel.Debug; + } + } +} \ No newline at end of file diff --git a/zero/Logging/ZeroLoggingModule.cs b/zero/Logging/ZeroLoggingModule.cs new file mode 100644 index 00000000..7a220a0e --- /dev/null +++ b/zero/Logging/ZeroLoggingModule.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace zero.Logging; + +public class ZeroLoggingModule : ZeroModule +{ + public override int Order { get; } = -100; + + + public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + services.AddLogging(builder => + { + // get seq configuration + IConfigurationSection seqConfig = configuration.GetSection("Zero:Seq"); + ZeroSeqOptions seqOptions = seqConfig.Get(); + + Console.WriteLine(seqOptions.ApiKey); + Console.WriteLine(seqOptions.ServerUrl); + Console.WriteLine("use seq: " + seqConfig.Exists()); + + // default level + builder.SetMinimumLevel(seqOptions.MinimumLevel); + + // apply log level overrides from zero + foreach (KeyValuePair levelOverride in seqOptions.LevelOverrides) + { + builder.AddFilter(levelOverride.Key, levelOverride.Value); + } + + // add optional seq sink + if (seqConfig.Exists()) + { + builder.AddSeq(seqOptions.ServerUrl, seqOptions.ApiKey, seqOptions.Enrichers); + } + }); + } +} \ No newline at end of file diff --git a/zero/Logging/ZeroSeqOptions.cs b/zero/Logging/ZeroSeqOptions.cs new file mode 100644 index 00000000..09abe036 --- /dev/null +++ b/zero/Logging/ZeroSeqOptions.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.Logging; +using Seq.Extensions.Logging; + +namespace zero.Logging; + +public class ZeroSeqOptions +{ + /// + /// URL to the Seq server + /// + public string ServerUrl { get; set; } = "http://localhost:5341"; + + /// + /// A Seq API key to authenticate or tag messages from the logger + /// + public string ApiKey { get; set; } + + /// + /// The level below which events will be suppressed + /// + public LogLevel MinimumLevel { get; set; } = LogLevel.Information; + + /// + /// A dictionary mapping logger name prefixes to minimum logging levels. + /// + public Dictionary LevelOverrides { get; set; } = new LogLevelOverrides(); + + /// + /// A collection of enrichers to apply. + /// + public List> Enrichers { get; set; } = []; +} \ No newline at end of file diff --git a/zero/ZeroBuilder.cs b/zero/ZeroBuilder.cs index 9b9a3643..27d5f587 100644 --- a/zero/ZeroBuilder.cs +++ b/zero/ZeroBuilder.cs @@ -1,9 +1,8 @@ using FluentValidation; using Microsoft.AspNetCore.Antiforgery; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using zero.Logging; using zero.Mails; using zero.Metadata; using zero.Mvc; @@ -52,7 +51,8 @@ public class ZeroBuilder // adds and discovers additional and built-in assemblies new AssemblyDiscovery(Mvc).Execute(_startupOptions.AssemblyDiscoveryRules); - + + Modules.Add(); Modules.Add(); Modules.Add(); Modules.Add(); diff --git a/zero/zero.csproj b/zero/zero.csproj index 16940bc4..c1c3096c 100644 --- a/zero/zero.csproj +++ b/zero/zero.csproj @@ -18,9 +18,14 @@ + + + + +