阅读目录

 

不管是Web应用程序还是WinForm应用程序,Visual Studio所带的调试功能都是足够强大,足以应付开发中的各种调试需求。但是,对于已经发布的应用,要记录错误、记载运行中的各种状态信息,就需要依靠日志系统了。

日志系统应具备的特性

一个好的日志系统,应该具备以下的特性:

1、运行稳定。因为日志的作用就是要在系统出现各种错误、各种异常的时候输出信息,因此,它必须具有足够的鲁棒性和稳定性,在任何时候都能发挥其功能。

2、适用性广。需要用到日志功能的地方,在程序中可以说无处不在:ASPX页面,WinForm窗体,类文件、ASHX页面、线程……因此,日志系统应当在任何位置都能发挥其功能。

3、分级管理。日志应当可以按照重要性分为不同的级别,如Info、Debug、Warning、Error、Fatal等。用户可以决定输出何种级别的日志。调试时,可以输出尽可能全面的信息,如Info、Debug等级别的信息都可以输出。部署后,仅仅输出Warning以上的级别。

4、输出丰富。可以根据用户的需求,按用户指定的格式输出日志。

Log4Net

上述的特征,其实就是Log4Net的特点。它来源于Java平台中著名的日志组件log4j,是一个非常成熟的日志系统。它的版本更新极慢,但即使是从在.Net 1.0下发布的版本,在后面的.Net版本中都能工作正常!

由于Log4Net是开源的,所以,可以对它进行各种各样的定制修改。官方网站地址是http://logging.apache.org/log4net/

介绍Log4Net的文章较多,因此在此不打算重复这些细节。本着最快实现的目标,争取把达到目标的必须的几个关键点点到即可。

配置文件:log4net.config

log4net的工作原理很简单,在代码中使用log4net的相应方法(从Info到Fatal)输出日志信息,而最终究竟输出到哪里?输出哪些都由log4net.config这个配置文件来控制。因此log4net.config的重要性可谓关键。下面是一个典型的配置文件,其实有它基本就够了!

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net>
<!--错误日志,保存到一个文件Error.log中-->
<appender name="Log" type="log4net.Appender.FileAppender">
<file value="log/log.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%date{yyyy-MM-dd HH:mm:ss}]%message - (%logger)%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="DEBUG" />
<param name="LevelMax" value="FATAL" />
</filter>
</appender> <root>
<level value="ALL" />
<appender-ref ref="Log" />
</root>
</log4net>
</configuration>

初始化

Log4Net作为一个全局的基础设置,因此必须要进行一个初始化。在Web程序和窗体程序中有所不同。

1、在WinForm应用程序中,需要显示调用以下语句:

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(System.Windows.Forms.Application.StartupPath + "\\log4net.config"));

2、Web应用程序,也可以通过调用初始化语句完成:

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(System.Web.HttpContext.Current.Server.MapPath("~")+"\\log4net.config"));

但是,由于Web应用程序不像WinForm应用程序那样有明确的入口点,所以Web程序的初始化往往在global.ascx中的Application_Start中添加设置,如下所示:

void Application_Start(object sender, EventArgs e)
{
// 在应用程序启动时运行的代码
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(Server.MapPath("~")+"\\log4net.config"));
}
所以,对Web程序,只要添加global.ascx,在Application_Start中添加代码即可。

输出信息

Log4Net输出信息的主要方法就是Debug()、Error()等方法,关键点在于获取Logger对象。有多种方法可以获取Logger对象,经过实验,使用下面的方法可以适用于普通类和静态类的输出:

 log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Info("ColumnClick"); 

在WinForm中进行简单的测试:

private void button1_Click(object sender, EventArgs e)
{
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Debug("普通类中的信息");
SClass.StaticFunc();
for (int i = 0; i < 5; i++)
{
(new Thread(test)).Start();
}
}
void test()
{
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Debug("线程中:"+Thread.CurrentThread.ManagedThreadId.ToString());
}

其中SClass中的StaticFunc是一个简单静态方法,其中有日志信息输出。最后的日志如下:

而在Web应用程序中,也可以进行类似的测试,证明适应性还是不错的。

对Log4Net的封装

经过各种测试,终于找到一些通用性强的方法,为防止以后每次都得回来复制粘贴,还是把它封装一下比较好,在CommonCode中,用Logger封装了日志的相关功能,如下:

public class Logger
{
public static void Init(string ConfigFile)
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(ConfigFile));
}
public static void WinFormInit() //WinForm程序的初始化
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(System.Windows.Forms.Application.StartupPath + "\\log4net.config"));
}
public static void WebInit() //WinForm程序的初始化
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(System.Web.HttpContext.Current.Server.MapPath("~")+"\\log4net.config"));
}
public static void Debug(String info)
{
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Debug(info);
}
public static void Info(String info)
{
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Info(info);
}
public static void Error(String info)
{
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Error(info);
}
public static void Fatal(String info)
{
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Fatal(info);
}
}

Web的调用还得修改Global.ascx,但WinForm中可以通过WinInit进行初始化了。至于输出信息,则可以通过

CommonCode.Logger.Debug(string)

的形式进行输出。

在CommonCode中,Log4Net是一个通用的输出机制,各种应用的日志输出都需要用它,所以,大多数情况下,需要把Log4Net.dll和CommonCode.dll放在一起。

log4net.config复杂配置

Log4net的输出非常强大,以下是我常用的一些配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net>
<!--按日期输出到Log文件中,不记录错误信息-->
<appender name="LogAppender" type="log4net.Appender.RollingFileAppender">
<file value="log/Logs_" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd&quot;.txt&quot;" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%date{HH:mm:ss}]%message - (%logger)%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="DEBUG" />
<param name="LevelMax" value="WARN" />
</filter>
</appender> <!--错误日志,保存到一个文件Error.log中-->
<appender name="ErrorLog" type="log4net.Appender.FileAppender">
<file value="log/Error.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%date{yyyy-MM-dd HH:mm:ss}]%message - (%logger)%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="ERROR" />
<param name="LevelMax" value="FATAL" />
</filter>
</appender> <!--输出到Log2Console,可以实时跟踪查看-->
<appender name="ToLog2Console" type="log4net.Appender.UdpAppender">
<param name="Encoding" value="utf-8" />
<param name="RemoteAddress" value="127.0.0.1" />
<param name="RemotePort" value="8003" />
<layout type="log4net.Layout.XmlLayoutSchemaLog4j" />
</appender> <root>
<level value="ALL" />
<appender-ref ref="LogAppender" />
<appender-ref ref="ErrorLog" />
<appender-ref ref="ToLog2Console" />
</root>
</log4net>
</configuration>

简单说明如下:

  • LogAppender:输出Debug到Warn的信息,存储在log文件下Log_时间戳.txt中,并且会随着文件的增加主动分割
  • ErrorLog:只输出错误信息
  • ToLog2Console:通过UDP向网络发送日志,可以同Log2Console等来接收

【5】基于Log4Net的日志系统的更多相关文章

  1. ELK+FileBeat+Log4Net搭建日志系统

    ELK+FileBeat+Log4Net搭建日志系统 来源:https://www.zybuluo.com/muyanfeixiang/note/608470 标签(空格分隔): ELK Log4Ne ...

  2. 基于log4net的日志组件扩展封装,实现自动记录交互日志 XYH.Log4Net.Extend(微服务监控)

    背景: 随着公司的项目不断的完善,功能越来越复杂,服务也越来越多(微服务),公司迫切需要对整个系统的每一个程序的运行情况进行监控,并且能够实现对自动记录不同服务间的程序调用的交互日志,以及通一个服务或 ...

  3. .NET基于Eleasticsearch搭建日志系统实战演练

    一.需求背景介绍 1.1.需求描述 大家都知道C/S架构模式的客户端应用程序(比如:WinForm桌面应用.WPF.移动App应用程序.控制台应用程序.Windows服务等等)的日志记录都存储在本地客 ...

  4. 基于Log4Net本地日志服务简单实现

    背景 项目开发中,我们或多或少会使用诸如NLog,Log4Net,Kafka+ELK等等日志套件: 基于关注点分离原则,业务开发的时候不应该关注日志具体实现:并且后续能方便切换其他日志套件: 这里先实 ...

  5. 【新阁教育】基于Log4Net实现日志信息双向存储(含源码)

    1.引言 在上位机开发中,日志记录是必不可少的,我们可以通过日志记录做日志分析及错误追踪.初学者会采用txt文本写入来实现日志保存,但是文本写入不是线程安全,当存在多个线程同时写入日志时,就会出现一些 ...

  6. 磨刀不误砍柴工——统一日志系统 Log4Net/ExceptionLess

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫必须注明原文地址:www.cnblogs.com/tdws . 一.   写在前面 本文Log4Net介绍了基础的方式,大数据量生产环境不能使用,中等 ...

  7. 统一日志系统 Log4Net/ExceptionLess

    一.   写在前面 本文Log4Net介绍了基础的方式,大数据量生产环境不能使用,中等日志量请日志单库. 希望爱技术的你不要错过exceptionless和ELK 第四节开始简单配置大牛们推荐的了Ex ...

  8. [开源]基于Log4Net简单实现KafkaAppender

    背景 基于之前基于Log4Net本地日志服务简单实现 实现本地日志服务,但是随着项目开发演进,本地日志服务满足不了需求,譬如在预发布环境或者生产环境,不可能让开发人员登录查看本地日志文件分析. Kaf ...

  9. nxlog4go 简介 - 基于log4go的下一代go语言日志系统

    nxlog4go的项目网址: https://github.com/ccpaging/nxlog4go 项目历史 ccpaging's log4go forked from https://githu ...

随机推荐

  1. pip作用

    介绍 pip 是一个安装和管理 Python 包的工具,python安装包的工具有easy_install, setuptools, pip,distribute.使用这些工具都能下载并安装djang ...

  2. 【BZOJ 2986】 莫比乌斯函数+容斥原理

    2986: Non-Squarefree Numbers Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 337  Solved: 156 Descri ...

  3. 【扩展欧几里得】BZOJ1477-青蛙的约会

    一直在WA,后来我发现我把东西看反了…… [题目大意] 给出一个长度为L的环状坐标轴,两个点开始时位于(X,0).(Y,0).每次两点分别往右边移动m和n,问能否相遇? [思路] 由题意,可得: X+ ...

  4. nginx安装第三方模块

    原已经安装好的nginx,现在需要添加一个未被编译安装的模块 举例说明:安装第三方的ngx_cache_purge模块(用于清除指定URL的缓存) nginx的模块是需要重新编译nginx,而不是像a ...

  5. [HDU6212]Zuma

    题目大意: 祖玛游戏. 给你一个01串,你可以往里面加一些0或1,如果连续的0或1超过3个,那么就可以消去.问消去所有的珠子至少要加几个珠子. 思路: 区间DP. 首先把原来的01串,改成存储连续的同 ...

  6. [HDU5343]MZL's Circle Zhou

    题目大意: 给你两个字符串a和b,从中分别取出子串x和y,求不同的x+y的个数. 思路: 对于每一个字符串,构建SAM. 为了保证相同的x+y不会被重复统计,我们可以想办法只统计相同的x+y中x最长的 ...

  7. Lunix/Mac下根据最后修改时间复制文件和文件夹,保持原有的目录结构

    度娘知道:http://zhidao.baidu.com/link?url=DD47jm6qDgT7yxsnz9e-NC4Fqd33oRoiIwcGLkw5TL4cbf50VKY2IONbHKH0IE ...

  8. 216. 组合总和 III

    216. 组合总和 III 题意 找出所有相加之和为 n 的 k 个数的组合.组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字. 说明: 所有数字都是正整数. 解集不能包含重复的 ...

  9. SmartProg2 Universal, ISP capable programmer

    http://www.elnec.com/products/universal-programmers/smartprog2/ 40 powerful TTL pindrivers provide H ...

  10. 【springboot+easypoi】一行代码搞定excel导入导出

    原文:https://www.jianshu.com/p/5d67fb720ece 开发中经常会遇到excel的处理,导入导出解析等等,java中比较流行的用poi,但是每次都要写大段工具类来搞定这事 ...