初步调整Serilog

This commit is contained in:
LemonNoCry 2023-04-01 23:25:56 +08:00
parent d1288b103e
commit 0d2a95e0e9
45 changed files with 1138 additions and 956 deletions

2
.gitignore vendored
View File

@ -356,3 +356,5 @@ Blog.Core/Blog.Core*.xml
Blog.Core.Api/WMBlog.db
Blog.Core.Api/wwwroot/ui/
*.db
/Blog.Core.Api/WMBlog.db-journal
Logs

View File

@ -26,21 +26,25 @@
<ItemGroup>
<Compile Remove="Extensions\**" />
<Compile Remove="Hubs\**" />
<Compile Remove="Logs\**" />
<Compile Remove="Log\**" />
<Compile Remove="Middlewares\**" />
<Compile Remove="wwwroot\ui\**" />
<Content Remove="Extensions\**" />
<Content Remove="Hubs\**" />
<Content Remove="Logs\**" />
<Content Remove="Log\**" />
<Content Remove="Middlewares\**" />
<Content Remove="wwwroot\ui\**" />
<EmbeddedResource Remove="Extensions\**" />
<EmbeddedResource Remove="Hubs\**" />
<EmbeddedResource Remove="Logs\**" />
<EmbeddedResource Remove="Log\**" />
<EmbeddedResource Remove="Middlewares\**" />
<EmbeddedResource Remove="wwwroot\ui\**" />
<None Remove="Extensions\**" />
<None Remove="Hubs\**" />
<None Remove="Logs\**" />
<None Remove="Log\**" />
<None Remove="Middlewares\**" />
<None Remove="wwwroot\ui\**" />
@ -51,8 +55,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="log4mongo-netcore" Version="3.2.0" />
<PackageReference Include="MicroKnights.Log4NetAdoNetAppender" Version="2.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="7.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />

View File

@ -760,7 +760,7 @@
Values控制器
</summary>
</member>
<member name="M:Blog.Core.Controllers.ValuesController.#ctor(Blog.Core.IServices.IBlogArticleServices,AutoMapper.IMapper,Blog.Core.IServices.IAdvertisementServices,Blog.Core.Model.Love,Blog.Core.IServices.IRoleModulePermissionServices,Blog.Core.Common.HttpContextUser.IUser,Blog.Core.IServices.IPasswordLibServices,Blog.Core.Common.WebApiClients.HttpApis.IBlogApi,Blog.Core.Common.WebApiClients.HttpApis.IDoubanApi,Blog.Core.Common.HttpPolly.IHttpPollyHelper)">
<member name="M:Blog.Core.Controllers.ValuesController.#ctor(Blog.Core.IServices.IBlogArticleServices,AutoMapper.IMapper,Blog.Core.IServices.IAdvertisementServices,Blog.Core.Model.Love,Blog.Core.IServices.IRoleModulePermissionServices,Blog.Core.Common.HttpContextUser.IUser,Blog.Core.IServices.IPasswordLibServices,Blog.Core.Common.WebApiClients.HttpApis.IBlogApi,Blog.Core.Common.WebApiClients.HttpApis.IDoubanApi,Blog.Core.Common.Https.HttpPolly.IHttpPollyHelper)">
<summary>
ValuesController
</summary>

View File

@ -1,7 +1,7 @@
using AutoMapper;
using Blog.Core.Common;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.Common.HttpPolly;
using Blog.Core.Common.Https.HttpPolly;
using Blog.Core.Common.WebApiClients.HttpApis;
using Blog.Core.EventBus;
using Blog.Core.EventBus.EventHandling;

View File

@ -3,14 +3,10 @@ using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Blog.Core.Hubs;
using Blog.Core.Model;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using StackExchange.Profiling;
using System;
namespace Blog.Core.Filter
{
@ -54,7 +50,7 @@ namespace Blog.Core.Filter
MiniProfiler.Current.CustomTiming("Errors", json.msg);
//采用log4net 进行错误日志记录
//进行错误日志记录
_loggerHelper.LogError(json.msg + WriteLog(json.msg, context.Exception));
if (AppSettings.app(new string[] { "Middleware", "SignalRSendLog", "Enabled" }).ObjToBool())
{

View File

@ -1,364 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<log4net>
<!--BEGIN*************** SQLite 结构化记录日志 *************************BEGIN -->
<!--2022/11/23 原因结构化日志SQLite支持,PR2022/11/23-->
<appender name="SQLiteAdoNetAppenderStructured" type="MicroKnights.Logging.AdoNetAppender, MicroKnights.Log4NetAdoNetAppender">
<bufferSize value="1" />
<connectionType value="Microsoft.Data.Sqlite.SqliteConnection, Microsoft.Data.Sqlite, Version=7.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" />
<connectionStringName value="sqlite" />
<connectionString value="Data Source=WMBlog.db" />
<commandText value="INSERT INTO GblLogAudit ([Date],[Thread],[Level],[Logger],[LogType],[DataType],[Message],[Exception],[TraceId]) VALUES (@log_date, @thread, @log_level, @logger,@logType,@dataType, @message, @exception,@traceId)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@logType" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{LogType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@dataType" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{DataType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="@traceId" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{TraceId}" />
</layout>
</parameter>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
</appender>
<!--END***************** SQLite 结构化记录日志 ***********************END -->
<!--BEGIN*************** SQLServer 结构化记录日志 *************************BEGIN -->
<!--2022/11/27 原因结构化日志SQLServer支持,PR2022/11/27-->
<!--如若使用请配置connectionString 节点复制appsettings.json对应配置字符替换即可-->
<!--然后启用下方日志记录器SQLServerAdoNetAppenderStructured-->
<appender name="SQLServerAdoNetAppenderStructured" type="MicroKnights.Logging.AdoNetAppender, MicroKnights.Log4NetAdoNetAppender">
<bufferSize value="1" />
<connectionType value="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient, Version=1.0.0.0,Culture=neutral,PublicKeyToken=23ec7fc2d6eaa4a5"/>
<connectionStringName value="sqlserver" />
<connectionString value="Server=xxxxxx;Database=xxxxxx;User Id=xx;Password=xxxxxx;" />
<commandText value="INSERT INTO GblLogAudit ([Date],[Thread],[Level],[Logger],[LogType],[DataType],[Message],[Exception],[TraceId]) VALUES (@log_date, @thread, @log_level, @logger,@logType,@dataType, @message, @exception,@traceId)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@logType" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{LogType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@dataType" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{DataType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="@traceId" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{TraceId}" />
</layout>
</parameter>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
</appender>
<!--END***************** SQLServer 结构化记录日志 ***********************END -->
<!--******************** MySQL 结构化记录日志 ********************BEGIN -->
<!--2022/11/27 原因结构化日志MySQL支持,PR2022/11/27-->
<!--如若使用请配置connectionString 节点复制appsettings.json对应配置字符替换即可-->
<!--然后启用下方日志记录器MySQLAdoNetAppenderStructured-->
<appender name="MySQLAdoNetAppenderStructured" type="MicroKnights.Logging.AdoNetAppender, MicroKnights.Log4NetAdoNetAppender">
<bufferSize value="1" />
<usetransactions value="false" />
<connectionType value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data, Version=8.0.21, Culture=neutral" />
<connectionStringName value="mysql" />
<connectionString value="server=xxxxxx;Database=xxxxxx;Uid=root;Pwd=xxxxxx;Port=3306;Allow User Variables=True;" />
<commandText value="INSERT INTO GblLogAudit (Date,Thread,Level,Logger,LogType,DataType,Message,Exception,TraceId) VALUES (@log_date, @thread, @log_level, @logger,@logType,@dataType, @message, @exception,@traceId)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@logType" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{LogType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@dataType" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{DataType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="@traceId" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{TraceId}" />
</layout>
</parameter>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
</appender>
<!--END***************** MySQL 结构化记录日志 ***********************END -->
<!--BEGIN*************** PostgreSql 结构化记录日志 *************************BEGIN -->
<!--2023/01/31 原因结构化日志PostgreSql支持,PR2023/01/31-->
<!--如若使用请配置connectionString 节点复制appsettings.json对应配置字符替换即可-->
<!--然后启用下方日志记录器PostgreSql-->
<appender name="PostgreSqlAdoNetAppenderStructured" type="MicroKnights.Logging.AdoNetAppender, MicroKnights.Log4NetAdoNetAppender">
<!--bufferSize缓存大小-->
<bufferSize value="1" />
<connectionType value="Npgsql.NpgsqlConnection, Npgsql, Version=5.0.7, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"/>
<connectionStringName value="postgresql" />
<connectionString value="PORT=5432;DATABASE=xxxxxx;HOST=xxxxxx;PASSWORD=xxxxxx;USER ID=postgres;" />
<commandText value="INSERT INTO GblLogAudit (Date,Thread,Level,Logger,LogType,DataType,Message,Exception,TraceId) VALUES (:log_date, :thread, :log_level, :logger,:logType,:dataType, :message, :exception,:traceId)" />
<!--参数eg:value="@log_date")名前面的@ 可删可不删测试都可以正常写入日志这里保持和上面sqlserver一致不删除-->
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@logType" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{LogType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@dataType" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{DataType}" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="999999999" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="@traceId" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{TraceId}" />
</layout>
</parameter>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
</appender>
<!--END***************** PostgreSql 结构化记录日志 ***********************END -->
<!--启用记录器-->
<root>
<!-- 控制级别由低到高ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF -->
<!-- 比如定义级别为INFO则INFO级别向下的级别比如DEBUG日志将不会被记录 -->
<!-- 如果没有定义LEVEL的值则缺省为DEBUG -->
<level value="ALL" />
<!--启用日志记录器,目前提供三种日志记录器-->
<!--SQLite日志-->
<appender-ref ref="SQLiteAdoNetAppenderStructured" />
<!--SQLServer日志记录器-->
<!--<appender-ref ref="SQLServerAdoNetAppenderStructured" />-->
<!--MySQL日志记录器-->
<!--<appender-ref ref="MySQLAdoNetAppenderStructured" />-->
<!--PostgreSql日志记录器-->
<!--<appender-ref ref="PostgreSqlAdoNetAppenderStructured" />-->
<!--启用日志记录器,目前提供三种日志记录器-->
</root>
<!--启用记录器-->
</log4net>

View File

@ -1,20 +1,16 @@
// 以下为asp.net 6.0的写法如果用5.0请看Program.five.cs文件
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Text;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Blog.Core;
using Blog.Core.Common;
using Blog.Core.Common.Core;
using Blog.Core.Common.LogHelper;
using Blog.Core.Extensions;
using Blog.Core.Extensions.Apollo;
using Blog.Core.Extensions.Middlewares;
using Blog.Core.Extensions.ServiceExtensions;
using Blog.Core.Filter;
using Blog.Core.Hubs;
using Blog.Core.IServices;
using Blog.Core.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Server.Kestrel.Core;
@ -22,34 +18,38 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Serilog;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Text;
using Blog.Core.Common.Https;
using Blog.Core.Serilog.Utility;
var builder = WebApplication.CreateBuilder(args);
// 1、配置host与容器
builder.Host
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule(new AutofacModuleRegister());
builder.RegisterModule<AutofacPropertityModuleReg>();
})
.ConfigureLogging((hostingContext, builder) =>
{
builder.AddFilter("System", LogLevel.Error);
builder.AddFilter("Microsoft", LogLevel.Error);
builder.SetMinimumLevel(LogLevel.Error);
builder.AddLog4Net(Path.Combine(Directory.GetCurrentDirectory(), "Log4net.config"));
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.Sources.Clear();
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
config.AddConfigurationApollo("appsettings.apollo.json");
});
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule(new AutofacModuleRegister());
builder.RegisterModule<AutofacPropertityModuleReg>();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.Sources.Clear();
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
config.AddConfigurationApollo("appsettings.apollo.json");
});
builder.ConfigureApplication();
// 2、配置服务
builder.Services.AddSingleton(new AppSettings(builder.Configuration));
builder.Services.AddSingleton(new LogLock(builder.Environment.ContentRootPath));
builder.Services.AddUiFilesZipSetup(builder.Environment);
Permissions.IsUseIds4 = AppSettings.app(new string[] { "Startup", "IdentityServer4", "Enabled" }).ObjToBool();
@ -62,6 +62,9 @@ builder.Services.AddMemoryCacheSetup();
builder.Services.AddRedisCacheSetup();
builder.Services.AddSqlsugarSetup();
builder.Services.AddDbSetup();
builder.Host.AddSerilogSetup();
builder.Services.AddAutoMapperSetup();
builder.Services.AddCorsSetup();
builder.Services.AddMiniProfilerSetup();
@ -92,34 +95,34 @@ builder.Services.AddIpPolicyRateLimitSetup(builder.Configuration);
builder.Services.AddSignalR().AddNewtonsoftJsonProtocol();
builder.Services.AddScoped<UseServiceDIAttribute>();
builder.Services.Configure<KestrelServerOptions>(x => x.AllowSynchronousIO = true)
.Configure<IISServerOptions>(x => x.AllowSynchronousIO = true);
.Configure<IISServerOptions>(x => x.AllowSynchronousIO = true);
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();
builder.Services.AddHttpPollySetup();
builder.Services.AddControllers(o =>
{
o.Filters.Add(typeof(GlobalExceptionsFilter));
//o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
})
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
options.SerializerSettings.Converters.Add(new StringEnumConverter());
})
//.AddFluentValidation(config =>
//{
// //程序集方式添加验证
// config.RegisterValidatorsFromAssemblyContaining(typeof(UserRegisterVoValidator));
// //是否与MvcValidation共存
// config.DisableDataAnnotationsValidation = true;
//})
;
{
o.Filters.Add(typeof(GlobalExceptionsFilter));
//o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
})
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
options.SerializerSettings.Converters.Add(new StringEnumConverter());
})
//.AddFluentValidation(config =>
//{
// //程序集方式添加验证
// config.RegisterValidatorsFromAssemblyContaining(typeof(UserRegisterVoValidator));
// //是否与MvcValidation共存
// config.DisableDataAnnotationsValidation = true;
//})
;
builder.Services.AddEndpointsApiExplorer();
@ -159,12 +162,23 @@ app.UseDefaultFiles(defaultFilesOptions);
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseStatusCodePages();
app.UseSerilogRequestLogging(options =>
{
options.GetLevel = SerilogRequestUtility.GetRequestLevel;
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
diagnosticContext.Set("RequestIp", httpContext.GetRequestIp());
};
});
app.UseRouting();
if (builder.Configuration.GetValue<bool>("AppSettings:UseLoadTest"))
{
app.UseMiddleware<ByPassAuthMiddleware>();
}
app.UseAuthentication();
app.UseAuthorization();
app.UseMiniProfilerMiddleware();

View File

@ -39,7 +39,6 @@ namespace Blog.Core
{
// 以下code可能与文章中不一样,对代码做了封装,具体查看右侧 Extensions 文件夹.
services.AddSingleton(new AppSettings(Configuration));
services.AddSingleton(new LogLock(Env.ContentRootPath));
services.AddUiFilesZipSetup(Env);
Permissions.IsUseIds4 = AppSettings.app(new string[] { "Startup", "IdentityServer4", "Enabled" }).ObjToBool();

View File

@ -1,98 +1,92 @@
{
"urls": "http://*:9291", //webIIS
"Logging": {
"LogLevel": {
"Default": "Information", //Defaultlog4net
"Blog.Core.AuthHelper.ApiResponseHandler": "Error"
},
"Debug": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning",
"Microsoft.Hosting.Lifetime": "Debug"
}
},
"Log4Net": {
"Name": "Blog.Core"
}
"urls": "http://*:9291", //webIIS
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Information",
"Microsoft.AspNetCore": "Warning",
"System": "Warning",
"System.Net.Http.HttpClient": "Warning",
"Hangfire": "Information",
"Magicodes": "Warning",
"DotNetCore.CAP": "Information",
"Savorboard.CAP": "Information",
"Quartz": "Information"
}
}
},
"AllowedHosts": "*",
"Redis": {
"ConnectionString": "127.0.0.1:6319,password=admin"
},
"RabbitMQ": {
"Enabled": false,
"Connection": "118.25.251.13",
"UserName": "",
"Password": "!",
"RetryCount": 3
},
"Kafka": {
"Enabled": false,
"Servers": "localhost:9092",
"Topic": "blog",
"GroupId": "blog-consumer",
"NumPartitions": 3 //
},
"EventBus": {
"Enabled": false,
"SubscriptionClientName": "Blog.Core"
},
"AppSettings": {
"RedisCachingAOP": {
"Enabled": false
},
"AllowedHosts": "*",
"Redis": {
"ConnectionString": "127.0.0.1:6319,password=admin"
"MemoryCachingAOP": {
"Enabled": true
},
"RabbitMQ": {
"Enabled": false,
"Connection": "118.25.251.13",
"UserName": "",
"Password": "!",
"RetryCount": 3
"LogAOP": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
}
},
"Kafka": {
"Enabled": false,
"Servers": "localhost:9092",
"Topic": "blog",
"GroupId": "blog-consumer",
"NumPartitions": 3 //
"TranAOP": {
"Enabled": true
},
"EventBus": {
"Enabled": false,
"SubscriptionClientName": "Blog.Core"
},
"AppSettings": {
"RedisCachingAOP": {
"Enabled": false
},
"MemoryCachingAOP": {
"Enabled": true
},
"LogAOP": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
}
},
"TranAOP": {
"Enabled": true
},
"SqlAOP": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": false
},
"LogToConsole": {
"Enabled": true
}
},
"Date": "2018-08-28",
"SeedDBEnabled": true, //
"SeedDBDataEnabled": true, //,
"Author": "Blog.Core",
"SvcName": "", // /svc/blog
"UseLoadTest": false
"SqlAOP": {
"Enabled": true,
"LogToFile": {
"Enabled": true
},
"LogToDB": {
"Enabled": false
},
"LogToConsole": {
"Enabled": true
}
},
"Date": "2018-08-28",
"SeedDBEnabled": true, //
"SeedDBDataEnabled": true, //,
"Author": "Blog.Core",
"SvcName": "", // /svc/blog
"UseLoadTest": false
},
// MainDBConnId,Enabledtrue
// *** MutiDBEnabled false ***
// *** MutiDBEnabled trueEnabledtrue **
// https://www.bilibili.com/video/BV1BJ411B7mn?p=6
"MainDB": "WMBLOG_SQLITE", //Enabledtrue
"MutiDBEnabled": false, //
"CQRSEnabled": false, //,SqlServer
"DBS": [
/*
// MainDBConnId,Enabledtrue
// *** MutiDBEnabled false ***
// *** MutiDBEnabled trueEnabledtrue **
// https://www.bilibili.com/video/BV1BJ411B7mn?p=6
//Log:
"MainDB": "WMBLOG_SQLITE", //Enabledtrue
"MutiDBEnabled": true, //
"CQRSEnabled": false, //,SqlServer
"DBS": [
/*
DBType
MySql = 0,
SqlServer = 1,
@ -102,225 +96,232 @@
Dm = 5,//
Kdbndp = 6,//
*/
{
"ConnId": "WMBLOG_SQLITE",
"DBType": 2,
"Enabled": true,
"HitRate": 50, //
"Connection": "WMBlog.db" //sqlite
},
{
"ConnId": "WMBLOG_MSSQL_1",
"DBType": 1,
"Enabled": false,
"HitRate": 40,
"Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
"ProviderName": "System.Data.SqlClient"
},
{
"ConnId": "WMBLOG_MSSQL_2",
"DBType": 1,
"Enabled": false,
"HitRate": 30,
"Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
"ProviderName": "System.Data.SqlClient"
},
{
"ConnId": "WMBLOG_MYSQL",
"DBType": 0,
"Enabled": false,
"HitRate": 20,
"Connection": "server=localhost;Database=blog;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
},
{
"ConnId": "WMBLOG_MYSQL_2",
"DBType": 0,
"Enabled": false,
"HitRate": 20,
"Connection": "server=localhost;Database=blogcore001;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
},
{
"ConnId": "WMBLOG_ORACLE",
"DBType": 3,
"Enabled": false,
"HitRate": 10,
"Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
},
{
"ConnId": "WMBLOG_DM",
"DBType": 5,
"Enabled": false,
"HitRate": 10,
"Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
},
{
"ConnId": "WMBLOG_KDBNDP",
"DBType": 6,
"Enabled": false,
"HitRate": 10,
"Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
}
],
"Audience": {
"Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //16+
"SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //Secret
"Issuer": "Blog.Core",
"Audience": "wr"
{
"ConnId": "WMBLOG_SQLITE",
"DBType": 2,
"Enabled": true,
"HitRate": 50, //
"Connection": "WMBlog.db" //sqlite
},
"Mongo": {
"ConnectionString": "mongodb://nosql.data",
"Database": "BlogCoreDb"
{
"ConnId": "Log",
"DBType": 2,
"Enabled": true,
"HitRate": 50, //
"Connection": "WMBlogLog.db" //sqlite
},
"Startup": {
"Domain": "http://localhost:9291",
"Cors": {
"PolicyName": "CorsIpAccess", //
"EnableAllIPs": false, //trueIP访
// /localhost:8000/
// http://127.0.0.1:1818 http://localhost:1818
"IPs": "http://127.0.0.1:2364,http://localhost:2364,http://127.0.0.1:6688,http://localhost:6688"
},
"AppConfigAlert": {
"Enabled": true
},
"ApiName": "Blog.Core",
"IdentityServer4": {
"Enabled": false, // false使jwttrue使Ids4
"AuthorizationUrl": "http://localhost:5004", //
"ApiName": "blog.core.api" //
},
"Authing": {
"Enabled": false,
"Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
"Audience": "63d51c4205c2849803be5178",
"JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
},
"RedisMq": {
"Enabled": false //redis
},
"MiniProfiler": {
"Enabled": false //
},
"Nacos": {
"Enabled": false //Nacos
}
{
"ConnId": "WMBLOG_MSSQL_1",
"DBType": 1,
"Enabled": false,
"HitRate": 40,
"Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
"ProviderName": "System.Data.SqlClient"
},
"Middleware": {
"RequestResponseLog": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
}
},
"IPLog": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
}
},
"RecordAccessLogs": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
},
"IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
},
"SignalR": {
"Enabled": false
},
"SignalRSendLog": {
"Enabled": false
},
"QuartzNetJob": {
"Enabled": true
},
"Consul": {
"Enabled": false
},
"IpRateLimit": {
"Enabled": true
}
{
"ConnId": "WMBLOG_MSSQL_2",
"DBType": 1,
"Enabled": false,
"HitRate": 30,
"Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
"ProviderName": "System.Data.SqlClient"
},
"IpRateLimiting": {
"EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
"StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"IpWhitelist": [], //
"EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
"ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
"QuotaExceededResponse": {
"Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
"ContentType": "application/json",
"StatusCode": 429
},
"HttpStatusCode": 429, //
"GeneralRules": [ //api,*
{
"Endpoint": "*:/api/blog*",
"Period": "1m",
"Limit": 20
},
{
"Endpoint": "*/api/*",
"Period": "1s",
"Limit": 3
},
{
"Endpoint": "*/api/*",
"Period": "1m",
"Limit": 30
},
{
"Endpoint": "*/api/*",
"Period": "12h",
"Limit": 500
}
]
{
"ConnId": "WMBLOG_MYSQL",
"DBType": 0,
"Enabled": false,
"HitRate": 20,
"Connection": "server=localhost;Database=blog;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
},
"ConsulSetting": {
"ServiceName": "BlogCoreService",
"ServiceIP": "localhost",
"ServicePort": "9291",
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
{
"ConnId": "WMBLOG_MYSQL_2",
"DBType": 0,
"Enabled": false,
"HitRate": 20,
"Connection": "server=localhost;Database=blogcore001;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
},
"PayInfo": { //
"MERCHANTID": "", //
"POSID": "", //
"BRANCHID": "", //
"pubKey": "", //
"USER_ID": "", //
"PASSWORD": "", //
"OutAddress": "http://127.0.0.1:12345" //
{
"ConnId": "WMBLOG_ORACLE",
"DBType": 3,
"Enabled": false,
"HitRate": 10,
"Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
},
"nacos": {
"ServerAddresses": [ "http://localhost:8848" ], // nacos
"DefaultTimeOut": 15000, //
"Namespace": "public", //
"ListenInterval": 10000, //
"ServiceName": "blog.Core.Api", //
"Port": "9291", //
"RegisterEnabled": true // nacos
{
"ConnId": "WMBLOG_DM",
"DBType": 5,
"Enabled": false,
"HitRate": 10,
"Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
},
"LogFiedOutPutConfigs": {
"tcpAddressHost": "", // elktcp
"tcpAddressPort": 0, // elktcp
"ConfigsInfo": [ // elk
{
"FiedName": "applicationName",
"FiedValue": "Blog.Core.Api"
}
]
{
"ConnId": "WMBLOG_KDBNDP",
"DBType": 6,
"Enabled": false,
"HitRate": 10,
"Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
}
],
"Audience": {
"Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //16+
"SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //Secret
"Issuer": "Blog.Core",
"Audience": "wr"
},
"Mongo": {
"ConnectionString": "mongodb://nosql.data",
"Database": "BlogCoreDb"
},
"Startup": {
"Domain": "http://localhost:9291",
"Cors": {
"PolicyName": "CorsIpAccess", //
"EnableAllIPs": false, //trueIP访
// /localhost:8000/
// http://127.0.0.1:1818 http://localhost:1818
"IPs": "http://127.0.0.1:2364,http://localhost:2364,http://127.0.0.1:6688,http://localhost:6688"
},
"AppConfigAlert": {
"Enabled": true
},
"ApiName": "Blog.Core",
"IdentityServer4": {
"Enabled": false, // false使jwttrue使Ids4
"AuthorizationUrl": "http://localhost:5004", //
"ApiName": "blog.core.api" //
},
"Authing": {
"Enabled": false,
"Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
"Audience": "63d51c4205c2849803be5178",
"JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
},
"RedisMq": {
"Enabled": false //redis
},
"MiniProfiler": {
"Enabled": false //
},
"Nacos": {
"Enabled": false //Nacos
}
},
"Middleware": {
"RequestResponseLog": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
}
},
"IPLog": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
}
},
"RecordAccessLogs": {
"Enabled": true,
"LogToFile": {
"Enabled": false
},
"LogToDB": {
"Enabled": true
},
"IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
},
"SignalR": {
"Enabled": false
},
"SignalRSendLog": {
"Enabled": false
},
"QuartzNetJob": {
"Enabled": true
},
"Consul": {
"Enabled": false
},
"IpRateLimit": {
"Enabled": true
}
},
"IpRateLimiting": {
"EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
"StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"IpWhitelist": [], //
"EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
"ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
"QuotaExceededResponse": {
"Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
"ContentType": "application/json",
"StatusCode": 429
},
"HttpStatusCode": 429, //
"GeneralRules": [ //api,*
{
"Endpoint": "*:/api/blog*",
"Period": "1m",
"Limit": 20
},
{
"Endpoint": "*/api/*",
"Period": "1s",
"Limit": 3
},
{
"Endpoint": "*/api/*",
"Period": "1m",
"Limit": 30
},
{
"Endpoint": "*/api/*",
"Period": "12h",
"Limit": 500
}
]
},
"ConsulSetting": {
"ServiceName": "BlogCoreService",
"ServiceIP": "localhost",
"ServicePort": "9291",
"ServiceHealthCheck": "/healthcheck",
"ConsulAddress": "http://localhost:8500"
},
"PayInfo": { //
"MERCHANTID": "", //
"POSID": "", //
"BRANCHID": "", //
"pubKey": "", //
"USER_ID": "", //
"PASSWORD": "", //
"OutAddress": "http://127.0.0.1:12345" //
},
"nacos": {
"ServerAddresses": [ "http://localhost:8848" ], // nacos
"DefaultTimeOut": 15000, //
"Namespace": "public", //
"ListenInterval": 10000, //
"ServiceName": "blog.Core.Api", //
"Port": "9291", //
"RegisterEnabled": true // nacos
},
"LogFiedOutPutConfigs": {
"tcpAddressHost": "", // elktcp
"tcpAddressPort": 0, // elktcp
"ConfigsInfo": [ // elk
{
"FiedName": "applicationName",
"FiedValue": "Blog.Core.Api"
}
]
}
}

View File

@ -11,7 +11,7 @@
},
"Logging": {
"Level": "Information",
"FilePath": "Log/skyapm-{Date}.log"
"FilePath": "Logs/Skyapm/skyapm-{Date}.log"
},
"Transport": {
"Interval": 3000,

View File

@ -1,14 +1,24 @@
using Blog.Core.Common.Core;
using Blog.Core.Common.HttpContextUser;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
namespace Blog.Core.Common;
public class App
{
public static IServiceProvider RootServices => InternalApp.RootServices ;
public static IServiceProvider RootServices => InternalApp.RootServices;
/// <summary>获取Web主机环境是否是开发环境生产环境等</summary>
public static IWebHostEnvironment WebHostEnvironment => InternalApp.WebHostEnvironment;
/// <summary>获取泛型主机环境,如,是否是开发环境,生产环境等</summary>
public static IHostEnvironment HostEnvironment => InternalApp.HostEnvironment;
/// <summary>
/// 获取请求上下文
@ -16,4 +26,55 @@ public class App
public static HttpContext HttpContext => RootServices?.GetService<IHttpContextAccessor>()?.HttpContext;
public static IUser User => HttpContext == null ? null : RootServices?.GetService<IUser>();
/// <summary>解析服务提供器</summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public static IServiceProvider GetServiceProvider(Type serviceType, bool mustBuild = false)
{
if (App.HostEnvironment == null || App.RootServices != null &&
InternalApp.InternalServices
.Where((u => u.ServiceType == (serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType)))
.Any((u => u.Lifetime == ServiceLifetime.Singleton)))
return App.RootServices;
HttpContext httpContext = App.HttpContext;
if (httpContext?.RequestServices != null)
return httpContext.RequestServices;
if (App.RootServices != null)
{
IServiceScope scope = App.RootServices.CreateScope();
return scope.ServiceProvider;
}
if (mustBuild)
{
throw new ApplicationException("当前不可用,必须要等到 WebApplication Build后");
}
ServiceProvider serviceProvider = InternalApp.InternalServices.BuildServiceProvider();
return serviceProvider;
}
public static TService GetService<TService>(bool mustBuild = true) where TService : class => App.GetService(typeof(TService), null, mustBuild) as TService;
/// <summary>获取请求生存周期的服务</summary>
/// <typeparam name="TService"></typeparam>
/// <param name="serviceProvider"></param>
/// <param name="mustBuild"></param>
/// <returns></returns>
public static TService GetService<TService>(IServiceProvider serviceProvider, bool mustBuild = true) where TService : class => App.GetService(typeof(TService), serviceProvider, mustBuild) as TService;
/// <summary>获取请求生存周期的服务</summary>
/// <param name="type"></param>
/// <param name="serviceProvider"></param>
/// <param name="mustBuild"></param>
/// <returns></returns>
public static object GetService(Type type, IServiceProvider serviceProvider = null, bool mustBuild = true) => (serviceProvider ?? App.GetServiceProvider(type, mustBuild)).GetService(type);
public static TOptions GetOptions<TOptions>(IServiceProvider serviceProvider = null) where TOptions : class, new()
{
IOptions<TOptions> service = App.GetService<IOptions<TOptions>>(serviceProvider ?? App.RootServices, false);
return service?.Value;
}
}

View File

@ -18,20 +18,23 @@
<ItemGroup>
<PackageReference Include="Magicodes.IE.Excel" Version="2.6.4" />
<PackageReference Include="InitQ" Version="1.0.0.12" />
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="MiniProfiler.Shared" Version="4.2.22" />
<PackageReference Include="PinYinConverterCore" Version="1.0.2" />
<PackageReference Include="RestSharp" Version="108.0.1" />
<PackageReference Include="RSAExtensions" Version="1.1.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.4.1" />
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="StackExchange.Redis" Version="2.6.48" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.22.1" />
<PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.1-dev-00771" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageReference Include="WebApiClient.Extensions.DependencyInjection" Version="2.0.3" />
<PackageReference Include="WebApiClient.JIT" Version="1.1.4" />
@ -45,6 +48,7 @@
<ItemGroup>
<Folder Include="Core\" />
<Folder Include="Const\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
namespace Blog.Core.Common.Const;
public class SqlSugarConst
{
/// <summary>
/// 默认Log数据库标识
/// </summary>
public const string LogConfigId = "Log";
}

View File

@ -1,17 +1,34 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
namespace Blog.Core.Common.Core;
public static class InternalApp
{
public static IServiceCollection InternalServices;
/// <summary>根服务</summary>
public static IServiceProvider RootServices;
public static void ConfigureApplication(this WebApplication app)
{
app.Lifetime.ApplicationStarted.Register(() => { InternalApp.RootServices = app.Services; });
/// <summary>获取Web主机环境</summary>
public static IWebHostEnvironment WebHostEnvironment;
app.Lifetime.ApplicationStopped.Register(() => { InternalApp.RootServices = null; });
/// <summary>获取泛型主机环境</summary>
public static IHostEnvironment HostEnvironment;
public static void ConfigureApplication(this WebApplicationBuilder wab)
{
HostEnvironment = wab.Environment;
WebHostEnvironment = wab.Environment;
InternalServices = wab.Services;
}
public static void ConfigureApplication(this IHost app)
{
RootServices = app.Services;
}
}

View File

@ -1,12 +1,40 @@
using Blog.Core.Model.Models.RootTkey;
using Blog.Core.Common.LogHelper;
using Blog.Core.Model.Models.RootTkey;
using Blog.Core.Model.Tenants;
using SqlSugar;
using StackExchange.Profiling;
using System;
using Serilog;
namespace Blog.Core.Common.DB.Aop;
public static class SqlSugarAop
{
public static void OnLogExecuting(ISqlSugarClient sqlSugarScopeProvider, string sql, SugarParameter[] p, ConnectionConfig config)
{
try
{
MiniProfiler.Current.CustomTiming($"ConnId:[{config.ConfigId}] SQL", GetParas(p) + "【SQL语句】" + sql);
if (!AppSettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool()) return;
if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToConsole", "Enabled" }).ObjToBool() ||
AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToFile", "Enabled" }).ObjToBool() ||
AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToDB", "Enabled" }).ObjToBool())
{
using (LogContextExtension.Create.SqlAopPushProperty(sqlSugarScopeProvider))
{
Log.Information("------------------ \r\n ConnId:[{ConnId}]【SQL语句】: \r\n {Sql}",
config.ConfigId, UtilMethods.GetSqlString(config.DbType, sql, p));
}
}
}
catch (Exception e)
{
Log.Error("Error occured OnLogExcuting:" + e);
}
}
public static void DataExecuting(object oldValue, DataFilterModel entityInfo)
{
if (entityInfo.EntityValue is BaseEntity root)

View File

@ -12,6 +12,7 @@ namespace Blog.Core.Common.DB
* appsettings.json设置为true的第一个db连接
*/
public static (List<MutiDBOperate> allDbs, List<MutiDBOperate> slaveDbs) MutiConnectionString => MutiInitConn();
public static ConnectionConfig LogConfig; //日志库
private static string DifDBConnOfSecurity(params string[] conn)
{
@ -107,8 +108,6 @@ namespace Blog.Core.Common.DB
return mutiDBOperate;
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Blog.Core.Common.Helper
@ -8,9 +9,8 @@ namespace Blog.Core.Common.Helper
/// </summary>
public static class RecursionHelper
{
public static void LoopToAppendChildren(List<PermissionTree> all, PermissionTree curItem, int pid, bool needbtn)
public static void LoopToAppendChildren(List<PermissionTree> all, PermissionTree curItem, long pid, bool needbtn)
{
var subItems = all.Where(ee => ee.Pid == curItem.value).ToList();
var btnItems = subItems.Where(ss => ss.isbtn == true).ToList();
@ -28,6 +28,7 @@ namespace Blog.Core.Common.Helper
{
subItems = subItems.Where(ss => ss.isbtn == false).ToList();
}
if (subItems.Count > 0)
{
curItem.children = new List<PermissionTree>();
@ -49,14 +50,15 @@ namespace Blog.Core.Common.Helper
{
//subItem.disabled = true;//禁用当前节点
}
LoopToAppendChildren(all, subItem, pid, needbtn);
}
}
public static void LoopToAppendChildren(List<DepartmentTree> all, DepartmentTree curItem, int pid)
{
var subItems = all.Where(ee => ee.Pid == curItem.value).ToList();
if (subItems.Count > 0)
{
curItem.children = new List<DepartmentTree>();
@ -73,15 +75,14 @@ namespace Blog.Core.Common.Helper
{
//subItem.disabled = true;//禁用当前节点
}
LoopToAppendChildren(all, subItem, pid);
}
}
public static void LoopNaviBarAppendChildren(List<NavigationBar> all, NavigationBar curItem)
{
var subItems = all.Where(ee => ee.pid == curItem.id).ToList();
if (subItems.Count > 0)
@ -102,7 +103,6 @@ namespace Blog.Core.Common.Helper
}
public static void LoopToAppendChildrenT<T>(List<T> all, T curItem, string parentIdName = "Pid", string idName = "value", string childrenName = "children")
{
var subItems = all.Where(ee => ee.GetType().GetProperty(parentIdName).GetValue(ee, null).ToString() == curItem.GetType().GetProperty(idName).GetValue(curItem, null).ToString()).ToList();
@ -113,12 +113,47 @@ namespace Blog.Core.Common.Helper
LoopToAppendChildrenT(all, subItem);
}
}
/// <summary>
/// 将父子级数据结构转换为普通list
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public static List<T> TreeToList<T>(List<T> list, Action<T, T, List<T>> action = null)
{
List<T> results = new List<T>();
foreach (var item in list)
{
results.Add(item);
OperationChildData(results, item, action);
}
return results;
}
/// <summary>
/// 递归子级数据
/// </summary>
/// <param name="allList">树形列表数据</param>
/// <param name="item">Item</param>
public static void OperationChildData<T>(List<T> allList, T item, Action<T, T, List<T>> action)
{
dynamic dynItem = item;
if (dynItem.Children == null) return;
if (dynItem.Children.Count <= 0) return;
allList.AddRange(dynItem.Children);
foreach (var subItem in dynItem.Children)
{
action?.Invoke(item, subItem, allList);
OperationChildData(allList, subItem, action);
}
}
}
public class PermissionTree
{
public int value { get; set; }
public int Pid { get; set; }
public long value { get; set; }
public long Pid { get; set; }
public string label { get; set; }
public int order { get; set; }
public bool isbtn { get; set; }
@ -139,8 +174,8 @@ namespace Blog.Core.Common.Helper
public class NavigationBar
{
public int id { get; set; }
public int pid { get; set; }
public long id { get; set; }
public long pid { get; set; }
public int order { get; set; }
public string name { get; set; }
public bool IsHide { get; set; } = false;
@ -158,15 +193,13 @@ namespace Blog.Core.Common.Helper
public bool requireAuth { get; set; } = true;
public bool NoTabPage { get; set; } = false;
public bool keepAlive { get; set; } = false;
}
public class NavigationBarPro
{
public int id { get; set; }
public int parentId { get; set; }
public long id { get; set; }
public long parentId { get; set; }
public int order { get; set; }
public string name { get; set; }
public bool IsHide { get; set; } = false;
@ -184,4 +217,4 @@ namespace Blog.Core.Common.Helper
public string icon { get; set; }
public bool show { get; set; } = false;
}
}
}

View File

@ -6,7 +6,7 @@ using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Common.HttpPolly
namespace Blog.Core.Common.Https.HttpPolly
{
public class HttpPollyHelper : IHttpPollyHelper
{
@ -35,7 +35,7 @@ namespace Blog.Core.Common.HttpPolly
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@ -72,7 +72,7 @@ namespace Blog.Core.Common.HttpPolly
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@ -110,7 +110,7 @@ namespace Blog.Core.Common.HttpPolly
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
@ -146,7 +146,7 @@ namespace Blog.Core.Common.HttpPolly
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
@ -182,7 +182,7 @@ namespace Blog.Core.Common.HttpPolly
}
var response = await client.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@ -219,7 +219,7 @@ namespace Blog.Core.Common.HttpPolly
}
var response = await client.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync(); ;
@ -256,7 +256,7 @@ namespace Blog.Core.Common.HttpPolly
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PutAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@ -294,7 +294,7 @@ namespace Blog.Core.Common.HttpPolly
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PutAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@ -331,7 +331,7 @@ namespace Blog.Core.Common.HttpPolly
}
var response = await client.DeleteAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Blog.Core.Common.HttpPolly
namespace Blog.Core.Common.Https.HttpPolly
{
public interface IHttpPollyHelper
{

View File

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Http;
namespace Blog.Core.Common.Https;
public static class RequestIpUtility
{
public static string GetRequestIp(this HttpContext context)
{
string ip = SplitCsv(GetHeaderValueAs<string>(context, "X-Forwarded-For")).FirstOrDefault();
if (string.IsNullOrWhiteSpace(ip))
ip = SplitCsv(GetHeaderValueAs<string>(context, "X-Real-IP")).FirstOrDefault();
if (string.IsNullOrWhiteSpace(ip) && context.Connection?.RemoteIpAddress != null)
ip = context.Connection.RemoteIpAddress.ToString();
if (string.IsNullOrWhiteSpace(ip))
ip = GetHeaderValueAs<string>(context, "REMOTE_ADDR");
return ip;
}
public static bool IsLocal(this HttpContext context)
{
return GetRequestIp(context) is "127.0.0.1" or "::1" || context.Request?.IsLocal() == true;
}
public static bool IsLocal(this HttpRequest req)
{
var connection = req.HttpContext.Connection;
if (connection.RemoteIpAddress != null)
{
if (connection.LocalIpAddress != null)
{
return connection.RemoteIpAddress.Equals(connection.LocalIpAddress);
}
else
{
return IPAddress.IsLoopback(connection.RemoteIpAddress);
}
}
// for in memory TestServer or when dealing with default connection info
if (connection.RemoteIpAddress == null && connection.LocalIpAddress == null)
{
return true;
}
return false;
}
private static T GetHeaderValueAs<T>(HttpContext context, string headerName)
{
if (context.Request?.Headers?.TryGetValue(headerName, out var values) ?? false)
{
string rawValues = values.ToString();
if (!string.IsNullOrWhiteSpace(rawValues))
return (T) Convert.ChangeType(values.ToString(), typeof(T));
}
return default;
}
private static List<string> SplitCsv(string csvList)
{
if (string.IsNullOrWhiteSpace(csvList))
return new List<string>();
return csvList
.TrimEnd(',')
.Split(',')
.AsEnumerable<string>()
.Select(s => s.Trim())
.ToList();
}
}

View File

@ -83,7 +83,8 @@ namespace Blog.Core.Hubs
//2、服务端主动向客户端发送数据名字千万不能错
if (AppSettings.app(new string[] { "Middleware", "SignalRSendLog", "Enabled" }).ObjToBool())
{
await Clients.All.ReceiveUpdate(LogLock.GetLogData());
//TODO 主动发送错误消息
//await Clients.All.ReceiveUpdate(LogLock.GetLogData());
}

View File

@ -0,0 +1,42 @@
using Serilog.Context;
using SqlSugar;
using System;
using System.Collections.Generic;
namespace Blog.Core.Common.LogHelper;
public class LogContextExtension : IDisposable
{
private readonly Stack<IDisposable> _disposableStack = new Stack<IDisposable>();
public static LogContextExtension Create => new();
public void AddStock(IDisposable disposable)
{
_disposableStack.Push(disposable);
}
public IDisposable SqlAopPushProperty(ISqlSugarClient db)
{
AddStock(LogContext.PushProperty(LogContextStatic.LogSource, LogContextStatic.AopSql));
AddStock(LogContext.PushProperty(LogContextStatic.SqlOutToConsole,
AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToConsole", "Enabled" }).ObjToBool()));
AddStock(LogContext.PushProperty(LogContextStatic.SqlOutToFile,
AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToFile", "Enabled" }).ObjToBool()));
AddStock(LogContext.PushProperty(LogContextStatic.OutToDb,
AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToDb", "Enabled" }).ObjToBool()));
AddStock(LogContext.PushProperty(LogContextStatic.SugarActionType, db.SugarActionType));
return this;
}
public void Dispose()
{
while (_disposableStack.Count > 0)
{
_disposableStack.Pop().Dispose();
}
}
}

View File

@ -0,0 +1,42 @@
using System.IO;
namespace Blog.Core.Common.LogHelper;
public class LogContextStatic
{
static LogContextStatic()
{
if (!Directory.Exists(BaseLogs))
{
Directory.CreateDirectory(BaseLogs);
}
}
public static readonly string BaseLogs = "Logs";
public static readonly string BasePathLogs = @"Logs";
public static readonly string LogSource = "LogSource";
public static readonly string AopSql = "AopSql";
public static readonly string SqlOutToConsole = "OutToConsole";
public static readonly string SqlOutToFile = "SqlOutToFile";
public static readonly string OutToDb = "OutToDb";
public static readonly string SugarActionType = "SugarActionType";
public static readonly string FileMessageTemplate = "{NewLine}Date{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel{Level}{NewLine}Message{Message}{NewLine}{Exception}" + new string('-', 100);
public static string Combine(string path1)
{
return Path.Combine(BaseLogs, path1);
}
public static string Combine(string path1, string path2)
{
return Path.Combine(BaseLogs, path1, path2);
}
public static string Combine(string path1, string path2, string path3)
{
return Path.Combine(BaseLogs, path1, path2, path3);
}
}

View File

@ -1,5 +1,4 @@
using Blog.Core.Common.Helper;
using log4net;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@ -7,12 +6,12 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Serilog;
namespace Blog.Core.Common.LogHelper
{
public class LogLock
{
private static readonly ILog log = LogManager.GetLogger(typeof(LogLock));
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
static int WritedCount = 0;
static int FailedCount = 0;
@ -53,12 +52,14 @@ namespace Blog.Core.Common.LogHelper
default:
break;
}
if (AppSettings.app(new string[] { AppSetingNodeName, AppSetingName, "Enabled" }).ObjToBool())
{
if (AppSettings.app(new string[] { AppSetingNodeName, AppSetingName, "LogToDB", "Enabled" }).ObjToBool())
{
OutSql2LogToDB(prefix, traceId, dataParas, IsHeader);
}
if (AppSettings.app(new string[] { AppSetingNodeName, AppSetingName, "LogToFile", "Enabled" }).ObjToBool())
{
OutSql2LogToFile(prefix, traceId, dataParas, IsHeader);
@ -90,6 +91,7 @@ namespace Blog.Core.Common.LogHelper
{
Directory.CreateDirectory(folderPath);
}
//string logFilePath = Path.Combine(path, $@"{filename}.log");
var logFilePath = FileHelper.GetAvailableFileWithPrefixOrderSize(folderPath, prefix);
switch (prefix)
@ -98,47 +100,48 @@ namespace Blog.Core.Common.LogHelper
AOPLogInfo apiLogAopInfo = JsonConvert.DeserializeObject<AOPLogInfo>(dataParas[1]);
//记录被拦截方法信息的日志信息
var dataIntercept = "" +
$"【操作时间】:{apiLogAopInfo.RequestTime}\r\n" +
$"【当前操作用户】:{ apiLogAopInfo.OpUserName} \r\n" +
$"【当前执行方法】:{ apiLogAopInfo.RequestMethodName} \r\n" +
$"【携带的参数有】: {apiLogAopInfo.RequestParamsName} \r\n" +
$"【携带的参数JSON】 {apiLogAopInfo.RequestParamsData} \r\n" +
$"【响应时间】:{apiLogAopInfo.ResponseIntervalTime}\r\n" +
$"【执行完成时间】:{apiLogAopInfo.ResponseTime}\r\n" +
$"【执行完成结果】:{apiLogAopInfo.ResponseJsonData}\r\n";
$"【操作时间】:{apiLogAopInfo.RequestTime}\r\n" +
$"【当前操作用户】:{apiLogAopInfo.OpUserName} \r\n" +
$"【当前执行方法】:{apiLogAopInfo.RequestMethodName} \r\n" +
$"【携带的参数有】: {apiLogAopInfo.RequestParamsName} \r\n" +
$"【携带的参数JSON】 {apiLogAopInfo.RequestParamsData} \r\n" +
$"【响应时间】:{apiLogAopInfo.ResponseIntervalTime}\r\n" +
$"【执行完成时间】:{apiLogAopInfo.ResponseTime}\r\n" +
$"【执行完成结果】:{apiLogAopInfo.ResponseJsonData}\r\n";
dataParas = new string[] { dataIntercept };
break;
case "AOPLogEx":
AOPLogExInfo apiLogAopExInfo = JsonConvert.DeserializeObject<AOPLogExInfo>(dataParas[1]);
var dataInterceptEx = "" +
$"【操作时间】:{apiLogAopExInfo.ApiLogAopInfo.RequestTime}\r\n" +
$"【当前操作用户】:{ apiLogAopExInfo.ApiLogAopInfo.OpUserName} \r\n" +
$"【当前执行方法】:{ apiLogAopExInfo.ApiLogAopInfo.RequestMethodName} \r\n" +
$"【携带的参数有】: {apiLogAopExInfo.ApiLogAopInfo.RequestParamsName} \r\n" +
$"【携带的参数JSON】 {apiLogAopExInfo.ApiLogAopInfo.RequestParamsData} \r\n" +
$"【响应时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseIntervalTime}\r\n" +
$"【执行完成时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseTime}\r\n" +
$"【执行完成结果】:{apiLogAopExInfo.ApiLogAopInfo.ResponseJsonData}\r\n" +
$"【执行完成异常信息】:方法中出现异常:{apiLogAopExInfo.ExMessage}\r\n" +
$"【执行完成异常】:方法中出现异常:{apiLogAopExInfo.InnerException}\r\n";
$"【操作时间】:{apiLogAopExInfo.ApiLogAopInfo.RequestTime}\r\n" +
$"【当前操作用户】:{apiLogAopExInfo.ApiLogAopInfo.OpUserName} \r\n" +
$"【当前执行方法】:{apiLogAopExInfo.ApiLogAopInfo.RequestMethodName} \r\n" +
$"【携带的参数有】: {apiLogAopExInfo.ApiLogAopInfo.RequestParamsName} \r\n" +
$"【携带的参数JSON】 {apiLogAopExInfo.ApiLogAopInfo.RequestParamsData} \r\n" +
$"【响应时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseIntervalTime}\r\n" +
$"【执行完成时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseTime}\r\n" +
$"【执行完成结果】:{apiLogAopExInfo.ApiLogAopInfo.ResponseJsonData}\r\n" +
$"【执行完成异常信息】:方法中出现异常:{apiLogAopExInfo.ExMessage}\r\n" +
$"【执行完成异常】:方法中出现异常:{apiLogAopExInfo.InnerException}\r\n";
dataParas = new string[] { dataInterceptEx };
break;
}
var now = DateTime.Now;
string logContent = String.Join("\r\n", dataParas);
if (IsHeader)
{
logContent = (
"--------------------------------\r\n" +
DateTime.Now + "|\r\n" +
String.Join("\r\n", dataParas) + "\r\n"
);
"--------------------------------\r\n" +
DateTime.Now + "|\r\n" +
String.Join("\r\n", dataParas) + "\r\n"
);
}
else
{
logContent = (
dataParas[1] + ",\r\n"
);
dataParas[1] + ",\r\n"
);
}
//if (logContent.IsNotEmptyOrNull() && logContent.Length > 500)
@ -148,12 +151,12 @@ namespace Blog.Core.Common.LogHelper
if (isWrt)
{
File.WriteAllText(logFilePath, logContent);
}
else
{
File.AppendAllText(logFilePath, logContent);
}
WritedCount++;
}
catch (Exception e)
@ -170,14 +173,15 @@ namespace Blog.Core.Common.LogHelper
LogWriteLock.ExitWriteLock();
}
}
public static void OutSql2LogToDB(string prefix, string traceId, string[] dataParas, bool IsHeader = true)
{
log4net.LogicalThreadContext.Properties["LogType"] = prefix;
log4net.LogicalThreadContext.Properties["TraceId"] = traceId;
if (dataParas.Length >= 2)
{
log4net.LogicalThreadContext.Properties["DataType"] = dataParas[0];
}
//log4net.LogicalThreadContext.Properties["LogType"] = prefix;
//log4net.LogicalThreadContext.Properties["TraceId"] = traceId;
//if (dataParas.Length >= 2)
//{
// log4net.LogicalThreadContext.Properties["DataType"] = dataParas[0];
//}
dataParas = dataParas.Skip(1).ToArray();
@ -186,32 +190,37 @@ namespace Blog.Core.Common.LogHelper
{
logContent = (String.Join("", dataParas));
}
switch (prefix)
{
//DEBUG | INFO | WARN | ERROR | FATAL
case "AOPLog":
log.Info(logContent);
//TODO 是否需要输出?
//Log.Information(logContent);
break;
case "AOPLogEx":
log.Error(logContent);
Log.Error(logContent);
break;
case "RequestIpInfoLog":
log.Debug(logContent);
//TODO 是否需要Debug输出
//Log.Debug(logContent);
break;
case "RecordAccessLogs":
log.Debug(logContent);
//TODO 是否需要Debug输出
//Log.Debug(logContent);
break;
case "SqlLog":
log.Info(logContent);
Log.Information(logContent);
break;
case "RequestResponseLog":
log.Debug(logContent);
//TODO 是否需要Debug输出
//Log.Debug(logContent);
break;
default:
break;
}
}
/// <summary>
/// 读取文件内容
/// </summary>
@ -287,6 +296,7 @@ namespace Blog.Core.Common.LogHelper
{
LogWriteLock.ExitReadLock();
}
return s;
}
@ -315,7 +325,6 @@ namespace Blog.Core.Common.LogHelper
}
}
}
}
return requestInfos;
@ -336,16 +345,18 @@ namespace Blog.Core.Common.LogHelper
if (!string.IsNullOrEmpty(aoplogContent))
{
aopLogs = aoplogContent.Split("--------------------------------")
.Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
.Select(d => new LogInfo
{
Datetime = d.Split("|")[0].ObjToDate(),
Content = d.Split("|")[1]?.Replace("\r\n", "<br>"),
LogColor = "AOP",
}).ToList();
.Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
.Select(d => new LogInfo
{
Datetime = d.Split("|")[0].ObjToDate(),
Content = d.Split("|")[1]?.Replace("\r\n", "<br>"),
LogColor = "AOP",
}).ToList();
}
}
catch (Exception) { }
catch (Exception)
{
}
try
{
@ -354,17 +365,19 @@ namespace Blog.Core.Common.LogHelper
if (!string.IsNullOrEmpty(exclogContent))
{
excLogs = exclogContent.Split("--------------------------------")
.Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
.Select(d => new LogInfo
{
Datetime = (d.Split("|")[0]).Split(',')[0].ObjToDate(),
Content = d.Split("|")[1]?.Replace("\r\n", "<br>"),
LogColor = "EXC",
Import = 9,
}).ToList();
.Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
.Select(d => new LogInfo
{
Datetime = (d.Split("|")[0]).Split(',')[0].ObjToDate(),
Content = d.Split("|")[1]?.Replace("\r\n", "<br>"),
LogColor = "EXC",
Import = 9,
}).ToList();
}
}
catch (Exception) { }
catch (Exception)
{
}
try
@ -374,16 +387,18 @@ namespace Blog.Core.Common.LogHelper
if (!string.IsNullOrEmpty(sqllogContent))
{
sqlLogs = sqllogContent.Split("--------------------------------")
.Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
.Select(d => new LogInfo
{
Datetime = d.Split("|")[0].ObjToDate(),
Content = d.Split("|")[1]?.Replace("\r\n", "<br>"),
LogColor = "SQL",
}).ToList();
.Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
.Select(d => new LogInfo
{
Datetime = d.Split("|")[0].ObjToDate(),
Content = d.Split("|")[1]?.Replace("\r\n", "<br>"),
LogColor = "SQL",
}).ToList();
}
}
catch (Exception) { }
catch (Exception)
{
}
//try
//{
@ -422,14 +437,17 @@ namespace Blog.Core.Common.LogHelper
{
aopLogs.AddRange(excLogs);
}
if (sqlLogs != null)
{
aopLogs.AddRange(sqlLogs);
}
if (reqresLogs != null)
{
aopLogs.AddRange(reqresLogs);
}
aopLogs = aopLogs.OrderByDescending(d => d.Import).ThenByDescending(d => d.Datetime).Take(100).ToList();
return aopLogs;
@ -450,7 +468,8 @@ namespace Blog.Core.Common.LogHelper
Logs = GetRequestInfo(ReadType.Prefix);
apiWeeks = (from n in Logs
group n by new { n.Week, n.Url } into g
group n by new { n.Week, n.Url }
into g
select new ApiWeek
{
week = g.Key.Week,
@ -459,7 +478,6 @@ namespace Blog.Core.Common.LogHelper
}).ToList();
//apiWeeks = apiWeeks.OrderByDescending(d => d.count).Take(8).ToList();
}
catch (Exception)
{
@ -489,10 +507,12 @@ namespace Blog.Core.Common.LogHelper
jsonBuilder.Append(item.count);
jsonBuilder.Append("\",");
}
if (apiweeksCurrentWeek.Count > 0)
{
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
}
jsonBuilder.Append("},");
}
@ -500,6 +520,7 @@ namespace Blog.Core.Common.LogHelper
{
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
}
jsonBuilder.Append("]");
//columns.AddRange(apiWeeks.OrderByDescending(d => d.count).Take(8).Select(d => d.url).ToList());
@ -521,7 +542,8 @@ namespace Blog.Core.Common.LogHelper
Logs = GetRequestInfo(ReadType.Prefix);
apiDates = (from n in Logs
group n by new { n.Date } into g
group n by new { n.Date }
into g
select new ApiDate
{
date = g.Key.Date,
@ -529,7 +551,6 @@ namespace Blog.Core.Common.LogHelper
}).ToList();
apiDates = apiDates.OrderByDescending(d => d.date).Take(7).ToList();
}
catch (Exception)
{
@ -552,7 +573,8 @@ namespace Blog.Core.Common.LogHelper
apiDates = (from n in Logs
where n.Datetime.ObjToDate() >= DateTime.Today
group n by new { hour = n.Datetime.ObjToDate().Hour } into g
group n by new { hour = n.Datetime.ObjToDate().Hour }
into g
select new ApiDate
{
date = g.Key.hour.ToString("00"),
@ -560,7 +582,6 @@ namespace Blog.Core.Common.LogHelper
}).ToList();
apiDates = apiDates.OrderBy(d => d.date).Take(24).ToList();
}
catch (Exception)
{
@ -580,14 +601,15 @@ namespace Blog.Core.Common.LogHelper
/// 精确查找一个
/// </summary>
Accurate,
/// <summary>
/// 指定前缀,模糊查找全部
/// </summary>
Prefix,
/// <summary>
/// 指定前缀,最新一个文件
/// </summary>
PrefixLatest
}
}
}

View File

@ -18,10 +18,10 @@
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="6.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" />
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
<PackageReference Include="NetDevPack.Security.JwtExtensions" Version="6.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
@ -35,6 +35,7 @@
<ItemGroup>
<ProjectReference Include="..\Blog.Core.EventBus\Blog.Core.EventBus.csproj" />
<ProjectReference Include="..\Blog.Core.Serilog\Blog.Core.Serilog.csproj" />
<ProjectReference Include="..\Blog.Core.Services\Blog.Core.Services.csproj" />
<ProjectReference Include="..\Blog.Core.Tasks\Blog.Core.Tasks.csproj" />
</ItemGroup>

View File

@ -4,14 +4,13 @@ using System.Threading.Tasks;
using Blog.Core.Model;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Serilog;
namespace Blog.Core.Extensions.Middlewares
{
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private static readonly log4net.ILog Log =
log4net.LogManager.GetLogger(typeof(ExceptionHandlerMiddleware));
public ExceptionHandlerMiddleware(RequestDelegate next)
{
@ -48,7 +47,9 @@ namespace Blog.Core.Extensions.Middlewares
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject((new ApiResponse(StatusCode.CODE500, e.Message)).MessageModel)).ConfigureAwait(false);
await context.Response
.WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE500, e.Message).MessageModel))
.ConfigureAwait(false);
}
}
}
}

View File

@ -1,8 +1,8 @@
using System;
using AspNetCoreRateLimit;
using AspNetCoreRateLimit;
using Blog.Core.Common;
using log4net;
using Microsoft.AspNetCore.Builder;
using System;
using Serilog;
namespace Blog.Core.Extensions.Middlewares
{
@ -11,7 +11,6 @@ namespace Blog.Core.Extensions.Middlewares
/// </summary>
public static class IpLimitMiddleware
{
private static readonly ILog Log = LogManager.GetLogger(typeof(IpLimitMiddleware));
public static void UseIpLimitMiddle(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));

View File

@ -1,10 +1,10 @@
using System;
using System.Threading.Tasks;
using Blog.Core.Common;
using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
namespace Blog.Core.Extensions.Middlewares
{
@ -19,7 +19,6 @@ namespace Blog.Core.Extensions.Middlewares
/// </summary>
private readonly RequestDelegate _next;
private readonly IWebHostEnvironment _environment;
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(IpLogMiddleware));
/// <summary>
///

View File

@ -1,7 +1,7 @@
using System;
using Blog.Core.Common;
using log4net;
using Blog.Core.Common;
using Microsoft.AspNetCore.Builder;
using System;
using Serilog;
namespace Blog.Core.Extensions.Middlewares
{
@ -10,7 +10,6 @@ namespace Blog.Core.Extensions.Middlewares
/// </summary>
public static class MiniProfilerMiddleware
{
private static readonly ILog Log = LogManager.GetLogger(typeof(MiniProfilerMiddleware));
public static void UseMiniProfilerMiddleware(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));

View File

@ -36,6 +36,7 @@ namespace Blog.Core.Extensions.Middlewares
{
if (AppSettings.app("Middleware", "SignalR", "Enabled").ObjToBool())
{
//TODO 主动发送错误消息
await _hubContext.Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData());
}
await _next(context);

View File

@ -1,10 +1,10 @@
using System;
using System.IO;
using System.Linq;
using Blog.Core.Common;
using log4net;
using Blog.Core.Common;
using Microsoft.AspNetCore.Builder;
using Swashbuckle.AspNetCore.SwaggerUI;
using System;
using System.IO;
using System.Linq;
using Serilog;
using static Blog.Core.Extensions.CustomApiVersion;
namespace Blog.Core.Extensions.Middlewares
@ -14,7 +14,6 @@ namespace Blog.Core.Extensions.Middlewares
/// </summary>
public static class SwaggerMiddleware
{
private static readonly ILog Log = LogManager.GetLogger(typeof(SwaggerMiddleware));
public static void UseSwaggerMiddle(this IApplicationBuilder app, Func<Stream> streamHtml)
{
if (app == null) throw new ArgumentNullException(nameof(app));
@ -24,10 +23,7 @@ namespace Blog.Core.Extensions.Middlewares
{
//根据版本名称倒序 遍历展示
var apiName = AppSettings.app(new string[] { "Startup", "ApiName" });
typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version =>
{
c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{apiName} {version}");
});
typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version => { c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{apiName} {version}"); });
c.SwaggerEndpoint($"https://petstore.swagger.io/v2/swagger.json", $"{apiName} pet");
@ -38,12 +34,13 @@ namespace Blog.Core.Extensions.Middlewares
Log.Error(msg);
throw new Exception(msg);
}
c.IndexStream = streamHtml;
c.DocExpansion(DocExpansion.None); //->修改界面打开时自动折叠
if (Permissions.IsUseIds4)
{
c.OAuthClientId("blogadminjs");
c.OAuthClientId("blogadminjs");
}
@ -52,4 +49,4 @@ namespace Blog.Core.Extensions.Middlewares
});
}
}
}
}

View File

@ -76,10 +76,10 @@ namespace Blog.Core.Extensions
var ipLogOpen = AppSettings.app(new string[] { "Middleware", "IPLog", "Enabled" }).ObjToBool();
var recordAccessLogsOpen = AppSettings.app(new string[] { "Middleware", "RecordAccessLogs", "Enabled" }).ObjToBool();
ConsoleHelper.WriteSuccessLine($"OPEN Log: " +
(requestResponseLogOpen ? "RequestResponseLog √," : "") +
(ipLogOpen ? "IPLog √," : "") +
(recordAccessLogsOpen ? "RecordAccessLogs √," : "")
);
(requestResponseLogOpen ? "RequestResponseLog √," : "") +
(ipLogOpen ? "IPLog √," : "") +
(recordAccessLogsOpen ? "RecordAccessLogs √," : "")
);
// 事务AOP
if (!AppSettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
@ -213,7 +213,6 @@ namespace Blog.Core.Extensions
Console.WriteLine();
}
}
public static void AddAppTableConfigSetup(this IServiceCollection services, IHostEnvironment env)
@ -222,7 +221,6 @@ namespace Blog.Core.Extensions
if (AppSettings.app(new string[] { "Startup", "AppConfigAlert", "Enabled" }).ObjToBool())
{
if (env.IsDevelopment())
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
@ -230,6 +228,7 @@ namespace Blog.Core.Extensions
}
#region
List<string[]> configInfos = new()
{
new string[] { "当前环境", Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") },
@ -238,7 +237,7 @@ namespace Blog.Core.Extensions
new string[] { "RabbitMQ消息列队", AppSettings.app("RabbitMQ", "Enabled") },
new string[] { "事件总线(必须开启消息列队)", AppSettings.app("EventBus", "Enabled") },
new string[] { "redis消息队列", AppSettings.app("Startup", "RedisMq", "Enabled") },
new string[] { "是否多库", AppSettings.app("MutiDBEnabled" ) },
new string[] { "是否多库", AppSettings.app("MutiDBEnabled") },
new string[] { "读写分离", AppSettings.app("CQRSEnabled") },
};
@ -253,17 +252,19 @@ namespace Blog.Core.Extensions
TableStyle = TableStyle.Alternative
}.Writer(ConsoleColor.Blue);
Console.WriteLine();
#endregion
#region AOP
List<string[]> aopInfos = new()
{
{
new string[] { "Redis缓存AOP", AppSettings.app("AppSettings", "RedisCachingAOP", "Enabled") },
new string[] { "内存缓存AOP", AppSettings.app("AppSettings", "MemoryCachingAOP", "Enabled") },
new string[] { "服务日志AOP", AppSettings.app("AppSettings", "LogAOP", "Enabled" ) },
new string[] { "事务AOP", AppSettings.app("AppSettings", "TranAOP", "Enabled" ) },
new string[] { "Sql执行AOP", AppSettings.app("AppSettings", "SqlAOP", "OutToLogFile", "Enabled" ) },
new string[] { "Sql执行AOP控制台输出", AppSettings.app("AppSettings", "SqlAOP", "OutToConsole", "Enabled" ) },
new string[] { "服务日志AOP", AppSettings.app("AppSettings", "LogAOP", "Enabled") },
new string[] { "事务AOP", AppSettings.app("AppSettings", "TranAOP", "Enabled") },
new string[] { "Sql执行AOP", AppSettings.app("AppSettings", "SqlAOP", "Enabled") },
new string[] { "Sql执行AOP控制台输出", AppSettings.app("AppSettings", "SqlAOP", "LogToConsole", "Enabled") },
};
new ConsoleTable
@ -277,15 +278,17 @@ namespace Blog.Core.Extensions
TableStyle = TableStyle.Alternative
}.Writer(ConsoleColor.Blue);
Console.WriteLine();
#endregion AOP
#region
List<string[]> MiddlewareInfos = new()
{
new string[] { "请求纪录中间件", AppSettings.app("Middleware", "RecordAccessLogs", "Enabled") },
new string[] { "IP记录中间件", AppSettings.app("Middleware", "IPLog", "Enabled" ) },
new string[] { "请求响应日志中间件", AppSettings.app("Middleware", "RequestResponseLog", "Enabled" ) },
new string[] { "SingnalR实时发送请求数据中间件", AppSettings.app("Middleware", "SignalR", "Enabled" ) },
new string[] { "IP记录中间件", AppSettings.app("Middleware", "IPLog", "Enabled") },
new string[] { "请求响应日志中间件", AppSettings.app("Middleware", "RequestResponseLog", "Enabled") },
new string[] { "SingnalR实时发送请求数据中间件", AppSettings.app("Middleware", "SignalR", "Enabled") },
new string[] { "IP限流中间件", AppSettings.app("Middleware", "IpRateLimit", "Enabled") },
new string[] { "性能分析中间件", AppSettings.app("Startup", "MiniProfiler", "Enabled") },
new string[] { "Consul注册服务", AppSettings.app("Middleware", "Consul", "Enabled") },
@ -302,10 +305,9 @@ namespace Blog.Core.Extensions
TableStyle = TableStyle.Alternative
}.Writer(ConsoleColor.Blue);
Console.WriteLine();
#endregion
}
}
}
}
}

View File

@ -6,20 +6,18 @@ using Blog.Core.IRepository.Base;
using Blog.Core.IServices.BASE;
using Blog.Core.Model;
using Blog.Core.Repository.Base;
using Blog.Core.Repository.UnitOfWorks;
using Blog.Core.Services.BASE;
using log4net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Blog.Core.Repository.UnitOfWorks;
using Serilog;
namespace Blog.Core.Extensions
{
public class AutofacModuleRegister : Autofac.Module
{
private static readonly ILog log = LogManager.GetLogger(typeof(AutofacModuleRegister));
protected override void Load(ContainerBuilder builder)
{
var basePath = AppContext.BaseDirectory;
@ -34,39 +32,39 @@ namespace Blog.Core.Extensions
if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
{
var msg = "Repository.dll和service.dll 丢失因为项目解耦了所以需要先F6编译再F5运行请检查 bin 文件夹,并拷贝。";
log.Error(msg);
Log.Error(msg);
throw new Exception(msg);
}
// AOP 开关,如果想要打开指定的功能,只需要在 appsettigns.json 对应对应 true 就行。
var cacheType = new List<Type>();
if (AppSettings.app(new string[] {"AppSettings", "RedisCachingAOP", "Enabled"}).ObjToBool())
if (AppSettings.app(new string[] { "AppSettings", "RedisCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogRedisCacheAOP>();
cacheType.Add(typeof(BlogRedisCacheAOP));
}
if (AppSettings.app(new string[] {"AppSettings", "MemoryCachingAOP", "Enabled"}).ObjToBool())
if (AppSettings.app(new string[] { "AppSettings", "MemoryCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogCacheAOP>();
cacheType.Add(typeof(BlogCacheAOP));
}
if (AppSettings.app(new string[] {"AppSettings", "TranAOP", "Enabled"}).ObjToBool())
if (AppSettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogTranAOP>();
cacheType.Add(typeof(BlogTranAOP));
}
if (AppSettings.app(new string[] {"AppSettings", "LogAOP", "Enabled"}).ObjToBool())
if (AppSettings.app(new string[] { "AppSettings", "LogAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogLogAOP>();
cacheType.Add(typeof(BlogLogAOP));
}
builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerDependency();//注册仓储
builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerDependency();//注册服务
builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerDependency(); //注册仓储
builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerDependency(); //注册服务
// 获取 Service.dll 程序集服务,并注册
var assemblysServices = Assembly.LoadFrom(servicesDllFile);

View File

@ -1,4 +1,4 @@
using Blog.Core.Common.HttpPolly;
using Blog.Core.Common.Https.HttpPolly;
using Blog.Core.Model;
using Microsoft.Extensions.DependencyInjection;
using Polly;

View File

@ -0,0 +1,37 @@
using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
using Blog.Core.Serilog.Extensions;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Debugging;
using System;
using System.IO;
namespace Blog.Core.Extensions.ServiceExtensions;
public static class SerilogSetup
{
public static IHostBuilder AddSerilogSetup(this IHostBuilder host)
{
if (host == null) throw new ArgumentNullException(nameof(host));
var loggerConfiguration = new LoggerConfiguration()
.ReadFrom.Configuration(AppSettings.Configuration)
.Enrich.FromLogContext()
//输出到控制台
.WriteToConsole()
//将日志保存到文件中
.WriteToFile();
//配置日志库
//.WriteToLogBatching();
Log.Logger = loggerConfiguration.CreateLogger();
//Serilog 内部日志
var file = File.CreateText(LogContextStatic.Combine($"SerilogDebug{DateTime.Now:yyyyMMdd}.txt"));
SelfLog.Enable(TextWriter.Synchronized(file));
host.UseSerilog();
return host;
}
}

View File

@ -1,6 +1,7 @@
using Blog.Core.Common;
using Blog.Core.Common.Const;
using Blog.Core.Common.DB;
using Blog.Core.Common.Helper;
using Blog.Core.Common.DB.Aop;
using Blog.Core.Common.LogHelper;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
@ -9,7 +10,6 @@ using StackExchange.Profiling;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Blog.Core.Common.DB.Aop;
namespace Blog.Core.Extensions
{
@ -48,7 +48,7 @@ namespace Blog.Core.Extensions
BaseDBConfig.MutiConnectionString.allDbs.ForEach(m =>
{
listConfig.Add(new ConnectionConfig()
var config = new ConnectionConfig()
{
ConfigId = m.ConnId.ObjToString().ToLower(),
ConnectionString = m.Connection,
@ -56,29 +56,6 @@ namespace Blog.Core.Extensions
IsAutoCloseConnection = true,
// Check out more information: https://github.com/anjoy8/Blog.Core/issues/122
//IsShardSameThread = false,
AopEvents = new AopEvents
{
OnLogExecuting = (sql, p) =>
{
if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool())
{
if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToFile", "Enabled" }).ObjToBool())
{
Parallel.For(0, 1, e =>
{
MiniProfiler.Current.CustomTiming("SQL", GetParas(p) + "【SQL语句】" + sql);
//LogLock.OutSql2Log("SqlLog", new string[] { GetParas(p), "【SQL语句】" + sql });
LogLock.OutLogAOP("SqlLog", "", new string[] { sql.GetType().ToString(), GetParas(p), "【SQL语句】" + sql });
});
}
if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToConsole", "Enabled" }).ObjToBool())
{
ConsoleHelper.WriteColorLine(string.Join("\r\n", new string[] { "--------", $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} " + GetWholeSql(p, sql) }), ConsoleColor.DarkCyan);
}
}
},
},
MoreSettings = new ConnMoreSettings()
{
//IsWithNoLockQuery = true,
@ -99,15 +76,29 @@ namespace Blog.Core.Extensions
}
},
InitKeyType = InitKeyType.Attribute
};
if (SqlSugarConst.LogConfigId.Equals(m.ConnId))
{
BaseDBConfig.LogConfig = config;
}
);
listConfig.Add(config);
});
if (BaseDBConfig.LogConfig is null)
{
throw new ApplicationException("未配置Log库连接");
}
return new SqlSugarScope(listConfig, db =>
{
listConfig.ForEach(config =>
{
var dbProvider = db.GetConnectionScope((string)config.ConfigId);
// 打印SQL语句
dbProvider.Aop.OnLogExecuting = (s, parameters) => SqlSugarAop.OnLogExecuting(dbProvider,s, parameters, config);
// 数据审计
dbProvider.Aop.DataExecuting = SqlSugarAop.DataExecuting;

View File

@ -1,7 +1,7 @@
using Blog.Core.Common;
using log4net;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Serilog;
using Swashbuckle.AspNetCore.Filters;
using System;
using System.Collections.Generic;
@ -17,10 +17,6 @@ namespace Blog.Core.Extensions
/// </summary>
public static class SwaggerSetup
{
private static readonly ILog log =
LogManager.GetLogger(typeof(SwaggerSetup));
public static void AddSwaggerSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
@ -59,7 +55,7 @@ namespace Blog.Core.Extensions
}
catch (Exception ex)
{
log.Error("Blog.Core.xml和Blog.Core.Model.xml 丢失,请检查并拷贝。\n" + ex.Message);
Log.Error("Blog.Core.xml和Blog.Core.Model.xml 丢失,请检查并拷贝。\n" + ex.Message);
}
// 开启加权小锁
@ -82,12 +78,13 @@ namespace Blog.Core.Extensions
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri($"{AppSettings.app(new string[] { "Startup", "IdentityServer4", "AuthorizationUrl" })}/connect/authorize"),
Scopes = new Dictionary<string, string> {
Scopes = new Dictionary<string, string>
{
"blog.core.api","ApiResource id"
{
"blog.core.api", "ApiResource id"
}
}
}
}
}
});
}
@ -97,14 +94,11 @@ namespace Blog.Core.Extensions
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
Name = "Authorization",//jwt默认的参数名称
In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
Name = "Authorization", //jwt默认的参数名称
In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中)
Type = SecuritySchemeType.ApiKey
});
}
});
services.AddSwaggerGenNewtonsoftSupport();
}
@ -124,11 +118,11 @@ namespace Blog.Core.Extensions
/// V1 版本
/// </summary>
V1 = 1,
/// <summary>
/// V2 版本
/// </summary>
V2 = 2,
}
}
}
}

View File

@ -11,7 +11,7 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" />
<PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Blog.Core.Common\Blog.Core.Common.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,121 @@
using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
using Serilog;
using Serilog.Events;
using Serilog.Filters;
using SqlSugar;
namespace Blog.Core.Serilog.Extensions;
public static class LoggerConfigurationExtensions
{
public static LoggerConfiguration WriteToSqlServer(this LoggerConfiguration loggerConfiguration)
{
var logConnectionStrings = AppSettings.app("LogConnectionStrings");
if (logConnectionStrings.IsNullOrEmpty()) return loggerConfiguration;
//输出SQL
//loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
// lg.FilterSqlLog().WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
// {
// TableName = "SqlLog",
// AutoCreateSqlTable = true
// }));
//输出普通日志
//loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
// lg.FilterRemoveSqlLog().Filter.ByIncludingOnly(p => p.Level >= LogEventLevel.Error)
// .WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
// {
// TableName = "ErrorLog",
// AutoCreateSqlTable = true
// }));
//loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
// lg.FilterRemoveSqlLog().Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning)
// .WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
// {
// TableName = "WarningLog",
// AutoCreateSqlTable = true
// }));
//loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
// lg.FilterRemoveSqlLog().Filter.ByIncludingOnly(p => p.Level <= LogEventLevel.Information)
// .WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
// {
// TableName = "InformationLog",
// AutoCreateSqlTable = true
// }));
return loggerConfiguration;
}
public static LoggerConfiguration WriteToConsole(this LoggerConfiguration loggerConfiguration)
{
//输出普通日志
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterRemoveSqlLog().WriteTo.Console());
//输出SQL
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterSqlLog().Filter.ByIncludingOnly(Matching.WithProperty<bool>(LogContextStatic.SqlOutToConsole, s => s))
.WriteTo.Console());
return loggerConfiguration;
}
public static LoggerConfiguration WriteToFile(this LoggerConfiguration loggerConfiguration)
{
//输出SQL
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterSqlLog().Filter.ByIncludingOnly(Matching.WithProperty<bool>(LogContextStatic.SqlOutToFile, s => s))
.WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.AopSql, @"AopSql.txt"), rollingInterval: RollingInterval.Day,
outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));
//输出普通日志
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterRemoveSqlLog().WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.BasePathLogs, @"Log.txt"), rollingInterval: RollingInterval.Day,
outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));
return loggerConfiguration;
}
public static LoggerConfiguration FilterSqlLog(this LoggerConfiguration lc)
{
lc = lc.Filter.ByIncludingOnly(Matching.WithProperty<string>(LogContextStatic.LogSource, s => LogContextStatic.AopSql.Equals(s)));
return lc;
}
public static IEnumerable<LogEvent> FilterSqlLog(this IEnumerable<LogEvent> batch)
{
return batch.Where(s => s.WithProperty<string>(LogContextStatic.LogSource, q => LogContextStatic.AopSql.Equals(q)))
.Where(s => s.WithProperty<SugarActionType>(LogContextStatic.SugarActionType,
q => !new[] { SugarActionType.UnKnown, SugarActionType.Query }.Contains(q)));
}
public static LoggerConfiguration FilterRemoveSqlLog(this LoggerConfiguration lc)
{
lc = lc.Filter.ByIncludingOnly(WithProperty<string>(LogContextStatic.LogSource, s => !LogContextStatic.AopSql.Equals(s)));
return lc;
}
public static IEnumerable<LogEvent> FilterRemoveOtherLog(this IEnumerable<LogEvent> batch)
{
return batch.Where(s => WithProperty<string>(LogContextStatic.LogSource,
q => !LogContextStatic.AopSql.Equals(q))(s));
}
public static Func<LogEvent, bool> WithProperty<T>(string propertyName, Func<T, bool> predicate)
{
//如果不包含属性 也认为是true
return e =>
{
if (!e.Properties.TryGetValue(propertyName, out var propertyValue)) return true;
return propertyValue is ScalarValue { Value: T value } && predicate(value);
};
}
public static bool WithProperty<T>(this LogEvent e, string key, Func<T, bool> predicate)
{
if (!e.Properties.TryGetValue(key, out var propertyValue)) return false;
return propertyValue is ScalarValue { Value: T value } && predicate(value);
}
}

View File

@ -0,0 +1,34 @@
using Microsoft.AspNetCore.Http;
using Serilog.Events;
namespace Blog.Core.Serilog.Utility;
public class SerilogRequestUtility
{
private static readonly List<string> _ignoreUrl = new()
{
"/job",
};
private static LogEventLevel DefaultGetLevel(
HttpContext ctx,
double _,
Exception? ex)
{
return ex is null && ctx.Response.StatusCode <= 499 ? LogEventLevel.Information : LogEventLevel.Error;
}
public static LogEventLevel GetRequestLevel(HttpContext ctx, double _, Exception? ex) =>
ex is null && ctx.Response.StatusCode <= 499 ? IgnoreRequest(ctx) : LogEventLevel.Error;
private static LogEventLevel IgnoreRequest(HttpContext ctx)
{
var path = ctx.Request.Path.Value;
if (path.IsNullOrEmpty())
{
return LogEventLevel.Information;
}
return _ignoreUrl.Any(s => path.StartsWith(s)) ? LogEventLevel.Verbose : LogEventLevel.Information;
}
}

View File

@ -34,7 +34,7 @@ namespace Blog.Core.Tasks
}
public async Task Run(IJobExecutionContext context)
{
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
@ -94,7 +94,7 @@ namespace Blog.Core.Tasks
Parallel.For(0, 1, e =>
{
LogLock.OutLogAOP("ACCESSTRENDLOG","",new string[] { activeUserVMs.GetType().ToString(), JsonConvert.SerializeObject(activeUserVMs) }, false);
LogLock.OutLogAOP("ACCESSTRENDLOG", "", new string[] { activeUserVMs.GetType().ToString(), JsonConvert.SerializeObject(activeUserVMs) }, false);
});
}

View File

@ -17,19 +17,21 @@ namespace Blog.Core.Tasks
{
public class Job_OperateLog_Quartz : JobBase, IJob
{
private readonly IOperateLogServices _operateLogServices;
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
public Job_OperateLog_Quartz(IOperateLogServices operateLogServices,IWebHostEnvironment environment, ITasksQzServices tasksQzServices,ITasksLogServices tasksLogServices)
:base(tasksQzServices, tasksLogServices)
public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, IWebHostEnvironment environment, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
: base(tasksQzServices, tasksLogServices)
{
_operateLogServices = operateLogServices;
_environment = environment;
_operateLogServices = operateLogServices;
_environment = environment;
}
public async Task Execute(IJobExecutionContext context)
{
var executeLog = await ExecuteJob(context, async () => await Run(context));
}
public async Task Run(IJobExecutionContext context)
{
@ -78,7 +80,4 @@ namespace Blog.Core.Tasks
}
}
}
}
}

View File

@ -59,7 +59,6 @@ namespace Blog.Core.Tests
services.AddAutoMapper(typeof(Startup));
services.AddSingleton(new AppSettings(basePath));
services.AddSingleton(new LogLock(basePath));
services.AddScoped<DBSeed>();
services.AddScoped<MyContext>();

View File

@ -57,6 +57,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Serilog.Es", "Blo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Nacos", "Ocelot.Provider.Nacos\Ocelot.Provider.Nacos.csproj", "{6463FB13-5F01-4A1D-8B62-A454FB3812EB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blog.Core.Serilog", "Blog.Core.Serilog\Blog.Core.Serilog.csproj", "{7F9057F0-ED8D-4694-B590-7D75C012DF00}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -119,6 +121,10 @@ Global
{6463FB13-5F01-4A1D-8B62-A454FB3812EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6463FB13-5F01-4A1D-8B62-A454FB3812EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6463FB13-5F01-4A1D-8B62-A454FB3812EB}.Release|Any CPU.Build.0 = Release|Any CPU
{7F9057F0-ED8D-4694-B590-7D75C012DF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F9057F0-ED8D-4694-B590-7D75C012DF00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F9057F0-ED8D-4694-B590-7D75C012DF00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F9057F0-ED8D-4694-B590-7D75C012DF00}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE