蜗牛历险记(二) 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);
    }
}

五、总结

日志框架是必不可少的,如何规范日志记录,方便查询排查,也需要在框架之外做更多工作。

时间: 2024-10-13 08:53:14

蜗牛历险记(二) Web框架(中)的相关文章

蜗牛历险记(二) Web框架(上)

接上篇所说,本篇主要内容是讲述如何使用Autofac来管理整个平台的生命周期(初级). 一.简述 插件式Web开发的同学应该还会记得PreApplicationStartMethod这个Assembly级别的Attribute,它可以在应用程序启动之初(Web启动之前)启动,一般我们用它来做一些插件资源拷贝.插件动态加载的工作. [assembly: PreApplicationStartMethod(typeof(PreApplicationInit), "InitializePlugins&

蜗牛历险记(二) Web框架(下)

Web框架第三篇--缓存篇 缓存的优劣很大程度上决定了框架的效率,一个有节操的缓存它应该是高效的,利用率高的,具备更多扩展功能的. 一.介绍之前 计算机各个硬件的运行效率是不一样的,CPU>>一级缓存>>二级缓存>>内存>>硬盘.如何提供CPU.一级缓存.二级缓存的使用率是操作系统的课题.我们需要做的就是如何提高内存使用效率,减少磁盘IO. 目前我们熟知的跟缓存有关的产品:.Net Mvc的CacheManager,Redis,Memcached 二.使用范

浅谈python web框架中的orm设计

看了一下廖雪峰的那个web框架,其实就是封装了web.py,请求使用异步并将aiomysql做为MySQL数据库提供了异步IO的驱动,前端部分则整合了jinja.其中最难的应该是orm部分了. 下面是orm一个简单的例子. class User(Model): __table__ = 'users' id = StringField(primary_key=True, default=next_id, ddl='varchar(50)') email = StringField(ddl='var

MVC在Web框架中的应用

MVC三个主要部分的定义大致如下: 模型:模型是描述程序设计人员感兴趣问题域的一些类,这些类通常封装存储在数据库中的数据,以及操作这些数据和执行特定域业务逻辑的代码. 在ASP.NET MVC中,模型就像使用了某种工具的数据访问层(Data Access Layer),这种工具包括实体框架(Entity Framework)或者包含 特定域逻辑的自定义代码组合在一起的NHibernate. 视图:一个动态生成HTML页面的模板 控制器:一个协调视图和模型之间关系的特殊类.它响应用户输入,与模型进

在 node.js 的 express web 框架中自动注册路由

该方法主要是动态注册自己写的 router . 注册器 router 文件名为 loader.js  . var express = require('express'); var fs = require('fs'); var router = express.Router(); var files = fs.readdirSync(__dirname); files .filter(function(file, index){ return file !== 'loader.js'; })

Django用户认证系统(二)Web请求中的认证

在每个Web请求中都提供一个 request.user 属性来表示当前用户.如果当前用户未登录,则该属性为AnonymousUser的一个实例,反之,则是一个User实例. 你可以通过is_authenticated()来区分,例如: if request.user.is_authenticated(): # Do something for authenticated users. else: # Do something for anonymous users. 登陆login login(

200行自定义异步非阻塞Web框架

Python的Web框架中Tornado以异步非阻塞而闻名.本篇将使用200行代码完成一个微型异步非阻塞Web框架:Snow. 一.源码 本文基于非阻塞的Socket以及IO多路复用从而实现异步非阻塞的Web框架,其中便是众多异步非阻塞Web框架内部原理. #!/usr/bin/env python # -*- coding:utf-8 -*- import re import socket import select import time class HttpResponse(object)

Python之Web框架Django

Python之Web框架: Django 一.  Web框架的本质: 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 1 #!/usr/bin/env python 2 #coding:utf-8 3 4 #web框架的基础结构,几乎所有开发者都是基于此基础结果进行扩展. 5 6 import socket 7 8 def handle_request(client): 9 buf = client.recv(1024) 10 clien

Tornado----自定义异步非阻塞Web框架:Snow

Python的Web框架中Tornado以异步非阻塞而闻名.本篇将使用200行代码完成一个微型异步非阻塞Web框架:Snow. 一.源码 本文基于非阻塞的Socket以及IO多路复用从而实现异步非阻塞的Web框架,其中便是众多异步非阻塞Web框架内部原理. 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 import socket 5 import select 6 import time 7 8 9 class Ht