ABP大型專案實戰(2) - 除錯與排錯 - 日誌 - 檢視審計日誌
這是《ABP大型專案實戰》系列文章的一篇。
專案釋出到生產環境後難免會有錯誤。
那麼如何進行除錯和排錯呢?
我看到俱樂部裡有人是直接登陸生產伺服器把資料庫下載到開發機器進行除錯排錯。
這種辦法是不適用於大型專案的:
-
首先,大型專案(特別是全球都有分公司的大型專案)很有可能24小時都有人在使用。所以儘量避免直接登入生產伺服器操作,就算部署,也應該用DevOps、藍綠部署等辦法。
-
另外,如果大型專案有采用金絲雀釋出和A/B測試,那麼把資料庫下載到開發機器這種方法是很不適用的。
-
即使大型專案沒有采用金絲雀釋出和A/B測試,也不適合把資料庫下載到開發機器進行除錯排錯。因為資料庫有可能很大,網路傳輸需要時間,特別是連VPN的時候,甚至有可能要從歐洲傳到中國,又要從中國回傳到歐洲。
-
生產環境資料庫下載後為了安全還需要脫敏,這也需要時間。
還有其他方法,但是這些方法都存在一個問題,就是時光不能倒流,很多時候你是不可能叫客戶回來重現一遍操作流程來複現bug的。
那麼有什麼好辦法呢?
有的,通過檢視日誌來除錯與排錯。
ABP在這方面做得不錯,內建了審計日誌,提供了詳細日誌基類。嗯,這是兩塊內容了,一篇文章是講不完的,所以我分開多篇文章來講。
先從審計日誌開始吧。
不得不說,ABP在這方面做得很好,審計日誌是透明的,你要關閉審計日誌反而要寫程式碼控制。當然,這裡不建議關閉審計日誌。
然而,ABP的審計日誌只提供了寫,沒有提供讀的UI,這樣的話,要看審計日誌就必須要開啟資料庫查看了。
從前面的描述看到,這種做法在大型專案肯定是行不通的啦。我們必須要提供讀取審計日誌的UI。這就是這篇文章的主題。
在我使用的ABP 3.4版本里面,並沒有提供審計日誌的讀取AppService, 但是提供了審計日誌的Entity class。(注意: ABP更新很頻繁,所以你目前使用的版本有可能新增甚至刪除了部分interface或class)
所以我們第一步是先圍繞ABP提供的審計日誌Entity class(AuditLog)來建立AppService class和相關讀取Mehtod. 以下是ABP 3.4版本的示例程式碼:
IAuditLogAppService.cs
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 : GHITAssetAppServiceBase, 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; } // 下面視具體業務情況實現介面的方法 }
第二步就是UI層面,因為審計日誌數量會很大,查閱基本要靠搜尋,所以要選一個查閱功能強大的Grid元件,根據我個人經驗,推薦使用primeng的table元件。具體程式碼因為沒有什麼技術難點,我就不貼了。
關於其他成熟框架元件庫和如何在angular中使用多個成熟控制元件框架,請參考我的另外一篇文章《如何用ABP框架快速完成專案(6) - 用ABP一個人快速完成專案(2) - 使用多個成熟控制元件框架 》
現在終於可以不用登陸生產伺服器就可以檢視審計日誌了。
但是這只是開始!
因為一個大型專案裡,審計日誌的增長速度是驚人的,如果審計日誌表和主資料庫放在一起,是十分不科學的。
那麼我們如何解決這個問題呢?敬請期待下一篇文章《ABP大型專案實戰(2) - 除錯與排錯 - 日誌 - 剝離ABP審計日誌》