log4net菜鸟指南二----生成access和txt

前言

有可能目标计算机缺少某些组件,导致无法生成access文件,或者打不开文件,这时txt文件就可以方便的使用了

 

一,标准的控制台程序输出日志到access

<?xml version="1.0" encoding="utf-8" ?>
<log4net xmlns="urn:log4net">
  <root xmlns="">
    <level value="ALL" />
    <appender-ref ref="AdoNetAppender_Access" />
  </root>
  <appender  xmlns="" name="AdoNetAppender_Access" type="log4net.Appender.AdoNetAppender">
    <connectionString value="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=log\log.mdb" />
    <commandText value="INSERT INTO Table1([LogDate],[Thread],[logLevel],[Logger],[Message]) VALUES(@logDate, @thread, @logLevel,@logger,@message)" />

    <!--BufferSize为缓冲区大小,只有日志记录超10条才会一块写入到数据库-->
    <bufferSize value="10"/>
    <!--定义各个参数-->
    <parameter>
      <parameterName value="@logDate" />
      <dbType value="String" />
      <size value="240" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@thread"/>
      <dbType value="String" />
      <size value="240" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%thread" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@logLevel" />
      <dbType value="String" />
      <size value="240" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%level" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@logger" />
      <dbType value="String" />
      <size value="240" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%logger" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@message" />
      <dbType value="String" />
      <size value="240" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message" />
      </layout>
    </parameter>
  </appender>
</log4net>
Access.config

 

 

注意:(1)文件属性设置为:如果较新则复制

         (2)connectionString设置里面的文件路径。绝对路径

         (3)在AssemblyInfo.cs文件里添加

                 [assembly: log4net.Config.XmlConfigurator(ConfigFile = "Access.config", Watch = true)]

        (4)在ConnectionString里面对应的路径中,创建log4net.mdb数据库,并创建表

CREATE TABLE [LogDetails] (
    ID   AutoIncrement,
    [logDate] longText,
    [Thread] longText,
    [logLevel] longText,
    [Logger] longText,
    [Message] longText,
    Primary  Key  (ID)
)

 

(5)添加代码 

log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
            Random random = new Random();
            for (int i = 0; i < 2; i++)
            {
                //记录错误日志 
                if (log.IsErrorEnabled)
                    log.Debug("你引起了一个错误,错误ID为:" + random.Next().ToString());

                //记录严重错误  
                if (log.IsFatalEnabled)
                    log.Fatal("你引发了一个终结者错误,可能导致系统终止,ID为:" + random.Next().ToString());
                //记录一般信息 
                if (log.IsInfoEnabled)
                    log.Info("你计划记录一个信息,id为:" + random.Next().ToString());
                //记录调试信息  
                if (log.IsDebugEnabled)
                    log.Debug("调试信息,调试ID为:" + random.Next().ToString());
                //记录警告信息 
                if (log.IsWarnEnabled)
                {
                    log.Warn("警告:警告ID为:" + random.Next().ToString());
                }
            }
main

 

注意:在64位的Windows7系统调试时,如果office是32位将你的应用程序将原有的AnyCPU更改为CPU x86.

        如果是64位,安装64位的Jet40驱动

       否则会报错:未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序。

  其它数据库,基本和Access类似,只是在连接字符串和,插入部分有所不同。 

 

二、通过代码控制

1、引入log4net.dll

2、添加配置文件 myLog4net.config

<?xml version="1.0"?>
<configuration>

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  
  <log4net>
    <appender name="AllRollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Log\"/>
      <!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
        <param name= "RollingStyle" value= "Composite"/>
      <!--按日期产生文件夹和文件名[在日期方式与混合方式下使用]-->
      <param name= "DatePattern" value= "yyyy-MM-dd\\yyyy-MM-dd&quot;log.txt&quot;"/>
      <!--是否追加到文件-->
      <param name= "AppendToFile" value= "false"/>
      <!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
      <param name= "MaxSizeRollBackups" value= "1"/>
      <!--是否只写到一个文件中-->
      <param name= "StaticLogFileName" value= "false"/>
      <!--每个文件的大小。只在混合方式与文件大小方式下使用。
      超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。
      可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志-->
        <param name= "maximumFileSize" value="50MB"/> 
           
      <layout type="logDemo.ReflectionLayout">
        <param name="ConversionPattern" value="[%-5level] [%date] [%property{Function}:%property{Line}] message:%property{Message} %newline" />
      </layout>
      
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="Debug" />
        <param name="LevelMax" value="Fatal" />
      </filter>  
    </appender>
    
    <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <mapping>
        <level value="ERROR" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
      <mapping>
        <level value="Info" />
        <foreColor value="Green" />
      </mapping>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="Info" />
        <param name="LevelMax" value="Fatal" />
      </filter>
      <filter type="log4net.Filter.DenyAllFilter" />
    </appender>

      <!--定义输出到数据库中,这里举例输出到Access数据库中,数据库为C盘的log4net.mdb-->
    <appender name="AdoNetAppender_Access" type="log4net.Appender.AdoNetAppender">
      <!--连接数据库字符串-->
      <connectionString value="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=access\\Log.mdb" />
      <!--插入到表Log-->
      <commandText value="INSERT INTO LogDetails (
                 LogDate,
         Thread,
         LogLevel,
                 File,
                 Function,
                 Line,
         Message,
                 MainModule,
                 SubModule,
               CustomModule1,
                 CustomModule2)
           VALUES (
                         @logDate,
                 @thread,
                 @logLevel,
                         @file,
                         @function,
                         @line,
                 @message,
                         @mainModule,
                         @subModule,
                       @customModule1,
                         @customModule2)" />
      <!--BufferSize为缓冲区大小,只有日志记录超设定值才会一块写入到数据库-->
      <bufferSize value="1" />
      <!--定义各个参数-->
      <parameter>
        <parameterName value="@logDate" />
        <dbType value="String" />
        <size value="32" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%date" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="16" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logLevel" />
        <dbType value="String" />
        <size value="8" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@file" />
        <dbType value="String" />
        <size value="128" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{File}" />
        </layout>
      </parameter>
        <parameter>
        <parameterName value="@function" />
        <dbType value="String" />
        <size value="128" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{Function}" />
        </layout>
      </parameter>
        <parameter>
        <parameterName value="@line" />
        <dbType value="String" />
        <size value="8" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{Line}" />
        </layout>
      </parameter>       
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="255" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{Message}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@mainModule" />
        <dbType value="String" />
        <size value="32" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{MainModule}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@subModule" />
        <dbType value="String" />
        <size value="32" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{SubModule}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@customModule1" />
        <dbType value="String" />
        <size value="255" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{CustomModule1}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@customModule2" />
        <dbType value="String" />
        <size value="32" />
        <layout type="logDemo.ReflectionLayout">
          <conversionPattern value="%property{CustomModule2}" />
        </layout>
      </parameter>

      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="Debug" />
        <param name="LevelMax" value="Fatal" />
        <filter type="log4net.Filter.DenyAllFilter" />
      </filter>
    </appender>

    <root>
      <level value="all" />
      <appender-ref ref="ColoredConsoleAppender"/>
      <appender-ref ref="AllRollingLogFileAppender"/>
        <appender-ref ref="AdoNetAppender_Access"/>
    </root>
  </log4net>
  
</configuration>

 

 3、代码引用

①通过重写布局Layout输出传入的 message对象的属性    ReflectionLayout.cs

using log4net.Layout;
using log4net.Layout.Pattern;
using System.Reflection;

namespace logDemo
{
    // 通过重写布局Layout输出传入的 message对象的属性
    // 通过继承log4net.Layout.PatternLayout类,使用log4net.Core.LoggingEvent类的方法得到了要输出的message类的名称,然后通过反射得到各个属性的值,使用PatternLayout类AddConverter方法传入得到的值。
    public class ReflectionLayout : PatternLayout
    {
        public ReflectionLayout()
        {
            this.AddConverter("property", typeof(ReflectionPatternConverter));
        }

        public ReflectionLayout(string pattern)
            : this()
        {
            base.ConversionPattern = pattern;
        }
    }
    
    public class ReflectionPatternConverter : PatternLayoutConverter
    {
        protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent)
        {
            if (Option != null)
            {
                // 写入指定键的值
                WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent));
            }
            else
            {
                // 写入所有关键值对
                WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties());
            }
        }

        /// <summary>
        /// 通过反射获取传入的日志对象的某个属性的值
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        private object LookupProperty(string property, log4net.Core.LoggingEvent loggingEvent)
        {
            object propertyValue = string.Empty;
            PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);
            if (propertyInfo != null)
            {
                propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);

            }
            return propertyValue;
        }
    }    
}

 

②自定义输出多列的类   LogModule.cs

namespace logDemo
{
    public class LogModule
    {
        /// <summary>
        /// 无参构造函数
        /// </summary>
        public LogModule()
        { }

        /// <summary>
        /// logModule构造方法
        /// </summary>
        /// <param name="dutModule"></param>
        /// <param name="message"></param>
        /// <param name="mainModule"></param>
        /// <param name="subModule"></param>
        /// <param name="customModule1"></param>
        /// <param name="customModule2"></param>
        /// <param name="file"></param>
        /// <param name="function"></param>
        /// <param name="line"></param>
        public LogModule(string mainModule = "",
                        string subModule = "",
                        string customModule1 = "",
                        string customModule2 = "",
                        string file = "",
                        string function = "",
                        string line = "",
                        string message = "")
        {
            this.MainModule = mainModule;
            this.SubModule = subModule;
            this.CustomModule1 = customModule1;
            this.CustomModule2 = customModule2;
            this.File = file;
            this.Function = function;
            this.Line = line;
            this.Message = message;
        }

        private string mainModule = "";
        /// <summary>
        /// 场景模块信息
        /// </summary>
        public string MainModule
        {
            get { return mainModule; }
            set { mainModule = value; }
        }

        private string subModule = "";
        /// <summary>
        /// 子场景模块
        /// </summary>
        public string SubModule
        {
            get { return subModule; }
            set { subModule = value; }
        }

        private string customModule1 = "";
        /// <summary>
        /// 自定义1模块
        /// </summary>
        public string CustomModule1
        {
            get { return customModule1; }
            set { customModule1 = value; }
        }

        private string customModule2 = "";
        /// <summary>
        /// 自定义2模块
        /// </summary>
        public string CustomModule2
        {
            get { return customModule2; }
            set { customModule2 = value; }
        }

        private string file = "";
        /// <summary>
        /// 文件名(类名)
        /// </summary>
        public string File
        {
            get { return file; }
            set { file = value; }
        }

        private string function = "";
        /// <summary>
        /// 方法名
        /// </summary>
        public string Function
        {
            get { return function; }
            set { function = value; }
        }

        private string line = "";
        /// <summary>
        /// 行号
        /// </summary>
        public string Line
        {
            get { return line; }
            set { line = value; }
        }

        private string message = "";
        /// <summary>
        /// 信息,主要收集需要收集的log信息(log内容)
        /// </summary>
        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }
}

 

③添加类  LogHelper.cs

using System;
using log4net;
using System.IO;
using log4net.Core;

namespace logDemo
{
    public class LogHelper
    {
        //如果定义了<logger>节点,则这里传入logger的name的值
        log4net.ILog log = log4net.LogManager.GetLogger("logName");

        protected log4net.ILog Log
        {
            get { return log; }
            set { log = value; }
        }

        LogModule module;
        /// <summary>
        /// 带入log模块信息
        /// </summary>
        /// <param name="module"></param>
        public LogHelper(LogModule module)
        {
            this.module = module;
        }    

        /// <summary>
        /// 打印log发送到log4ent
        /// </summary>
        /// <param name="level">等级</param>
        /// <param name="msg">log信息</param>
        public void Print(Levels level, String msg)
        {         
            module.Message = msg;
            module.File = new System.Diagnostics.StackTrace(true).GetFrame(1).GetFileName();
            module.Function = new System.Diagnostics.StackTrace(true).GetFrame(1).GetMethod().ToString();
            module.Line = new System.Diagnostics.StackTrace(true).GetFrame(1).GetFileLineNumber().ToString();
            
            Print(level, module);
        }

        /// <summary>
        /// log信息发送到log4net进行打印
        /// </summary>
        /// <param name="level">等级</param>
        /// <param name="module">log模块</param>
        private void Print(Levels level, LogModule module)
        {
            if (module == null)
                return;

            if (level.Equals(Levels.FATAL))
                Log.Fatal(module);

            if (level.Equals(Levels.ERROR))
                Log.Error(module);

            if (level.Equals(Levels.DEBUG))
                Log.Debug(module);

            if (level.Equals(Levels.WARN))
                Log.Warn(module);

            if (level.Equals(Levels.INFO))
                Log.Info(module);
        }
    }

    /// <summary>
    /// 自定义log等级
    /// </summary>
    public enum Levels
    {
        OFF = 0,
        FATAL,
        ERROR,
        WARN,
        INFO,
        DEBUG
    }
}

 

④用自定义的列输出日志

using System;
using System.Windows.Forms;
using System.IO;
using ADOX;

namespace logDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {          
            //如果没有数据库则创建一个
            CreateAcces(Path.Combine(Application.StartupPath, "access"));

            //监听配置文件的变化
            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(Path.Combine(Application.StartupPath, "myLog4net.config")));
        }

        public static LogHelper newlog;
        private void button1_Click(object sender, EventArgs e)
        {
            LogModule module1 = new LogModule("main信息", "sub信息", "自定义1", "自定义2");
            newlog = new LogHelper(module1);
            newlog.Print(Levels.FATAL, "fatal级别的message");

            LogModule module2 = new LogModule();
            module2.MainModule = "mianModule";
            module2.SubModule = "SubModule";
            module2.CustomModule1 = "CustomModule1";
            newlog = new LogHelper(module2);
            newlog.Print(Levels.DEBUG, "debug级别的message");
        }

        /// <summary>
        /// access操作类
        /// </summary>
        /// <param name="accessDirectoryPath"></param>
        public static void CreateAcces(string accessDirectoryPath)
        {
            // 目录不存在 则创建目录
            string temppath = accessDirectoryPath;
            if (!Directory.Exists(temppath))
            {
                Directory.CreateDirectory(temppath);
            }

            string mdbPath = Path.Combine(accessDirectoryPath, "Log.mdb");
            if (File.Exists(mdbPath)) //检查数据库是否已存在   
            {
                return;
            }

            // 数据库不存在 则创建数据库  (可以加上密码,这样创建后的数据库必须输入密码后才能打开)
            mdbPath = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + mdbPath;

            // 创建一个CatalogClass对象的实例,   
            ADOX.CatalogClass cat = new ADOX.CatalogClass();

            // 使用CatalogClass对象的Create方法创建ACCESS数据库
            cat.Create(mdbPath);

            // 连接数据库
            ADODB.Connection conn = new ADODB.Connection();
            conn.Open(mdbPath, null, null, -1);

            cat.ActiveConnection = conn;

            // 创建一个自动增长的主键列
            Column col = new Column();
            col.ParentCatalog = cat;
            col.Type = DataTypeEnum.adInteger;
            col.Name = "ID";
            col.DefinedSize = 9;
            col.Properties["AutoIncrement"].Value = true;

            // 创建表
            Table table = new Table();
            table.Name = "LogDetails";

            table.Columns.Append(col, DataTypeEnum.adInteger, 9);
            table.Keys.Append("FirstPrimaryKey", KeyTypeEnum.adKeyPrimary, col, null, null);

            // 表中添加自定义列
            table.Columns.Append("LogDate", DataTypeEnum.adVarWChar, 32);
            table.Columns.Append("Thread", DataTypeEnum.adVarWChar, 16);
            table.Columns.Append("LogLevel", DataTypeEnum.adVarWChar, 8);
            table.Columns.Append("File", DataTypeEnum.adVarWChar, 128);
            table.Columns.Append("Function", DataTypeEnum.adVarWChar, 128);
            table.Columns.Append("Line", DataTypeEnum.adVarWChar, 8);
            
            table.Columns.Append("Message", DataTypeEnum.adVarWChar, 255);
            table.Columns.Append("MainModule", DataTypeEnum.adVarWChar, 32);
            table.Columns.Append("SubModule", DataTypeEnum.adVarWChar, 32);
            table.Columns.Append("CustomModule1", DataTypeEnum.adVarWChar, 255);
            table.Columns.Append("CustomModule2", DataTypeEnum.adVarWChar, 32);

            cat.Tables.Append(table);

            //创建数据库后关闭连接
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cat.ActiveConnection);
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cat);
        }         
    }
}

 

⑤输出结果,以txt和access两种形式保存

Debug\Log\2018-07-05\2018-07-05log.txt

Debug\access\log.mdb

 

 

参考

[1]log4net示例2-日志输入存入Access

[2]非常完善的Log4net详细说明

posted @ 2018-06-29 17:08  quanzhan  阅读(313)  评论(0编辑  收藏  举报