3 changed files with 280 additions and 0 deletions
@ -0,0 +1,85 @@
|
||||
using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Api; |
||||
using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Api.Output; |
||||
using ATS.NonCustodial.Shared.Common.Attributes; |
||||
using ATS.NonCustodial.Shared.Common.UnifiedResults; |
||||
using ATS.NonCustodial.Shared.Extensions; |
||||
|
||||
namespace ATS.NonCustodial.AdminUi.Helpers.Logs |
||||
{ |
||||
/// <summary> |
||||
/// Api帮助类 |
||||
/// </summary> |
||||
/// Author:mxg |
||||
/// CreatedTimed:2022-05-18 09:46 AM |
||||
[SingleInstance] |
||||
public class ApiHelper |
||||
{ |
||||
#region Identity |
||||
|
||||
private List<ApiHelperDto> _apis; |
||||
private static readonly object LockObject = new(); |
||||
private readonly IApiService _apiService; |
||||
|
||||
public ApiHelper(IApiService apiService) |
||||
{ |
||||
_apiService = apiService; |
||||
} |
||||
|
||||
#endregion Identity |
||||
|
||||
/// <summary> |
||||
/// 主要是在Action 操作的时候添加操作日志时候用 |
||||
/// </summary> |
||||
/// <returns></returns> |
||||
public List<ApiHelperDto> GetApis() |
||||
{ |
||||
if (_apis != null && _apis.Any()) return _apis; |
||||
|
||||
lock (LockObject) |
||||
{ |
||||
if (_apis != null && _apis.Any()) return _apis; |
||||
|
||||
_apis = new List<ApiHelperDto>(); |
||||
|
||||
var apis = ((ResultOutput<List<ApiListOutput>>)_apiService.GetListAsync("").Result) |
||||
.Data |
||||
.Select(a => new |
||||
{ |
||||
a.Id, |
||||
a.ParentId, |
||||
a.Label, |
||||
a.Path |
||||
}); |
||||
|
||||
foreach (var api in apis) |
||||
{ |
||||
var parentLabel = apis.FirstOrDefault(a => a.Id == api.ParentId)?.Label; |
||||
|
||||
_apis.Add(new ApiHelperDto |
||||
{ |
||||
Label = parentLabel.NotNull() ? $"{parentLabel} / {api.Label}" : api.Label, |
||||
Path = api.Path?.ToLower().Trim('/') |
||||
}); |
||||
} |
||||
|
||||
return _apis; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// |
||||
/// </summary> |
||||
public class ApiHelperDto |
||||
{ |
||||
/// <summary> |
||||
/// 接口名称 |
||||
/// </summary> |
||||
public string Label { get; set; } |
||||
|
||||
/// <summary> |
||||
/// 接口地址 |
||||
/// </summary> |
||||
public string Path { get; set; } |
||||
} |
||||
} |
||||
@ -0,0 +1,20 @@
|
||||
using Microsoft.AspNetCore.Mvc.Filters; |
||||
|
||||
namespace ATS.NonCustodial.AdminUi.Helpers.Logs |
||||
{ |
||||
/// <summary> |
||||
/// 操作日志处理接口 |
||||
/// </summary> |
||||
/// Author:mxg |
||||
/// CreatedTimed:2022-05-18 09:46 AM |
||||
public interface ILogHandler |
||||
{ |
||||
/// <summary> |
||||
/// 写操作日志 |
||||
/// </summary> |
||||
/// <param name="context"></param> |
||||
/// <param name="next"></param> |
||||
/// <returns></returns> |
||||
Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next); |
||||
} |
||||
} |
||||
@ -0,0 +1,175 @@
|
||||
using ATS.NonCustodial.Application.Contracts.Interfaces.Logs.OprationLog; |
||||
using ATS.NonCustodial.Application.Contracts.Interfaces.Logs.OprationLog.Input; |
||||
using ATS.NonCustodial.AuditLogging.AuditLoggings.Services; |
||||
using ATS.NonCustodial.Shared.Common.UnifiedResults; |
||||
using Microsoft.AspNetCore.Mvc; |
||||
using Microsoft.AspNetCore.Mvc.Controllers; |
||||
using Microsoft.AspNetCore.Mvc.Filters; |
||||
using Microsoft.Extensions.Logging; |
||||
using Newtonsoft.Json; |
||||
using System.Diagnostics; |
||||
using System.Reflection; |
||||
|
||||
namespace ATS.NonCustodial.AdminUi.Helpers.Logs |
||||
{ |
||||
/// <summary> |
||||
/// 控制器操作日志记录 ==> 操作日志处理 |
||||
/// </summary> |
||||
/// Author:mxg |
||||
/// CreatedTimed:2022-05-18 09:46 AM |
||||
public class LogHandler : ILogHandler |
||||
{ |
||||
#region Identity |
||||
|
||||
private readonly ILogger _logger; |
||||
private readonly ApiHelper _apiHelper; |
||||
private readonly IOperationLogService _operationLogService; |
||||
private readonly IAuditEventLogger _auditEventLogger; |
||||
|
||||
public LogHandler( |
||||
ILogger<LogHandler> logger, |
||||
ApiHelper apiHelper, |
||||
IOperationLogService operationLogService, |
||||
IAuditEventLogger auditEventLogger |
||||
) |
||||
{ |
||||
_logger = logger; |
||||
_apiHelper = apiHelper; |
||||
_operationLogService = operationLogService; |
||||
_auditEventLogger = auditEventLogger; |
||||
} |
||||
|
||||
#endregion Identity |
||||
|
||||
/// <summary> |
||||
/// |
||||
/// </summary> |
||||
/// <param name="context"></param> |
||||
/// <param name="next"></param> |
||||
/// <returns></returns> |
||||
public async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next) |
||||
{ |
||||
var sw = new Stopwatch(); |
||||
sw.Start(); |
||||
//调用接口 |
||||
var actionExecutedContext = await next(); |
||||
sw.Stop(); |
||||
|
||||
try |
||||
{ |
||||
//接口Type |
||||
var controllerType = (context.ActionDescriptor as ControllerActionDescriptor)?.ControllerTypeInfo.AsType().GetSummary(); |
||||
|
||||
//方法信息 |
||||
var controllerAction = (context.ActionDescriptor as ControllerActionDescriptor)?.MethodInfo.GetSummary(); |
||||
|
||||
var input = new OprationLogAddInput |
||||
{ |
||||
ApiLabel = $"{controllerType}/{controllerAction}".Trim('/'), |
||||
ApiMethod = context.HttpContext.Request.Method.ToLower(), |
||||
ApiPath = context.ActionDescriptor.AttributeRouteInfo?.Template?.ToLower(), |
||||
ElapsedMilliseconds = sw.ElapsedMilliseconds, |
||||
Params = JsonConvert.SerializeObject(context.ActionArguments) |
||||
}; |
||||
|
||||
if (actionExecutedContext.Result is ObjectResult { Value: IResultOutput res }) |
||||
{ |
||||
input.Status = res.Success; |
||||
input.Msg = res.Msg; |
||||
} |
||||
|
||||
#region 设置参数 |
||||
|
||||
//switch (context.HttpContext.Request.Method) |
||||
//{ |
||||
// case "GET": |
||||
// case "DELETE": |
||||
// input.Params = context.HttpContext.Request.Path; |
||||
// break; |
||||
// case "PUT": |
||||
// case "POST": |
||||
// context.HttpContext.Request.EnableBuffering(); |
||||
// context.HttpContext.Request.Body.Position = 0; |
||||
// StreamReader reader = new StreamReader(context.HttpContext.Request.Body, Encoding.UTF8); |
||||
// input.Params = reader.ReadToEndAsync().GetAwaiter().GetResult(); |
||||
// context.HttpContext.Request.Body.Position = 0; |
||||
// break; |
||||
// default: break; |
||||
//} |
||||
//if (input.Params is { Length: > 1024 }) |
||||
//{ |
||||
// input.Params = input.Params.Substring(0, 1021) + "..."; |
||||
//} |
||||
|
||||
#endregion 设置参数 |
||||
|
||||
#region 设置返回值 |
||||
|
||||
try |
||||
{ |
||||
if (actionExecutedContext.Exception != null && !actionExecutedContext.ExceptionHandled) |
||||
{ |
||||
input.Exception = actionExecutedContext.Exception.StackTrace; |
||||
} |
||||
} |
||||
catch (Exception ex) |
||||
{ |
||||
input.Exception = ex.StackTrace; |
||||
throw; |
||||
} |
||||
finally |
||||
{ |
||||
if (input.Exception is { Length: > 2048 }) |
||||
{ |
||||
input.Exception = input.Exception.Substring(0, 2045) + "..."; |
||||
} |
||||
|
||||
if (actionExecutedContext != null) |
||||
{ |
||||
input.Result = actionExecutedContext.Result switch |
||||
{ |
||||
ObjectResult objectResult => JsonConvert.SerializeObject(objectResult.Value), |
||||
JsonResult jsonResult => JsonConvert.SerializeObject(jsonResult.Value), |
||||
ContentResult contentResult => contentResult.Content, |
||||
_ => input.Result |
||||
}; |
||||
if (input.Result is { Length: > 2048 }) |
||||
{ |
||||
input.Result = input.Result.Substring(0, 2045) + "..."; |
||||
} |
||||
} |
||||
} |
||||
|
||||
#endregion 设置返回值 |
||||
|
||||
//接口名称 |
||||
//input.ApiLabel = _apiHelper.GetApis().FirstOrDefault(a => a.Path == input.ApiPath)?.Label; |
||||
|
||||
//添加操作日志 |
||||
await _operationLogService.AddAsync(input); |
||||
|
||||
#region 添加审计日志 |
||||
|
||||
//var apiAuditLog = new CustomizedLogEvent() |
||||
//{ |
||||
// Category = nameof(CustomizedLogEvent), |
||||
// SubjectType = AuditSubjectTypes.machine, |
||||
// SubjectName = Environment.MachineName, |
||||
// SubjectIdentifier = Environment.MachineName, |
||||
// Action = new { Method = input.ApiPath, Class = context.Controller.ToString() } |
||||
//}; |
||||
//await _auditEventLogger.LogEventAsync(apiAuditLog, options => |
||||
//{ |
||||
// options.UseDefaultSubject = false; |
||||
// options.UseDefaultAction = false; |
||||
//}); |
||||
|
||||
#endregion 添加审计日志 |
||||
} |
||||
catch (Exception ex) |
||||
{ |
||||
_logger.LogError("操作日志插入异常:{@ex}", ex); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue