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,一经查实,立即删除!

相关文章

[Swift]LeetCode826. 安排工作以达到最大收益 | Most Profit Assigning Work

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号&#xff1a;山青咏芝&#xff08;shanqingyongzhi&#xff09;➤博客园地址&#xff1a;山青咏芝&#xff08;https://www.cnblogs.com/strengthen/&#xff09;➤GitHub地址&a…

H5第四天(1)

boostrap框架介绍 核心知识点 boostrap框架栅格系统[重点,不是难点]基本的全局样式 学习目标 能够使用boostrap框架中的基本样式能够使用栅格系统完成阿里百秀案例 boostrap框架 介绍 https://www.bootcss.com/ Bootstrap 是最受欢迎的 HTML、CSS 和 JS 框架&#xff0c;用…

javascript基础入门知识点整理

学习目标:- 掌握编程的基本思维- 掌握编程的基本语法 typora-copy-images-to: mediaJavaScript基础 HTML和CSS 京东 课前娱乐 众人皆笑我疯癫,我笑尔等看不穿 课前说明 目标&#xff1a;掌握编程的基本思想掌握JavaScript的基础语法,使用常见API(备注)完成相应案例及练习和作业…

学习笔记-canny边缘检测

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

H5第四天(2)

Bootstrap框架 Bootstrap框架 为什么要学Bootstrap框架 Bootstrap框架: 为我们提供了用来实现响应式开发的公共资源 总结: Bootstrap框架用来实现响应式布局Bootstrap框架中重点学什么 Bootstrap框架提供了很多丰富的网页开发资源,代码有上万行代码.1. 重点学习框架中提供的基…

javascript高级实战学习

学习目标:- 理解面向对象开发思想- 掌握 JavaScript 面向对象开发相关模式- 掌握在 JavaScript 中使用正则表达式- typora-copy-images-to mediaJavaScript 高级 课程介绍 课程大纲 在线地址&#xff1a;JavaScript 高级 目标 理解面向对象开发思想 掌握 JavaScript 面向对象…

H5C3笔记微整合

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

如何开发出优秀的APICloud应用

APICloud定制平台项目实施规范APICloud应用优化策略Top30如何开发出运行体验良好、高性能的App如何开发出客户满意、能够顺利交付的App1. 引擎或模块问题&#xff1a; 遇到应用层无法解决的问题&#xff0c;如果能确定需要引擎和模块支持的&#xff0c;不要自己想办法绕过去&am…

收破烂怎么入行

收破烂分为几个环节。1、回收&#xff08;回收利用、消息传递&#xff0c;消息处理&#xff09;2、集中处理&#xff08;垃圾分类&#xff0c;垃圾测试&#xff0c;垃圾投入使用&#xff0c;成品&#xff09;3、应用&#xff08;垃圾回收再应用&#xff0c;提供给需要资源的单位…

javaScript第一天(2)

javaScript基础 1. javaScript的由来【了解】 为什么会出现js 早期出现js的原因就是为了解决一个问题: 用户和浏览器(网页)进行交互其他了解: 系统程序员Brendan Eich 设计了js语言, js语言1借鉴C语言的基本语法; (2)借鉴Java语言的数据类型和内存管理; (3)借鉴Scheme语言&…

WC2018 通道

好久以前开的坑&#xff0e; 到今天才填上&#xff0e; 首先考虑队第一颗树边分&#xff0c;然后分成两个集合\(L,R\)&#xff0c;在第二棵树上建出虚树&#xff0c;在每个路径\(lca\)处统计答案&#xff0c;维护点集的直径只有正权很好维护&#xff0e; #include <bits/std…

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; 语法 //…

关于单链表的头插法和尾插法

#include<stdio.h>#include<stdlib.h> typedef struct Node { // 定义的链表类型 int data; struct Node *next; }LNode , *Linklist; void print(Linklist L){ //这是一个将链表数据输出的函数 Linklist temL; whi…