X-AdminABP框架开发-系统日志

  网站正常运行中有时出现异常在所难免,查看系统运行日志分析问题并能够根据错误信息快速解决问题尤为重要,ABP对于系统运行日志这块已经做了很好的处理,默认采用的Log4Net已经足够满足开发过程中的需要了(当然有需要的话也可以更换为其它日志组件)。

  ABP官网地址:https://aspnetboilerplate.com/

 

一、日志文件

  ABP框架默认使用了Log4Net日志组件,日志记录在txt文件中,也可以替换成其它日志组件诸如Nlog,方便将日志文件信息直接记录到数据库中,具体情形使用具体组件。

  

  当一个文件达到了在Log4Net配置中设置好的文件大小上限时,在文件名后按照数字倒排后开始继续增加文件。

  

  当需要查看错误信息时,直接在日期最近的文件中找出错误信息即可,但是这个过程比较繁琐,还需要从日志文件中去查看,并且日志文件中虽然做了分类,哪些是正常信息,哪些是错误信息,但是不太直观,因此,可以考虑直接将日志文件在页面中呈现,对信息进一步加工,方便直接查看。

   

  参考了AbpZero中的部分代码并根据实际需要进行整合,开始在页面中设计日志展示层。 

 

二、页面展示日志信息

1、系统日志服务应属于整个系统中相对其他业务模块独立的一部分,因此,首先在应用层中新建一个Logging文件夹并创建一个日志应用层服务接口与其实现。在接口中声明两个方法,直接查看当前最近的日志文件中的日志信息以及从服务器下载所有的日志文件。

/// <summary>
/// 网站运行日志应用层服务
/// </summary>
public interface IWebSiteLogAppService : IApplicationService
{/// <summary>/// 获取最近的一个日志文件/// </summary>/// <returns></returns>
    GetLatestWebLogsOutput GetLatestWebLogs();/// <summary>/// 下载所有的日志文件/// </summary>/// <returns></returns>
    FileDto DownloadWebLogs();
}

   首先考虑直接获取最近的日志文件信息,直接读取即可,遵循的规则是读取指定文件夹下指定文件后缀名更改日期为最大的文件然后从中读取日志信息,并返回到前端。

public GetLatestWebLogsOutput GetLatestWebLogs()
{var directory = new DirectoryInfo(AppConsts.LogFilePath);if (!directory.Exists){return new GetLatestWebLogsOutput{LatestWebLogLines = new List<string>()};}var lastLogFile = directory.GetFiles("*.txt", SearchOption.AllDirectories).OrderByDescending(f => f.LastWriteTime).FirstOrDefault();if (lastLogFile == null){return new GetLatestWebLogsOutput();}var lines = AppFileHelper.ReadLines(lastLogFile.FullName).Reverse().Take(1000).ToList();var logLineCount = 0;var lineCount = 0;foreach (var line in lines){if (line.StartsWith("DEBUG") ||line.StartsWith("INFO") ||line.StartsWith("WARN") ||line.StartsWith("ERROR") ||line.StartsWith("FATAL"))logLineCount++;lineCount++;if (logLineCount == 100) break;}return new GetLatestWebLogsOutput{LatestWebLogLines = lines.Take(lineCount).Reverse().ToList()};
}

  

2、在前端处理日志信息,Mvc层中新增一个控制器,并写一个方法调用日志服务获取最近的日志文件信息,并处理好权限问题及页面左侧菜单的展示。

/// <summary>
/// 系统维护控制器
/// </summary>
[AbpMvcAuthorize]
public class MaintenanceController : SurroundControllerBase
{private readonly IWebSiteLogAppService _webSiteLogAppService;public MaintenanceController(IWebSiteLogAppService webSiteLogAppService){_webSiteLogAppService = webSiteLogAppService;}/// <summary>/// 首页/// </summary>/// <returns></returns>public IActionResult Index(){return View();}/// <summary>/// 获取最近日志信息/// </summary>/// <returns></returns>public JsonResult GetLatestWebLogs(){var getLatestWebLogsOutput = _webSiteLogAppService.GetLatestWebLogs();return Json(getLatestWebLogsOutput);}
}

   增加一个视图文件并开始编写前端代码获取日志文件,利用abp前端封装好的ajax请求快速的获取日志文件,然后通过layui中提供的徽章进行加工处理,如此一来,通过颜色快速区分哪些是错误信息,哪些信息权重更大,更值得关注,此处引用了一个lodash.js,该js中提供了许多的辅助方法。

function getFormattedLogs(logLines) {var resultHtml = '';$.each(logLines, function (index, logLine) {resultHtml += '<span>' + _.escape(logLine).replace('DEBUG', '<span class="layui-badge layui-bg-gray">DEBUG</span>').replace('INFO', '<span class="layui-badge layui-bg-green">INFO</span>').replace('WARN', '<span class="layui-badge layui-bg-orange">WARN</span>').replace('ERROR', '<span class="layui-badge">ERROR</span>').replace('FATAL', '<span class="layui-badge">FATAL</span>') + '</span><br/>';});return resultHtml;
}

   通过刷新按钮获取最近的日志信息。

  

三、下载日志文件

   也可以直接下载日志文件去分析,当然,从使用频率讲,这个功能的权重远低于直接页面查看,但是细想一下,如果说一个异常发生,没有及时去页面中查看,那么就得去成堆的日志中翻找,反而凸显其作用了。

public FileDto DownloadWebLogs()
{var logFiles = GetAllLogFiles();var zipFileDto = new FileDto("WebSiteLogs.zip", MimeTypeNames.ApplicationZip);using (var outputZipFileStream = new MemoryStream()){using (var zipStream = new ZipArchive(outputZipFileStream, ZipArchiveMode.Create)){foreach (var logFile in logFiles){var entry = zipStream.CreateEntry(logFile.Name);using (var entryStream = entry.Open()){using (var fs = new FileStream(logFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 0x1000, FileOptions.SequentialScan)){fs.CopyTo(entryStream);entryStream.Flush();}}}}_tempFileCacheManager.SetFile(zipFileDto.FileToken, outputZipFileStream.ToArray());}return zipFileDto;
}private List<FileInfo> GetAllLogFiles()
{var directory = new DirectoryInfo(AppConsts.LogFilePath);return directory.GetFiles("*.*", SearchOption.TopDirectoryOnly).ToList();
}

   将日志文件全部读取出来,然后打包存储在缓存中,前端点击下载按钮时后台返回压缩包的标识信息供前端直接下载,此处在控制器中加入一个文件管理的控制器,来作为系统中大部分文件下载的渠道。

var waitIndex = parent.layer.load(2);
abp.ajax({type:"Get",url: "@Url.Action("DownloadWebLogs", "Maintenance")",abpHandleError: false
}).done(function (file) {location.href = '@Url.Action("DownloadTempFile", "File")' + abp.utils.formatString("?fileToken={0}&fileType={1}&fileName={2}", file.fileToken, file.fileType, file.fileName);
}).fail(function (jqXHR) {parent.layer.msg(jqXHR.message, { icon: 5 });
}).always(function () {parent.layer.close(waitIndex);
});

  点击日志下载,浏览器开始执行下载任务。   

  

  至此,系统日志的页面查看就完成了,对于加入诸如查询等更加丰富的功能,可以再进行扩展,也可以考虑直接使用已有的组件更方便的呈现的日志信息而无需手动实现,诸如LogDashBoard等,可以很快速的接入到系统中。 

  代码地址:https://gitee.com/530521314/Partner.Surround.git

 

2019-08-03,望技术有成后能回来看见自己的脚步

转载于:https://www.cnblogs.com/CKExp/p/11290808.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248314.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习笔记-canny边缘检测

Canny边缘检测 声明&#xff1a;阅读本文需要了解线性代数里面的点乘&#xff08;图像卷积的原理&#xff09;&#xff0c;高等数学里的二元函数的梯度&#xff0c;极大值定义&#xff0c;了解概率论里的二维高斯分布 1.canny边缘检测原理和简介 2.实现步骤 3.总结 一、 Canny边…

H5C3笔记微整合

传统布局&#xff08;宽度百分比设置&#xff09; 伸缩布局&#xff08;flex&#xff09; 自适应布局&#xff08;lessrem媒体查询&#xff09; 1、less的使用 2、rem的使用 我的理解&#xff1a; 1、假如想把ui 给的图片设置在网页上&#xff0c;给网页设置个份额值为 x 2、…

javaScript第一天(1)

01-JavaScript基础 核心知识点 javaScript书写位置javaScript变量javaScript数据类型javaScript数据类型转换javaScript运算符 今日学习目标 能够定义一个变量并完成变量的赋值能够说出每一种具体的数据类型能够数据类型之间的相互转化能够掌握各种运算符的作用 序言 Java…

javaScript第二天(1)

02-JavaScript基础 1.核心知识点 运算符分支语句 【重点】断点调试 [查看程序逻辑的一个技能] 2.今日学习目标 能够掌握js中相关的运算符 能够掌握理解算数运算符使用及特点能够掌握赋值运算符的使用及特点能够掌握一元运算符的使用及特点能够掌握比较运算符的特点,理解等于…

第四周总结

第四周作业 这次作业属于哪个课程C语言程序设计这个作业要求在哪里第四周作业我的课程目标全部学会这个作业在那个具体方面帮助我实现目标深入了解二维数组参考文献教科书一&#xff0c;基础作业 程序填空题5-1 输入一个正整数 n (1≤n≤10)和n 阶方阵a的元素&#xff0c;如果方…

2019春季学期第四周作业

2019春季学期第四周作业 这个作业属于那个课程C语言程序设计Ⅰ这次作业要求在哪里2019春季学期第四周作业我在这个课程的目标是我希望能够更加掌握循环和排序参考文献无选择法排序 本题要求将给定的n个整数从大到小排序后输出。输入格式&#xff1a; 输入第一行给出一个不超过1…

javaScript第二天(2)

02JavaScript基础随堂笔记 01.运算符[☆] 知识点-算数运算符 作用就是进行 加, 减, 乘, 除 , 取余运算的 算数运算符的重点是通过算数运算和可以实现类型转换 加号可以实现数据类型转换: 一个数字和一个空字串相加最后的结果就是字符串减号也可以实现数据类型转换乘法符号也可…

MFC中的基本知识

转载于:https://www.cnblogs.com/o8le/archive/2012/05/21/2512178.html

Python中字符串操作函数string.split('str1')和string.join(ls)

Python中的字符串操作函数split 和 join能够实现字符串和列表之间的简单转换&#xff0c; 使用 .split()可以将字符串中特定部分以多个字符的形式&#xff0c;存储成列表 1 def split(self, *args, **kwargs): # real signature unknown2 """3 …

javaScript第三天(1)

03-JavaScript基础 1.核心知识点 分支语句 【重点】断点调试 [查看程序逻辑的一个技能]循环语句[重点 ☆☆☆] 2.今日学习目标 能够掌握条件判断分支语句能够掌握switch分支语句能够掌握三元表达式分支语句能够掌握循环语句 条件判断&#xff08;分支&#xff09; 语法 //…

javascript第三天(2)

03JavaScript基础课堂笔记 01-分支语句 知识点-多条件判断分支语句 语法 if(条件) {代码1 }else if(条件) {代码2 }else if(条件) {代码3 }else {代码4 }执行过程 1. 代码自上而下执行 2. 程序先判断第一个条件是否成立 true 还是 false 3. 如何第一个条件的结果是 true,那么就…

VI编辑器常用命令

vi —终端中的编辑器 vi 简介 打开和新建文件 三种工作模式 常用命令 分屏命令 01. vi 简介 1.1 学习 vi 的目的 在工作中&#xff0c;要对 服务器 上的文件进行 简单 的修改&#xff0c;可以使用 ssh 远程登录到服务器上&#xff0c;并且使用 vi 进行快速的编辑即可 常见…

20175213 2018-2019-2 《Java程序设计》第4周学习总结

## 教材学习内容总结 在第四周的学习过程中&#xff0c;我学习了第五章的内容。 第五章内容总结&#xff1a; 1.子类继承的方法只能操作子类继承和隐藏的成员变量。 2.子类和父类在同一包的继承性 子类自然继承了其父类中不是private的成员作为自己的成员。 3.子类和父类不在同…

伪静态回发

&#xff08;1&#xff09;自定义一个Actionlessform类&#xff0c;在aspx中不再使用系统提供的form 标记 创建此类并对其进行编译之后&#xff0c;要在 ASP.NET Web 应用程序中使用它&#xff0c;应首先将其添加到 Web 应用程序的 References 文件夹中。然后&#xff0c;要 使…

Supercomputer 解题报告

Supercomputer 设\(f_i\)为前\(i\)个时间内必须的完成的任务个数&#xff0c;那么答案就是\[ \max_{i}\lceil\frac{f_i}{i}\rceil \] 现在要支持区间加和全局\(\max\) 考虑分块&#xff0c;对每个块维护一个\(tag\)表示加标记 块内的\(\max\)则为\[ \max_i \frac{1}{i}\times t…

Reversing-x64Elf-100

一道很简单的小题 作为python小白这道题主要是学习了一点python知识...... 可以看出来 sub_4006FD 这个函数是用来判断输入密码是否正确的 我们看一下它的伪代码&#xff1a; signed __int64 __fastcall sub_4006FD(__int64 a1) {signed int i; // [rsp14h] [rbp-24h]const ch…

javaScript第六天(2)

07-javaScript基础 ☞ 函数其他部分 arguments [掌握] arguments 作用? 解决当函数的形参个数不确定的时候,通过arguments获取实参的值如何使用arguments 获取用户传递实参的值? arguments 在函数中就是用来保存实参信息的伪数组 (可以按照数组的方式去遍历, 但是不能使用数…

论wpf的设备无关性 - 简书

论wpf的设备无关性 - 简书 原文:论wpf的设备无关性 - 简书 WPF从发布之日起&#xff0c;一直将“分辨率无关(resolution independence)”作为其亮点&#xff0c;声称使用WPF制作的用户界面在轻巧的Ultra-Mobile PC的屏幕上和在50英寸的电视机上都能很好地显示。微软之所以称WPF…

浅谈Aho-Corasick automaton(AC自动机)

Aho-Corasick automaton是什么&#xff1f; 要学会AC自动机&#xff0c;我们必须知道什么是Trie&#xff0c;也就是字典树。Trie树&#xff0c;又称单词查找树或键树&#xff0c;是一种树形结构&#xff0c;是一种哈希树的变种。典型应用是用于统计和排序大量的字符串&#xff…

javaScript第七天(2)

javaScript基础 ☞ 对象其他部分 [理解] 自定义构造函数创建对象[掌握] //继续简化 自定义构造函数 function People(uName, uAge) {this.uName uName;this.uAge uAge; } // 如何通过自定义构造函数创建对象? var zs new People(张三, 20); console.log(zs);注意事项: 自定…