蜗牛历险记(二) Web框架(中)
上篇简单介绍了框架所使用的Autofac,采用Autofac提供的Ioc管理整个Web项目中所有对象的生命周期,实现框架面向接口编程。接下来介绍框架的日志系统。
一、介绍之前
框架日志是否有存在的必要性?假如你认为你的框架永远不会出现Bug,或者你能根据错误提示就能还原现场,重现这个问题,那你不需要日志。目前看来这样的项目不存在(Helloworld之类除外)。因此日志框架还是很必要的。
日志框架用于记录:系统运行过程中错误详情;用于记录系统使用过程中产生的意外情况;用于记录系统一些状态信息等等。通过不同分类,不同严重级别的日志信息可以很方便地为我们解决问题、为提高系统能效提供等提供数据支持。
目前.Net方向上成熟的日志框架有Log4net、NLog等,这两个框架各有优劣,具体如何选择要根据个人熟悉程度,以及使用环境来判断。
二、初始化
或许会因为各种原因,我们会在系统投入使用后,替换原有的日志框架。因此,在系统设计之初,我们就应该注意不要让框架本身与日志框架有太大的依赖。所以,我们定义日志的级别和日志的标准接口:
1.日志等级
/// <summary>
/// 日志等级
/// </summary>
public enum LogLevel {
/// <summary>
/// 调试
/// </summary>
Debug,
/// <summary>
/// 信息
/// </summary>
Information,
/// <summary>
/// 警告
/// </summary>
Warning,
/// <summary>
/// 错误
/// </summary>
Error,
/// <summary>
/// 严重错误
/// </summary>
Fatal
}
2.日志基础接口:
/// <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.日志扩展方法:
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,用工厂根据不同条件提供具体的日志实现方式。
四、日志的使用
一个健康的日志应该包含:发生时间、日志级别、日志类别、日志堆栈,日志内容。
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);
}
}
五、总结
日志框架是必不可少的,如何规范日志记录,方便查询排查,也需要在框架之外做更多工作。
蜗牛历险记(二) Web框架(中)的更多相关文章
- 蜗牛历险记(二) Web框架(上)
接上篇所说,本篇主要内容是讲述如何使用Autofac来管理整个平台的生命周期(初级). 一.简述 插件式Web开发的同学应该还会记得PreApplicationStartMethod这个Assembl ...
- 蜗牛历险记(二) Web框架(下)
Web框架第三篇--缓存篇 缓存的优劣很大程度上决定了框架的效率,一个有节操的缓存它应该是高效的,利用率高的,具备更多扩展功能的. 一.介绍之前 计算机各个硬件的运行效率是不一样的,CPU>&g ...
- 在 node.js 的 express web 框架中自动注册路由
该方法主要是动态注册自己写的 router . 注册器 router 文件名为 loader.js . var express = require('express'); var fs = requ ...
- 浅谈python web框架中的orm设计
看了一下廖雪峰的那个web框架,其实就是封装了web.py,请求使用异步并将aiomysql做为MySQL数据库提供了异步IO的驱动,前端部分则整合了jinja.其中最难的应该是orm部分了. 下面是 ...
- Django用户认证系统(二)Web请求中的认证
在每个Web请求中都提供一个 request.user 属性来表示当前用户.如果当前用户未登录,则该属性为AnonymousUser的一个实例,反之,则是一个User实例. 你可以通过is_authe ...
- 关于bottle WEB框架中签名cookie的一点理解
首先要理解一个概念 MAC (message authenticate code) 消息认证码(带密钥的Hash函数):密码学中,通信实体双方使用的一种验证机制,保证消息数据完整性的一种工具. 构造方 ...
- unittest(二)框架中的概念与断言
test case一个 TestCase 的实例就是一个测试用例.什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),实现测试过程的代码(run),以及测试后环境的还原( ...
- Python之Web框架
Python之Web框架: 一. Web框架的本质: 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env pyth ...
- python web框架——扩展Django&tornado
一 Django自定义分页 目的:自定义分页功能,并把它写成模块(注意其中涉及到的python基础知识) models.py文件 # Create your models here. class Us ...
随机推荐
- HDU 4259 - Double Dealing(求循环节)
首先将扑克牌进行一次置换,然后分解出所有的循环节,所有循环节的扑克牌个数的最小公倍数即为答案 #include <stdio.h> #include <string.h> #i ...
- Hibernate初级
文章来源: http://blog.csdn.net/jiuqiyuliang/article/details/39078749/ 持久化(Persistence),把数据(如内存中的对象)保存到可永 ...
- GitHub 建立远程仓库
终端所有信息: Last login: Fri Aug 14 08:58:01 on console wuxiaoyuan:~ lan$ ls -al ~/.ssh ls: /Users/lan/.s ...
- 巧用Red Gate SQL Compare破解加密了的存储过程和函数
最近项目中遇到了一个遗留系统的存储过程和函数被加密了,网上找了半天,解决办法倒是有,但需要写一大堆脚本, 怕影响原系统的运行,就说先同步到其他服务器上去破解.没想到,打开Sql Compare一比 ...
- Tomcat启动报错 Failed to start component [StandardServer[8005]]解决
SEVERE: The required Server component failed to start so Tomcat is unable to start. org.apache.catal ...
- 局域网内sqldeveloper客户端连接oracle服务器
1:输入参数 输入连接名(随便写) 用户名:system/tiger/sys或者是创建的用户 口令:设置的口令 主机名:连接的数据库所在的ip 端口:默认是1521 sid:orcl安装时自己设置的 ...
- java集合总结
java中集合是很重要的一点,巩固这边学习的知识,把知识理一下 按马士兵的视频,总结的也很好,集合就是一个“1136” 1个图,1个类Collections,3个知识点:增强for循环,泛型,打包和解 ...
- Lodop实现web套打
WEB套打可选方案不多,理想的更少,利用免费控件Lodop+JavaScript实现精确套打,算是较为经典的选择.这种方案其实比较简单,利用一个htm文件就可以实现模板设计过程,几乎是“空手套”式的开 ...
- Android进阶——声波振幅显示
最近博主想做一个app,中间有一个是录音的功能.于是博主想把UI做的好看一些,想仿照微信或者QQ语音输入时,能够随着声音的大小显示声波振幅.于是查找了一些资料,现在把这个功能的Demo分享给大家,以后 ...
- cl: cannot open file 'kernel32.lib'
在测试 jni时, 使用 cl命令, 如 cl -I xx\jdk1.7.0_17\include -I xx\jdk1.7.0_17\include\win32 -LD HelloNative.c ...