diff --git a/src/InterfaceForward.Api/InterfaceForward.Api.csproj b/src/InterfaceForward.Api/InterfaceForward.Api.csproj index b3a6390..51a3bbe 100644 --- a/src/InterfaceForward.Api/InterfaceForward.Api.csproj +++ b/src/InterfaceForward.Api/InterfaceForward.Api.csproj @@ -16,11 +16,11 @@ - + - + - + diff --git a/src/InterfaceForward.Api/InterfaceForwardApiModule.cs b/src/InterfaceForward.Api/InterfaceForwardApiModule.cs index dc1460f..4f52e70 100644 --- a/src/InterfaceForward.Api/InterfaceForwardApiModule.cs +++ b/src/InterfaceForward.Api/InterfaceForwardApiModule.cs @@ -1,17 +1,13 @@ using Fake.AspNetCore; -using Fake.AspNetCore.Mvc; +using Fake.AspNetCore.Auditing; using Fake.AspNetCore.Mvc.Conventions; -using Fake.Authorization; using Fake.Autofac; using Fake.Modularity; using InterfaceForward.Application; -using InterfaceForward.Application.Filters; -using Microsoft.AspNetCore.Mvc; namespace InterfaceForward.Api; [DependsOn(typeof(FakeAutofacModule))] -[DependsOn(typeof(FakeAspNetCoreMvcModule))] [DependsOn(typeof(InterfaceForwardApplicationModule))] public class InterfaceForwardApiModule : FakeModule { @@ -23,20 +19,16 @@ public class InterfaceForwardApiModule : FakeModule // Add services to the container. services.AddProblemDetails(); - - services.Configure(options => - { - options.Filters.AddService(); - options.Filters.AddService(); - }); - + services.Configure(options => { options.AddAssembly(typeof(InterfaceForwardApplicationModule).Assembly); }); - - services.AddUnifiedResultFilter(); - services.AddFakeSwaggerGen(); + + services.AddFakeSwaggerGen() + .AddFakeExceptionFilter() + .AddFakeValidationActionFilter() + .AddFakeAspNetCoreAuditing(); services.AddCors(options => { @@ -54,11 +46,9 @@ public class InterfaceForwardApiModule : FakeModule { var app = context.GetWebApplication(); - app.MapControllers(); - // Add Aspire default endpoints. app.MapDefaultEndpoints(); - + app.MapControllers(); // Configure the HTTP request pipeline. app.UseFakeSwagger(); @@ -66,16 +56,4 @@ public class InterfaceForwardApiModule : FakeModule app.UseCors(DefaultCorsPolicyName); } -} - -public static class ServiceCollectionExtensions -{ - public static IServiceCollection AddSwagger(this IServiceCollection services) - { - // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle - services.AddEndpointsApiExplorer(); - services.AddSwaggerGen(); - - return services; - } } \ No newline at end of file diff --git a/src/InterfaceForward.Api/Logs/SerilogHostingExtensions.cs b/src/InterfaceForward.Api/Logs/SerilogHostingExtensions.cs deleted file mode 100644 index d7b8bb7..0000000 --- a/src/InterfaceForward.Api/Logs/SerilogHostingExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ - -using InterfaceForward.Domain.Shared.Options; -using InterfaceForward.Repositories.Log; -using Serilog; - -namespace InterfaceForward.Api.Logs; - -public static class SerilogHostingExtensions -{ - public static WebApplicationBuilder UseSerilogDefault(this WebApplicationBuilder builder) - { - var configuration = builder.Configuration; - - Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(configuration) - .CreateLogger(); - - //初始化配置 - var environment = configuration["Environment"]; - var options = configuration.GetSection("Notice")?.Get(); - if (options == null) - Console.Write("-- 未找到日志飞书通知相关配置"); - else - LogHelper.Init(options, environment == "uat" || environment == "Product");//写死了 - - builder.Host.UseSerilog(); - return builder; - } -} \ No newline at end of file diff --git a/src/InterfaceForward.Api/Program.cs b/src/InterfaceForward.Api/Program.cs index edbdf93..a5d6a02 100644 --- a/src/InterfaceForward.Api/Program.cs +++ b/src/InterfaceForward.Api/Program.cs @@ -1,13 +1,16 @@ using InterfaceForward.Api; -using InterfaceForward.Api.Logs; using Serilog; +var builder = WebApplication.CreateSlimBuilder(args); +var configuration = builder.Configuration; +Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .CreateLogger(); + try { - var builder = WebApplication.CreateSlimBuilder(args); - builder.UseSerilogDefault(); builder.WebHost.UseUrls(builder.Configuration.GetSection("App:Urls").Get() ?? []); - builder.Host.UseAutofac(); + builder.Host.UseAutofac().UseSerilog(); builder.Services.AddApplication(); // Add service defaults & Aspire components. diff --git a/src/InterfaceForward.Api/appsettings.json b/src/InterfaceForward.Api/appsettings.json index 91fe569..a3c9a1e 100644 --- a/src/InterfaceForward.Api/appsettings.json +++ b/src/InterfaceForward.Api/appsettings.json @@ -26,5 +26,9 @@ "CorsOrigins": [ "http://localhost:8888" ] + }, + "FeiShuNotice": { + "Title": "InterfaceForward-Dev", + "Webhook": "https://open.feishu.cn/open-apis/bot/v2/hook/255c44ff-5891-4902-9b6a-6d0250e745f7" } } diff --git a/src/InterfaceForward.Application.Contracts/ForwardCore/InterfaceRelayUnifyResultDto.cs b/src/InterfaceForward.Application.Contracts/ForwardCore/InterfaceRelayUnifyResultDto.cs index eb3fd9f..2267827 100644 --- a/src/InterfaceForward.Application.Contracts/ForwardCore/InterfaceRelayUnifyResultDto.cs +++ b/src/InterfaceForward.Application.Contracts/ForwardCore/InterfaceRelayUnifyResultDto.cs @@ -3,13 +3,18 @@ namespace InterfaceForward.Application.Contracts.ForwardCore; [Serializable] -public class InterfaceRelayUnifyResultDto : UnifyResultDto +public class InterfaceRelayUnifyResultDto { /// /// 请求Id /// public Guid RequestId { get; set; } + /// + /// 消息 + /// + public string? Message { get; set; } + /// /// 原报文 /// diff --git a/src/InterfaceForward.Application/AutoMapper/AppProfile.cs b/src/InterfaceForward.Application/AutoMapper/AppProfile.cs index abf5eb7..7be97a3 100644 --- a/src/InterfaceForward.Application/AutoMapper/AppProfile.cs +++ b/src/InterfaceForward.Application/AutoMapper/AppProfile.cs @@ -2,15 +2,14 @@ using InterfaceForward.Application.Contracts.Dtos.App; using InterfaceForward.Repositories.App.Entitys; -namespace InterfaceForward.Application.AutoMapper +namespace InterfaceForward.Application.AutoMapper; + +internal class AppProfile : Profile { - internal class AppProfile : Profile + public AppProfile() { - public AppProfile() - { - CreateMap(MemberList.None); - CreateMap(MemberList.None); - CreateMap(MemberList.None); - } + CreateMap(MemberList.None); + CreateMap(MemberList.None); + CreateMap(MemberList.None); } -} +} \ No newline at end of file diff --git a/src/InterfaceForward.Application/Filters/DisableRequestLogAttribute.cs b/src/InterfaceForward.Application/Filters/DisableRequestLogAttribute.cs deleted file mode 100644 index 3e530cb..0000000 --- a/src/InterfaceForward.Application/Filters/DisableRequestLogAttribute.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace InterfaceForward.Application.Filters; - -public class DisableRequestLogAttribute:Attribute; \ No newline at end of file diff --git a/src/InterfaceForward.Application/Filters/ForwardAuthorizeFilter.cs b/src/InterfaceForward.Application/Filters/ForwardAuthorizeFilter.cs index 626b3f3..fd90df3 100644 --- a/src/InterfaceForward.Application/Filters/ForwardAuthorizeFilter.cs +++ b/src/InterfaceForward.Application/Filters/ForwardAuthorizeFilter.cs @@ -1,7 +1,7 @@ using System.Text; +using Fake.AspNetCore.Http; using InterfaceForward.Repositories; using InterfaceForward.Repositories.Log.Services; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; @@ -9,43 +9,24 @@ using Newtonsoft.Json; namespace InterfaceForward.Application.Filters; -public class ForwardAuthorizeFilter : IAsyncActionFilter +public class ForwardAuthorizeFilter( + InterfaceForwardQuery interfaceForwardQuery, + ILogRepository logRepository, + IHttpClientInfoProvider httpClientInfoProvider) + : IAsyncActionFilter { - private readonly InterfaceForwardQuery _interfaceForwardQuery; - private readonly ILogRepository _logRepository; - - private readonly IHttpContextAccessor _httpContextAccessor; - // private readonly IEntrySegmentContextAccessor _segContext; - - public ForwardAuthorizeFilter( - InterfaceForwardQuery interfaceForwardQuery - // , IEntrySegmentContextAccessor segContext - , ILogRepository logRepository - , IHttpContextAccessor httpContextAccessor) - { - _interfaceForwardQuery = interfaceForwardQuery; - _logRepository = logRepository; - _httpContextAccessor = httpContextAccessor; - // _segContext = segContext; - } - public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var start = DateTime.Now; // _segContext.Context.Span.AddLog(LogEvent.Message("进入授权过滤器")); - var log = _logRepository.AppRequestLog; + var log = logRepository.AppRequestLog; log.RequestTime = start; var httpContext = context.HttpContext; log.IsApp = true; - var ip = _httpContextAccessor.HttpContext!.Connection.RemoteIpAddress?.MapToIPv4().ToString(); - if (_httpContextAccessor.HttpContext.Request.Headers.TryGetValue("X-Forwarded-For", out var header)) - { - ip = header.ToString(); - } - log.ClientIP = ip; + log.ClientIp = httpClientInfoProvider.ClientIpAddress; log.Address = httpContext.Request.GetDisplayUrl(); // body @@ -66,20 +47,16 @@ public class ForwardAuthorizeFilter : IAsyncActionFilter throw new BusinessException(message: "应用授权失败,AppKey和AppSecret是必填的"); } - var app = await _interfaceForwardQuery.FindAppAsync(appKey, appSecret); + var app = await interfaceForwardQuery.FindAppAsync(appKey!, appSecret!); if (app == null) throw new BusinessException(message: "应用授权失败,请检查AppKey或AppSecret是否正确"); log.Name = app.Name; if (!app.IsOnline) throw new BusinessException(message: "应用已被禁用,请检查应用状态"); - _logRepository.AppId = app.Id; + logRepository.AppId = app.Id; - // await InterfaceLimitAsync(httpContext, app.Id); - - // _segContext.Context.Span.AddLog(LogEvent.Message("开始执行action")); var actionContext = await next(); - // _segContext.Context.Span.AddLog(LogEvent.Message("action执行完毕")); if (actionContext.Exception == null) { @@ -91,10 +68,10 @@ public class ForwardAuthorizeFilter : IAsyncActionFilter } else { - log.Response = actionContext.Result?.ToString(); + log.Response = actionContext.Result?.ToString()?? string.Empty; } - _ = _logRepository.WriteAppLog(); + _ = logRepository.WriteAppLogAsync(); } } } \ No newline at end of file diff --git a/src/InterfaceForward.Application/Filters/ForwardExceptionFilter.cs b/src/InterfaceForward.Application/Filters/ForwardExceptionFilter.cs deleted file mode 100644 index a41c2f1..0000000 --- a/src/InterfaceForward.Application/Filters/ForwardExceptionFilter.cs +++ /dev/null @@ -1,55 +0,0 @@ -using InterfaceForward.Application.Contracts; -using InterfaceForward.Application.Contracts.ForwardCore; -using InterfaceForward.Repositories.Log.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using SJZY.InterfaceRelay.Application.Contracts; - -namespace InterfaceForward.Application.Filters; - -public class ForwardExceptionFilter(ILogRepository logRepository) : IAsyncExceptionFilter -{ - public async Task OnExceptionAsync(ExceptionContext context) - { - if (context.ExceptionHandled) return; - - /* - * ServiceProviderRequestLog设计的意义是: - * 最大可能限度的保留请求服务商发生异常时附近的日志信息,以便于排查问题 - */ - var originMessage = bool.TryParse(context.HttpContext.Request.Headers["isReturnMessage"].ToString(), - out var isReturnMessage) - ? isReturnMessage ? logRepository.ServiceProviderRequestLog.Response : null - : null; - - var res = new InterfaceRelayUnifyResultDto - { - Code = StatusCodes.Status400BadRequest.ToString(), - RequestId = logRepository.AppRequestLog.RequestId, - OriginalMessage = originMessage, - Attach = context.HttpContext.Request.Headers["attach"] - }; - if (context.Exception is BusinessException business) //业务异常 - { - res.Code = string.IsNullOrEmpty(business.Code) ? StatusCodes.Status400BadRequest.ToString() : business.Code; - res.Message = business.Message; - context.Result = new JsonResult(res); - } - else //未处理异常 - { - logRepository.SendFeiShu(context.Exception); - res.Code = StatusCodes.Status500InternalServerError.ToString(); - res.Message = "服务器发生未处理异常!"; - context.Result = new JsonResult(res); - } - - // 异常情况也要记录app日志 - logRepository.AppRequestLog.Response = JsonConvert.SerializeObject(res); - _ = logRepository.WriteAppLog(context.Exception); - context.ExceptionHandled = true; - } -} \ No newline at end of file diff --git a/src/InterfaceForward.Application/Filters/ForwardExceptionSubscriber.cs b/src/InterfaceForward.Application/Filters/ForwardExceptionSubscriber.cs new file mode 100644 index 0000000..ed1093a --- /dev/null +++ b/src/InterfaceForward.Application/Filters/ForwardExceptionSubscriber.cs @@ -0,0 +1,55 @@ +using Fake.ExceptionHandling; +using InterfaceForward.Application.Contracts.ForwardCore; +using InterfaceForward.Domain.Shared.FeiShu; +using InterfaceForward.Repositories.Log.Services; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +namespace InterfaceForward.Application.Filters; + +public class ForwardExceptionSubscriber : IExceptionSubscriber +{ + public Task HandleAsync(ExceptionNotificationContext context) + { + var httpContext = context.ServiceProvider.GetRequiredService().HttpContext; + var logRepository = context.ServiceProvider.GetRequiredService(); + var feiShuNoticer = context.ServiceProvider.GetRequiredService(); + +// if (httpContext == null) +// { +// feiShuNoticer.NoticeAsync($""" +// 日志请求id:{ServiceProviderRequestLog.RequestId} +// 服务商--接口:{ServiceProviderRequestLog.Name}--{ServiceProviderRequestLog.InterfaceName} +// 异常原因:{Truncate(contextException.ToString())} +// 请求地址:{ServiceProviderRequestLog.Address} +// 原始报文: +// {Truncate(AppRequestLog.Content)} +// 请求报文: +// {Truncate(ServiceProviderRequestLog.Content)} +// 响应报文: +// {Truncate(ServiceProviderRequestLog.Response)} +// """) +// } +// + /* + * ServiceProviderRequestLog设计的意义是: + * 最大可能限度的保留请求服务商发生异常时附近的日志信息,以便于排查问题 + */ + var originMessage = bool.TryParse(httpContext.Request.Headers["isReturnMessage"].ToString(), + out var isReturnMessage) + ? isReturnMessage ? logRepository.ServiceProviderRequestLog.Response : null + : null; + var res = new InterfaceRelayUnifyResultDto + { + RequestId = logRepository.AppRequestLog.RequestId, + OriginalMessage = originMessage, + Message = context.Exception.Message, + Attach = httpContext.Request.Headers["attach"] + }; + logRepository.AppRequestLog.Response = JsonConvert.SerializeObject(res); + // 异常情况也要记录app日志 + _ = logRepository.WriteAppLogAsync(context.Exception); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/InterfaceForward.Application/Filters/GlobalExceptionFilter.cs b/src/InterfaceForward.Application/Filters/GlobalExceptionFilter.cs deleted file mode 100644 index d433c58..0000000 --- a/src/InterfaceForward.Application/Filters/GlobalExceptionFilter.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Net; -using Fake.DependencyInjection; -using InterfaceForward.Domain.Shared.Dtos; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Hosting; - -namespace InterfaceForward.Application.Filters; - -public class GlobalExceptionFilter(IHostEnvironment environment) : IAsyncExceptionFilter, ITransientDependency -{ - public Task OnExceptionAsync(ExceptionContext context) - { - if (context.ExceptionHandled) return Task.CompletedTask; - - var result = new UnifyResultDto - { - Message = context.Exception.Message - }; - if (environment.IsDevelopment()) - { - result.Message = context.Exception.ToString(); - } - - if (context.Exception is BusinessException) //业务异常 - { - result.Code = HttpStatusCode.BadRequest.ToString(); - } - else //未处理异常 - { - result.Code = HttpStatusCode.InternalServerError.ToString(); - } - - context.Result = new JsonResult(result); - context.ExceptionHandled = true; - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/src/InterfaceForward.Application/Filters/IgnoreLogDetailAttribute.cs b/src/InterfaceForward.Application/Filters/IgnoreLogDetailAttribute.cs deleted file mode 100644 index 5b52298..0000000 --- a/src/InterfaceForward.Application/Filters/IgnoreLogDetailAttribute.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace InterfaceForward.Application.Filters -{ - [AttributeUsage(AttributeTargets.Method)] - public class IgnoreLogDetailAttribute : Attribute; -} diff --git a/src/InterfaceForward.Application/Filters/RequestLogFilter.cs b/src/InterfaceForward.Application/Filters/RequestLogFilter.cs deleted file mode 100644 index e0a708d..0000000 --- a/src/InterfaceForward.Application/Filters/RequestLogFilter.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Diagnostics; -using Fake.DependencyInjection; -using InterfaceForward.Repositories.Log; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Newtonsoft.Json; - -namespace InterfaceForward.Application.Filters; - -public class RequestLogFilter : IAsyncActionFilter, ISingletonDependency -{ - - public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) - { - var logInfo = new RequestLogInfo(); - try - { - var httpContext = context.HttpContext; - var httpRequest = httpContext.Request; - var currentTime = DateTime.Now; - var requestCode = Guid.NewGuid().ToString("N"); - - //获取请求参数 - var parameters = context?.ActionDescriptor?.Parameters; - var paramsterNames = parameters?.Where(x => x.BindingInfo != null && x.BindingInfo.BindingSource != BindingSource.Services)?.Select(x => x.Name)?.ToArray(); - logInfo.RequestParamsters = httpRequest.Method == "GET" ? httpRequest.QueryString.ToString() : JsonConvert.SerializeObject(context?.ActionArguments?.Where(m => paramsterNames.Contains(m.Key))); - context.HttpContext.Request.Headers.Add(FilterSettingConstant.RequestCode, requestCode); - context.HttpContext.Request.Headers.Add(FilterSettingConstant.RequestParameters, logInfo.RequestParamsters); - - var sw = new Stopwatch(); - sw.Start(); - var actionContext = await next(); - sw.Stop(); - - // 记录日志 - logInfo.RequestCode = requestCode; - logInfo.TotalTime = sw.ElapsedMilliseconds; - logInfo.RequestPath = httpRequest.Path; - logInfo.ExecuteTime = currentTime; - - if (actionContext.Exception != null) - { - logInfo.Result = actionContext.Exception.ToString(); - } - else - { - if (!context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(IgnoreLogDetailAttribute))) - { - string? exceptionMsg = null; - if (actionContext.Exception == null) - { - if (actionContext.Result is FileResult) - { - exceptionMsg = $"...[文件流结果日志已忽略打印]..."; - } - else - { - exceptionMsg = JsonConvert.SerializeObject((actionContext.Result as dynamic)?.Value); - } - } - else - { - exceptionMsg = actionContext.Exception.ToString(); - } - logInfo.Result = exceptionMsg; - } - else - { - logInfo.Result = $"...[日志已忽略打印]..."; - } - } - logInfo.Headers = httpRequest.Headers; - logInfo.Exception = actionContext.Exception; - - } - catch (Exception ex) - { - Console.WriteLine($"记录日志发生未处理异常:{ex}"); - } - finally - { - var log = $@" - |-请求编号:{logInfo.RequestCode} - |-消耗时间:{logInfo.TotalTime}毫秒 - |-请求路径:{logInfo.RequestPath} - |-执行时间:{logInfo.ExecuteTime.ToString("yyyy-MM-dd HH:mm:ss ffff")} - |-用户信息:{logInfo.UserInfo} - |-请求参数:{logInfo.RequestParamsters} - |-执行结果:{logInfo.Result} - |-Headers:{(logInfo.Headers == null ? "" : JsonConvert.SerializeObject(logInfo.Headers))}"; - - - LogHelper.Info(log); - } - } -} - -internal static class FilterSettingConstant -{ - internal const string RequestCode = "SJZY_Request_Code"; - internal const string RequestParameters = "SJZY_Request_Parameter"; - internal const string Authorization = "Authorization"; -} \ No newline at end of file diff --git a/src/InterfaceForward.Application/Filters/RequestLogInfo.cs b/src/InterfaceForward.Application/Filters/RequestLogInfo.cs deleted file mode 100644 index eca25eb..0000000 --- a/src/InterfaceForward.Application/Filters/RequestLogInfo.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.AspNetCore.Http; - -namespace InterfaceForward.Application.Filters; - -public struct RequestLogInfo -{ - /// - /// 执行时间 - /// - public DateTime ExecuteTime { get; set; } - - /// - /// 执行时长 - /// - public long TotalTime { get; set; } - - /// - /// 请求编号 - /// - public string RequestCode { get; set; } - - /// - /// 请求路径 - /// - public string RequestPath { get; set; } - - /// - /// 请求参数 - /// - public string RequestParamsters { get; set; } - - /// - /// 返回结果 - /// - public dynamic Result { get; set; } - - /// - /// 请求头 - /// - public IHeaderDictionary Headers { get; set; } - - /// - /// 异常信息 - /// - public Exception? Exception { get; internal set; } - - /// - /// 用户信息 - /// - public string UserInfo { get; internal set; } -} \ No newline at end of file diff --git a/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs b/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs index 1b8c73d..6fb0ec7 100644 --- a/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs +++ b/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs @@ -273,9 +273,7 @@ public class DefaultForwardFlow : IForwardFlow context.ServiceProviderRequestLog.Address = context.TargetInterface.RequestAddress; context.ServiceProviderRequestLog.IsSuccess = false; - throw new BusinessException( - code: code, - message: msg); + throw new BusinessException(message: msg); } /// @@ -285,7 +283,7 @@ public class DefaultForwardFlow : IForwardFlow public virtual void BeforeRequest(ForwardCoreContext context) { var log = context.ServiceProviderRequestLog; - log.ClientIP = NetUtil.GetLanIp(); + log.ClientIp = NetUtil.GetLanIp(); log.Content = context.TargetInterfaceInput; context.ServiceProviderRequestLog.RequestTime = DateTime.Now; @@ -384,7 +382,7 @@ public class DefaultForwardFlow : IForwardFlow { if (!await CanVisitInterfaceAsync(context.TargetInterface.Code, qps)) { - throw new BusinessException("4004", $"服务商接口qps已达到上限{qps},稍后请求"); + throw new BusinessException($"服务商接口qps已达到上限{qps},稍后请求"); } } diff --git a/src/InterfaceForward.Application/InterfaceForward.Application.csproj b/src/InterfaceForward.Application/InterfaceForward.Application.csproj index 89d1b2b..5f69f77 100644 --- a/src/InterfaceForward.Application/InterfaceForward.Application.csproj +++ b/src/InterfaceForward.Application/InterfaceForward.Application.csproj @@ -17,10 +17,9 @@ + + - - - diff --git a/src/InterfaceForward.Application/InterfaceForwardApplicationModule.cs b/src/InterfaceForward.Application/InterfaceForwardApplicationModule.cs index 0d23ed6..7c38515 100644 --- a/src/InterfaceForward.Application/InterfaceForwardApplicationModule.cs +++ b/src/InterfaceForward.Application/InterfaceForwardApplicationModule.cs @@ -1,5 +1,5 @@ using System.Security.Authentication; -using Fake.AspNetCore.Mvc; +using Fake.AspNetCore; using Fake.Modularity; using Fake.ObjectMapping.AutoMapper; using InterfaceForward.Application.Contracts; @@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection; namespace InterfaceForward.Application; +[DependsOn(typeof(FakeAspNetCoreModule))] [DependsOn(typeof(FakeObjectMappingAutoMapperModule))] [DependsOn(typeof(InterfaceForwardRepositoriesModule))] public class InterfaceForwardApplicationModule:FakeModule diff --git a/src/InterfaceForward.Application/Services/App/AppsService.cs b/src/InterfaceForward.Application/Services/App/AppsService.cs index 5c8ad9e..28ebdb7 100644 --- a/src/InterfaceForward.Application/Services/App/AppsService.cs +++ b/src/InterfaceForward.Application/Services/App/AppsService.cs @@ -19,7 +19,7 @@ namespace InterfaceForward.Application.Services.App; /// [Route("App")] [ApiExplorerSettings(GroupName = "应用服务")] -public class AppsService : ApplicationService +public class AppsService : BaseService { private readonly IAppRepository _appRepository; private readonly IAppScopeRepository _appScopeRepository; @@ -59,7 +59,7 @@ public class AppsService : ApplicationService var urlDic = OSSHelper.GetUrlByKeys(logoKeys); foreach (var url in urlDic) - res.Items.Find(x => x.LogoKey == url.Key)!.LogoUrl = url.Value; + res.Items.First(x => x.LogoKey == url.Key).LogoUrl = url.Value; return res; } diff --git a/src/InterfaceForward.Application/Services/App/DictionaryService.cs b/src/InterfaceForward.Application/Services/App/DictionaryService.cs index cb3330a..a6437d9 100644 --- a/src/InterfaceForward.Application/Services/App/DictionaryService.cs +++ b/src/InterfaceForward.Application/Services/App/DictionaryService.cs @@ -8,7 +8,7 @@ namespace InterfaceForward.Application.Services.App /// [Route("Dictionary")] [ApiExplorerSettings(GroupName = "应用服务")] - public class DictionaryService : ApplicationService + public class DictionaryService : BaseService { private readonly IDictionaryRepository _dictionaryRepository; diff --git a/src/InterfaceForward.Application/Services/App/LogService.cs b/src/InterfaceForward.Application/Services/App/LogService.cs index 26cdd6f..39d3243 100644 --- a/src/InterfaceForward.Application/Services/App/LogService.cs +++ b/src/InterfaceForward.Application/Services/App/LogService.cs @@ -12,7 +12,7 @@ namespace InterfaceForward.Application.Services.App /// [Route("Log")] [ApiExplorerSettings(GroupName = "应用服务")] - public class LogService : ApplicationService + public class LogService : BaseService { private readonly ILogRepository _logRepository; @@ -97,7 +97,7 @@ namespace InterfaceForward.Application.Services.App /// /// [HttpGet("GetById")] - public async Task GetByIdAsync(string id) + public async Task GetByIdAsync(string id) { return await _logRepository.GetDetailsByIdAsync(id); } diff --git a/src/InterfaceForward.Application/Services/BaseService.cs b/src/InterfaceForward.Application/Services/BaseService.cs new file mode 100644 index 0000000..6385c2f --- /dev/null +++ b/src/InterfaceForward.Application/Services/BaseService.cs @@ -0,0 +1,5 @@ +namespace InterfaceForward.Application.Services; + +public abstract class BaseService : ApplicationService +{ +} \ No newline at end of file diff --git a/src/InterfaceForward.Application/Services/Interface/InterfaceReturnConfigService.cs b/src/InterfaceForward.Application/Services/Interface/InterfaceReturnConfigService.cs index 3ea9901..484511a 100644 --- a/src/InterfaceForward.Application/Services/Interface/InterfaceReturnConfigService.cs +++ b/src/InterfaceForward.Application/Services/Interface/InterfaceReturnConfigService.cs @@ -13,7 +13,7 @@ namespace InterfaceForward.Application.Services.Interface; /// 接口返回配置 /// [ApiExplorerSettings(GroupName = "接口服务")] -public class InterfaceReturnConfigService : ApplicationService +public class InterfaceReturnConfigService : BaseService { private readonly IInterfaceReturnConfigRepository _interfaceReturnConfigRepository; private readonly IInterfaceRepository _interfaceRepository; diff --git a/src/InterfaceForward.Application/Services/Interface/ServiceProviderInterfaceService.cs b/src/InterfaceForward.Application/Services/Interface/ServiceProviderInterfaceService.cs index d25dde1..337d09c 100644 --- a/src/InterfaceForward.Application/Services/Interface/ServiceProviderInterfaceService.cs +++ b/src/InterfaceForward.Application/Services/Interface/ServiceProviderInterfaceService.cs @@ -18,7 +18,7 @@ namespace InterfaceForward.Application.Services.Interface; /// 服务商接口 /// [ApiExplorerSettings(GroupName = "接口服务")] -public class ServiceProviderInterfaceService : ApplicationService +public class ServiceProviderInterfaceService : BaseService { private ParameterService ParameterService => LazyServiceProvider.GetRequiredService(); diff --git a/src/InterfaceForward.Application/Services/Interface/SystemInterfaceService.cs b/src/InterfaceForward.Application/Services/Interface/SystemInterfaceService.cs index ce221c6..8b7aecc 100644 --- a/src/InterfaceForward.Application/Services/Interface/SystemInterfaceService.cs +++ b/src/InterfaceForward.Application/Services/Interface/SystemInterfaceService.cs @@ -17,7 +17,7 @@ namespace InterfaceForward.Application.Services.Interface; /// 系统接口 /// [ApiExplorerSettings(GroupName = "接口服务")] -public class SystemInterfaceService : ApplicationService +public class SystemInterfaceService : BaseService { #region ctor diff --git a/src/InterfaceForward.Application/Services/InterfaceForwardService.cs b/src/InterfaceForward.Application/Services/InterfaceForwardService.cs index b4f35b3..8bd6612 100644 --- a/src/InterfaceForward.Application/Services/InterfaceForwardService.cs +++ b/src/InterfaceForward.Application/Services/InterfaceForwardService.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations; -using Fake.AspNetCore.Mvc.Filters.UnifiedResult; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; @@ -15,12 +14,10 @@ namespace InterfaceForward.Application.Services; /// 接口转发服务 /// [ApiExplorerSettings(GroupName = "接口转发服务")] -[TypeFilter(typeof(ForwardAuthorizeFilter))] -[TypeFilter(typeof(ForwardExceptionFilter))] -[DisableRequestLog] +[TypeFilter(typeof(ForwardAuthorizeFilter))] [AllowAnonymous] [Route("InterfaceForward")] -public class InterfaceForwardService : ApplicationService, IInterfaceForwardService +public class InterfaceForwardService : BaseService, IInterfaceForwardService { private readonly InterfaceForwardCommon _forwardCommon; private readonly ILogRepository _logRepository; @@ -38,7 +35,6 @@ public class InterfaceForwardService : ApplicationService, IInterfaceForwardServ _options = options.Value; } - [DisableUnifiedResult] [HttpPost("ForwardWithSubscribe")] public async Task ForwardWithSubscribeAsync( [FromQuery] [Required] string upStreamCode, diff --git a/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapPublishService.cs b/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapPublishService.cs index 8995185..2f5a027 100644 --- a/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapPublishService.cs +++ b/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapPublishService.cs @@ -20,7 +20,7 @@ namespace InterfaceForward.Application.Services.InterfaceMap; /// 接口映射发布修改 /// [ApiExplorerSettings(GroupName = "接口映射服务")] -public class InterfaceMapPublishService : ApplicationService +public class InterfaceMapPublishService : BaseService { private readonly static JsonSerializerSettings Settings = new JsonSerializerSettings { diff --git a/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapService.cs b/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapService.cs index f27b53b..45e5553 100644 --- a/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapService.cs +++ b/src/InterfaceForward.Application/Services/InterfaceMap/InterfaceMapService.cs @@ -16,7 +16,7 @@ namespace InterfaceForward.Application.Services.InterfaceMap; /// 接口映射服务 /// [ApiExplorerSettings(GroupName = "接口映射服务")] -public class InterfaceMapService : ApplicationService +public class InterfaceMapService : BaseService { private readonly IInterfaceMapRepository _interfaceMapRepository; private readonly IBasicRepository _interfaceRepository; diff --git a/src/InterfaceForward.Application/Services/Parameter/FixedParameterService.cs b/src/InterfaceForward.Application/Services/Parameter/FixedParameterService.cs index 6dd062b..3b328f8 100644 --- a/src/InterfaceForward.Application/Services/Parameter/FixedParameterService.cs +++ b/src/InterfaceForward.Application/Services/Parameter/FixedParameterService.cs @@ -13,7 +13,7 @@ namespace InterfaceForward.Application.Services.Parameter; /// 固定参数配置 /// [ApiExplorerSettings(GroupName = "参数服务")] -public class FixedParameterService : ApplicationService +public class FixedParameterService : BaseService { private readonly IFixedParameterRepository _fixedParameterRepository; private readonly IServiceProviderRepository _serviceProviderRepository; diff --git a/src/InterfaceForward.Application/Services/Parameter/FormParameterService.cs b/src/InterfaceForward.Application/Services/Parameter/FormParameterService.cs index 8d74b59..28f7292 100644 --- a/src/InterfaceForward.Application/Services/Parameter/FormParameterService.cs +++ b/src/InterfaceForward.Application/Services/Parameter/FormParameterService.cs @@ -12,7 +12,7 @@ namespace InterfaceForward.Application.Services.Parameter; /// 表单参数配置 /// [ApiExplorerSettings(GroupName = "参数服务")] -public class FormParameterService : ApplicationService +public class FormParameterService : BaseService { private readonly IBasicRepository _formParameterRepository; diff --git a/src/InterfaceForward.Application/Services/Parameter/ParameterService.cs b/src/InterfaceForward.Application/Services/Parameter/ParameterService.cs index 958dd2c..4916a03 100644 --- a/src/InterfaceForward.Application/Services/Parameter/ParameterService.cs +++ b/src/InterfaceForward.Application/Services/Parameter/ParameterService.cs @@ -18,7 +18,7 @@ namespace InterfaceForward.Application.Services.Parameter; /// 参数服务 /// [ApiExplorerSettings(GroupName = "参数服务")] -public class ParameterService : ApplicationService +public class ParameterService : BaseService { private readonly IInterfaceRepository _interfaceRepository; private readonly IParameterRepository _parameterRepository; diff --git a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAccountService.cs b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAccountService.cs index a58232c..f2943f9 100644 --- a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAccountService.cs +++ b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAccountService.cs @@ -14,7 +14,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider; /// 服务商账户 /// [ApiExplorerSettings(GroupName = "服务商服务")] -public class ServiceProviderAccountService : ApplicationService +public class ServiceProviderAccountService : BaseService { private readonly IServiceProviderAccountFieldRepository _serviceProviderAccountFieldRepository; private readonly IServiceProviderAccountFieldValueRepository _serviceProviderAccountFieldValueRepository; @@ -211,6 +211,8 @@ public class ServiceProviderAccountService : ApplicationService var fields = await _serviceProviderAccountFieldRepository.GetAccountFieldWithValueListByServiceProviderIdAsync( serviceProviderId); + + var dics = new List>(); foreach (var item in data.Items) { // 一行数据 @@ -234,10 +236,11 @@ public class ServiceProviderAccountService : ApplicationService } dic[nameof(ServiceProviderAccountPageValueObject.UpdateTime)] = updateTime; - - res.Items.Add(dic); + + dics.Add(dic); } + res.Items = dics; return res; } diff --git a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAuthService.cs b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAuthService.cs index a4529bb..0b2a557 100644 --- a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAuthService.cs +++ b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderAuthService.cs @@ -15,7 +15,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider; /// 服务商授权配置 /// [ApiExplorerSettings(GroupName = "服务商服务")] -public class ServiceProviderAuthService : ApplicationService +public class ServiceProviderAuthService : BaseService { private readonly IBasicRepository _interfaceRepository; private readonly IBasicRepository _parameterRepository; diff --git a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderImportExportService.cs b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderImportExportService.cs index a487b50..afeaa24 100644 --- a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderImportExportService.cs +++ b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderImportExportService.cs @@ -21,7 +21,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider; /// 导入导出服务 /// [ApiExplorerSettings(GroupName = "服务商服务")] -public class ServiceProviderImportExportService : ApplicationService +public class ServiceProviderImportExportService : BaseService { private readonly ISugarDbContextProvider _sqlSugarClientProvider; diff --git a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderService.cs b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderService.cs index 1c45def..3ffe2a9 100644 --- a/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderService.cs +++ b/src/InterfaceForward.Application/Services/ServiceProvider/ServiceProviderService.cs @@ -1,7 +1,6 @@ using System.ComponentModel.DataAnnotations; using InterfaceForward.Application.Contracts.Dtos.ServiceProvider; using InterfaceForward.Application.ForwardCore; -using InterfaceForward.Domain.Shared.Dtos; using InterfaceForward.Domain.Shared.Enum; using InterfaceForward.Repositories; using InterfaceForward.Repositories.Interface.Entitys; @@ -16,7 +15,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider; /// 服务商服务 /// [ApiExplorerSettings(GroupName = "服务商服务")] -public class ServiceProviderService : ApplicationService +public class ServiceProviderService : BaseService { private readonly IBasicRepository _interfaceRepository; private readonly IServiceProviderRepository _serviceProviderRepository; diff --git a/src/InterfaceForward.Domain.Shared/Dtos/RequestLogDto.cs b/src/InterfaceForward.Domain.Shared/Dtos/RequestLogDto.cs index 908d8f2..0018d40 100644 --- a/src/InterfaceForward.Domain.Shared/Dtos/RequestLogDto.cs +++ b/src/InterfaceForward.Domain.Shared/Dtos/RequestLogDto.cs @@ -1,19 +1,13 @@ namespace InterfaceForward.Domain.Shared.Dtos; -public class RequestLogDto +public class RequestLogDto(Guid requestId) { - public const string Init = null; - - public RequestLogDto(Guid requestId) - { - RequestId = requestId; - Response = Init; - } + public const string Init = null!; /// /// 请求Id /// - public Guid RequestId { get; set; } + public Guid RequestId { get; set; } = requestId; /// /// 请求时间(务必设置) @@ -33,7 +27,7 @@ public class RequestLogDto /// /// 发起请求IP /// - public string ClientIP { get; set; } + public string? ClientIp { get; set; } /// /// 接口代码 @@ -68,7 +62,7 @@ public class RequestLogDto /// /// 响应结果 /// - public string Response { get; set; } + public string Response { get; set; } = Init; /// /// 是否成功调用 diff --git a/src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticeOptions.cs b/src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticeOptions.cs new file mode 100644 index 0000000..a9a8e34 --- /dev/null +++ b/src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticeOptions.cs @@ -0,0 +1,14 @@ +namespace InterfaceForward.Domain.Shared.FeiShu; + +public class FeiShuNoticeOptions +{ + /// + /// 飞书通知webhook + /// + public string Webhook { get; set; } + + /// + /// 消息标题前缀 + /// + public string TitlePrefix { get; set; } +} \ No newline at end of file diff --git a/src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticer.cs b/src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticer.cs new file mode 100644 index 0000000..2d3cbd3 --- /dev/null +++ b/src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticer.cs @@ -0,0 +1,78 @@ +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace InterfaceForward.Domain.Shared.FeiShu; + +public class FeiShuNoticer : IFeiShuNoticer +{ + private readonly FeiShuNoticeOptions _options; + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + + public FeiShuNoticer(IOptions options, HttpClient httpClient, ILogger logger) + { + _options = options.Value; + _httpClient = httpClient; + _logger = logger; + } + + public async Task NoticeAsync(string content, string subTitle = "") + { + try + { + if (_options.Webhook.IsNullOrWhiteSpace()) + { + _logger.LogWarning("未配置飞书webhook"); + return; + } + + var title = subTitle.IsNullOrWhiteSpace() + ? _options.TitlePrefix + : _options.TitlePrefix + "_" + subTitle; + + await HandleNoticeAsync(content, title); + } + catch (Exception e) + { + // 这里失败不应该影响业务 + _logger.LogWarning($"飞书通知失败,{e.Message}"); + } + } + + + private async Task HandleNoticeAsync(string content, string title) + { + var message = new + { + msg_type = "post", + content = new + { + post = new + { + zh_cn = new + { + title, + content = new List() + { + new List() + { + new + { + tag = "text", + text = content + Environment.NewLine + } + } + } + } + } + } + }; + + var httpContent = new StringContent(JsonSerializer.Serialize(message), Encoding.UTF8); + httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + await _httpClient.PostAsync(_options.Webhook, httpContent); + } +} \ No newline at end of file diff --git a/src/InterfaceForward.Domain.Shared/FeiShu/IFeiShuNoticer.cs b/src/InterfaceForward.Domain.Shared/FeiShu/IFeiShuNoticer.cs new file mode 100644 index 0000000..f1d54d3 --- /dev/null +++ b/src/InterfaceForward.Domain.Shared/FeiShu/IFeiShuNoticer.cs @@ -0,0 +1,8 @@ +using Fake.DependencyInjection; + +namespace InterfaceForward.Domain.Shared.FeiShu; + +public interface IFeiShuNoticer: ITransientDependency +{ + public Task NoticeAsync(string content, string subTitle = ""); +} \ No newline at end of file diff --git a/src/InterfaceForward.Domain.Shared/Helpers/LogHelper.cs b/src/InterfaceForward.Domain.Shared/Helpers/LogHelper.cs deleted file mode 100644 index f05ce23..0000000 --- a/src/InterfaceForward.Domain.Shared/Helpers/LogHelper.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System.Net; -using System.Net.Http.Headers; -using System.Text; -using InterfaceForward.Domain.Shared.Enum; -using InterfaceForward.Domain.Shared.Options; -using Newtonsoft.Json; - -namespace InterfaceForward.Repositories.Log; - -public class LogHelper -{ - #region 参数初始化 - private static string _webhook, _title = ""; - private static bool _needAtAll = false; - public static void Init(NoticeOptions options, bool needAtAll) - { - _webhook = options.Webhook; - _title = options.Title; - _needAtAll = needAtAll; - } - #endregion - - public static void Debug(string msg, bool isSendNotice = false, params object[] propertyValues) - { - Serilog.Log.Debug(msg, propertyValues); - if (isSendNotice) - SendNotice(msg, MessageType.Debug); - } - public static void Error(Exception error, bool isSendNotice = true, params object[] propertyValues) - { - Error(error.ToString(), isSendNotice, propertyValues); - } - public static void Error(string msg, bool isSendNotice = true, params object[] propertyValues) - { - Serilog.Log.Error(msg, propertyValues); - if (isSendNotice) - SendNotice(msg, MessageType.Error); - } - - public static void Info(string msg, bool isSendNotice = false, params object[] propertyValues) - { - Serilog.Log.Information(msg, propertyValues); - if (isSendNotice) - SendNotice(msg, MessageType.Info); - } - - public static void Warn(string msg, bool isSendNotice = false, params object[] propertyValues) - { - Serilog.Log.Warning(msg, propertyValues); - if (isSendNotice) - SendNotice(msg, MessageType.Warn); - } - - /// - /// 发送通知 - /// - /// 消息内容 - /// 机器人webhook地址 - /// 消息类型 - /// 本地环境依然发布消息 - public static async void SendNotice(string message, string webhook, string title = "", MessageType messageType = MessageType.Notice, bool hardSend = false) - { - try - { - if (System.Diagnostics.Debugger.IsAttached && hardSend == false) //如果是本地环境,且没开启这个开关则直接跳过,不发消息 - { - Console.WriteLine($"{Environment.NewLine}-- 本地开发环境,跳过发送飞书通知逻辑"); - return; - } - - if (string.IsNullOrEmpty(webhook)) - { - Console.WriteLine($"{Environment.NewLine}-- 未找到配置的webhook地址"); - return; - } - - if (webhook.IndexOf("feishu") <= -1) - { - Console.WriteLine($"{Environment.NewLine}-- 暂时只支持飞书通知,当前配置:{webhook}"); - return; - } - var sendMessage = new - { - msg_type = "post", - content = new - { - post = new - { - zh_cn = new - { - title = title + "_" + messageType, - content = (_needAtAll && messageType != MessageType.Notice) ? - new List { - new List{ - new { - tag = "text", - text = message + Environment.NewLine - }, - new { - tag = "at", - user_id = "all" - } - } - } : - new List { - new List{ - new { - tag = "text", - text = message + Environment.NewLine - } - } - } - } - } - } - }; - - - _ = Task.Run(() => - { - _ = PostAsync(webhook, postData: JsonConvert.SerializeObject(sendMessage)); - }); - - } - catch (Exception e) - { - Console.WriteLine($"{Environment.NewLine}通知发送失败!{e}"); - } - } - - /// - /// 发送通知,从配置文件取飞书配置 - /// - /// 消息内容 - /// 消息类型 - /// 本地环境是否强制发送 - public static void SendNotice(string message, MessageType messageType = MessageType.Notice, bool hardSend = false) - { - if (string.IsNullOrEmpty(_webhook)) - { - Console.WriteLine($"{Environment.NewLine}-- 未找到配置的webhook地址"); - return; - } - - SendNotice(message, _webhook, _title, messageType, hardSend); - } - - /// - /// 发送消息,指定webhok地址 - /// - /// - /// - /// - /// - public static void SendNotice(string message, string wbeHook) - { - if (string.IsNullOrEmpty(wbeHook)) - throw new NullReferenceException("wbeHok参数不能为空"); - - SendNotice(message, wbeHook, _title, MessageType.Notice, true); - } - - - private static async Task PostAsync(string url, string postData = null, string contentType = null, int timeOut = 30, Dictionary headers = null, bool ignoreStatusCodeCheck = false) where T : new() - { - try - { - postData = postData ?? ""; - - //设置Header - using HttpClient client = new HttpClient(); - client.Timeout = new TimeSpan(0, 0, timeOut); - if (headers != null) - { - foreach (var header in headers) - client.DefaultRequestHeaders.Add(header.Key, header.Value); - } - - //设置ContentType - using HttpContent httpContent = new StringContent(postData, Encoding.UTF8); - if (contentType != null) - httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); - else - httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - - //处理请求 - var response = await client.PostAsync(url, httpContent); - if (ignoreStatusCodeCheck == false && response.StatusCode != HttpStatusCode.OK) - { - Console.WriteLine($"{Environment.NewLine}发送飞书通知返回异常状态码:{response.StatusCode},请求参数:{postData}"); - throw new Exception($"飞书通知返回状态码异常!当前返回状态码:{response.StatusCode}"); - } - - var resultStr = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(resultStr); - } - catch (Exception ex) - { - throw new Exception($"返回参数序列化失败,异常信息{ex}!"); - } - } -} \ No newline at end of file diff --git a/src/InterfaceForward.Domain.Shared/InterfaceForward.Domain.Shared.csproj b/src/InterfaceForward.Domain.Shared/InterfaceForward.Domain.Shared.csproj index 088b2d1..df62c1c 100644 --- a/src/InterfaceForward.Domain.Shared/InterfaceForward.Domain.Shared.csproj +++ b/src/InterfaceForward.Domain.Shared/InterfaceForward.Domain.Shared.csproj @@ -6,11 +6,11 @@ - + - + diff --git a/src/InterfaceForward.Domain.Shared/InterfaceForwardDomainSharedModule.cs b/src/InterfaceForward.Domain.Shared/InterfaceForwardDomainSharedModule.cs index 6f3e29f..4fe79d5 100644 --- a/src/InterfaceForward.Domain.Shared/InterfaceForwardDomainSharedModule.cs +++ b/src/InterfaceForward.Domain.Shared/InterfaceForwardDomainSharedModule.cs @@ -1,8 +1,15 @@ using Fake.Modularity; +using InterfaceForward.Domain.Shared.FeiShu; +using Microsoft.Extensions.DependencyInjection; namespace InterfaceForward.Domain.Shared { - public class InterfaceForwardDomainSharedModule:FakeModule + public class InterfaceForwardDomainSharedModule : FakeModule { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var config = context.Services.GetConfiguration(); + context.Services.Configure(config.GetSection("FeiShuNotice")); + } } } \ No newline at end of file diff --git a/src/InterfaceForward.Repositories/InterfaceForward.Repositories.csproj b/src/InterfaceForward.Repositories/InterfaceForward.Repositories.csproj index 0c6e84c..cd2c8a8 100644 --- a/src/InterfaceForward.Repositories/InterfaceForward.Repositories.csproj +++ b/src/InterfaceForward.Repositories/InterfaceForward.Repositories.csproj @@ -7,8 +7,7 @@ - - + diff --git a/src/InterfaceForward.Repositories/Log/Entitys/LogIndex.cs b/src/InterfaceForward.Repositories/Log/Entitys/LogIndex.cs index 6a66f95..69e280a 100644 --- a/src/InterfaceForward.Repositories/Log/Entitys/LogIndex.cs +++ b/src/InterfaceForward.Repositories/Log/Entitys/LogIndex.cs @@ -29,7 +29,7 @@ public class LogIndex : IdBaseIndex /// /// 发起请求IP /// - public string ClientIP { get; set; } + public string? ClientIp { get; set; } /// /// 接口代码 diff --git a/src/InterfaceForward.Repositories/Log/Services/ILogRepository.cs b/src/InterfaceForward.Repositories/Log/Services/ILogRepository.cs index d02d992..d9897d5 100644 --- a/src/InterfaceForward.Repositories/Log/Services/ILogRepository.cs +++ b/src/InterfaceForward.Repositories/Log/Services/ILogRepository.cs @@ -31,13 +31,7 @@ public interface ILogRepository /// /// 异常 /// - Task WriteAppLog(Exception exception = null); - - /// - /// 发飞书 - /// - /// - void SendFeiShu(Exception contextException); + Task WriteAppLogAsync(Exception? exception = null); /// /// 添加日志 @@ -65,7 +59,7 @@ public interface ILogRepository /// /// /// - Task GetDetailsByIdAsync(string id); + Task GetDetailsByIdAsync(string id); /// /// 根据给定请求id,获取请求日志 diff --git a/src/InterfaceForward.Repositories/Log/Services/LogRepository.cs b/src/InterfaceForward.Repositories/Log/Services/LogRepository.cs index aec6806..db45af4 100644 --- a/src/InterfaceForward.Repositories/Log/Services/LogRepository.cs +++ b/src/InterfaceForward.Repositories/Log/Services/LogRepository.cs @@ -1,7 +1,7 @@ using Nest; using InterfaceForward.Domain.Shared.Dtos; using InterfaceForward.Domain.Shared.Enum; -using InterfaceForward.Domain.Shared.Helpers; +using InterfaceForward.Domain.Shared.FeiShu; using InterfaceForward.Repositories.Log.Entitys; using InterfaceForward.Repositories.Log.ES; using InterfaceForward.Repositories.Log.ValueObjects; @@ -14,11 +14,16 @@ namespace InterfaceForward.Repositories.Log.Services; /// public class LogRepository : ElasticSearchContextAbstract, ILogRepository, IScopedDependency { - public LogRepository(ConnectionFactory connection) : base(connection) + private readonly IFeiShuNoticer _feiShuNoticer; + + public LogRepository(ConnectionFactory connection, IFeiShuNoticer feiShuNoticer) : base(connection) { + _feiShuNoticer = feiShuNoticer; var guid = Guid.NewGuid(); - AppRequestLog = new RequestLogDto(guid); - AppRequestLog.IsSuccess = true; // 只有接口通发生未处理异常才算应用失败 + AppRequestLog = new RequestLogDto(guid) + { + IsSuccess = true // 只有接口通发生未处理异常才算应用失败 + }; ServiceProviderRequestLog = new RequestLogDto(guid); } @@ -26,7 +31,7 @@ public class LogRepository : ElasticSearchContextAbstract, ILogReposit public RequestLogDto AppRequestLog { get; set; } public RequestLogDto ServiceProviderRequestLog { get; set; } - public async Task WriteAppLog(Exception exception = null) + public async Task WriteAppLogAsync(Exception? exception = null) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract if (exception != null) @@ -39,22 +44,7 @@ public class LogRepository : ElasticSearchContextAbstract, ILogReposit await AddLogAsync(AppRequestLog); } - - public void SendFeiShu(Exception contextException) - { - LogHelper.Error($""" - 日志请求id:{ServiceProviderRequestLog.RequestId} - 服务商--接口:{ServiceProviderRequestLog.Name}--{ServiceProviderRequestLog.InterfaceName} - 异常原因:{Truncate(contextException.ToString())} - 请求地址:{ServiceProviderRequestLog.Address} - 原始报文: - {Truncate(AppRequestLog.Content)} - 请求报文: - {Truncate(ServiceProviderRequestLog.Content)} - 响应报文: - {Truncate(ServiceProviderRequestLog.Response)} - """); - } + public async Task AddLogAsync(RequestLogDto requestLog) { @@ -66,7 +56,7 @@ public class LogRepository : ElasticSearchContextAbstract, ILogReposit RequestTime = requestLog.RequestTime == default ? DateTime.Now : requestLog.RequestTime, IsApp = requestLog.IsApp, Name = requestLog.Name, - ClientIP = requestLog.ClientIP, + ClientIp = requestLog.ClientIp, InterfaceCode = requestLog.InterfaceCode, InterfaceName = requestLog.InterfaceName, Address = requestLog.Address, @@ -78,16 +68,11 @@ public class LogRepository : ElasticSearchContextAbstract, ILogReposit Exception = requestLog.Exception }; - try + IndexResponse response = await Context.IndexAsync(idx, + request => request.Index($"sjzy_interface_forward-{DateTime.Now:yyyy.MM.dd}")); + if (!response.IsValid) { - //await Context.IndexDocumentAsync(idx); - IndexResponse response = await Context.IndexAsync(idx, - request => request.Index($"sjzy_interface_forward-{DateTime.Now:yyyy.MM.dd}")); - if (!response.IsValid) LogHelper.Error("数据添加失败,原因:" + response.DebugInformation); - } - catch (Exception ex) - { - LogHelper.Error($"日志插入ES失败:{ex.Message}。{idx.ToJson()}"); + await _feiShuNoticer.NoticeAsync("数据添加失败,原因:" + response.DebugInformation); } } @@ -96,7 +81,7 @@ public class LogRepository : ElasticSearchContextAbstract, ILogReposit var data = await Context.SearchAsync(x => x .Source(s => s.Includes(i => i.Fields( f => f.Id, f => f.RequestId, f => f.RequestTime, f => f.IsApp, - f => f.Name, f => f.ClientIP, f => f.InterfaceName, f => f.InterfaceCode, f => f.Address, + f => f.Name, f => f.ClientIp, f => f.InterfaceName, f => f.InterfaceCode, f => f.Address, f => f.Cost, f => f.IsSuccess))) .Query(q => (input.Type != LogListInputTypeEnum.应用 ? null : q.Term(p => p.IsApp, true)) @@ -203,9 +188,9 @@ public class LogRepository : ElasticSearchContextAbstract, ILogReposit ); } - public async Task GetDetailsByIdAsync(string id) + public async Task GetDetailsByIdAsync(string id) { - var data = await Context.SearchAsync(x => x + ISearchResponse data = await Context.SearchAsync(x => x .Size(1) .Query(q => q.Term(t => t .Field(f => f.Id.Suffix("keyword"))