1
This commit is contained in:
parent
54f42ddb73
commit
87a2eec61b
@ -16,11 +16,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\InterfaceForward.Application\InterfaceForward.Application.csproj" />
|
<ProjectReference Include="..\InterfaceForward.Application\InterfaceForward.Application.csproj" />
|
||||||
<ProjectReference Include="..\InterfaceForward.ServiceDefaults\InterfaceForward.ServiceDefaults.csproj"/>
|
<ProjectReference Include="..\InterfaceForward.ServiceDefaults\InterfaceForward.ServiceDefaults.csproj"/>
|
||||||
<PackageReference Include="Fake.Autofac" Version="8.0.0-preview6" />
|
<PackageReference Include="Fake.Autofac" Version="8.0.0-preview8.4" />
|
||||||
|
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2-dev-00338" />
|
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="10.0.0" />
|
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="10.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.1.0-dev-00943" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,17 +1,13 @@
|
|||||||
using Fake.AspNetCore;
|
using Fake.AspNetCore;
|
||||||
using Fake.AspNetCore.Mvc;
|
using Fake.AspNetCore.Auditing;
|
||||||
using Fake.AspNetCore.Mvc.Conventions;
|
using Fake.AspNetCore.Mvc.Conventions;
|
||||||
using Fake.Authorization;
|
|
||||||
using Fake.Autofac;
|
using Fake.Autofac;
|
||||||
using Fake.Modularity;
|
using Fake.Modularity;
|
||||||
using InterfaceForward.Application;
|
using InterfaceForward.Application;
|
||||||
using InterfaceForward.Application.Filters;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace InterfaceForward.Api;
|
namespace InterfaceForward.Api;
|
||||||
|
|
||||||
[DependsOn(typeof(FakeAutofacModule))]
|
[DependsOn(typeof(FakeAutofacModule))]
|
||||||
[DependsOn(typeof(FakeAspNetCoreMvcModule))]
|
|
||||||
[DependsOn(typeof(InterfaceForwardApplicationModule))]
|
[DependsOn(typeof(InterfaceForwardApplicationModule))]
|
||||||
public class InterfaceForwardApiModule : FakeModule
|
public class InterfaceForwardApiModule : FakeModule
|
||||||
{
|
{
|
||||||
@ -23,20 +19,16 @@ public class InterfaceForwardApiModule : FakeModule
|
|||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
services.AddProblemDetails();
|
services.AddProblemDetails();
|
||||||
|
|
||||||
services.Configure<MvcOptions>(options =>
|
|
||||||
{
|
|
||||||
options.Filters.AddService<GlobalExceptionFilter>();
|
|
||||||
options.Filters.AddService<RequestLogFilter>();
|
|
||||||
});
|
|
||||||
|
|
||||||
services.Configure<RemoteServiceConventionOptions>(options =>
|
services.Configure<RemoteServiceConventionOptions>(options =>
|
||||||
{
|
{
|
||||||
options.AddAssembly(typeof(InterfaceForwardApplicationModule).Assembly);
|
options.AddAssembly(typeof(InterfaceForwardApplicationModule).Assembly);
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddUnifiedResultFilter();
|
services.AddFakeSwaggerGen()
|
||||||
services.AddFakeSwaggerGen();
|
.AddFakeExceptionFilter()
|
||||||
|
.AddFakeValidationActionFilter()
|
||||||
|
.AddFakeAspNetCoreAuditing();
|
||||||
|
|
||||||
services.AddCors(options =>
|
services.AddCors(options =>
|
||||||
{
|
{
|
||||||
@ -54,11 +46,9 @@ public class InterfaceForwardApiModule : FakeModule
|
|||||||
{
|
{
|
||||||
var app = context.GetWebApplication();
|
var app = context.GetWebApplication();
|
||||||
|
|
||||||
app.MapControllers();
|
|
||||||
|
|
||||||
// Add Aspire default endpoints.
|
// Add Aspire default endpoints.
|
||||||
app.MapDefaultEndpoints();
|
app.MapDefaultEndpoints();
|
||||||
|
app.MapControllers();
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
app.UseFakeSwagger();
|
app.UseFakeSwagger();
|
||||||
|
|
||||||
@ -66,16 +56,4 @@ public class InterfaceForwardApiModule : FakeModule
|
|||||||
|
|
||||||
app.UseCors(DefaultCorsPolicyName);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -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<NoticeOptions>();
|
|
||||||
if (options == null)
|
|
||||||
Console.Write("-- 未找到日志飞书通知相关配置");
|
|
||||||
else
|
|
||||||
LogHelper.Init(options, environment == "uat" || environment == "Product");//写死了
|
|
||||||
|
|
||||||
builder.Host.UseSerilog();
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,13 +1,16 @@
|
|||||||
using InterfaceForward.Api;
|
using InterfaceForward.Api;
|
||||||
using InterfaceForward.Api.Logs;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateSlimBuilder(args);
|
||||||
|
var configuration = builder.Configuration;
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.ReadFrom.Configuration(configuration)
|
||||||
|
.CreateLogger();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var builder = WebApplication.CreateSlimBuilder(args);
|
|
||||||
builder.UseSerilogDefault();
|
|
||||||
builder.WebHost.UseUrls(builder.Configuration.GetSection("App:Urls").Get<string[]>() ?? []);
|
builder.WebHost.UseUrls(builder.Configuration.GetSection("App:Urls").Get<string[]>() ?? []);
|
||||||
builder.Host.UseAutofac();
|
builder.Host.UseAutofac().UseSerilog();
|
||||||
builder.Services.AddApplication<InterfaceForwardApiModule>();
|
builder.Services.AddApplication<InterfaceForwardApiModule>();
|
||||||
|
|
||||||
// Add service defaults & Aspire components.
|
// Add service defaults & Aspire components.
|
||||||
|
|||||||
@ -26,5 +26,9 @@
|
|||||||
"CorsOrigins": [
|
"CorsOrigins": [
|
||||||
"http://localhost:8888"
|
"http://localhost:8888"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"FeiShuNotice": {
|
||||||
|
"Title": "InterfaceForward-Dev",
|
||||||
|
"Webhook": "https://open.feishu.cn/open-apis/bot/v2/hook/255c44ff-5891-4902-9b6a-6d0250e745f7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,18 @@
|
|||||||
namespace InterfaceForward.Application.Contracts.ForwardCore;
|
namespace InterfaceForward.Application.Contracts.ForwardCore;
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class InterfaceRelayUnifyResultDto : UnifyResultDto
|
public class InterfaceRelayUnifyResultDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求Id
|
/// 请求Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid RequestId { get; set; }
|
public Guid RequestId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息
|
||||||
|
/// </summary>
|
||||||
|
public string? Message { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 原报文
|
/// 原报文
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -2,15 +2,14 @@
|
|||||||
using InterfaceForward.Application.Contracts.Dtos.App;
|
using InterfaceForward.Application.Contracts.Dtos.App;
|
||||||
using InterfaceForward.Repositories.App.Entitys;
|
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<CreateAppInput, AppEntity>(MemberList.None);
|
||||||
{
|
CreateMap<UpdateAppInput, AppEntity>(MemberList.None);
|
||||||
CreateMap<CreateAppInput, AppEntity>(MemberList.None);
|
CreateMap<CreateAppScopeInput, AppScopeEntity>(MemberList.None);
|
||||||
CreateMap<UpdateAppInput, AppEntity>(MemberList.None);
|
|
||||||
CreateMap<CreateAppScopeInput, AppScopeEntity>(MemberList.None);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,3 +0,0 @@
|
|||||||
namespace InterfaceForward.Application.Filters;
|
|
||||||
|
|
||||||
public class DisableRequestLogAttribute:Attribute;
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Fake.AspNetCore.Http;
|
||||||
using InterfaceForward.Repositories;
|
using InterfaceForward.Repositories;
|
||||||
using InterfaceForward.Repositories.Log.Services;
|
using InterfaceForward.Repositories.Log.Services;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Http.Extensions;
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
@ -9,43 +9,24 @@ using Newtonsoft.Json;
|
|||||||
|
|
||||||
namespace InterfaceForward.Application.Filters;
|
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)
|
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||||
{
|
{
|
||||||
var start = DateTime.Now;
|
var start = DateTime.Now;
|
||||||
// _segContext.Context.Span.AddLog(LogEvent.Message("进入授权过滤器"));
|
// _segContext.Context.Span.AddLog(LogEvent.Message("进入授权过滤器"));
|
||||||
var log = _logRepository.AppRequestLog;
|
var log = logRepository.AppRequestLog;
|
||||||
log.RequestTime = start;
|
log.RequestTime = start;
|
||||||
|
|
||||||
var httpContext = context.HttpContext;
|
var httpContext = context.HttpContext;
|
||||||
|
|
||||||
log.IsApp = true;
|
log.IsApp = true;
|
||||||
|
|
||||||
var ip = _httpContextAccessor.HttpContext!.Connection.RemoteIpAddress?.MapToIPv4().ToString();
|
log.ClientIp = httpClientInfoProvider.ClientIpAddress;
|
||||||
if (_httpContextAccessor.HttpContext.Request.Headers.TryGetValue("X-Forwarded-For", out var header))
|
|
||||||
{
|
|
||||||
ip = header.ToString();
|
|
||||||
}
|
|
||||||
log.ClientIP = ip;
|
|
||||||
log.Address = httpContext.Request.GetDisplayUrl();
|
log.Address = httpContext.Request.GetDisplayUrl();
|
||||||
|
|
||||||
// body
|
// body
|
||||||
@ -66,20 +47,16 @@ public class ForwardAuthorizeFilter : IAsyncActionFilter
|
|||||||
throw new BusinessException(message: "应用授权失败,AppKey和AppSecret是必填的");
|
throw new BusinessException(message: "应用授权失败,AppKey和AppSecret是必填的");
|
||||||
}
|
}
|
||||||
|
|
||||||
var app = await _interfaceForwardQuery.FindAppAsync(appKey, appSecret);
|
var app = await interfaceForwardQuery.FindAppAsync(appKey!, appSecret!);
|
||||||
if (app == null)
|
if (app == null)
|
||||||
throw new BusinessException(message: "应用授权失败,请检查AppKey或AppSecret是否正确");
|
throw new BusinessException(message: "应用授权失败,请检查AppKey或AppSecret是否正确");
|
||||||
log.Name = app.Name;
|
log.Name = app.Name;
|
||||||
if (!app.IsOnline)
|
if (!app.IsOnline)
|
||||||
throw new BusinessException(message: "应用已被禁用,请检查应用状态");
|
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();
|
var actionContext = await next();
|
||||||
// _segContext.Context.Span.AddLog(LogEvent.Message("action执行完毕"));
|
|
||||||
|
|
||||||
if (actionContext.Exception == null)
|
if (actionContext.Exception == null)
|
||||||
{
|
{
|
||||||
@ -91,10 +68,10 @@ public class ForwardAuthorizeFilter : IAsyncActionFilter
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log.Response = actionContext.Result?.ToString();
|
log.Response = actionContext.Result?.ToString()?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = _logRepository.WriteAppLog();
|
_ = logRepository.WriteAppLogAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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<IHttpContextAccessor>().HttpContext;
|
||||||
|
var logRepository = context.ServiceProvider.GetRequiredService<ILogRepository>();
|
||||||
|
var feiShuNoticer = context.ServiceProvider.GetRequiredService<IFeiShuNoticer>();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
namespace InterfaceForward.Application.Filters
|
|
||||||
{
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public class IgnoreLogDetailAttribute : Attribute;
|
|
||||||
}
|
|
||||||
@ -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";
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
|
|
||||||
namespace InterfaceForward.Application.Filters;
|
|
||||||
|
|
||||||
public struct RequestLogInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 执行时间
|
|
||||||
/// </summary>
|
|
||||||
public DateTime ExecuteTime { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 执行时长
|
|
||||||
/// </summary>
|
|
||||||
public long TotalTime { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求编号
|
|
||||||
/// </summary>
|
|
||||||
public string RequestCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求路径
|
|
||||||
/// </summary>
|
|
||||||
public string RequestPath { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求参数
|
|
||||||
/// </summary>
|
|
||||||
public string RequestParamsters { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 返回结果
|
|
||||||
/// </summary>
|
|
||||||
public dynamic Result { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求头
|
|
||||||
/// </summary>
|
|
||||||
public IHeaderDictionary Headers { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 异常信息
|
|
||||||
/// </summary>
|
|
||||||
public Exception? Exception { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用户信息
|
|
||||||
/// </summary>
|
|
||||||
public string UserInfo { get; internal set; }
|
|
||||||
}
|
|
||||||
@ -273,9 +273,7 @@ public class DefaultForwardFlow : IForwardFlow
|
|||||||
context.ServiceProviderRequestLog.Address = context.TargetInterface.RequestAddress;
|
context.ServiceProviderRequestLog.Address = context.TargetInterface.RequestAddress;
|
||||||
context.ServiceProviderRequestLog.IsSuccess = false;
|
context.ServiceProviderRequestLog.IsSuccess = false;
|
||||||
|
|
||||||
throw new BusinessException(
|
throw new BusinessException(message: msg);
|
||||||
code: code,
|
|
||||||
message: msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -285,7 +283,7 @@ public class DefaultForwardFlow : IForwardFlow
|
|||||||
public virtual void BeforeRequest(ForwardCoreContext context)
|
public virtual void BeforeRequest(ForwardCoreContext context)
|
||||||
{
|
{
|
||||||
var log = context.ServiceProviderRequestLog;
|
var log = context.ServiceProviderRequestLog;
|
||||||
log.ClientIP = NetUtil.GetLanIp();
|
log.ClientIp = NetUtil.GetLanIp();
|
||||||
log.Content = context.TargetInterfaceInput;
|
log.Content = context.TargetInterfaceInput;
|
||||||
|
|
||||||
context.ServiceProviderRequestLog.RequestTime = DateTime.Now;
|
context.ServiceProviderRequestLog.RequestTime = DateTime.Now;
|
||||||
@ -384,7 +382,7 @@ public class DefaultForwardFlow : IForwardFlow
|
|||||||
{
|
{
|
||||||
if (!await CanVisitInterfaceAsync(context.TargetInterface.Code, qps))
|
if (!await CanVisitInterfaceAsync(context.TargetInterface.Code, qps))
|
||||||
{
|
{
|
||||||
throw new BusinessException("4004", $"服务商接口qps已达到上限{qps},稍后请求");
|
throw new BusinessException($"服务商接口qps已达到上限{qps},稍后请求");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,10 +17,9 @@
|
|||||||
<PackageReference Include="DiffPlex" Version="1.7.2" />
|
<PackageReference Include="DiffPlex" Version="1.7.2" />
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||||
<PackageReference Include="DotNetCore.Natasha.CSharp" Version="5.2.2.1"/>
|
<PackageReference Include="DotNetCore.Natasha.CSharp" Version="5.2.2.1"/>
|
||||||
|
<PackageReference Include="Fake.AspNetCore" Version="8.0.0-preview8.4" />
|
||||||
|
<PackageReference Include="Fake.ObjectMapping.AutoMapper" Version="8.0.0-preview8.4" />
|
||||||
<PackageReference Include="FreeRedis" Version="1.2.15" />
|
<PackageReference Include="FreeRedis" Version="1.2.15" />
|
||||||
|
|
||||||
<PackageReference Include="Fake.AspNetCore.Mvc" Version="8.0.0-preview5" />
|
|
||||||
<PackageReference Include="Fake.ObjectMapping.AutoMapper" Version="8.0.0-preview6" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using Fake.AspNetCore.Mvc;
|
using Fake.AspNetCore;
|
||||||
using Fake.Modularity;
|
using Fake.Modularity;
|
||||||
using Fake.ObjectMapping.AutoMapper;
|
using Fake.ObjectMapping.AutoMapper;
|
||||||
using InterfaceForward.Application.Contracts;
|
using InterfaceForward.Application.Contracts;
|
||||||
@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
|
|
||||||
namespace InterfaceForward.Application;
|
namespace InterfaceForward.Application;
|
||||||
|
|
||||||
|
[DependsOn(typeof(FakeAspNetCoreModule))]
|
||||||
[DependsOn(typeof(FakeObjectMappingAutoMapperModule))]
|
[DependsOn(typeof(FakeObjectMappingAutoMapperModule))]
|
||||||
[DependsOn(typeof(InterfaceForwardRepositoriesModule))]
|
[DependsOn(typeof(InterfaceForwardRepositoriesModule))]
|
||||||
public class InterfaceForwardApplicationModule:FakeModule
|
public class InterfaceForwardApplicationModule:FakeModule
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace InterfaceForward.Application.Services.App;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("App")]
|
[Route("App")]
|
||||||
[ApiExplorerSettings(GroupName = "应用服务")]
|
[ApiExplorerSettings(GroupName = "应用服务")]
|
||||||
public class AppsService : ApplicationService
|
public class AppsService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IAppRepository _appRepository;
|
private readonly IAppRepository _appRepository;
|
||||||
private readonly IAppScopeRepository _appScopeRepository;
|
private readonly IAppScopeRepository _appScopeRepository;
|
||||||
@ -59,7 +59,7 @@ public class AppsService : ApplicationService
|
|||||||
var urlDic = OSSHelper.GetUrlByKeys(logoKeys);
|
var urlDic = OSSHelper.GetUrlByKeys(logoKeys);
|
||||||
|
|
||||||
foreach (var url in urlDic)
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace InterfaceForward.Application.Services.App
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("Dictionary")]
|
[Route("Dictionary")]
|
||||||
[ApiExplorerSettings(GroupName = "应用服务")]
|
[ApiExplorerSettings(GroupName = "应用服务")]
|
||||||
public class DictionaryService : ApplicationService
|
public class DictionaryService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IDictionaryRepository _dictionaryRepository;
|
private readonly IDictionaryRepository _dictionaryRepository;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace InterfaceForward.Application.Services.App
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("Log")]
|
[Route("Log")]
|
||||||
[ApiExplorerSettings(GroupName = "应用服务")]
|
[ApiExplorerSettings(GroupName = "应用服务")]
|
||||||
public class LogService : ApplicationService
|
public class LogService : BaseService
|
||||||
{
|
{
|
||||||
private readonly ILogRepository _logRepository;
|
private readonly ILogRepository _logRepository;
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ namespace InterfaceForward.Application.Services.App
|
|||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet("GetById")]
|
[HttpGet("GetById")]
|
||||||
public async Task<LogIndex> GetByIdAsync(string id)
|
public async Task<LogIndex?> GetByIdAsync(string id)
|
||||||
{
|
{
|
||||||
return await _logRepository.GetDetailsByIdAsync(id);
|
return await _logRepository.GetDetailsByIdAsync(id);
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/InterfaceForward.Application/Services/BaseService.cs
Normal file
5
src/InterfaceForward.Application/Services/BaseService.cs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
namespace InterfaceForward.Application.Services;
|
||||||
|
|
||||||
|
public abstract class BaseService : ApplicationService
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@ namespace InterfaceForward.Application.Services.Interface;
|
|||||||
/// 接口返回配置
|
/// 接口返回配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "接口服务")]
|
[ApiExplorerSettings(GroupName = "接口服务")]
|
||||||
public class InterfaceReturnConfigService : ApplicationService
|
public class InterfaceReturnConfigService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IInterfaceReturnConfigRepository _interfaceReturnConfigRepository;
|
private readonly IInterfaceReturnConfigRepository _interfaceReturnConfigRepository;
|
||||||
private readonly IInterfaceRepository _interfaceRepository;
|
private readonly IInterfaceRepository _interfaceRepository;
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace InterfaceForward.Application.Services.Interface;
|
|||||||
/// 服务商接口
|
/// 服务商接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "接口服务")]
|
[ApiExplorerSettings(GroupName = "接口服务")]
|
||||||
public class ServiceProviderInterfaceService : ApplicationService
|
public class ServiceProviderInterfaceService : BaseService
|
||||||
{
|
{
|
||||||
private ParameterService ParameterService => LazyServiceProvider.GetRequiredService<ParameterService>();
|
private ParameterService ParameterService => LazyServiceProvider.GetRequiredService<ParameterService>();
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace InterfaceForward.Application.Services.Interface;
|
|||||||
/// 系统接口
|
/// 系统接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "接口服务")]
|
[ApiExplorerSettings(GroupName = "接口服务")]
|
||||||
public class SystemInterfaceService : ApplicationService
|
public class SystemInterfaceService : BaseService
|
||||||
{
|
{
|
||||||
#region ctor
|
#region ctor
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -20,7 +20,7 @@ namespace InterfaceForward.Application.Services.InterfaceMap;
|
|||||||
/// 接口映射发布修改
|
/// 接口映射发布修改
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "接口映射服务")]
|
[ApiExplorerSettings(GroupName = "接口映射服务")]
|
||||||
public class InterfaceMapPublishService : ApplicationService
|
public class InterfaceMapPublishService : BaseService
|
||||||
{
|
{
|
||||||
private readonly static JsonSerializerSettings Settings = new JsonSerializerSettings
|
private readonly static JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||||
{
|
{
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace InterfaceForward.Application.Services.InterfaceMap;
|
|||||||
/// 接口映射服务
|
/// 接口映射服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "接口映射服务")]
|
[ApiExplorerSettings(GroupName = "接口映射服务")]
|
||||||
public class InterfaceMapService : ApplicationService
|
public class InterfaceMapService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IInterfaceMapRepository _interfaceMapRepository;
|
private readonly IInterfaceMapRepository _interfaceMapRepository;
|
||||||
private readonly IBasicRepository<InterfaceEntity> _interfaceRepository;
|
private readonly IBasicRepository<InterfaceEntity> _interfaceRepository;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace InterfaceForward.Application.Services.Parameter;
|
|||||||
/// 固定参数配置
|
/// 固定参数配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "参数服务")]
|
[ApiExplorerSettings(GroupName = "参数服务")]
|
||||||
public class FixedParameterService : ApplicationService
|
public class FixedParameterService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IFixedParameterRepository _fixedParameterRepository;
|
private readonly IFixedParameterRepository _fixedParameterRepository;
|
||||||
private readonly IServiceProviderRepository _serviceProviderRepository;
|
private readonly IServiceProviderRepository _serviceProviderRepository;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace InterfaceForward.Application.Services.Parameter;
|
|||||||
/// 表单参数配置
|
/// 表单参数配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "参数服务")]
|
[ApiExplorerSettings(GroupName = "参数服务")]
|
||||||
public class FormParameterService : ApplicationService
|
public class FormParameterService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IBasicRepository<FormParameterEntity> _formParameterRepository;
|
private readonly IBasicRepository<FormParameterEntity> _formParameterRepository;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace InterfaceForward.Application.Services.Parameter;
|
|||||||
/// 参数服务
|
/// 参数服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "参数服务")]
|
[ApiExplorerSettings(GroupName = "参数服务")]
|
||||||
public class ParameterService : ApplicationService
|
public class ParameterService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IInterfaceRepository _interfaceRepository;
|
private readonly IInterfaceRepository _interfaceRepository;
|
||||||
private readonly IParameterRepository _parameterRepository;
|
private readonly IParameterRepository _parameterRepository;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider;
|
|||||||
/// 服务商账户
|
/// 服务商账户
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "服务商服务")]
|
[ApiExplorerSettings(GroupName = "服务商服务")]
|
||||||
public class ServiceProviderAccountService : ApplicationService
|
public class ServiceProviderAccountService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IServiceProviderAccountFieldRepository _serviceProviderAccountFieldRepository;
|
private readonly IServiceProviderAccountFieldRepository _serviceProviderAccountFieldRepository;
|
||||||
private readonly IServiceProviderAccountFieldValueRepository _serviceProviderAccountFieldValueRepository;
|
private readonly IServiceProviderAccountFieldValueRepository _serviceProviderAccountFieldValueRepository;
|
||||||
@ -211,6 +211,8 @@ public class ServiceProviderAccountService : ApplicationService
|
|||||||
var fields =
|
var fields =
|
||||||
await _serviceProviderAccountFieldRepository.GetAccountFieldWithValueListByServiceProviderIdAsync(
|
await _serviceProviderAccountFieldRepository.GetAccountFieldWithValueListByServiceProviderIdAsync(
|
||||||
serviceProviderId);
|
serviceProviderId);
|
||||||
|
|
||||||
|
var dics = new List<Dictionary<string, object?>>();
|
||||||
foreach (var item in data.Items)
|
foreach (var item in data.Items)
|
||||||
{
|
{
|
||||||
// 一行数据
|
// 一行数据
|
||||||
@ -234,10 +236,11 @@ public class ServiceProviderAccountService : ApplicationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
dic[nameof(ServiceProviderAccountPageValueObject.UpdateTime)] = updateTime;
|
dic[nameof(ServiceProviderAccountPageValueObject.UpdateTime)] = updateTime;
|
||||||
|
|
||||||
res.Items.Add(dic);
|
dics.Add(dic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.Items = dics;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider;
|
|||||||
/// 服务商授权配置
|
/// 服务商授权配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "服务商服务")]
|
[ApiExplorerSettings(GroupName = "服务商服务")]
|
||||||
public class ServiceProviderAuthService : ApplicationService
|
public class ServiceProviderAuthService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IBasicRepository<InterfaceEntity> _interfaceRepository;
|
private readonly IBasicRepository<InterfaceEntity> _interfaceRepository;
|
||||||
private readonly IBasicRepository<ParameterEntity> _parameterRepository;
|
private readonly IBasicRepository<ParameterEntity> _parameterRepository;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider;
|
|||||||
/// 导入导出服务
|
/// 导入导出服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "服务商服务")]
|
[ApiExplorerSettings(GroupName = "服务商服务")]
|
||||||
public class ServiceProviderImportExportService : ApplicationService
|
public class ServiceProviderImportExportService : BaseService
|
||||||
{
|
{
|
||||||
private readonly ISugarDbContextProvider<InterfaceForwardDbContext> _sqlSugarClientProvider;
|
private readonly ISugarDbContextProvider<InterfaceForwardDbContext> _sqlSugarClientProvider;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using InterfaceForward.Application.Contracts.Dtos.ServiceProvider;
|
using InterfaceForward.Application.Contracts.Dtos.ServiceProvider;
|
||||||
using InterfaceForward.Application.ForwardCore;
|
using InterfaceForward.Application.ForwardCore;
|
||||||
using InterfaceForward.Domain.Shared.Dtos;
|
|
||||||
using InterfaceForward.Domain.Shared.Enum;
|
using InterfaceForward.Domain.Shared.Enum;
|
||||||
using InterfaceForward.Repositories;
|
using InterfaceForward.Repositories;
|
||||||
using InterfaceForward.Repositories.Interface.Entitys;
|
using InterfaceForward.Repositories.Interface.Entitys;
|
||||||
@ -16,7 +15,7 @@ namespace InterfaceForward.Application.Services.ServiceProvider;
|
|||||||
/// 服务商服务
|
/// 服务商服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiExplorerSettings(GroupName = "服务商服务")]
|
[ApiExplorerSettings(GroupName = "服务商服务")]
|
||||||
public class ServiceProviderService : ApplicationService
|
public class ServiceProviderService : BaseService
|
||||||
{
|
{
|
||||||
private readonly IBasicRepository<InterfaceEntity> _interfaceRepository;
|
private readonly IBasicRepository<InterfaceEntity> _interfaceRepository;
|
||||||
private readonly IServiceProviderRepository _serviceProviderRepository;
|
private readonly IServiceProviderRepository _serviceProviderRepository;
|
||||||
|
|||||||
@ -1,19 +1,13 @@
|
|||||||
namespace InterfaceForward.Domain.Shared.Dtos;
|
namespace InterfaceForward.Domain.Shared.Dtos;
|
||||||
|
|
||||||
public class RequestLogDto
|
public class RequestLogDto(Guid requestId)
|
||||||
{
|
{
|
||||||
public const string Init = null;
|
public const string Init = null!;
|
||||||
|
|
||||||
public RequestLogDto(Guid requestId)
|
|
||||||
{
|
|
||||||
RequestId = requestId;
|
|
||||||
Response = Init;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求Id
|
/// 请求Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid RequestId { get; set; }
|
public Guid RequestId { get; set; } = requestId;
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 请求时间(务必设置)
|
/// 请求时间(务必设置)
|
||||||
@ -33,7 +27,7 @@ public class RequestLogDto
|
|||||||
///<summary>
|
///<summary>
|
||||||
/// 发起请求IP
|
/// 发起请求IP
|
||||||
///</summary>
|
///</summary>
|
||||||
public string ClientIP { get; set; }
|
public string? ClientIp { get; set; }
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 接口代码
|
/// 接口代码
|
||||||
@ -68,7 +62,7 @@ public class RequestLogDto
|
|||||||
///<summary>
|
///<summary>
|
||||||
/// 响应结果
|
/// 响应结果
|
||||||
///</summary>
|
///</summary>
|
||||||
public string Response { get; set; }
|
public string Response { get; set; } = Init;
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 是否成功调用
|
/// 是否成功调用
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
namespace InterfaceForward.Domain.Shared.FeiShu;
|
||||||
|
|
||||||
|
public class FeiShuNoticeOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 飞书通知webhook
|
||||||
|
/// </summary>
|
||||||
|
public string Webhook { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息标题前缀
|
||||||
|
/// </summary>
|
||||||
|
public string TitlePrefix { get; set; }
|
||||||
|
}
|
||||||
78
src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticer.cs
Normal file
78
src/InterfaceForward.Domain.Shared/FeiShu/FeiShuNoticer.cs
Normal file
@ -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<FeiShuNoticer> _logger;
|
||||||
|
|
||||||
|
public FeiShuNoticer(IOptions<FeiShuNoticeOptions> options, HttpClient httpClient, ILogger<FeiShuNoticer> 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<object>()
|
||||||
|
{
|
||||||
|
new List<object>()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
using Fake.DependencyInjection;
|
||||||
|
|
||||||
|
namespace InterfaceForward.Domain.Shared.FeiShu;
|
||||||
|
|
||||||
|
public interface IFeiShuNoticer: ITransientDependency
|
||||||
|
{
|
||||||
|
public Task NoticeAsync(string content, string subTitle = "");
|
||||||
|
}
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送通知
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">消息内容</param>
|
|
||||||
/// <param name="webhook">机器人webhook地址</param>
|
|
||||||
/// <param name="messageType">消息类型</param>
|
|
||||||
/// <param name="hardSend">本地环境依然发布消息</param>
|
|
||||||
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<dynamic> {
|
|
||||||
new List<dynamic>{
|
|
||||||
new {
|
|
||||||
tag = "text",
|
|
||||||
text = message + Environment.NewLine
|
|
||||||
},
|
|
||||||
new {
|
|
||||||
tag = "at",
|
|
||||||
user_id = "all"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} :
|
|
||||||
new List<dynamic> {
|
|
||||||
new List<dynamic>{
|
|
||||||
new {
|
|
||||||
tag = "text",
|
|
||||||
text = message + Environment.NewLine
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
_ = Task.Run(() =>
|
|
||||||
{
|
|
||||||
_ = PostAsync<object>(webhook, postData: JsonConvert.SerializeObject(sendMessage));
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{Environment.NewLine}通知发送失败!{e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送通知,从配置文件取飞书配置
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">消息内容</param>
|
|
||||||
/// <param name="messageType">消息类型</param>
|
|
||||||
/// <param name="hardSend">本地环境是否强制发送</param>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发送消息,指定webhok地址
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
/// <param name="wbeHok"></param>
|
|
||||||
/// <param name="title"></param>
|
|
||||||
/// <exception cref="NullReferenceException"></exception>
|
|
||||||
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<T> PostAsync<T>(string url, string postData = null, string contentType = null, int timeOut = 30, Dictionary<string, string> 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<T>(resultStr);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"返回参数序列化失败,异常信息{ex}!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Serilog" Version="4.0.0-dev-02167" />
|
<PackageReference Include="Serilog" Version="4.0.0-dev-02174" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Fake.DomainDrivenDesign" Version="8.0.0-preview6" />
|
<PackageReference Include="Fake.DomainDrivenDesign" Version="8.0.0-preview8.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
using Fake.Modularity;
|
using Fake.Modularity;
|
||||||
|
using InterfaceForward.Domain.Shared.FeiShu;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace InterfaceForward.Domain.Shared
|
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<FeiShuNoticeOptions>(config.GetSection("FeiShuNotice"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,8 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Fake.DomainDrivenDesign" Version="8.0.0-preview6" />
|
<PackageReference Include="Fake.SqlSugarCore" Version="8.0.0-preview8.4" />
|
||||||
<PackageReference Include="Fake.SqlSugarCore" Version="8.0.0-preview6" />
|
|
||||||
<PackageReference Include="NEST" Version="7.17.5" />
|
<PackageReference Include="NEST" Version="7.17.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class LogIndex : IdBaseIndex
|
|||||||
///<summary>
|
///<summary>
|
||||||
/// 发起请求IP
|
/// 发起请求IP
|
||||||
///</summary>
|
///</summary>
|
||||||
public string ClientIP { get; set; }
|
public string? ClientIp { get; set; }
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 接口代码
|
/// 接口代码
|
||||||
|
|||||||
@ -31,13 +31,7 @@ public interface ILogRepository
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exception">异常</param>
|
/// <param name="exception">异常</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task WriteAppLog(Exception exception = null);
|
Task WriteAppLogAsync(Exception? exception = null);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发飞书
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="contextException"></param>
|
|
||||||
void SendFeiShu(Exception contextException);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加日志
|
/// 添加日志
|
||||||
@ -65,7 +59,7 @@ public interface ILogRepository
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<LogIndex> GetDetailsByIdAsync(string id);
|
Task<LogIndex?> GetDetailsByIdAsync(string id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据给定请求id,获取请求日志
|
/// 根据给定请求id,获取请求日志
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using Nest;
|
using Nest;
|
||||||
using InterfaceForward.Domain.Shared.Dtos;
|
using InterfaceForward.Domain.Shared.Dtos;
|
||||||
using InterfaceForward.Domain.Shared.Enum;
|
using InterfaceForward.Domain.Shared.Enum;
|
||||||
using InterfaceForward.Domain.Shared.Helpers;
|
using InterfaceForward.Domain.Shared.FeiShu;
|
||||||
using InterfaceForward.Repositories.Log.Entitys;
|
using InterfaceForward.Repositories.Log.Entitys;
|
||||||
using InterfaceForward.Repositories.Log.ES;
|
using InterfaceForward.Repositories.Log.ES;
|
||||||
using InterfaceForward.Repositories.Log.ValueObjects;
|
using InterfaceForward.Repositories.Log.ValueObjects;
|
||||||
@ -14,11 +14,16 @@ namespace InterfaceForward.Repositories.Log.Services;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LogRepository : ElasticSearchContextAbstract<LogIndex>, ILogRepository, IScopedDependency
|
public class LogRepository : ElasticSearchContextAbstract<LogIndex>, 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();
|
var guid = Guid.NewGuid();
|
||||||
AppRequestLog = new RequestLogDto(guid);
|
AppRequestLog = new RequestLogDto(guid)
|
||||||
AppRequestLog.IsSuccess = true; // 只有接口通发生未处理异常才算应用失败
|
{
|
||||||
|
IsSuccess = true // 只有接口通发生未处理异常才算应用失败
|
||||||
|
};
|
||||||
ServiceProviderRequestLog = new RequestLogDto(guid);
|
ServiceProviderRequestLog = new RequestLogDto(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +31,7 @@ public class LogRepository : ElasticSearchContextAbstract<LogIndex>, ILogReposit
|
|||||||
public RequestLogDto AppRequestLog { get; set; }
|
public RequestLogDto AppRequestLog { get; set; }
|
||||||
public RequestLogDto ServiceProviderRequestLog { 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
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
@ -39,22 +44,7 @@ public class LogRepository : ElasticSearchContextAbstract<LogIndex>, ILogReposit
|
|||||||
|
|
||||||
await AddLogAsync(AppRequestLog);
|
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)
|
public async Task AddLogAsync(RequestLogDto requestLog)
|
||||||
{
|
{
|
||||||
@ -66,7 +56,7 @@ public class LogRepository : ElasticSearchContextAbstract<LogIndex>, ILogReposit
|
|||||||
RequestTime = requestLog.RequestTime == default ? DateTime.Now : requestLog.RequestTime,
|
RequestTime = requestLog.RequestTime == default ? DateTime.Now : requestLog.RequestTime,
|
||||||
IsApp = requestLog.IsApp,
|
IsApp = requestLog.IsApp,
|
||||||
Name = requestLog.Name,
|
Name = requestLog.Name,
|
||||||
ClientIP = requestLog.ClientIP,
|
ClientIp = requestLog.ClientIp,
|
||||||
InterfaceCode = requestLog.InterfaceCode,
|
InterfaceCode = requestLog.InterfaceCode,
|
||||||
InterfaceName = requestLog.InterfaceName,
|
InterfaceName = requestLog.InterfaceName,
|
||||||
Address = requestLog.Address,
|
Address = requestLog.Address,
|
||||||
@ -78,16 +68,11 @@ public class LogRepository : ElasticSearchContextAbstract<LogIndex>, ILogReposit
|
|||||||
Exception = requestLog.Exception
|
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);
|
await _feiShuNoticer.NoticeAsync("数据添加失败,原因:" + response.DebugInformation);
|
||||||
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()}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +81,7 @@ public class LogRepository : ElasticSearchContextAbstract<LogIndex>, ILogReposit
|
|||||||
var data = await Context.SearchAsync<LogIndex>(x => x
|
var data = await Context.SearchAsync<LogIndex>(x => x
|
||||||
.Source(s => s.Includes(i => i.Fields(
|
.Source(s => s.Includes(i => i.Fields(
|
||||||
f => f.Id, f => f.RequestId, f => f.RequestTime, f => f.IsApp,
|
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)))
|
f => f.Cost, f => f.IsSuccess)))
|
||||||
.Query(q =>
|
.Query(q =>
|
||||||
(input.Type != LogListInputTypeEnum.应用 ? null : q.Term(p => p.IsApp, true))
|
(input.Type != LogListInputTypeEnum.应用 ? null : q.Term(p => p.IsApp, true))
|
||||||
@ -203,9 +188,9 @@ public class LogRepository : ElasticSearchContextAbstract<LogIndex>, ILogReposit
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LogIndex> GetDetailsByIdAsync(string id)
|
public async Task<LogIndex?> GetDetailsByIdAsync(string id)
|
||||||
{
|
{
|
||||||
var data = await Context.SearchAsync<LogIndex>(x => x
|
ISearchResponse<LogIndex?> data = await Context.SearchAsync<LogIndex>(x => x
|
||||||
.Size(1)
|
.Size(1)
|
||||||
.Query(q => q.Term(t => t
|
.Query(q => q.Term(t => t
|
||||||
.Field(f => f.Id.Suffix("keyword"))
|
.Field(f => f.Id.Suffix("keyword"))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user