Log4net记录日志到本地或数据库

OperatorLog

/****** Object:  Table [dbo].[OperatorLog]    Script Date: 
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[OperatorLog](
    [Id] [BIGINT] IDENTITY(1,1) NOT NULL,
    [Createdate] [DATETIME] NOT NULL DEFAULT (GETDATE()),
    [CreatedBy] [NVARCHAR](50) NULL,
    [IsDeleted] [BIT] NOT NULL,
    [ModuleName] [NVARCHAR](30) NULL,
    [Origin] [NVARCHAR](50) NULL,
    [Type] [NVARCHAR](50) NULL,
    [LogLevel] [NVARCHAR](20) NOT NULL,
    [LogMessage] [NVARCHAR](500) NULL,
    [Exception] [NVARCHAR](500) NULL,    
    [Logger] [NVARCHAR](500) NULL
 CONSTRAINT [PK_OperatorLog] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志表主键ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Id'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Createdate'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建人' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'CreatedBy'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否删除' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'IsDeleted'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'模块名称' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'ModuleName'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'来源' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Origin'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'类型' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Type'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志级别' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'LogLevel'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志内容' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'LogMessage'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'异常信息' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Exception'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志名称' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Logger'
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志记录' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog'
GO

loghelper:

using System;
using System.ComponentModel;
using System.IO;
using log4net;
using ShiShuo.Utilities;

namespace Log4Net
{
    public enum LogCategory
    {
        [Description("调试")]
        Debug,
        [Description("信息")]
        Info,
        [Description("警告")]
        Warn,
        [Description("错误")]
        Error,
        [Description("过错")]
        Fault
    }
    public class LogHelper
    {
        private static readonly log4net.ILog infoLogger = log4net.LogManager.GetLogger("loginfo");     //选择<logger name="loginfo">的配置 
        private static readonly log4net.ILog errorLogger = log4net.LogManager.GetLogger("logerror");   //选择<logger name="logerror">的配置 
        private static readonly log4net.ILog warnLogger = log4net.LogManager.GetLogger("logwarn");     //选择<logger name="logwarn">的配置 
        private static readonly log4net.ILog debugLogger = log4net.LogManager.GetLogger("logdebug");   //选择<logger name="logdebug">的配置 
        private static OperatorLogModel logEntity;
        public static string CreatedBy = String.Empty;
        
        static LogHelper()
        {
            string configPath = Path.Combine(PathHelper.ConfigDir, "log4net.xml");
            if (!File.Exists(configPath))
            {
                throw new FileNotFoundException("找不到日志服务配置文件!");
            }
            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(configPath));
        }

        /// <summary>
        /// 记录log信息到文件中  LogHelper.Log("检测更新启动时异常", LogCategory.Error, ex);    LogHelper.Log(ex);
        /// </summary>
        /// <param name="message">需要记录的信息</param>
        /// <param name="category">log类型</param>
        /// <param name="exception">异常信息</param>
        public static void Log(string message, LogCategory category, Exception exception = null)
        {
            try
            {
                switch (category)
                {
                    case LogCategory.Debug:
                        {
                           
                            debugLogger.Debug(BuildMessageMode(message));
                            break;
                        }
                    case LogCategory.Info:
                        {
                            infoLogger.Info(BuildMessageMode(message));
                            break;
                        }
                    case LogCategory.Warn:
                        {
                            if (null == exception)
                            {
                                warnLogger.Warn(BuildMessageMode(message));
                            }
                            else
                            {
                                warnLogger.Warn(BuildMessageMode(message), exception);
                            }
                            break;
                        }
                    case LogCategory.Error:
                        {
                            if (null == exception)
                            {
                                errorLogger.Error(BuildMessageMode(message));
                            }
                            else
                            {
                                errorLogger.Error(BuildMessageMode(message), exception);
                            }
                            break;
                        }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        /// <summary>
        /// 构造消息实体
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        private static OperatorLogModel BuildMessageMode(string message) {
            if (logEntity == null) {
                logEntity = new OperatorLogModel();
                logEntity.Createdate = DateTime.Now;
                logEntity.CreatedBy = CreatedBy;
                logEntity.IsDeleted = false;
                logEntity.LogMessage = message;
            }
            else
                logEntity.LogMessage = message;

            return logEntity;
        }

        /// <summary>
        /// 写基本信息日志
        /// </summary>
        /// <param name="mesage"></param>
        public static void Log(string mesage)
        {
            Log(mesage, LogCategory.Info, null);
        }

        /// <summary>
        /// 出错信息日志
        /// </summary>
        /// <param name="exception"></param>
        public static void Log(Exception exception)
        {
            Log($"error message:{exception.Message}", LogCategory.Error, exception);
        }

    }
}

pathhelper:

using System;
using System.IO;
using System.Reflection;

namespace ShiShuo.Utilities
{
    public static class PathHelper
    {
        private static readonly string _appDir;
        private static readonly string _configDir;
        private static readonly string _dataDir;
        static PathHelper()
        {
            //网站与后台服务路径不同,网站需要上翻一级;后台服务则不需要;通过判断使用的配置文件是否是web.config来判断是网站,还是服务。
            bool isWeb = false;
            var appDomain = AppDomain.CurrentDomain;

            if (appDomain != null)
            {
                var startInfo = appDomain.SetupInformation;
                if (startInfo != null)
                {
                    if (startInfo.ConfigurationFile != null)
                    {
                        if (startInfo.ConfigurationFile.EndsWith("web.config", StringComparison.OrdinalIgnoreCase))
                        {
                            isWeb = true;   //配置文件是网站
                        }
                    }
                }
            }
            _appDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Substring(8))); //获取此处配置文件在程序目录
            //_appDir = _appDir.Substring(0, _appDir.Length - 4);

            if (isWeb)
            {
                _appDir = _appDir.Substring(0, _appDir.LastIndexOf("\", StringComparison.Ordinal));  // LastIndexOf("\") => LastIndexOf(@""),向上翻一级
            }
            _configDir = Path.Combine(_appDir, "Config\");
            _dataDir = Path.Combine(_appDir, "App_Data\");
        }
        #region 公共目录
        /// <summary>
        /// 应用程序所在的目录
        /// </summary>
        public static string AppDir => _appDir;

        /// <summary>
        /// 根目录中的Cinfig文件夹
        /// </summary>
        public static string ConfigDir => _configDir;

        /// <summary>
        /// 根目录中的App_Data文件夹
        /// </summary>
        public static string DataDir => _dataDir;

        #endregion
    }
}

MyLayout:

using log4net.Layout;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Log4Net {
    public class MyLayout : PatternLayout {
        public MyLayout() {
            this.AddConverter("property", typeof(MyPatternConverter));
        }
    }
}

MyPatternConverter:

using log4net.Layout.Pattern;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;

namespace Log4Net {
    public class MyPatternConverter : 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());
        }

        //通过反射获取传入的日志对象的某个属性的值
        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;
        }
    }
}

log4net.xml

<?xml version="1.0" encoding="utf-8"?>
<log4net debug="false">

  <!--错误日志配置-->
  <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="./Log/Error/" />
    <param name="Encoding" value="utf-8"/>
    <param name="AppendToFile" value="true" />
    <param name="MaxSizeRollBackups" value="100" />
    <param name="MaxFileSize" value="10240" />
    <!--设置单个文件大小,设置文件名使用组合方式-->
    <param name="MaximumFileSize" value="100MB"/>
    <!--最小锁定模型以允许多个进程可以写入同一个文件-->
    <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />
    <param name="StaticLogFileName" value="false" />
    <param name="DatePattern" value="&quot;&quot;yyyyMMdd&quot;.log&quot;" />
    <param name="RollingStyle" value="Composite" />
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="ERROR" />
      <levelMax value="FATAL" />
    </filter>
    <!--<layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%n异常时间:%d [%t] %n异常级别:%-5p %n异 常 类:%c [%x] %n%m %n " />
    </layout>-->
    <layout type="Log4Net.MyLayout">
      <param name="ConversionPattern" value="日志时间:%d [%t] %n日志级别:%-5p %n日志信息:%property{LogMessage} %n异常信息:%exception %n%n"/>
    </layout>
  </appender>

  <!--信息日志配置-->
  <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="./Log/Info/" />
    <param name="Encoding" value="utf-8"/>
    <param name="AppendToFile" value="true" />
    <param name="MaxSizeRollBackups" value="100" />
    <param name="MaxFileSize" value="10240" />
    <param name="MaximumFileSize" value="100MB"/>
    <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />
    <param name="MaxSizeRollBackups" value="100" />
    <param name="StaticLogFileName" value="false" />
    <param name="DatePattern" value="&quot;&quot;yyyyMMdd&quot;.log&quot;" />
    <param name="RollingStyle" value="Composite" />
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="DEBUG" />
      <levelMax value="WARN" />
    </filter>
    <!--<layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%n异常时间:%d [%t] %n异常级别:%-5p %n异 常 类:%c [%x] %n%m %n " />
    </layout>-->
    <layout type="Log4Net.MyLayout">
      <param name="ConversionPattern" value="日志时间:%d [%t] %n日志级别:%-5p %n日志信息:%property{LogMessage} %n异常信息:%exception %n%n"/>
    </layout>
  </appender>

  <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
    <bufferSize value="1" />
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <connectionString value="Data Source=.sql2014;Initial Catalog=FirstVueAdminDB;Persist Security Info=True;User ID=sa;Password=Aa123456;MultipleActiveResultSets=True;"/>
    <commandText value="INSERT INTO OperatorLog(Createdate,CreatedBy,IsDeleted,ModuleName,Origin,Type,LogLevel,LogMessage,Exception,Logger) VALUES(@Createdate,@CreatedBy,@IsDeleted,@ModuleName,@Origin,@Type,@LogLevel,@LogMessage,@Exception,@logger)" />
    <parameter>
      <parameterName value="@Createdate" />
      <dbType value="DateTime" />
      <layout type="log4net.Layout.RawTimeStampLayout" />
    </parameter>
    <parameter>
      <parameterName value="@CreatedBy" />
      <dbType value="String" />
      <size value="50" />
      <layout type="Log4Net.MyLayout" >
        <conversionPattern value = "%property{CreatedBy}"/>
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@IsDeleted" />
      <dbType value="String" />
      <size value="50" />
      <layout type="Log4Net.MyLayout" >
        <conversionPattern value = "%property{IsDeleted}"/>
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@ModuleName" />
      <dbType value="String" />
      <size value="30" />
      <layout type="Log4Net.MyLayout" >
        <conversionPattern value = "%property{ModuleName}"/>
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@Origin" />
      <dbType value="String" />
      <size value="50" />
      <layout type="Log4Net.MyLayout" >
        <conversionPattern value = "%property{Origin}"/>
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@Type" />
      <dbType value="String" />
      <size value="50" />
      <layout type="Log4Net.MyLayout" >
        <conversionPattern value = "%property{Type}"/>
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@LogLevel" />
      <dbType value="String" />
      <size value="20" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%p" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@LogMessage" />
      <dbType value="String" />
      <size value="500" />
      <layout type="Log4Net.MyLayout">
        <conversionPattern value="%property{LogMessage}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@Exception"/>
      <dbType value="String"/>
      <size value="500"/>
      <layout type="log4net.Layout.ExceptionLayout"/>
    </parameter>
    <parameter>
      <parameterName value="@logger" />
      <dbType value="String" />
      <size value="500" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%logger" />
      </layout>
    </parameter>
  </appender>

  <!--log4net.LogManager.GetLogger("logerror")用这个来选择这种类型-->
  <!--<logger name="logerror">
    <level value="ERROR" />
    <appender-ref ref="ErrorAppender" />
  </logger>
  <logger name="loginfo">
    <level value="INFO" />
    <appender-ref ref="InfoAppender" />
  </logger>
  <logger name="logwarn">
    <level value="WARN"/>
    <appender-ref ref="WarningAppender"/>
  </logger>
  <logger name="logdebug">
    <level value="DEBUG"/>
    <appender-ref ref="DebugAppender"/>
  </logger>
  -->
  <!--<logger name="logexceptionless">
      <level value="INFO"/>
      <appender-ref ref="Exceptionless"/>
    </logger>-->
  <root>
    <!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
    <!--比如定义级别为INFO,则INFO级别向下的级别,比如DEBUG日志将不会被记录-->
    <!--如果没有定义LEVEL的值,则缺省为DEBUG-->
    <level value="ALL" />
    <!--根据log级别记录到不同的日志文件-->
    <!--文件形式记录日志-->
    <appender-ref ref="InfoAppender"/>
    <appender-ref ref="ErrorAppender" />
    <appender-ref ref="ADONetAppender" />
 
  </root>

</log4net>

log4net 有四种主要的组件,分别是Logger(记录器), Repository(库), Appender(附着器)以及 Layout(布局).

Log4net框架定义了一个ILog接口,所有的logger类都必须实现这个接口。如果你想实现一个自定义的logger,你必须首先实现这个接口。你可以参考在/extension目录下的几个例子。

log4net.Layout.PatternLayout中的转换模式(ConversionPattern)

%m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息

%n(new line):换行

%d(datetime):输出当前语句运行的时刻

%r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数

%t(thread id):当前语句所在的线程ID

%p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等

%c(class):当前日志对象的名称,例如:

       模式字符串为:%-10c -%m%n

       代码为:

ILog log=LogManager.GetLogger(“Exam.Log”);

log.Debug(“Hello”);

    则输出为下面的形式:

Exam.Log       - Hello

%L:输出语句所在的行号

%F:输出语句所在的文件名

%-数字:表示该项的最小长度,如果不够,则用空格填充

Logger

作用:直接与应用交互的组件,用于触发日志事件

级别(日志事件) 优先级
OFF                    6
FATAL       5
ERROR      4
WARN        3
INFO          2
DEBUG       1
ALL            0

其他参考

http://www.cnblogs.com/zhangchenliang/p/4546352.html 

http://www.cnblogs.com/RainbowInTheSky/p/5914766.html    自定义记录日志

https://www.cnblogs.com/maijin/p/4618435.html
https://www.cnblogs.com/zhihaospace/p/8419946.html
https://blog.csdn.net/kongwei521/article/details/52242319
https://blog.51cto.com/790381375/1742018
https://www.cnblogs.com/izreo/p/5651139.html

原文地址:https://www.cnblogs.com/shy1766IT/p/5384762.html