蜗牛历险记(二) Web框架(中)
上篇简单介绍了框架所使用的Autofac,采用Autofac提供的Ioc管理整个Web项目中所有对象的生命周期,实现框架面向接口编程。接下来介绍框架的日志系统。
一、介绍之前
框架日志是否有存在的必要性?假如你认为你的框架永远不会出现Bug,或者你能根据错误提示就能还原现场,重现这个问题,那你不需要日志。目前看来这样的项目不存在(Helloworld之类除外)。因此日志框架还是很必要的。
日志框架用于记录:系统运行过程中错误详情;用于记录系统使用过程中产生的意外情况;用于记录系统一些状态信息等等。通过不同分类,不同严重级别的日志信息可以很方便地为我们解决问题、为提高系统能效提供等提供数据支持。
目前.Net方向上成熟的日志框架有Log4net、NLog等,这两个框架各有优劣,具体如何选择要根据个人熟悉程度,以及使用环境来判断。
二、初始化
或许会因为各种原因,我们会在系统投入使用后,替换原有的日志框架。因此,在系统设计之初,我们就应该注意不要让框架本身与日志框架有太大的依赖。所以,我们定义日志的级别和日志的标准接口:
1.日志等级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /// <summary> /// 日志等级 /// </summary> public enum LogLevel { /// <summary> /// 调试 /// </summary> Debug, /// <summary> /// 信息 /// </summary> Information, /// <summary> /// 警告 /// </summary> Warning, /// <summary> /// 错误 /// </summary> Error, /// <summary> /// 严重错误 /// </summary> Fatal } |
2.日志基础接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /// <summary> /// 日志接口 /// </summary> public interface ILogger { /// <summary> /// 判断日志等级是否开启 /// </summary> /// <param name="level">日志等级</param> /// <returns>若开启则返回true,否则返回false</returns> bool IsEnabled(LogLevel level); /// <summary> /// 记录日志 /// </summary> /// <param name="level">日志等级</param> /// <param name="exception">异常信息</param> /// <param name="format">日志格式</param> /// <param name="args">日志格式的格式化参数</param> void Log(LogLevel level, Exception exception, string format, params object [] args); } |
3.日志扩展方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | public static class LoggingExtensions { /// <summary> /// 记录调试日志 /// </summary> /// <param name="logger">日志对象</param> /// <param name="message">消息</param> public static void Debug( this ILogger logger, string message) { FilteredLog(logger, LogLevel.Debug, null , message, null ); } /// <summary> /// 记录信息日志 /// </summary> /// <param name="logger">日志对象</param> /// <param name="message">消息</param> public static void Information( this ILogger logger, string message) { FilteredLog(logger, LogLevel.Information, null , message, null ); } /// <summary> /// 记录警告日志 /// </summary> /// <param name="logger">日志对象</param> /// <param name="message">消息</param> public static void Warning( this ILogger logger, string message) { FilteredLog(logger, LogLevel.Warning, null , message, null ); } /// <summary> /// 记录错误日志 /// </summary> /// <param name="logger">日志对象</param> /// <param name="message">消息</param> public static void Error( this ILogger logger, string message) { FilteredLog(logger, LogLevel.Error, null , message, null ); } /// <summary> /// 记录严重错误日志 /// </summary> /// <param name="logger">日志对象</param> /// <param name="message">消息</param> public static void Fatal( this ILogger logger, string message) { FilteredLog(logger, LogLevel.Fatal, null , message, null ); } public static void Debug( this ILogger logger, Exception exception, string message) { FilteredLog(logger, LogLevel.Debug, exception, message, null ); } public static void Information( this ILogger logger, Exception exception, string message) { FilteredLog(logger, LogLevel.Information, exception, message, null ); } public static void Warning( this ILogger logger, Exception exception, string message) { FilteredLog(logger, LogLevel.Warning, exception, message, null ); } public static void Error( this ILogger logger, Exception exception, string message) { FilteredLog(logger, LogLevel.Error, exception, message, null ); } public static void Fatal( this ILogger logger, Exception exception, string message) { FilteredLog(logger, LogLevel.Fatal, exception, message, null ); } public static void Debug( this ILogger logger, string format, params object [] args) { FilteredLog(logger, LogLevel.Debug, null , format, args); } public static void Information( this ILogger logger, string format, params object [] args) { FilteredLog(logger, LogLevel.Information, null , format, args); } public static void Warning( this ILogger logger, string format, params object [] args) { FilteredLog(logger, LogLevel.Warning, null , format, args); } public static void Error( this ILogger logger, string format, params object [] args) { FilteredLog(logger, LogLevel.Error, null , format, args); } public static void Fatal( this ILogger logger, string format, params object [] args) { FilteredLog(logger, LogLevel.Fatal, null , format, args); } public static void Debug( this ILogger logger, Exception exception, string format, params object [] args) { FilteredLog(logger, LogLevel.Debug, exception, format, args); } public static void Information( this ILogger logger, Exception exception, string format, params object [] args) { FilteredLog(logger, LogLevel.Information, exception, format, args); } public static void Warning( this ILogger logger, Exception exception, string format, params object [] args) { FilteredLog(logger, LogLevel.Warning, exception, format, args); } public static void Error( this ILogger logger, Exception exception, string format, params object [] args) { FilteredLog(logger, LogLevel.Error, exception, format, args); } public static void Fatal( this ILogger logger, Exception exception, string format, params object [] args) { FilteredLog(logger, LogLevel.Fatal, exception, format, args); } private static void FilteredLog(ILogger logger, LogLevel level, Exception exception, string format, object [] objects) { if (logger.IsEnabled(level)) { logger.Log(level, exception, format, objects); } } } |
我们可以自己实现基于Log4net的实现Log4NetLogger,基于NLog的实现NLogLogger,均继承ILogger接口,并实现Log方法,由于类似文章众多,本篇不赘述。
三、与Ioc结合的优劣
设置日志框架为全局单例,这样可以减少每次都CreateLogger,提高效率。但有时我们又需要在框架初始化之前就需要日志记录。比如蜗牛历险记(二) Web框架(上)中简述部分的PreApplicationStartMethod,我们需要在框架初始化之前做插件的拷贝初始化工作,这里记录日志,方便我们分析解决框架启动失败等问题。因此我们有必要提供独立于框架之外的日志系统,同时也需要提供为框架使用的IOC环境内的日志系统。我们可以再加一个LoggerFactory,用工厂根据不同条件提供具体的日志实现方式。
四、日志的使用
一个健康的日志应该包含:发生时间、日志级别、日志类别、日志堆栈,日志内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class HomeController:Controller{ public ILogger Logger{ get ; set ;} //日志采用属性注入 private readonly IService _service; public HomeController(IService service){ _service=service; } public ActionResult Index(){ var val=_service.DoSomeBusiness(); Logger.Information( null , "记录日志,开始业务。结果是:" +val); // return View(val); } } |
五、总结
日志框架是必不可少的,如何规范日志记录,方便查询排查,也需要在框架之外做更多工作。
作者:散漫的小蜗牛
出处:http://www.cnblogs.com/leafly
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题,可以邮件:UpdateServer@163.com 非常感谢。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步