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="""yyyyMMdd".log"" /> <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="""yyyyMMdd".log"" /> <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