ABP大型项目实战(2) - 调试与排错 - 日志 - 查看审计日志
- 首先,大型项目(特别是全球都有分公司的大型项目)很有可能24小时都有人在使用。所以尽量避免直接登录生产服务器操作,就算部署,也应该用DevOps、蓝绿部署等办法。
- 另外,如果大型项目有采用金丝雀发布和A/B测试,那么把数据库下载到开发机器这种方法是很不适用的。
- 即使大型项目没有采用金丝雀发布和A/B测试,也不适合把数据库下载到开发机器进行调试排错。因为数据库有可能很大,网络传输需要时间,特别是连VPN的时候,甚至有可能要从欧洲传到中国,又要从中国回传到欧洲。
- 生产环境数据库下载后为了安全还需要脱敏,这也需要时间。
public interface IAuditLogAppService : IApplicationService
{
/// <summary>
/// 大型项目的审计日志量会十分大,所以最起码要分页
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<PagedResultDto<AuditLogListDto>> GetAuditLogs(GetAuditLogsInput input);
/// <summary>
/// 一定要提供Excel下载功能,一般建议是按照时间段选取
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<FileDto> GetAuditLogsToExcel(GetAuditLogsInput input);
/// <summary>
/// 提供全部审计日志的Excel下载,因为数据量会比较大,需要在服务器先压缩好,再提供给客户端下载。
/// </summary>
/// <returns></returns>
Task<FileDto> GetAuditLogsToExcel(); //List<AuditLogListDto> GetAllAuditLogs(); //错误案例示范,大型项目的审计日志量会十分大,所以最起码要分页
}
AuditLogListDto.cs
using System;
using Abp.Application.Services.Dto;
using Abp.Auditing;
using Abp.AutoMapper; [AutoMapFrom(typeof(AuditLog))]
public class AuditLogListDto : EntityDto<long>
{
public long? UserId { get; set; } public string UserName { get; set; } public int? ImpersonatorTenantId { get; set; } public long? ImpersonatorUserId { get; set; } public string ServiceName { get; set; } public string MethodName { get; set; } public string Parameters { get; set; } public DateTime ExecutionTime { get; set; } public int ExecutionDuration { get; set; } public string ClientIpAddress { get; set; } public string ClientName { get; set; } public string BrowserInfo { get; set; } public string Exception { get; set; } public string CustomData { get; set; }
}
AuditLogAppService.cs
[DisableAuditing] //屏蔽这个AppService的审计功能
[AbpAuthorize(AppPermissions.Pages_Administration_AuditLogs)]
public class AuditLogAppService : DemoAppServiceBase, IAuditLogAppService
{
private readonly IRepository<AuditLog, long> _auditLogRepository;
private readonly IRepository<User, long> _userRepository;
private readonly IAuditLogListExcelExporter _auditLogListExcelExporter;
private readonly INamespaceStripper _namespaceStripper; public AuditLogAppService(
IRepository<AuditLog, long> auditLogRepository,
IRepository<User, long> userRepository,
IAuditLogListExcelExporter auditLogListExcelExporter,
INamespaceStripper namespaceStripper)
{
_auditLogRepository = auditLogRepository;
_userRepository = userRepository;
_auditLogListExcelExporter = auditLogListExcelExporter;
_namespaceStripper = namespaceStripper;
} // 下面视具体业务情况实现接口的方法
}
以下是使用EF来查询Auditlog关联User表数据的示例代码:
IQueryable<AuditLogAndUser> query = from auditLog in _auditLogRepository.GetAll()
join user in _userRepository.GetAll() on auditLog.UserId equals user.Id into userJoin
from joinedUser in userJoin.DefaultIfEmpty()
where auditLog.ExecutionTime >= input.StartDate && auditLog.ExecutionTime <= input.EndDate
select new AuditLogAndUser { AuditLog = auditLog, User = joinedUser }; query = query
//.WhereIf(!input.UserName.IsNullOrWhiteSpace(), item => item.User.UserName.Contains(input.UserName))// 以前的写法,不支持多个用户名查询
.WhereIf(usernamelist != null, item => usernamelist.Contains(item.User.UserName))
//.WhereIf(!input.RealUserName.IsNullOrWhiteSpace(), item => item.User.Name.Contains(input.RealUserName))// 以前的写法,不支持多个用户名查询
.WhereIf(realusernamelist != null, item => realusernamelist.Contains(item.User.Name))
.WhereIf(!input.ServiceName.IsNullOrWhiteSpace(), item => item.AuditLog.ServiceName.Contains(input.ServiceName))
.WhereIf(!input.MethodName.IsNullOrWhiteSpace(), item => item.AuditLog.MethodName.Contains(input.MethodName))
.WhereIf(!input.BrowserInfo.IsNullOrWhiteSpace(), item => item.AuditLog.BrowserInfo.Contains(input.BrowserInfo))
.WhereIf(input.MinExecutionDuration.HasValue && input.MinExecutionDuration > , item => item.AuditLog.ExecutionDuration >= input.MinExecutionDuration.Value)
.WhereIf(input.MaxExecutionDuration.HasValue && input.MaxExecutionDuration < int.MaxValue, item => item.AuditLog.ExecutionDuration <= input.MaxExecutionDuration.Value)
.WhereIf(input.HasException == true, item => item.AuditLog.Exception != null && item.AuditLog.Exception != "")
.WhereIf(input.HasException == false, item => item.AuditLog.Exception == null || item.AuditLog.Exception == "");
这里可以看到,既有大量数据又有多表关联查询哦,并且纯是使用EF去做,实践证明EF性能并不差,顺便推广一下Edi的另一篇文章《Entity Framework 的一些性能建议》
然而还是有同学强烈要求提供SQL版本,好吧,以下是最简单的sql版本:
select * from AbpAuditLogs left join AbpUsers on (AbpAuditLogs.UserId = AbpUsers.Id)
where AbpAuditLogs .ExecutionTime >= '2019/2/18' and AbpAuditLogs.ExecutionTime <= '2019/2/19'
这里还有个小技巧可以节省时间:
- 先手动建立一个AuditLog类
public class AuditLog
{
/// <summary>
/// TenantId.
/// </summary>
public virtual int? TenantId { get; set; } /// <summary>
/// UserId.
/// </summary>
public virtual long? UserId { get; set; } /// <summary>
/// Service (class/interface) name.
/// </summary>
public virtual string ServiceName { get; set; } /// <summary>
/// Executed method name.
/// </summary>
public virtual string MethodName { get; set; } /// <summary>
/// Calling parameters.
/// </summary>
public virtual string Parameters { get; set; } /// <summary>
/// Return values.
/// </summary>
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>
public virtual string ClientIpAddress { get; set; } /// <summary>
/// Name (generally computer name) of the client.
/// </summary>
public virtual string ClientName { get; set; } /// <summary>
/// Browser information if this method is called in a web request.
/// </summary>
public virtual string BrowserInfo { get; set; } /// <summary>
/// Exception object, if an exception occured during execution of the method.
/// </summary>
public virtual string Exception { get; set; } /// <summary>
/// <see cref="AuditInfo.ImpersonatorUserId"/>.
/// </summary>
public virtual long? ImpersonatorUserId { get; set; } /// <summary>
/// <see cref="AuditInfo.ImpersonatorTenantId"/>.
/// </summary>
public virtual int? ImpersonatorTenantId { get; set; } /// <summary>
/// <see cref="AuditInfo.CustomData"/>.
/// </summary>
public virtual string CustomData { get; set; } } - 选中这个类然后鼠标右键52abp代码生成器
- 生成后再把AppService接口和类改成上面的代码
- 删除第一步建立的AuditLog类。把引用修正为“Abp.Auditing”
这个小技巧大概可以节省你三十分钟时间吧。
- 如何禁用具体某个接口的审计功能?
答:在类头加上如下属性[DisableAuditing] //屏蔽这个AppService的审计功能
[AbpAuthorize(AppPermissions.Pages_Administration_AuditLogs)]
public class AuditLogAppService : GHITAssetAppServiceBase, IAuditLogAppService
ABP大型项目实战(2) - 调试与排错 - 日志 - 查看审计日志的更多相关文章
- ABP大型项目实战(1) - 目录
前面我写了<如何用ABP框架快速完成项目>系列文章,讲述了如何用ABP快速完成项目. 然后我收到很多反馈,其中一个被经常问到的问题就是,“看了你的课程,发现ABP的优势是快速开发,那么 ...
- Java 18套JAVA企业级大型项目实战分布式架构高并发高可用微服务电商项目实战架构
Java 开发环境:idea https://www.jianshu.com/p/7a824fea1ce7 从无到有构建大型电商微服务架构三个阶段SpringBoot+SpringCloud+Solr ...
- GraphQL + React Apollo + React Hook 大型项目实战(32 个视频)
GraphQL + React Apollo + React Hook 大型项目实战(32 个视频) GraphQL + React Apollo + React Hook 大型项目实战 #1 介绍「 ...
- Spark大型项目实战:电商用户行为分析大数据平台
本项目主要讲解了一套应用于互联网电商企业中,使用Java.Spark等技术开发的大数据统计分析平台,对电商网站的各种用户行为(访问行为.页面跳转行为.购物行为.广告点击行为等)进行复杂的分析.用统计分 ...
- 项目实战8.2-Linux下Tomcat开启查看GC信息
本文收录在Linux运维企业架构实战系列 转自https://www.cnblogs.com/along21/ 一.开启GC日志 1.在Tomcat 的安装路径下,找到bin/catalina.sh ...
- ABP开发框架前后端开发系列---(7)系统审计日志和登录日志的管理
我们了解ABP框架内部自动记录审计日志和登录日志的,但是这些信息只是在相关的内部接口里面进行记录,并没有一个管理界面供我们了解,但是其系统数据库记录了这些数据信息,我们可以为它们设计一个查看和导出这些 ...
- JAVA架构之单点登录 任务调度 权限管理 性能优化大型项目实战
单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...
- 企业项目实战 .Net Core + Vue/Angular 分库分表日志系统 | 简单的分库分表设计
前言 项目涉及到了一些设计模式,如果你看的不是很明白,没有关系坚持下来,写完之后去思考去品,你就会有一种突拨开云雾的感觉,所以请不要在半途感觉自己看不懂选择放弃,如果我哪里写的详细,或者需要修正请联系 ...
- 企业项目实战 .Net Core + Vue/Angular 分库分表日志系统 | 前言
介绍 大家好我是初久,一名从业4年的.Net开发攻城狮,从今天开始我会和大家一起对企业开发中常用的技术进行分享,一方面督促自己学习,一方面也希望大家可以给我指点出更好的方案,我们一起进步. 项目背景 ...
随机推荐
- 初识TensorFlow
在前边几期的文章中,笔者已经用TensorFlow进行的一些基础性的探索工作,想必大家对TensorFlow框架也是非常的好奇,本着发扬雷锋精神,笔者将详细的阐述TensorFlow框架的基本用法,并 ...
- C# List 集合 交集、并集、差集、去重, 对象集合、 对象、引用类型、交并差补、List<T>
关键词:C# List 集合 交集.并集.差集.去重, 对象集合. 对象.引用类型.交并差.List<T> 有时候看官网文档是最高效的学习方式! 一.简单集合 Intersect 交集, ...
- 记一次servlet项目启动
前言 tomcat 和 jetty 都属于 web 容器. mac安装tomcat brew install tomcat 安装之后,输入 catalina -h,可以看到各种命令,如run.star ...
- Java开发笔记(八)五种算术运算符
计算机科学起源于数学,早期的计算机也确实多用于数学运算,以至于后来的各路编程语言,仍然保留着古老的加减乘除四则运算.这四则运算在Java语言中有专门的运算符加以表示,像加法符号“+”对应Java的“+ ...
- Java开发笔记(十七)各得其所的多路分支
前面提到条件语句的标准格式为“if (条件) { /* 条件成立时的操作代码 */ } else { /* 条件不成立时的操作代码 */ }”,乍看之下仿佛只有两个分支,一个是条件成立时的分支,另一个 ...
- Maven(十四)Maven 继承
以Junit为例 由于junit的依赖的范围为test,所以在每一个项目中都必须配置一个junit. 为了统一管理方便,可以单独创建一个项目用来进行**统一管理**junit的版本 即在子项目中不设置 ...
- 零基础学Python--------第4章 序列的应用
第4章 序列的应用 4.1序列 序列是一块用于存放多个值的连续内存空间,并且按上一定顺序排列,每一个值(称为元素)都分配一个数字,称为索引或位置.通过该索引可以取出相应的值.例如,我们可以把一家酒店看 ...
- 20190322-a标签、img标签、三列表、特殊字符实体、表格
目录 1.a标签 a标签的属性 锚点 2.img标签 img标签的属性 图像热区 3.三列表 有序列表(Ordered List) ol>li 无序列表(Unordered List) ...
- vue中如何使用mockjs摸拟接口的各种数据
mockjs的作用 生成模拟数据 模拟 Ajax 请求,返回模拟数据 基于 HTML 模板生成模拟数据(后续更新) 帮助编写单元测试(后续更新) Vue 中使用 mock 有两种使用方式,一种是仅编写 ...
- ssm基础搭建步骤
今天搭建新的项目环境,从网上找了些ssm的搭建步骤,终于找到了一位csdn的大佬,可以说写的特别详细,按照上面步骤搭建即可,为了方便日后参考,转载到本人博客,原文链接:https://blog.csd ...