博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

abp框架扩展AbpAuditLogs审计日志

Posted on 2022-03-02 13:31  无所谓%  阅读(887)  评论(0)    收藏  举报

ABP框架默认提供审计日志功能,只需实现并重写IAuditingStore接口即可

 

1.创建自定义审计日志的model,可以自定义字段内容以及字段类型

public class AuditLog : AuditedEntity<long>
    {


        /// <summary>
        /// Maximum length of <see cref="ServiceName"/> property.
        /// </summary>
        public const int MaxServiceNameLength = 256;

        /// <summary>
        /// Maximum length of <see cref="MethodName"/> property.
        /// </summary>
        public const int MaxMethodNameLength = 256;

        /// <summary>
        /// Maximum length of <see cref="Parameters"/> property.
        /// </summary>
        public const int MaxParametersLength = 1024;

        /// <summary>
        /// Maximum length of <see cref="ReturnValue"/> property.
        /// </summary>
        public const int MaxReturnValueLength = 1024;

        /// <summary>
        /// Maximum length of <see cref="ClientIpAddress"/> property.
        /// </summary>
        public const int MaxClientIpAddressLength = 64;

        /// <summary>
        /// Maximum length of <see cref="ClientName"/> property.
        /// </summary>
        public const int MaxClientNameLength = 128;

        /// <summary>
        /// Maximum length of <see cref="BrowserInfo"/> property.
        /// </summary>
        public const int MaxBrowserInfoLength = 512;

        /// <summary>
        /// Maximum length of <see cref="Exception"/> property.
        /// </summary>
        public const int MaxExceptionLength = 2048;

        /// <summary>
        /// Maximum length of <see cref="CustomData"/> property.
        /// </summary>
        public const int MaxCustomDataLength = 2048;



        /// <summary>
        /// Service (class/interface) name.
        /// </summary>
        [StringLength(MaxServiceNameLength)]
        public virtual string ServiceName { get; set; }

        /// <summary>
        /// Executed method name.
        /// </summary>
        [StringLength(MaxMethodNameLength)]
        public virtual string MethodName { get; set; }

        /// <summary>
        /// Calling parameters.
        /// </summary>
        [StringLength(MaxParametersLength)]
        public virtual string Parameters { get; set; }

        /// <summary>
        /// Return values.
        /// </summary>
        [StringLength(MaxReturnValueLength)]
        public virtual string ReturnValue { get; set; }

        /// <summary>
        /// Start time of the method execution.
        /// </summary>
        public virtual DateTime ExecutionTime { get; set; }

        /// <summary>
        /// Total duration of the method call as milliseconds.
        /// </summary>
        public virtual int ExecutionDuration { get; set; }

        /// <summary>
        /// IP address of the client.
        /// </summary>
        [StringLength(MaxClientIpAddressLength)]
        public virtual string ClientIpAddress { get; set; }

        /// <summary>
        /// Name (generally computer name) of the client.
        /// </summary>
        [StringLength(MaxClientNameLength)]
        public virtual string ClientName { get; set; }

        /// <summary>
        /// Browser information if this method is called in a web request.
        /// </summary>
        [StringLength(MaxBrowserInfoLength)]
        public virtual string BrowserInfo { get; set; }

        /// <summary>
        /// Exception object, if an exception occured during execution of the method.
        /// </summary>
        [StringLength(MaxExceptionLength)]
        public virtual string Exception { get; set; }

        /// <summary>
        /// <see cref="AuditInfo.CustomData"/>.
        /// </summary>
        [StringLength(MaxCustomDataLength)]
        public virtual string CustomData { get; set; }

        /// <summary>
        /// Creates a new CreateFromAuditInfo from given <paramref name="auditInfo"/>.
        /// </summary>
        /// <param name="auditInfo">Source <see cref="AuditInfo"/> object</param>
        /// <param name="account">Source <see cref="IAccountInfo"/> object</param>
        /// <returns>The <see cref="AuditLog"/> object that is created using <paramref name="auditInfo"/></returns>
        public static AuditLog CreateFromAuditInfo(AuditInfo auditInfo)
        {
            var exceptionMessage = GetAbpClearException(auditInfo.Exception);

            return new AuditLog
            {
                ServiceName = auditInfo.ServiceName.TruncateWithPostfix(MaxServiceNameLength),
                MethodName = auditInfo.MethodName.TruncateWithPostfix(MaxMethodNameLength),
                Parameters = auditInfo.Parameters.TruncateWithPostfix(MaxParametersLength),
                ReturnValue = auditInfo.ReturnValue.TruncateWithPostfix(MaxReturnValueLength),
                ExecutionTime = auditInfo.ExecutionTime,
                ExecutionDuration = auditInfo.ExecutionDuration,
                ClientIpAddress = auditInfo.ClientIpAddress.TruncateWithPostfix(MaxClientIpAddressLength),
                ClientName = auditInfo.ClientName.TruncateWithPostfix(MaxClientNameLength),
                BrowserInfo = auditInfo.BrowserInfo.TruncateWithPostfix(MaxBrowserInfoLength),
                Exception = exceptionMessage.TruncateWithPostfix(MaxExceptionLength),
                CustomData = auditInfo.CustomData.TruncateWithPostfix(MaxCustomDataLength)
            };
        }
 public static string GetAbpClearException(Exception exception)
        {
            var clearMessage = "";
            switch (exception)
            {
                case null:
                    return null;

                case AbpValidationException abpValidationException:
                    clearMessage = "There are " + abpValidationException.ValidationErrors.Count + " validation errors:";
                    foreach (var validationResult in abpValidationException.ValidationErrors)
                    {
                        var memberNames = "";
                        if (validationResult.MemberNames != null && validationResult.MemberNames.Any())
                        {
                            memberNames = " (" + string.Join(", ", validationResult.MemberNames) + ")";
                        }

                        clearMessage += "\r\n" + validationResult.ErrorMessage + memberNames;
                    }
                    break;

                case UserFriendlyException userFriendlyException:
                    clearMessage =
                        $"UserFriendlyException.Code:{userFriendlyException.Code}\r\nUserFriendlyException.Details:{userFriendlyException.Details}";
                    break;
            }

            return exception + (clearMessage.IsNullOrWhiteSpace() ? "" : "\r\n\r\n" + clearMessage);
        }
    }

  

2.在对应的DBContext中添加对应的model 并生成迁移文件,完成迁移

 public virtual DbSet<AuditLog> AuditLog { get; set; }

Add-Migration test
Update-Database

 

3.自定义AuditStore实现Abp的IAuditingStore,重写对应方法

public class AuditingStoreTest : IAuditingStore, ITransientDependency
    {
        private readonly IRepository<AuditLog, long> _auditLogRepository;


        /// <summary>
        /// Creates a new <see cref="AuditingStore"/>.
        /// </summary>
        public AuditingStoreTest(IRepository<AuditLog, long> auditLogRepository)
        {
            _auditLogRepository = auditLogRepository;
        }

        public virtual Task SaveAsync(AuditInfo auditInfo)
        {
            return _auditLogRepository.InsertAsync(AuditLog.CreateFromAuditInfo(auditInfo));
        }

        public virtual void Save(AuditInfo auditInfo)
        {
            _auditLogRepository.Insert(AuditLog.CreateFromAuditInfo(auditInfo));
        }
    }

  

4.找一个实现AbpModule模块的类中将原有的审计日志替换为自定义的

   Configuration.ReplaceService(typeof(IAuditingStore), () =>
            {
                IocManager.IocContainer.Register(
                    Component.For<IAuditingStore>()
                .ImplementedBy<AuditingStoreTest>()
                .LifestyleTransient()
                );
            });

  

根据以上四步即可完成对abp审计日志的自定义扩展